1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 31 #include "AccessibleChartView.hxx" 32 #include "chartview/ExplicitValueProvider.hxx" 33 #include "servicenames.hxx" 34 #include "macros.hxx" 35 #include "ObjectHierarchy.hxx" 36 #include "ObjectIdentifier.hxx" 37 #include "ResId.hxx" 38 #include "Strings.hrc" 39 #include "AccessibleViewForwarder.hxx" 40 41 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 42 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 43 #include <com/sun/star/accessibility/AccessibleRole.hpp> 44 45 #include <tools/string.hxx> 46 #include <vcl/window.hxx> 47 #include <toolkit/helper/vclunohelper.hxx> 48 // for SolarMutex 49 #include <vcl/svapp.hxx> 50 51 // header for typedef MutexGuard 52 #include <osl/mutex.hxx> 53 54 using namespace ::com::sun::star; 55 using namespace ::com::sun::star::accessibility; 56 57 using ::com::sun::star::uno::Sequence; 58 using ::com::sun::star::uno::Reference; 59 using ::com::sun::star::uno::WeakReference; 60 using ::com::sun::star::uno::Any; 61 using ::rtl::OUString; 62 using osl::MutexGuard; 63 64 //............................................................................. 65 namespace chart 66 { 67 //............................................................................. 68 69 AccessibleChartView::AccessibleChartView( 70 const Reference< uno::XComponentContext >& xContext, SdrView* pView ) : 71 impl::AccessibleChartView_Base( 72 AccessibleElementInfo(), // empty for now 73 true, // has children 74 true // always transparent 75 ), 76 m_xContext( xContext ), 77 m_pSdrView( pView ), 78 m_pViewForwarder( NULL ) 79 { 80 AddState( AccessibleStateType::OPAQUE ); 81 } 82 83 AccessibleChartView::~AccessibleChartView() 84 { 85 delete m_pViewForwarder; 86 } 87 88 89 awt::Rectangle AccessibleChartView::GetWindowPosSize() const 90 { 91 Reference< awt::XWindow > xWindow( GetInfo().m_xWindow ); 92 if( ! xWindow.is()) 93 return awt::Rectangle(); 94 95 // this should do, but it doesn't => HACK 96 // return xWindow->getPosSize(); 97 98 awt::Rectangle aBBox( xWindow->getPosSize() ); 99 100 Window* pWindow( VCLUnoHelper::GetWindow( GetInfo().m_xWindow )); 101 if( pWindow ) 102 { 103 // /-- solar 104 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 105 Point aVCLPoint( pWindow->OutputToAbsoluteScreenPixel( Point( 0, 0 ) )); 106 aBBox.X = aVCLPoint.getX(); 107 aBBox.Y = aVCLPoint.getY(); 108 // \-- solar 109 } 110 111 return aBBox; 112 } 113 114 awt::Point AccessibleChartView::GetUpperLeftOnScreen() const 115 { 116 awt::Point aParentPosition; 117 118 awt::Rectangle aBBox( GetWindowPosSize() ); 119 aParentPosition.X = aBBox.X; 120 aParentPosition.Y = aBBox.Y; 121 122 return aParentPosition; 123 } 124 125 // ________ XAccessibleContext ________ 126 OUString SAL_CALL AccessibleChartView::getAccessibleName() 127 throw (uno::RuntimeException) 128 { 129 return OUString( String( SchResId( STR_OBJECT_DIAGRAM ))); 130 } 131 132 OUString SAL_CALL AccessibleChartView::getAccessibleDescription() 133 throw (uno::RuntimeException) 134 { 135 return getAccessibleName(); 136 } 137 138 Reference< XAccessible > SAL_CALL AccessibleChartView::getAccessibleParent() 139 throw (uno::RuntimeException) 140 { 141 return Reference< XAccessible >( m_xParent ); 142 } 143 144 sal_Int32 SAL_CALL AccessibleChartView::getAccessibleIndexInParent() 145 throw (uno::RuntimeException) 146 { 147 // the document is always the only child of the window 148 return 0; 149 } 150 151 sal_Int16 SAL_CALL AccessibleChartView::getAccessibleRole() 152 throw (uno::RuntimeException) 153 { 154 return AccessibleRole::DOCUMENT; 155 } 156 157 // ________ XAccessibleComponent ________ 158 awt::Rectangle SAL_CALL AccessibleChartView::getBounds() 159 throw (uno::RuntimeException) 160 { 161 awt::Rectangle aResult( GetWindowPosSize()); 162 Reference< XAccessible > xParent( m_xParent ); 163 if( xParent.is()) 164 { 165 Reference< XAccessibleComponent > xContext( xParent->getAccessibleContext(), uno::UNO_QUERY ); 166 if( xContext.is()) 167 { 168 awt::Point aParentPosition = xContext->getLocationOnScreen(); 169 aResult.X -= aParentPosition.X; 170 aResult.Y -= aParentPosition.Y; 171 } 172 } 173 return aResult; 174 } 175 176 awt::Point SAL_CALL AccessibleChartView::getLocationOnScreen() 177 throw (uno::RuntimeException) 178 { 179 awt::Rectangle aBounds( getBounds()); 180 awt::Point aResult; 181 Reference< XAccessible > xParent( m_xParent ); 182 if( xParent.is()) 183 { 184 Reference< XAccessibleComponent > xAccComp( 185 xParent->getAccessibleContext(), uno::UNO_QUERY ); 186 aResult = xAccComp->getLocationOnScreen(); 187 aResult.X += aBounds.X; 188 aResult.Y += aBounds.Y; 189 } 190 return aResult; 191 } 192 193 //----------------------------------------------------------------- 194 // lang::XInitialization 195 //----------------------------------------------------------------- 196 197 void SAL_CALL AccessibleChartView::initialize( const Sequence< Any >& rArguments ) 198 throw (uno::Exception, uno::RuntimeException) 199 { 200 //0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself 201 //1: frame::XModel representing the chart model - offers access to object data 202 //2: lang::XInterface representing the normal chart view - offers access to some extra object data 203 204 //all arguments are only valid until next initialization 205 bool bChanged = false; 206 bool bOldInvalid = false; 207 bool bNewInvalid = false; 208 209 Reference< view::XSelectionSupplier > xSelectionSupplier; 210 Reference< frame::XModel > xChartModel; 211 Reference< uno::XInterface > xChartView; 212 Reference< XAccessible > xParent; 213 Reference< awt::XWindow > xWindow; 214 { 215 MutexGuard aGuard( GetMutex()); 216 xSelectionSupplier.set( m_xSelectionSupplier ); 217 xChartModel.set( m_xChartModel ); 218 xChartView.set( m_xChartView ); 219 xParent.set( m_xParent ); 220 xWindow.set( m_xWindow ); 221 } 222 223 if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) 224 { 225 bOldInvalid = true; 226 } 227 228 if( rArguments.getLength() > 1 ) 229 { 230 Reference< frame::XModel > xNewChartModel; 231 rArguments[1] >>= xNewChartModel; 232 if( xNewChartModel != xChartModel ) 233 { 234 xChartModel = xNewChartModel; 235 bChanged = true; 236 } 237 } 238 else if( xChartModel.is() ) 239 { 240 bChanged = true; 241 xChartModel = 0; 242 } 243 244 if( rArguments.getLength() > 2 ) 245 { 246 Reference< uno::XInterface > xNewChartView; 247 rArguments[2] >>= xNewChartView; 248 if( xNewChartView != xChartView ) 249 { 250 xChartView = xNewChartView; 251 bChanged = true; 252 } 253 } 254 else if( xChartView.is() ) 255 { 256 bChanged = true; 257 xChartView = 0; 258 } 259 260 if( rArguments.getLength() > 3 ) 261 { 262 Reference< XAccessible > xNewParent; 263 rArguments[3] >>= xNewParent; 264 if( xNewParent != xParent ) 265 { 266 xParent = xNewParent; 267 bChanged = true; 268 } 269 } 270 271 if( rArguments.getLength() > 4 ) 272 { 273 Reference< awt::XWindow > xNewWindow; 274 rArguments[4] >>= xNewWindow; 275 if( xNewWindow != xWindow ) 276 { 277 xWindow.set( xNewWindow ); 278 bChanged = true; 279 } 280 } 281 282 if( rArguments.getLength() > 0 && xChartModel.is() && xChartView.is() ) 283 { 284 Reference< view::XSelectionSupplier > xNewSelectionSupplier; 285 rArguments[0] >>= xNewSelectionSupplier; 286 if(xSelectionSupplier!=xNewSelectionSupplier) 287 { 288 bChanged = true; 289 if(xSelectionSupplier.is()) 290 xSelectionSupplier->removeSelectionChangeListener(this); 291 if(xNewSelectionSupplier.is()) 292 xNewSelectionSupplier->addSelectionChangeListener(this); 293 xSelectionSupplier = xNewSelectionSupplier; 294 } 295 } 296 else if( xSelectionSupplier.is() ) 297 { 298 bChanged = true; 299 xSelectionSupplier->removeSelectionChangeListener(this); 300 xSelectionSupplier = 0; 301 } 302 303 if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() ) 304 { 305 if(xSelectionSupplier.is()) 306 xSelectionSupplier->removeSelectionChangeListener(this); 307 xSelectionSupplier = 0; 308 xChartModel.clear(); 309 xChartView.clear(); 310 xParent.clear(); 311 xWindow.clear(); 312 313 bNewInvalid = true; 314 } 315 316 { 317 MutexGuard aGuard( GetMutex()); 318 m_xSelectionSupplier = WeakReference< view::XSelectionSupplier >(xSelectionSupplier); 319 m_xChartModel = WeakReference< frame::XModel >(xChartModel); 320 m_xChartView = WeakReference< uno::XInterface >(xChartView); 321 m_xParent = WeakReference< XAccessible >(xParent); 322 m_xWindow = WeakReference< awt::XWindow >(xWindow); 323 } 324 325 if( bOldInvalid && bNewInvalid ) 326 bChanged = false; 327 328 if( bChanged ) 329 { 330 { 331 //before notification we prepare for creation of new context 332 //the old context will be deleted after notification than 333 MutexGuard aGuard( GetMutex()); 334 Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY ); 335 if( xChartDoc.is()) 336 m_spObjectHierarchy.reset( new ObjectHierarchy( xChartDoc, getExplicitValueProvider() )); 337 else 338 m_spObjectHierarchy.reset(); 339 } 340 341 { 342 AccessibleElementInfo aAccInfo; 343 aAccInfo.m_aOID = ObjectIdentifier( C2U( "ROOT" ) ); 344 aAccInfo.m_xChartDocument = uno::WeakReference< chart2::XChartDocument >( 345 uno::Reference< chart2::XChartDocument >( m_xChartModel.get(), uno::UNO_QUERY )); 346 aAccInfo.m_xSelectionSupplier = m_xSelectionSupplier; 347 aAccInfo.m_xView = m_xChartView; 348 aAccInfo.m_xWindow = m_xWindow; 349 aAccInfo.m_pParent = 0; 350 aAccInfo.m_spObjectHierarchy = m_spObjectHierarchy; 351 aAccInfo.m_pSdrView = m_pSdrView; 352 Window* pWindow = VCLUnoHelper::GetWindow( m_xWindow ); 353 if ( m_pViewForwarder ) 354 { 355 delete m_pViewForwarder; 356 } 357 m_pViewForwarder = new AccessibleViewForwarder( this, pWindow ); 358 aAccInfo.m_pViewForwarder = m_pViewForwarder; 359 // broadcasts an INVALIDATE_ALL_CHILDREN event globally 360 SetInfo( aAccInfo ); 361 } 362 } 363 } 364 365 ExplicitValueProvider* AccessibleChartView::getExplicitValueProvider() 366 { 367 return ExplicitValueProvider::getExplicitValueProvider(m_xChartView); 368 } 369 370 //------------------------------------------------------------------------- 371 // view::XSelectionChangeListener 372 //------------------------------------------------------------------------- 373 374 void SAL_CALL AccessibleChartView::selectionChanged( const lang::EventObject& /*rEvent*/ ) 375 throw (uno::RuntimeException) 376 { 377 Reference< view::XSelectionSupplier > xSelectionSupplier; 378 { 379 MutexGuard aGuard( GetMutex()); 380 xSelectionSupplier = Reference< view::XSelectionSupplier >(m_xSelectionSupplier); 381 } 382 383 if( xSelectionSupplier.is() ) 384 { 385 ObjectIdentifier aSelectedOID( xSelectionSupplier->getSelection() ); 386 if ( m_aCurrentSelectionOID.isValid() ) 387 { 388 NotifyEvent( LOST_SELECTION, m_aCurrentSelectionOID ); 389 } 390 if( aSelectedOID.isValid() ) 391 { 392 NotifyEvent( GOT_SELECTION, aSelectedOID ); 393 } 394 m_aCurrentSelectionOID = aSelectedOID; 395 } 396 } 397 398 //------------------------------------------------------------------------- 399 // lang::XComponent::dispose() 400 //------------------------------------------------------------------------- 401 void SAL_CALL AccessibleChartView::disposing() 402 { 403 AccessibleBase::disposing(); 404 } 405 406 //------------------------------------------------------------------------- 407 // XEventListener 408 //------------------------------------------------------------------------- 409 void SAL_CALL AccessibleChartView::disposing( const lang::EventObject& /*Source*/ ) 410 throw (uno::RuntimeException) 411 { 412 } 413 414 //............................................................................. 415 } //namespace chart 416 //............................................................................. 417