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_chartcontroller.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
AccessibleChartView(const Reference<uno::XComponentContext> & xContext,SdrView * pView)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
~AccessibleChartView()79 AccessibleChartView::~AccessibleChartView()
80 {
81 delete m_pViewForwarder;
82 }
83
84
GetWindowPosSize() const85 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
GetUpperLeftOnScreen() const110 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 ________
getAccessibleName()122 OUString SAL_CALL AccessibleChartView::getAccessibleName()
123 {
124 return OUString( String( SchResId( STR_OBJECT_DIAGRAM )));
125 }
126
getAccessibleDescription()127 OUString SAL_CALL AccessibleChartView::getAccessibleDescription()
128 {
129 return getAccessibleName();
130 }
131
getAccessibleParent()132 Reference< XAccessible > SAL_CALL AccessibleChartView::getAccessibleParent()
133 {
134 return Reference< XAccessible >( m_xParent );
135 }
136
getAccessibleIndexInParent()137 sal_Int32 SAL_CALL AccessibleChartView::getAccessibleIndexInParent()
138 {
139 // the document is always the only child of the window
140 return 0;
141 }
142
getAccessibleRole()143 sal_Int16 SAL_CALL AccessibleChartView::getAccessibleRole()
144 {
145 return AccessibleRole::DOCUMENT;
146 }
147
148 // ________ XAccessibleComponent ________
getBounds()149 awt::Rectangle SAL_CALL AccessibleChartView::getBounds()
150 {
151 awt::Rectangle aResult( GetWindowPosSize());
152 Reference< XAccessible > xParent( m_xParent );
153 if( xParent.is())
154 {
155 Reference< XAccessibleComponent > xContext( xParent->getAccessibleContext(), uno::UNO_QUERY );
156 if( xContext.is())
157 {
158 awt::Point aParentPosition = xContext->getLocationOnScreen();
159 aResult.X -= aParentPosition.X;
160 aResult.Y -= aParentPosition.Y;
161 }
162 }
163 return aResult;
164 }
165
getLocationOnScreen()166 awt::Point SAL_CALL AccessibleChartView::getLocationOnScreen()
167 {
168 awt::Rectangle aBounds( getBounds());
169 awt::Point aResult;
170 Reference< XAccessible > xParent( m_xParent );
171 if( xParent.is())
172 {
173 Reference< XAccessibleComponent > xAccComp(
174 xParent->getAccessibleContext(), uno::UNO_QUERY );
175 aResult = xAccComp->getLocationOnScreen();
176 aResult.X += aBounds.X;
177 aResult.Y += aBounds.Y;
178 }
179 return aResult;
180 }
181
182 //-----------------------------------------------------------------
183 // lang::XInitialization
184 //-----------------------------------------------------------------
185
initialize(const Sequence<Any> & rArguments)186 void SAL_CALL AccessibleChartView::initialize( const Sequence< Any >& rArguments )
187 {
188 //0: view::XSelectionSupplier offers notifications for selection changes and access to the selection itself
189 //1: frame::XModel representing the chart model - offers access to object data
190 //2: lang::XInterface representing the normal chart view - offers access to some extra object data
191
192 //all arguments are only valid until next initialization
193 bool bChanged = false;
194 bool bOldInvalid = false;
195 bool bNewInvalid = false;
196
197 Reference< view::XSelectionSupplier > xSelectionSupplier;
198 Reference< frame::XModel > xChartModel;
199 Reference< uno::XInterface > xChartView;
200 Reference< XAccessible > xParent;
201 Reference< awt::XWindow > xWindow;
202 {
203 MutexGuard aGuard( GetMutex());
204 xSelectionSupplier.set( m_xSelectionSupplier );
205 xChartModel.set( m_xChartModel );
206 xChartView.set( m_xChartView );
207 xParent.set( m_xParent );
208 xWindow.set( m_xWindow );
209 }
210
211 if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() )
212 {
213 bOldInvalid = true;
214 }
215
216 if( rArguments.getLength() > 1 )
217 {
218 Reference< frame::XModel > xNewChartModel;
219 rArguments[1] >>= xNewChartModel;
220 if( xNewChartModel != xChartModel )
221 {
222 xChartModel = xNewChartModel;
223 bChanged = true;
224 }
225 }
226 else if( xChartModel.is() )
227 {
228 bChanged = true;
229 xChartModel = 0;
230 }
231
232 if( rArguments.getLength() > 2 )
233 {
234 Reference< uno::XInterface > xNewChartView;
235 rArguments[2] >>= xNewChartView;
236 if( xNewChartView != xChartView )
237 {
238 xChartView = xNewChartView;
239 bChanged = true;
240 }
241 }
242 else if( xChartView.is() )
243 {
244 bChanged = true;
245 xChartView = 0;
246 }
247
248 if( rArguments.getLength() > 3 )
249 {
250 Reference< XAccessible > xNewParent;
251 rArguments[3] >>= xNewParent;
252 if( xNewParent != xParent )
253 {
254 xParent = xNewParent;
255 bChanged = true;
256 }
257 }
258
259 if( rArguments.getLength() > 4 )
260 {
261 Reference< awt::XWindow > xNewWindow;
262 rArguments[4] >>= xNewWindow;
263 if( xNewWindow != xWindow )
264 {
265 xWindow.set( xNewWindow );
266 bChanged = true;
267 }
268 }
269
270 if( rArguments.getLength() > 0 && xChartModel.is() && xChartView.is() )
271 {
272 Reference< view::XSelectionSupplier > xNewSelectionSupplier;
273 rArguments[0] >>= xNewSelectionSupplier;
274 if(xSelectionSupplier!=xNewSelectionSupplier)
275 {
276 bChanged = true;
277 if(xSelectionSupplier.is())
278 xSelectionSupplier->removeSelectionChangeListener(this);
279 if(xNewSelectionSupplier.is())
280 xNewSelectionSupplier->addSelectionChangeListener(this);
281 xSelectionSupplier = xNewSelectionSupplier;
282 }
283 }
284 else if( xSelectionSupplier.is() )
285 {
286 bChanged = true;
287 xSelectionSupplier->removeSelectionChangeListener(this);
288 xSelectionSupplier = 0;
289 }
290
291 if( !xSelectionSupplier.is() || !xChartModel.is() || !xChartView.is() )
292 {
293 if(xSelectionSupplier.is())
294 xSelectionSupplier->removeSelectionChangeListener(this);
295 xSelectionSupplier = 0;
296 xChartModel.clear();
297 xChartView.clear();
298 xParent.clear();
299 xWindow.clear();
300
301 bNewInvalid = true;
302 }
303
304 {
305 MutexGuard aGuard( GetMutex());
306 m_xSelectionSupplier = WeakReference< view::XSelectionSupplier >(xSelectionSupplier);
307 m_xChartModel = WeakReference< frame::XModel >(xChartModel);
308 m_xChartView = WeakReference< uno::XInterface >(xChartView);
309 m_xParent = WeakReference< XAccessible >(xParent);
310 m_xWindow = WeakReference< awt::XWindow >(xWindow);
311 }
312
313 if( bOldInvalid && bNewInvalid )
314 bChanged = false;
315
316 if( bChanged )
317 {
318 {
319 //before notification we prepare for creation of new context
320 //the old context will be deleted after notification than
321 MutexGuard aGuard( GetMutex());
322 Reference< chart2::XChartDocument > xChartDoc( xChartModel, uno::UNO_QUERY );
323 if( xChartDoc.is())
324 m_spObjectHierarchy.reset( new ObjectHierarchy( xChartDoc, getExplicitValueProvider() ));
325 else
326 m_spObjectHierarchy.reset();
327 }
328
329 {
330 AccessibleElementInfo aAccInfo;
331 aAccInfo.m_aOID = ObjectIdentifier( C2U( "ROOT" ) );
332 aAccInfo.m_xChartDocument = uno::WeakReference< chart2::XChartDocument >(
333 uno::Reference< chart2::XChartDocument >( m_xChartModel.get(), uno::UNO_QUERY ));
334 aAccInfo.m_xSelectionSupplier = m_xSelectionSupplier;
335 aAccInfo.m_xView = m_xChartView;
336 aAccInfo.m_xWindow = m_xWindow;
337 aAccInfo.m_pParent = 0;
338 aAccInfo.m_spObjectHierarchy = m_spObjectHierarchy;
339 aAccInfo.m_pSdrView = m_pSdrView;
340 Window* pWindow = VCLUnoHelper::GetWindow( m_xWindow );
341 if ( m_pViewForwarder )
342 {
343 delete m_pViewForwarder;
344 }
345 m_pViewForwarder = new AccessibleViewForwarder( this, pWindow );
346 aAccInfo.m_pViewForwarder = m_pViewForwarder;
347 // broadcasts an INVALIDATE_ALL_CHILDREN event globally
348 SetInfo( aAccInfo );
349 }
350 }
351 }
352
getExplicitValueProvider()353 ExplicitValueProvider* AccessibleChartView::getExplicitValueProvider()
354 {
355 return ExplicitValueProvider::getExplicitValueProvider(m_xChartView);
356 }
357
358 //-------------------------------------------------------------------------
359 // view::XSelectionChangeListener
360 //-------------------------------------------------------------------------
361
selectionChanged(const lang::EventObject &)362 void SAL_CALL AccessibleChartView::selectionChanged( const lang::EventObject& /*rEvent*/ )
363 {
364 Reference< view::XSelectionSupplier > xSelectionSupplier;
365 {
366 MutexGuard aGuard( GetMutex());
367 xSelectionSupplier = Reference< view::XSelectionSupplier >(m_xSelectionSupplier);
368 }
369
370 if( xSelectionSupplier.is() )
371 {
372 ObjectIdentifier aSelectedOID( xSelectionSupplier->getSelection() );
373 if ( m_aCurrentSelectionOID.isValid() )
374 {
375 NotifyEvent( LOST_SELECTION, m_aCurrentSelectionOID );
376 }
377 if( aSelectedOID.isValid() )
378 {
379 NotifyEvent( GOT_SELECTION, aSelectedOID );
380 }
381 m_aCurrentSelectionOID = aSelectedOID;
382 }
383 }
384
385 //-------------------------------------------------------------------------
386 // lang::XComponent::dispose()
387 //-------------------------------------------------------------------------
disposing()388 void SAL_CALL AccessibleChartView::disposing()
389 {
390 AccessibleBase::disposing();
391 }
392
393 //-------------------------------------------------------------------------
394 // XEventListener
395 //-------------------------------------------------------------------------
disposing(const lang::EventObject &)396 void SAL_CALL AccessibleChartView::disposing( const lang::EventObject& /*Source*/ )
397 {
398 }
399
400 //.............................................................................
401 } //namespace chart
402 //.............................................................................
403