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