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