Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 : :
29 : : #include "accessibility/extended/AccessibleToolPanelDeck.hxx"
30 : :
31 : : #include <com/sun/star/accessibility/AccessibleRole.hpp>
32 : : #include <com/sun/star/accessibility/AccessibleEventId.hpp>
33 : : #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 : : #include <com/sun/star/lang/DisposedException.hpp>
35 : :
36 : : #include <svtools/toolpanel/toolpaneldeck.hxx>
37 : : #include <toolkit/awt/vclxwindow.hxx>
38 : : #include <toolkit/helper/vclunohelper.hxx>
39 : : #include <vcl/svapp.hxx>
40 : : #include <osl/mutex.hxx>
41 : : #include <unotools/accessiblestatesethelper.hxx>
42 : : #include <tools/diagnose_ex.h>
43 : :
44 : : #include <boost/noncopyable.hpp>
45 : :
46 : : //......................................................................................................................
47 : : namespace accessibility
48 : : {
49 : : //......................................................................................................................
50 : :
51 : : /** === begin UNO using === **/
52 : : using ::com::sun::star::uno::Reference;
53 : : using ::com::sun::star::uno::XInterface;
54 : : using ::com::sun::star::uno::UNO_QUERY;
55 : : using ::com::sun::star::uno::UNO_QUERY_THROW;
56 : : using ::com::sun::star::uno::UNO_SET_THROW;
57 : : using ::com::sun::star::uno::Exception;
58 : : using ::com::sun::star::uno::RuntimeException;
59 : : using ::com::sun::star::uno::Any;
60 : : using ::com::sun::star::uno::makeAny;
61 : : using ::com::sun::star::uno::Sequence;
62 : : using ::com::sun::star::uno::Type;
63 : : using ::com::sun::star::accessibility::XAccessible;
64 : : using ::com::sun::star::accessibility::XAccessibleContext;
65 : : using ::com::sun::star::lang::DisposedException;
66 : : using ::com::sun::star::lang::IndexOutOfBoundsException;
67 : : using ::com::sun::star::lang::Locale;
68 : : using ::com::sun::star::accessibility::XAccessibleRelationSet;
69 : : using ::com::sun::star::accessibility::XAccessibleStateSet;
70 : : using ::com::sun::star::accessibility::IllegalAccessibleComponentStateException;
71 : : using ::com::sun::star::awt::XFont;
72 : : /** === end UNO using === **/
73 : : namespace AccessibleRole = ::com::sun::star::accessibility::AccessibleRole;
74 : : namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
75 : : namespace AccessibleStateType = ::com::sun::star::accessibility::AccessibleStateType;
76 : :
77 : : typedef ::com::sun::star::awt::Point UnoPoint;
78 : :
79 : : //==================================================================================================================
80 : : //= AccessibleToolPanelDeck_Impl - declaration
81 : : //==================================================================================================================
82 : : class AccessibleToolPanelDeck_Impl :public ::boost::noncopyable
83 : : ,public ::svt::IToolPanelDeckListener
84 : : {
85 : : public:
86 : : AccessibleToolPanelDeck_Impl(
87 : : AccessibleToolPanelDeck& i_rAntiImpl,
88 : : const Reference< XAccessible >& i_rAccessibleParent,
89 : : ::svt::ToolPanelDeck& i_rPanelDeck
90 : : );
91 : :
92 : : void checkDisposed();
93 : 0 : bool isDisposed() const { return m_pPanelDeck == NULL; }
94 : : void dispose();
95 : :
96 : : virtual ~AccessibleToolPanelDeck_Impl();
97 : :
98 : : Reference< XAccessible > getOwnAccessible() const;
99 : : Reference< XAccessible > getActivePanelAccessible();
100 : :
101 : : protected:
102 : : // IToolPanelDeckListener
103 : : virtual void PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition );
104 : : virtual void PanelRemoved( const size_t i_nPosition );
105 : : virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive );
106 : : virtual void LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter );
107 : : virtual void Dying();
108 : :
109 : : public:
110 : : AccessibleToolPanelDeck& m_rAntiImpl;
111 : : Reference< XAccessible > m_xAccessibleParent;
112 : : ::svt::ToolPanelDeck* m_pPanelDeck;
113 : :
114 : : Reference< XAccessible > m_xActivePanelAccessible;
115 : : };
116 : :
117 : : //==================================================================================================================
118 : : //= MethodGuard
119 : : //==================================================================================================================
120 : : namespace
121 : : {
122 : : class MethodGuard
123 : : {
124 : : public:
125 : 0 : MethodGuard( AccessibleToolPanelDeck_Impl& i_rImpl )
126 : 0 : :m_aGuard()
127 : : {
128 [ # # ]: 0 : i_rImpl.checkDisposed();
129 : 0 : }
130 : 0 : ~MethodGuard()
131 : 0 : {
132 : 0 : }
133 : :
134 : : private:
135 : : SolarMutexGuard m_aGuard;
136 : : };
137 : : }
138 : :
139 : : //==================================================================================================================
140 : : //= AccessibleToolPanelDeck_Impl - implementation
141 : : //==================================================================================================================
142 : : //------------------------------------------------------------------------------------------------------------------
143 : 0 : AccessibleToolPanelDeck_Impl::AccessibleToolPanelDeck_Impl( AccessibleToolPanelDeck& i_rAntiImpl, const Reference< XAccessible >& i_rAccessibleParent,
144 : : ::svt::ToolPanelDeck& i_rPanelDeck )
145 : : :m_rAntiImpl( i_rAntiImpl )
146 : : ,m_xAccessibleParent( i_rAccessibleParent )
147 : : ,m_pPanelDeck( &i_rPanelDeck )
148 : 0 : ,m_xActivePanelAccessible()
149 : : {
150 [ # # ]: 0 : m_pPanelDeck->AddListener( *this );
151 : 0 : }
152 : :
153 : : //------------------------------------------------------------------------------------------------------------------
154 : 0 : AccessibleToolPanelDeck_Impl::~AccessibleToolPanelDeck_Impl()
155 : : {
156 [ # # ]: 0 : if ( !isDisposed() )
157 [ # # ]: 0 : dispose();
158 [ # # ]: 0 : }
159 : :
160 : : //------------------------------------------------------------------------------------------------------------------
161 : 0 : void AccessibleToolPanelDeck_Impl::dispose()
162 : : {
163 [ # # ]: 0 : ENSURE_OR_RETURN_VOID( !isDisposed(), "disposed twice" );
164 : 0 : m_pPanelDeck->RemoveListener( *this );
165 : 0 : m_pPanelDeck = NULL;
166 : 0 : m_xAccessibleParent.clear();
167 : : }
168 : :
169 : : //------------------------------------------------------------------------------------------------------------------
170 : 0 : void AccessibleToolPanelDeck_Impl::checkDisposed()
171 : : {
172 [ # # ]: 0 : if ( isDisposed() )
173 [ # # ][ # # ]: 0 : throw DisposedException( ::rtl::OUString(), *&m_rAntiImpl );
174 : 0 : }
175 : :
176 : : //------------------------------------------------------------------------------------------------------------------
177 : 0 : Reference< XAccessible > AccessibleToolPanelDeck_Impl::getOwnAccessible() const
178 : : {
179 [ # # ]: 0 : Reference< XAccessible > xOwnAccessible( static_cast< XAccessible* >( m_rAntiImpl.GetVCLXWindow() ) );
180 : : OSL_ENSURE( xOwnAccessible->getAccessibleContext() == Reference< XAccessibleContext >( &m_rAntiImpl ),
181 : : "AccessibleToolPanelDeck_Impl::getOwnAccessible: could not retrieve proper XAccessible for /myself!" );
182 : 0 : return xOwnAccessible;
183 : : }
184 : :
185 : : //------------------------------------------------------------------------------------------------------------------
186 : 0 : Reference< XAccessible > AccessibleToolPanelDeck_Impl::getActivePanelAccessible()
187 : : {
188 [ # # ]: 0 : ENSURE_OR_RETURN( !isDisposed(), "AccessibleToolPanelDeck_Impl::getActivePanelAccessible: already disposed!", NULL );
189 : :
190 [ # # ]: 0 : if ( !m_xActivePanelAccessible.is() )
191 : : {
192 [ # # ]: 0 : ::boost::optional< size_t > aActivePanel( m_pPanelDeck->GetActivePanel() );
193 [ # # ][ # # ]: 0 : ENSURE_OR_RETURN( !!aActivePanel, "AccessibleToolPanelDeck_Impl::getActivePanelAccessible: this should not be called without an active panel!", NULL );
[ # # ]
194 [ # # ][ # # ]: 0 : ::svt::PToolPanel pActivePanel( m_pPanelDeck->GetPanel( *aActivePanel ) );
195 [ # # ][ # # ]: 0 : ENSURE_OR_RETURN( pActivePanel.get() != NULL, "AccessibleToolPanelDeck_Impl::getActivePanelAccessible: no active panel!", NULL );
196 [ # # ][ # # ]: 0 : m_xActivePanelAccessible = pActivePanel->CreatePanelAccessible( getOwnAccessible() );
[ # # ][ # # ]
197 [ # # ][ # # ]: 0 : OSL_ENSURE( m_xActivePanelAccessible.is(), "AccessibleToolPanelDeck_Impl::getActivePanelAccessible: illegal accessible returned by the panel!" );
[ # # ]
198 : : }
199 : :
200 : 0 : return m_xActivePanelAccessible;
201 : : }
202 : :
203 : : //------------------------------------------------------------------------------------------------------------------
204 : 0 : void AccessibleToolPanelDeck_Impl::PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition )
205 : : {
206 : : (void)i_pPanel;
207 : : (void)i_nPosition;
208 : 0 : }
209 : :
210 : : //------------------------------------------------------------------------------------------------------------------
211 : 0 : void AccessibleToolPanelDeck_Impl::PanelRemoved( const size_t i_nPosition )
212 : : {
213 : : (void)i_nPosition;
214 : 0 : }
215 : :
216 : : //------------------------------------------------------------------------------------------------------------------
217 : 0 : void AccessibleToolPanelDeck_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
218 : : {
219 [ # # ]: 0 : if ( !!i_rOldActive )
220 : : {
221 [ # # ]: 0 : if ( !m_xActivePanelAccessible.is() )
222 : : {
223 : : // again, this might in theory happen if the XAccessible for the active panel has never before been requested.
224 : : // In this case, just say that all our children are invalid, so they all must be re-requested.
225 [ # # ]: 0 : m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any() );
226 : : }
227 : : else
228 : : {
229 [ # # ][ # # ]: 0 : m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::CHILD, makeAny( m_xActivePanelAccessible ), Any() );
230 : : }
231 : : }
232 : :
233 : 0 : m_xActivePanelAccessible.clear();
234 : :
235 [ # # ]: 0 : if ( !!i_rNewActive )
236 : : {
237 [ # # ][ # # ]: 0 : m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), makeAny( getActivePanelAccessible() ) );
238 : : }
239 : 0 : }
240 : :
241 : : //------------------------------------------------------------------------------------------------------------------
242 : 0 : void AccessibleToolPanelDeck_Impl::LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter )
243 : : {
244 [ # # ]: 0 : MethodGuard aGuard( *this );
245 : :
246 : : (void)i_rNewLayouter;
247 [ # # ][ # # ]: 0 : m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any() );
248 : 0 : }
249 : :
250 : : //------------------------------------------------------------------------------------------------------------------
251 : 0 : void AccessibleToolPanelDeck_Impl::Dying()
252 : : {
253 : : // the tool panel deck is dying, so dispose ourself
254 : 0 : m_rAntiImpl.dispose();
255 : 0 : }
256 : :
257 : : //==================================================================================================================
258 : : //= AccessibleToolPanelDeck
259 : : //==================================================================================================================
260 : : //------------------------------------------------------------------------------------------------------------------
261 : 0 : AccessibleToolPanelDeck::AccessibleToolPanelDeck( const Reference< XAccessible >& i_rAccessibleParent,
262 : : ::svt::ToolPanelDeck& i_rPanelDeck )
263 : : :AccessibleToolPanelDeck_Base( i_rPanelDeck.GetWindowPeer() )
264 [ # # ][ # # ]: 0 : ,m_pImpl( new AccessibleToolPanelDeck_Impl( *this, i_rAccessibleParent, i_rPanelDeck ) )
265 : : {
266 : 0 : }
267 : :
268 : : //------------------------------------------------------------------------------------------------------------------
269 [ # # ]: 0 : AccessibleToolPanelDeck::~AccessibleToolPanelDeck()
270 : : {
271 [ # # ]: 0 : }
272 : :
273 : : //------------------------------------------------------------------------------------------------------------------
274 : 0 : sal_Int32 SAL_CALL AccessibleToolPanelDeck::getAccessibleChildCount( ) throw (RuntimeException)
275 : : {
276 [ # # ]: 0 : MethodGuard aGuard( *m_pImpl );
277 : :
278 [ # # ][ # # ]: 0 : sal_Int32 nChildCount( m_pImpl->m_pPanelDeck->GetLayouter()->GetAccessibleChildCount() );
[ # # ]
279 : :
280 [ # # ]: 0 : ::boost::optional< size_t > aActivePanel( m_pImpl->m_pPanelDeck->GetActivePanel() );
281 [ # # ][ # # ]: 0 : if ( !!aActivePanel )
282 : 0 : return ++nChildCount;
283 : :
284 [ # # ][ # # ]: 0 : return nChildCount;
285 : : }
286 : :
287 : : //------------------------------------------------------------------------------------------------------------------
288 : 0 : Reference< XAccessible > SAL_CALL AccessibleToolPanelDeck::getAccessibleChild( sal_Int32 i_nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
289 : : {
290 [ # # ]: 0 : MethodGuard aGuard( *m_pImpl );
291 : :
292 [ # # ]: 0 : const sal_Int32 nChildCount( getAccessibleChildCount() );
293 [ # # ][ # # ]: 0 : if ( ( i_nIndex < 0 ) || ( i_nIndex >= nChildCount ) )
294 [ # # ][ # # ]: 0 : throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
295 : :
296 : : // first "n" children are provided by the layouter
297 [ # # ][ # # ]: 0 : const size_t nLayouterCount( m_pImpl->m_pPanelDeck->GetLayouter()->GetAccessibleChildCount() );
[ # # ]
298 [ # # ]: 0 : if ( size_t( i_nIndex ) < nLayouterCount )
299 [ # # ][ # # ]: 0 : return m_pImpl->m_pPanelDeck->GetLayouter()->GetAccessibleChild(
300 : : size_t( i_nIndex ),
301 : : m_pImpl->getOwnAccessible()
302 [ # # ][ # # ]: 0 : );
303 : :
304 : : // the last child is the XAccessible of the active panel
305 [ # # ][ # # ]: 0 : return m_pImpl->getActivePanelAccessible();
306 : : }
307 : :
308 : : //------------------------------------------------------------------------------------------------------------------
309 : 0 : Reference< XAccessible > SAL_CALL AccessibleToolPanelDeck::getAccessibleParent( ) throw (RuntimeException)
310 : : {
311 [ # # ]: 0 : MethodGuard aGuard( *m_pImpl );
312 [ # # ]: 0 : const Reference< XAccessible > xParent = implGetForeignControlledParent();
313 [ # # ]: 0 : if ( xParent.is() )
314 : 0 : return xParent;
315 [ # # ]: 0 : return m_pImpl->m_xAccessibleParent;
316 : : }
317 : :
318 : : //------------------------------------------------------------------------------------------------------------------
319 : 0 : sal_Int16 SAL_CALL AccessibleToolPanelDeck::getAccessibleRole( ) throw (RuntimeException)
320 : : {
321 [ # # ]: 0 : MethodGuard aGuard( *m_pImpl );
322 [ # # ]: 0 : return AccessibleRole::PANEL;
323 : : }
324 : :
325 : : //------------------------------------------------------------------------------------------------------------------
326 : 0 : Reference< XAccessible > SAL_CALL AccessibleToolPanelDeck::getAccessibleAtPoint( const UnoPoint& i_rPoint ) throw (RuntimeException)
327 : : {
328 [ # # ]: 0 : MethodGuard aGuard( *m_pImpl );
329 : :
330 [ # # ]: 0 : const ::Point aRequestedPoint( VCLUnoHelper::ConvertToVCLPoint( i_rPoint ) );
331 : : // check the panel window itself
332 [ # # ]: 0 : const ::Window& rActivePanelAnchor( m_pImpl->m_pPanelDeck->GetPanelWindowAnchor() );
333 [ # # ][ # # ]: 0 : const Rectangle aPanelAnchorArea( rActivePanelAnchor.GetPosPixel(), rActivePanelAnchor.GetOutputSizePixel() );
334 [ # # ][ # # ]: 0 : if ( aPanelAnchorArea.IsInside( aRequestedPoint ) )
335 : : // note that this assumes that the Window which actually implements the concrete panel covers
336 : : // the complete area of its "anchor" Window. But this is ensured by the ToolPanelDeck implementation.
337 [ # # ]: 0 : return m_pImpl->getActivePanelAccessible();
338 : :
339 : : // check the XAccessible instances provided by the layouter
340 : : try
341 : : {
342 [ # # ]: 0 : const ::svt::PDeckLayouter pLayouter( m_pImpl->m_pPanelDeck->GetLayouter() );
343 [ # # ][ # # ]: 0 : ENSURE_OR_THROW( pLayouter.get() != NULL, "invalid layouter" );
[ # # ][ # # ]
344 : :
345 [ # # ]: 0 : const size_t nLayouterChildren = pLayouter->GetAccessibleChildCount();
346 [ # # ]: 0 : for ( size_t i=0; i<nLayouterChildren; ++i )
347 : : {
348 [ # # ][ # # ]: 0 : const Reference< XAccessible > xLayoutItemAccessible( pLayouter->GetAccessibleChild( i, m_pImpl->getOwnAccessible() ), UNO_SET_THROW );
[ # # ]
349 [ # # ][ # # ]: 0 : const Reference< XAccessibleComponent > xLayoutItemComponent( xLayoutItemAccessible->getAccessibleContext(), UNO_QUERY_THROW );
[ # # ]
350 [ # # ][ # # ]: 0 : const ::Rectangle aLayoutItemBounds( VCLUnoHelper::ConvertToVCLRect( xLayoutItemComponent->getBounds() ) );
[ # # ]
351 [ # # ][ # # ]: 0 : if ( aLayoutItemBounds.IsInside( aRequestedPoint ) )
352 : 0 : return xLayoutItemAccessible;
353 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
[ # # ]
354 : : }
355 [ # # ]: 0 : catch( const Exception& )
356 : : {
357 : : DBG_UNHANDLED_EXCEPTION();
358 : : }
359 : :
360 [ # # ][ # # ]: 0 : return NULL;
361 : : }
362 : :
363 : : //------------------------------------------------------------------------------------------------------------------
364 : 0 : void SAL_CALL AccessibleToolPanelDeck::grabFocus( ) throw (RuntimeException)
365 : : {
366 [ # # ]: 0 : MethodGuard aGuard( *m_pImpl );
367 [ # # ][ # # ]: 0 : m_pImpl->m_pPanelDeck->GrabFocus();
368 : 0 : }
369 : :
370 : : //------------------------------------------------------------------------------------------------------------------
371 : 0 : void SAL_CALL AccessibleToolPanelDeck::disposing()
372 : : {
373 : 0 : AccessibleToolPanelDeck_Base::disposing();
374 : 0 : m_pImpl->dispose();
375 : 0 : }
376 : :
377 : : //------------------------------------------------------------------------------------------------------------------
378 : 0 : Reference< XAccessible > AccessibleToolPanelDeck::GetChildAccessible( const VclWindowEvent& i_rVclWindowEvent )
379 : : {
380 : : // don't let the base class generate any A11Y events from VclWindowEvent, we completely manage those
381 : : // A11Y events ourself
382 : : (void)i_rVclWindowEvent;
383 : 0 : return NULL;
384 : : }
385 : :
386 : : //------------------------------------------------------------------------------------------------------------------
387 : 0 : void AccessibleToolPanelDeck::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& i_rStateSet )
388 : : {
389 : 0 : AccessibleToolPanelDeck_Base::FillAccessibleStateSet( i_rStateSet );
390 [ # # ]: 0 : if ( m_pImpl->isDisposed() )
391 : : {
392 : 0 : i_rStateSet.AddState( AccessibleStateType::DEFUNC );
393 : : }
394 : : else
395 : : {
396 : 0 : i_rStateSet.AddState( AccessibleStateType::FOCUSABLE );
397 : : }
398 : 0 : }
399 : :
400 : : //......................................................................................................................
401 : : } // namespace accessibility
402 : : //......................................................................................................................
403 : :
404 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|