xref: /trunk/main/chart2/source/controller/accessibility/AccessibleChartView.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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