1 /*************************************************************************
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * Copyright 2000, 2010 Oracle and/or its affiliates.
5  *
6  * OpenOffice.org - a multi-platform office productivity suite
7  *
8  * This file is part of OpenOffice.org.
9  *
10  * OpenOffice.org is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Lesser General Public License version 3
12  * only, as published by the Free Software Foundation.
13  *
14  * OpenOffice.org is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU Lesser General Public License version 3 for more details
18  * (a copy is included in the LICENSE file that accompanied this code).
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * version 3 along with OpenOffice.org.  If not, see
22  * <http://www.openoffice.org/license.html>
23  * for a copy of the LGPLv3 License.
24  *
25  ************************************************************************/
26 
27 #include "precompiled_accessibility.hxx"
28 
29 #include "accessibility/extended/AccessibleToolPanelDeckTabBarItem.hxx"
30 
31 /** === begin UNO includes === **/
32 #include <com/sun/star/accessibility/AccessibleRole.hpp>
33 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
34 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
35 #include <com/sun/star/lang/DisposedException.hpp>
36 /** === end UNO includes === **/
37 
38 #include <svtools/toolpanel/toolpaneldeck.hxx>
39 #include <svtools/toolpanel/paneltabbar.hxx>
40 #include <unotools/accessiblestatesethelper.hxx>
41 #include <unotools/accessiblerelationsethelper.hxx>
42 #include <tools/diagnose_ex.h>
43 #include <vcl/svapp.hxx>
44 #include <vos/mutex.hxx>
45 
46 //......................................................................................................................
47 namespace accessibility
48 {
49 //......................................................................................................................
50 
51     typedef ::com::sun::star::awt::Rectangle    UnoRectangle;
52     typedef ::com::sun::star::awt::Point        UnoPoint;
53 
54 	/** === begin UNO using === **/
55 	using ::com::sun::star::uno::Reference;
56 	using ::com::sun::star::uno::XInterface;
57 	using ::com::sun::star::uno::UNO_QUERY;
58 	using ::com::sun::star::uno::UNO_QUERY_THROW;
59 	using ::com::sun::star::uno::UNO_SET_THROW;
60 	using ::com::sun::star::uno::Exception;
61 	using ::com::sun::star::uno::RuntimeException;
62 	using ::com::sun::star::uno::Any;
63 	using ::com::sun::star::uno::makeAny;
64 	using ::com::sun::star::uno::Sequence;
65 	using ::com::sun::star::uno::Type;
66     using ::com::sun::star::accessibility::XAccessible;
67     using ::com::sun::star::lang::DisposedException;
68     using ::com::sun::star::lang::IndexOutOfBoundsException;
69     using ::com::sun::star::accessibility::XAccessibleRelationSet;
70     using ::com::sun::star::accessibility::XAccessibleStateSet;
71     using ::com::sun::star::accessibility::XAccessibleComponent;
72     using ::com::sun::star::accessibility::XAccessibleExtendedComponent;
73     using ::com::sun::star::awt::XFont;
74 	/** === end UNO using === **/
75 
76     namespace AccessibleRole = ::com::sun::star::accessibility::AccessibleRole;
77     namespace AccessibleStateType = ::com::sun::star::accessibility::AccessibleStateType;
78     namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
79 
80 	//==================================================================================================================
81 	//= AccessibleToolPanelDeckTabBarItem_Impl
82 	//==================================================================================================================
83     class AccessibleToolPanelDeckTabBarItem_Impl : public ::svt::IToolPanelDeckListener
84     {
85     public:
86         AccessibleToolPanelDeckTabBarItem_Impl(
87             AccessibleToolPanelDeckTabBarItem& i_rAntiImpl,
88             const Reference< XAccessible >& i_rAccessibleParent,
89             ::svt::IToolPanelDeck& i_rPanelDeck,
90             ::svt::PanelTabBar& i_rTabBar,
91             const size_t i_nItemPos
92         );
93         ~AccessibleToolPanelDeckTabBarItem_Impl();
94 
95         ::svt::PanelTabBar* getTabBar() const { return m_pTabBar; }
96 
97         // IToolPanelDeckListener
98         virtual void PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition );
99         virtual void PanelRemoved( const size_t i_nPosition );
100         virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive );
101         virtual void LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter );
102         virtual void Dying();
103 
104     public:
105         bool    isDisposed() const { return m_pPanelDeck == NULL; }
106         void    checkDisposed() const;
107         void    dispose();
108 
109         const Reference< XAccessible >&
110                 getAccessibleParent() const { return m_xAccessibleParent; }
111         size_t  getItemPos() const { return m_nItemPos; }
112 
113         Reference< XAccessibleComponent >   getParentAccessibleComponent() const;
114         ::svt::IToolPanelDeck*              getPanelDeck() const { return m_pPanelDeck; }
115         ::rtl::OUString                     getPanelDisplayName();
116 
117     private:
118         void impl_notifyBoundRectChanges();
119         void impl_notifyStateChange( const sal_Int16 i_nLostState, const sal_Int16 i_nGainedState );
120 
121     private:
122         AccessibleToolPanelDeckTabBarItem&  m_rAntiImpl;
123         Reference< XAccessible >            m_xAccessibleParent;
124         ::svt::IToolPanelDeck*              m_pPanelDeck;
125         ::svt::PanelTabBar*                 m_pTabBar;
126         size_t                              m_nItemPos;
127     };
128 
129 	//==================================================================================================================
130 	//= AccessibleToolPanelDeckTabBarItem_Impl
131 	//==================================================================================================================
132 	//------------------------------------------------------------------------------------------------------------------
133     AccessibleToolPanelDeckTabBarItem_Impl::AccessibleToolPanelDeckTabBarItem_Impl( AccessibleToolPanelDeckTabBarItem& i_rAntiImpl,
134             const Reference< XAccessible >& i_rAccessibleParent, ::svt::IToolPanelDeck& i_rPanelDeck, ::svt::PanelTabBar& i_rTabBar,
135             const size_t i_nItemPos )
136         :m_rAntiImpl( i_rAntiImpl )
137         ,m_xAccessibleParent( i_rAccessibleParent )
138         ,m_pPanelDeck( &i_rPanelDeck )
139         ,m_pTabBar( &i_rTabBar )
140         ,m_nItemPos( i_nItemPos )
141     {
142         m_pPanelDeck->AddListener( *this );
143     }
144 
145 	//------------------------------------------------------------------------------------------------------------------
146     AccessibleToolPanelDeckTabBarItem_Impl::~AccessibleToolPanelDeckTabBarItem_Impl()
147     {
148     }
149 
150 	//------------------------------------------------------------------------------------------------------------------
151     void AccessibleToolPanelDeckTabBarItem_Impl::checkDisposed() const
152     {
153         if ( isDisposed() )
154             throw DisposedException( ::rtl::OUString(), *&m_rAntiImpl );
155     }
156 
157 	//------------------------------------------------------------------------------------------------------------------
158     void AccessibleToolPanelDeckTabBarItem_Impl::dispose()
159     {
160         ENSURE_OR_RETURN_VOID( !isDisposed(), "AccessibleToolPanelDeckTabBarItem_Impl::dispose: disposed twice!" );
161 
162         m_xAccessibleParent.clear();
163         m_pPanelDeck->RemoveListener( *this );
164         m_pPanelDeck = NULL;
165         m_pTabBar = NULL;
166     }
167 
168     //------------------------------------------------------------------------------------------------------------------
169     Reference< XAccessibleComponent > AccessibleToolPanelDeckTabBarItem_Impl::getParentAccessibleComponent() const
170     {
171         Reference< XAccessible > xAccessibleParent( m_rAntiImpl.getAccessibleParent(), UNO_QUERY_THROW );
172         return Reference< XAccessibleComponent >( xAccessibleParent->getAccessibleContext(), UNO_QUERY );
173     }
174 
175     //------------------------------------------------------------------------------------------------------------------
176     ::rtl::OUString AccessibleToolPanelDeckTabBarItem_Impl::getPanelDisplayName()
177     {
178         const ::svt::PToolPanel pPanel( m_pPanelDeck->GetPanel( getItemPos() ) );
179         if ( pPanel.get() == NULL )
180             throw DisposedException();
181         return pPanel->GetDisplayName();
182     }
183 
184     //------------------------------------------------------------------------------------------------------------------
185     void AccessibleToolPanelDeckTabBarItem_Impl::impl_notifyBoundRectChanges()
186     {
187         m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any() );
188     }
189 
190     //------------------------------------------------------------------------------------------------------------------
191     void AccessibleToolPanelDeckTabBarItem_Impl::impl_notifyStateChange( const sal_Int16 i_nLostState, const sal_Int16 i_nGainedState )
192     {
193         m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED,
194             i_nLostState > -1 ? makeAny( i_nLostState ) : Any(),
195             i_nGainedState > -1 ? makeAny( i_nGainedState ) : Any()
196         );
197     }
198 
199     //------------------------------------------------------------------------------------------------------------------
200     void AccessibleToolPanelDeckTabBarItem_Impl::PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition )
201     {
202         (void)i_pPanel;
203         if ( i_nPosition <= m_nItemPos )
204             ++m_nItemPos;
205         impl_notifyBoundRectChanges();
206     }
207 
208 	//------------------------------------------------------------------------------------------------------------------
209     void AccessibleToolPanelDeckTabBarItem_Impl::PanelRemoved( const size_t i_nPosition )
210     {
211         if ( i_nPosition == m_nItemPos )
212         {
213             m_rAntiImpl.dispose();
214         }
215         else if ( i_nPosition < m_nItemPos )
216         {
217             --m_nItemPos;
218             impl_notifyBoundRectChanges();
219         }
220     }
221 
222 	//------------------------------------------------------------------------------------------------------------------
223     void AccessibleToolPanelDeckTabBarItem_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
224     {
225         if ( m_nItemPos == i_rOldActive )
226         {
227             impl_notifyStateChange( AccessibleStateType::ACTIVE, -1 );
228             impl_notifyStateChange( AccessibleStateType::SELECTED, -1 );
229         }
230         else if ( m_nItemPos == i_rNewActive )
231         {
232             impl_notifyStateChange( -1, AccessibleStateType::ACTIVE );
233             impl_notifyStateChange( -1, AccessibleStateType::SELECTED );
234         }
235     }
236 
237 	//------------------------------------------------------------------------------------------------------------------
238     void AccessibleToolPanelDeckTabBarItem_Impl::LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter )
239     {
240         (void)i_rNewLayouter;
241         // if the tool panel deck has a new layouter, then the old layouter, and thus all items it was
242         // responsible for, died. So do we.
243         dispose();
244     }
245 
246     //------------------------------------------------------------------------------------------------------------------
247     void AccessibleToolPanelDeckTabBarItem_Impl::Dying()
248     {
249         // if the tool panel deck is dying, then its layouter dies, so should we.
250         dispose();
251     }
252 
253 	//==================================================================================================================
254 	//= ItemMethodGuard
255 	//==================================================================================================================
256     class ItemMethodGuard
257     {
258     public:
259         ItemMethodGuard( AccessibleToolPanelDeckTabBarItem_Impl& i_rImpl )
260             :m_aGuard( Application::GetSolarMutex() )
261         {
262             i_rImpl.checkDisposed();
263         }
264         ~ItemMethodGuard()
265         {
266         }
267 
268         void clear()
269         {
270             m_aGuard.clear();
271         }
272 
273     private:
274         ::vos::OClearableGuard  m_aGuard;
275     };
276 
277 	//==================================================================================================================
278 	//= AccessibleToolPanelDeckTabBarItem
279 	//==================================================================================================================
280 	//------------------------------------------------------------------------------------------------------------------
281     AccessibleToolPanelDeckTabBarItem::AccessibleToolPanelDeckTabBarItem( const Reference< XAccessible >& i_rAccessibleParent,
282             ::svt::IToolPanelDeck& i_rPanelDeck, ::svt::PanelTabBar& i_rTabBar, const size_t i_nItemPos )
283         :m_pImpl( new AccessibleToolPanelDeckTabBarItem_Impl( *this, i_rAccessibleParent, i_rPanelDeck, i_rTabBar, i_nItemPos ) )
284     {
285     }
286 
287 	//------------------------------------------------------------------------------------------------------------------
288     AccessibleToolPanelDeckTabBarItem::~AccessibleToolPanelDeckTabBarItem()
289     {
290     }
291 
292     //--------------------------------------------------------------------
293     sal_Int32 SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleChildCount(  ) throw (RuntimeException)
294     {
295         return 0;
296     }
297 
298     //--------------------------------------------------------------------
299     Reference< XAccessible > SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
300     {
301         (void)i;
302         throw IndexOutOfBoundsException( ::rtl::OUString(), *this );
303     }
304 
305     //--------------------------------------------------------------------
306     Reference< XAccessible > SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleParent(  ) throw (RuntimeException)
307     {
308         ItemMethodGuard aGuard( *m_pImpl );
309         return m_pImpl->getAccessibleParent();
310     }
311 
312     //--------------------------------------------------------------------
313     sal_Int16 SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleRole(  ) throw (RuntimeException)
314     {
315         return AccessibleRole::PAGE_TAB;
316     }
317 
318     //--------------------------------------------------------------------
319     ::rtl::OUString SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleDescription(  ) throw (RuntimeException)
320     {
321         ItemMethodGuard aGuard( *m_pImpl );
322         return m_pImpl->getPanelDisplayName();
323     }
324 
325     //--------------------------------------------------------------------
326     ::rtl::OUString SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleName(  ) throw (RuntimeException)
327     {
328         ItemMethodGuard aGuard( *m_pImpl );
329         return m_pImpl->getPanelDisplayName();
330     }
331 
332     //--------------------------------------------------------------------
333     Reference< XAccessibleRelationSet > SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleRelationSet(  ) throw (RuntimeException)
334     {
335         ItemMethodGuard aGuard( *m_pImpl );
336         ::utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper;
337         return pRelationSet;
338     }
339 
340     //--------------------------------------------------------------------
341     Reference< XAccessibleStateSet > SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleStateSet(  ) throw (RuntimeException)
342     {
343         ItemMethodGuard aGuard( *m_pImpl );
344 
345         ::utl::AccessibleStateSetHelper* pStateSet( new ::utl::AccessibleStateSetHelper );
346         pStateSet->AddState( AccessibleStateType::FOCUSABLE );
347         pStateSet->AddState( AccessibleStateType::SELECTABLE );
348         pStateSet->AddState( AccessibleStateType::ICONIFIED );
349 
350         if ( m_pImpl->getItemPos() == m_pImpl->getPanelDeck()->GetActivePanel() )
351         {
352             pStateSet->AddState( AccessibleStateType::ACTIVE );
353             pStateSet->AddState( AccessibleStateType::SELECTED );
354         }
355 
356         if ( m_pImpl->getItemPos() == m_pImpl->getTabBar()->GetFocusedPanelItem() )
357             pStateSet->AddState( AccessibleStateType::FOCUSED );
358 
359         if ( m_pImpl->getTabBar()->IsEnabled() )
360             pStateSet->AddState( AccessibleStateType::ENABLED );
361 
362         if ( m_pImpl->getTabBar()->IsVisible() )
363         {
364             pStateSet->AddState( AccessibleStateType::SHOWING );
365             pStateSet->AddState( AccessibleStateType::VISIBLE );
366         }
367 
368         return pStateSet;
369     }
370 
371 
372     //--------------------------------------------------------------------
373     Reference< XAccessible > SAL_CALL AccessibleToolPanelDeckTabBarItem::getAccessibleAtPoint( const UnoPoint& i_rLocation ) throw (RuntimeException)
374     {
375         ItemMethodGuard aGuard( *m_pImpl );
376         // we do not have children ...
377         (void)i_rLocation;
378         return NULL;
379     }
380 
381     //--------------------------------------------------------------------
382     void SAL_CALL AccessibleToolPanelDeckTabBarItem::grabFocus(  ) throw (RuntimeException)
383     {
384         ItemMethodGuard aGuard( *m_pImpl );
385         m_pImpl->getTabBar()->FocusPanelItem( m_pImpl->getItemPos() );
386     }
387 
388     //--------------------------------------------------------------------
389     ::sal_Int32 SAL_CALL AccessibleToolPanelDeckTabBarItem::getForeground(  ) throw (RuntimeException)
390     {
391         ItemMethodGuard aGuard( *m_pImpl );
392         Reference< XAccessibleComponent > xParentComponent( m_pImpl->getParentAccessibleComponent(), UNO_SET_THROW );
393         return xParentComponent->getForeground();
394     }
395 
396     //--------------------------------------------------------------------
397     ::sal_Int32 SAL_CALL AccessibleToolPanelDeckTabBarItem::getBackground(  ) throw (RuntimeException)
398     {
399         ItemMethodGuard aGuard( *m_pImpl );
400         Reference< XAccessibleComponent > xParentComponent( m_pImpl->getParentAccessibleComponent(), UNO_SET_THROW );
401         return xParentComponent->getBackground();
402     }
403 
404     //--------------------------------------------------------------------
405     Reference< XFont > SAL_CALL AccessibleToolPanelDeckTabBarItem::getFont(  ) throw (RuntimeException)
406     {
407         ItemMethodGuard aGuard( *m_pImpl );
408         Reference< XAccessibleExtendedComponent > xParentComponent( m_pImpl->getParentAccessibleComponent(), UNO_QUERY_THROW );
409         // TODO: strictly, this is not correct: The TabBar implementation of the TabLayouter might use
410         // a different font ...
411         return xParentComponent->getFont();
412     }
413 
414     //--------------------------------------------------------------------
415     ::rtl::OUString SAL_CALL AccessibleToolPanelDeckTabBarItem::getTitledBorderText(  ) throw (RuntimeException)
416     {
417         ItemMethodGuard aGuard( *m_pImpl );
418         // no support
419         return ::rtl::OUString();
420     }
421 
422     //--------------------------------------------------------------------
423     ::rtl::OUString SAL_CALL AccessibleToolPanelDeckTabBarItem::getToolTipText(  ) throw (RuntimeException)
424     {
425         ItemMethodGuard aGuard( *m_pImpl );
426         return m_pImpl->getPanelDisplayName();
427     }
428 
429     //--------------------------------------------------------------------
430 	UnoRectangle SAL_CALL AccessibleToolPanelDeckTabBarItem::implGetBounds() throw (RuntimeException)
431     {
432         ItemMethodGuard aGuard( *m_pImpl );
433 
434         const ::Rectangle aItemScreenRect( m_pImpl->getTabBar()->GetItemScreenRect( m_pImpl->getItemPos() ) );
435 
436         Reference< XAccessibleComponent > xParentComponent( m_pImpl->getParentAccessibleComponent(), UNO_SET_THROW );
437         const UnoPoint aParentLocation( xParentComponent->getLocationOnScreen() );
438         return UnoRectangle(
439             aItemScreenRect.Left() - aParentLocation.X,
440             aItemScreenRect.Top() - aParentLocation.Y,
441             aItemScreenRect.GetWidth(),
442             aItemScreenRect.GetHeight()
443         );
444     }
445 
446     //--------------------------------------------------------------------
447     void SAL_CALL AccessibleToolPanelDeckTabBarItem::disposing()
448     {
449         ItemMethodGuard aGuard( *m_pImpl );
450         m_pImpl->dispose();
451     }
452 
453 //......................................................................................................................
454 } // namespace accessibility
455 //......................................................................................................................
456