Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / accessibility / source / extended / AccessibleToolPanelDeckTabBar.cxx
blobcd95a11ccd30604fb1dcce5e4122a79706c392e6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "accessibility/extended/AccessibleToolPanelDeckTabBar.hxx"
22 #include "accessibility/extended/AccessibleToolPanelDeckTabBarItem.hxx"
23 #include "accessibility/helper/accresmgr.hxx"
24 #include "accessibility/helper/accessiblestrings.hrc"
26 #include <com/sun/star/accessibility/AccessibleRole.hpp>
27 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
29 #include <com/sun/star/lang/DisposedException.hpp>
31 #include <svtools/toolpanel/toolpaneldeck.hxx>
32 #include <svtools/toolpanel/paneltabbar.hxx>
33 #include <unotools/accessiblestatesethelper.hxx>
34 #include <toolkit/awt/vclxwindow.hxx>
35 #include <toolkit/helper/vclunohelper.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/button.hxx>
38 #include <osl/mutex.hxx>
39 #include <tools/diagnose_ex.h>
41 #include <vector>
43 //......................................................................................................................
44 namespace accessibility
46 //......................................................................................................................
48 /** === begin UNO using === **/
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::XInterface;
51 using ::com::sun::star::uno::UNO_QUERY;
52 using ::com::sun::star::uno::UNO_QUERY_THROW;
53 using ::com::sun::star::uno::UNO_SET_THROW;
54 using ::com::sun::star::uno::Exception;
55 using ::com::sun::star::uno::RuntimeException;
56 using ::com::sun::star::uno::Any;
57 using ::com::sun::star::uno::makeAny;
58 using ::com::sun::star::uno::Sequence;
59 using ::com::sun::star::uno::Type;
60 using ::com::sun::star::accessibility::XAccessible;
61 using ::com::sun::star::lang::DisposedException;
62 using ::com::sun::star::lang::IndexOutOfBoundsException;
63 using ::com::sun::star::accessibility::XAccessibleContext;
64 /** === end UNO using === **/
66 namespace AccessibleRole = ::com::sun::star::accessibility::AccessibleRole;
67 namespace AccessibleEventId = ::com::sun::star::accessibility::AccessibleEventId;
68 namespace AccessibleStateType = ::com::sun::star::accessibility::AccessibleStateType;
70 typedef ::com::sun::star::awt::Point UnoPoint;
72 //==================================================================================================================
73 //= AccessibleWrapper
74 //==================================================================================================================
75 typedef ::cppu::WeakImplHelper1< XAccessible > AccessibleWrapper_Base;
76 class AccessibleWrapper : public AccessibleWrapper_Base
78 public:
79 AccessibleWrapper( const Reference< XAccessibleContext >& i_rContext )
80 :m_xContext( i_rContext )
84 // XAccessible
85 virtual Reference< XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (RuntimeException)
87 return m_xContext;
90 private:
91 const Reference< XAccessibleContext > m_xContext;
94 //==================================================================================================================
95 //= AccessibleToolPanelTabBar_Impl
96 //==================================================================================================================
97 class AccessibleToolPanelTabBar_Impl :public ::boost::noncopyable
98 ,public ::svt::IToolPanelDeckListener
100 public:
101 AccessibleToolPanelTabBar_Impl(
102 AccessibleToolPanelTabBar& i_rAntiImpl,
103 const Reference< XAccessible >& i_rAccessibleParent,
104 ::svt::IToolPanelDeck& i_rPanelDeck,
105 ::svt::PanelTabBar& i_rTabBar
107 virtual ~AccessibleToolPanelTabBar_Impl();
109 void checkDisposed();
110 bool isDisposed() const { return m_pPanelDeck == NULL; }
111 void dispose();
113 ::svt::IToolPanelDeck* getPanelDeck() const { return m_pPanelDeck; }
114 ::svt::PanelTabBar* getTabBar() const { return m_pTabBar; }
115 const Reference< XAccessible >& getAccessibleParent() const { return m_xAccessibleParent; }
116 Reference< XAccessible > getAccessiblePanelItem( size_t i_nPosition );
117 Reference< XAccessible > getOwnAccessible() const;
119 protected:
120 // IToolPanelDeckListener
121 virtual void PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition );
122 virtual void PanelRemoved( const size_t i_nPosition );
123 virtual void ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive );
124 virtual void LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter );
125 virtual void Dying();
127 DECL_LINK( OnWindowEvent, const VclSimpleEvent* );
129 private:
130 AccessibleToolPanelTabBar& m_rAntiImpl;
131 Reference< XAccessible > m_xAccessibleParent;
132 ::svt::IToolPanelDeck* m_pPanelDeck;
133 ::svt::PanelTabBar* m_pTabBar;
134 ::std::vector< Reference< XAccessible > > m_aChildren;
137 //------------------------------------------------------------------------------------------------------------------
138 AccessibleToolPanelTabBar_Impl::AccessibleToolPanelTabBar_Impl( AccessibleToolPanelTabBar& i_rAntiImpl,
139 const Reference< XAccessible >& i_rAccessibleParent, ::svt::IToolPanelDeck& i_rPanelDeck, ::svt::PanelTabBar& i_rTabBar )
140 :m_rAntiImpl( i_rAntiImpl )
141 ,m_xAccessibleParent( i_rAccessibleParent )
142 ,m_pPanelDeck( &i_rPanelDeck )
143 ,m_pTabBar( &i_rTabBar )
144 ,m_aChildren()
146 m_pPanelDeck->AddListener( *this );
147 m_aChildren.resize( m_pPanelDeck->GetPanelCount() );
149 const String sAccessibleDescription( TK_RES_STRING( RID_STR_ACC_DESC_PANELDECL_TABBAR ) );
150 i_rTabBar.SetAccessibleName( sAccessibleDescription );
151 i_rTabBar.SetAccessibleDescription( sAccessibleDescription );
153 i_rTabBar.GetScrollButton( true ).AddEventListener( LINK( this, AccessibleToolPanelTabBar_Impl, OnWindowEvent ) );
154 i_rTabBar.GetScrollButton( false ).AddEventListener( LINK( this, AccessibleToolPanelTabBar_Impl, OnWindowEvent ) );
157 //------------------------------------------------------------------------------------------------------------------
158 void AccessibleToolPanelTabBar_Impl::checkDisposed()
160 if ( isDisposed() )
161 throw DisposedException( OUString(), *&m_rAntiImpl );
164 //------------------------------------------------------------------------------------------------------------------
165 AccessibleToolPanelTabBar_Impl::~AccessibleToolPanelTabBar_Impl()
167 if ( !isDisposed() )
168 dispose();
171 //------------------------------------------------------------------------------------------------------------------
172 void AccessibleToolPanelTabBar_Impl::dispose()
174 ENSURE_OR_RETURN_VOID( !isDisposed(), "disposed twice" );
175 m_pPanelDeck->RemoveListener( *this );
176 m_pPanelDeck = NULL;
178 m_pTabBar->GetScrollButton( true ).RemoveEventListener( LINK( this, AccessibleToolPanelTabBar_Impl, OnWindowEvent ) );
179 m_pTabBar->GetScrollButton( false ).RemoveEventListener( LINK( this, AccessibleToolPanelTabBar_Impl, OnWindowEvent ) );
180 m_pTabBar = NULL;
182 m_xAccessibleParent.clear();
185 //------------------------------------------------------------------------------------------------------------------
186 Reference< XAccessible > AccessibleToolPanelTabBar_Impl::getAccessiblePanelItem( size_t i_nPosition )
188 ENSURE_OR_RETURN( !isDisposed(), "AccessibleToolPanelTabBar_Impl::getAccessiblePanelItem: already disposed!", NULL );
189 ENSURE_OR_RETURN( i_nPosition < m_aChildren.size(), "AccessibleToolPanelTabBar_Impl::getAccessiblePanelItem: invalid index!", NULL );
191 Reference< XAccessible >& rAccessibleChild( m_aChildren[ i_nPosition ] );
192 if ( !rAccessibleChild.is() )
194 ::rtl::Reference< AccessibleToolPanelDeckTabBarItem > pAccesibleItemContext( new AccessibleToolPanelDeckTabBarItem(
195 getOwnAccessible(), *m_pPanelDeck, *m_pTabBar, i_nPosition ) );
196 rAccessibleChild.set( new AccessibleWrapper( pAccesibleItemContext.get() ) );
197 pAccesibleItemContext->lateInit( rAccessibleChild );
199 return rAccessibleChild;
202 //------------------------------------------------------------------------------------------------------------------
203 Reference< XAccessible > AccessibleToolPanelTabBar_Impl::getOwnAccessible() const
205 Reference< XAccessible > xOwnAccessible( static_cast< XAccessible* >( m_rAntiImpl.GetVCLXWindow() ) );
206 OSL_ENSURE( xOwnAccessible->getAccessibleContext() == Reference< XAccessibleContext >( &m_rAntiImpl ),
207 "AccessibleToolPanelTabBar_Impl::getOwnAccessible: could not retrieve proper XAccessible for /myself!" );
208 return xOwnAccessible;
211 //------------------------------------------------------------------------------------------------------------------
212 void AccessibleToolPanelTabBar_Impl::PanelInserted( const ::svt::PToolPanel& i_pPanel, const size_t i_nPosition )
214 ENSURE_OR_RETURN_VOID( i_nPosition <= m_aChildren.size(), "AccessibleToolPanelTabBar_Impl::PanelInserted: illegal position (or invalid cache!)" );
215 (void)i_pPanel;
216 m_aChildren.insert( m_aChildren.begin() + i_nPosition, (Reference< XAccessible >)NULL );
217 m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), makeAny( getAccessiblePanelItem( i_nPosition ) ) );
220 //------------------------------------------------------------------------------------------------------------------
221 void AccessibleToolPanelTabBar_Impl::PanelRemoved( const size_t i_nPosition )
223 ENSURE_OR_RETURN_VOID( i_nPosition < m_aChildren.size(), "AccessibleToolPanelTabBar_Impl::PanelInserted: illegal position (or invalid cache!)" );
225 const Reference< XAccessible > xOldChild( getAccessiblePanelItem( i_nPosition ) );
226 m_aChildren.erase( m_aChildren.begin() + i_nPosition );
227 m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::CHILD, makeAny( xOldChild ), Any() );
230 //------------------------------------------------------------------------------------------------------------------
231 void AccessibleToolPanelTabBar_Impl::ActivePanelChanged( const ::boost::optional< size_t >& i_rOldActive, const ::boost::optional< size_t >& i_rNewActive )
233 (void)i_rOldActive;
234 (void)i_rNewActive;
237 //------------------------------------------------------------------------------------------------------------------
238 void AccessibleToolPanelTabBar_Impl::LayouterChanged( const ::svt::PDeckLayouter& i_rNewLayouter )
240 (void)i_rNewLayouter;
241 m_rAntiImpl.dispose();
244 //------------------------------------------------------------------------------------------------------------------
245 void AccessibleToolPanelTabBar_Impl::Dying()
247 m_rAntiImpl.dispose();
250 //------------------------------------------------------------------------------------------------------------------
251 IMPL_LINK( AccessibleToolPanelTabBar_Impl, OnWindowEvent, const VclSimpleEvent*, i_pEvent )
253 ENSURE_OR_RETURN( !isDisposed(), "AccessibleToolPanelTabBar_Impl::OnWindowEvent: already disposed!", 0L );
255 const VclWindowEvent* pWindowEvent( dynamic_cast< const VclWindowEvent* >( i_pEvent ) );
256 if ( !pWindowEvent )
257 return 0L;
259 const bool bForwardButton = ( pWindowEvent->GetWindow() == &m_pTabBar->GetScrollButton( true ) );
260 const bool bBackwardButton = ( pWindowEvent->GetWindow() == &m_pTabBar->GetScrollButton( false ) );
261 ENSURE_OR_RETURN( bForwardButton || bBackwardButton, "AccessibleToolPanelTabBar_Impl::OnWindowEvent: where does this come from?", 0L );
263 const bool bShow = ( i_pEvent->GetId() == VCLEVENT_WINDOW_SHOW );
264 const bool bHide = ( i_pEvent->GetId() == VCLEVENT_WINDOW_HIDE );
265 if ( !bShow && !bHide )
266 // not interested in events other than visibility changes
267 return 0L;
269 const Reference< XAccessible > xButtonAccessible( m_pTabBar->GetScrollButton( bForwardButton ).GetAccessible() );
270 const Any aOldChild( bHide ? xButtonAccessible : Reference< XAccessible >() );
271 const Any aNewChild( bShow ? xButtonAccessible : Reference< XAccessible >() );
272 m_rAntiImpl.NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldChild, aNewChild );
274 return 1L;
277 //==================================================================================================================
278 //= MethodGuard
279 //==================================================================================================================
280 namespace
282 class MethodGuard
284 public:
285 MethodGuard( AccessibleToolPanelTabBar_Impl& i_rImpl )
286 :m_aGuard()
288 i_rImpl.checkDisposed();
290 ~MethodGuard()
294 private:
295 SolarMutexGuard m_aGuard;
299 //==================================================================================================================
300 //= AccessibleToolPanelTabBar
301 //==================================================================================================================
302 //------------------------------------------------------------------------------------------------------------------
303 AccessibleToolPanelTabBar::AccessibleToolPanelTabBar( const Reference< XAccessible >& i_rAccessibleParent,
304 ::svt::IToolPanelDeck& i_rPanelDeck, ::svt::PanelTabBar& i_rTabBar )
305 :AccessibleToolPanelTabBar_Base( i_rTabBar.GetWindowPeer() )
306 ,m_pImpl( new AccessibleToolPanelTabBar_Impl( *this, i_rAccessibleParent, i_rPanelDeck, i_rTabBar ) )
310 //------------------------------------------------------------------------------------------------------------------
311 AccessibleToolPanelTabBar::~AccessibleToolPanelTabBar()
315 //------------------------------------------------------------------------------------------------------------------
316 sal_Int32 SAL_CALL AccessibleToolPanelTabBar::getAccessibleChildCount( ) throw (RuntimeException)
318 MethodGuard aGuard( *m_pImpl );
320 const bool bHasScrollBack = m_pImpl->getTabBar()->GetScrollButton( false ).IsVisible();
321 const bool bHasScrollForward = m_pImpl->getTabBar()->GetScrollButton( true ).IsVisible();
323 return m_pImpl->getPanelDeck()->GetPanelCount()
324 + ( bHasScrollBack ? 1 : 0 )
325 + ( bHasScrollForward ? 1 : 0 );
328 //------------------------------------------------------------------------------------------------------------------
329 Reference< XAccessible > SAL_CALL AccessibleToolPanelTabBar::getAccessibleChild( sal_Int32 i_nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
331 MethodGuard aGuard( *m_pImpl );
333 const bool bHasScrollBack = m_pImpl->getTabBar()->GetScrollButton( false ).IsVisible();
334 const bool bHasScrollForward = m_pImpl->getTabBar()->GetScrollButton( true ).IsVisible();
336 const bool bScrollBackRequested = ( bHasScrollBack && ( i_nIndex == 0 ) );
337 const bool bScrollForwardRequested = ( bHasScrollForward && ( i_nIndex == getAccessibleChildCount() - 1 ) );
338 OSL_ENSURE( !( bScrollBackRequested && bScrollForwardRequested ), "AccessibleToolPanelTabBar::getAccessibleChild: ouch!" );
340 if ( bScrollBackRequested || bScrollForwardRequested )
342 Reference< XAccessible > xScrollButtonAccessible( m_pImpl->getTabBar()->GetScrollButton( bScrollForwardRequested ).GetAccessible() );
343 ENSURE_OR_RETURN( xScrollButtonAccessible.is(), "AccessibleToolPanelTabBar::getAccessibleChild: invalid button accessible!", NULL );
344 #if OSL_DEBUG_LEVEL > 0
345 Reference< XAccessibleContext > xScrollButtonContext( xScrollButtonAccessible->getAccessibleContext() );
346 ENSURE_OR_RETURN( xScrollButtonContext.is(), "AccessibleToolPanelTabBar::getAccessibleChild: invalid button accessible context!", xScrollButtonAccessible );
347 OSL_ENSURE( xScrollButtonContext->getAccessibleParent() == m_pImpl->getOwnAccessible(),
348 "AccessibleToolPanelTabBar::getAccessibleChild: wrong parent at the button's accesible!" );
349 #endif
350 return xScrollButtonAccessible;
353 return m_pImpl->getAccessiblePanelItem( i_nIndex - ( bHasScrollBack ? 1 : 0 ) );
356 //------------------------------------------------------------------------------------------------------------------
357 Reference< XAccessible > SAL_CALL AccessibleToolPanelTabBar::getAccessibleParent( ) throw (RuntimeException)
359 MethodGuard aGuard( *m_pImpl );
360 return m_pImpl->getAccessibleParent();
363 //------------------------------------------------------------------------------------------------------------------
364 sal_Int16 SAL_CALL AccessibleToolPanelTabBar::getAccessibleRole( ) throw (RuntimeException)
366 MethodGuard aGuard( *m_pImpl );
367 return AccessibleRole::PAGE_TAB_LIST;
370 //------------------------------------------------------------------------------------------------------------------
371 namespace
373 bool lcl_covers( const ::Window& i_rWindow, const ::Point& i_rPoint )
375 const Rectangle aWindowBounds( i_rWindow.GetWindowExtentsRelative( i_rWindow.GetParent() ) );
376 return aWindowBounds.IsInside( i_rPoint );
380 //------------------------------------------------------------------------------------------------------------------
381 Reference< XAccessible > SAL_CALL AccessibleToolPanelTabBar::getAccessibleAtPoint( const UnoPoint& i_rPoint ) throw (RuntimeException)
383 MethodGuard aGuard( *m_pImpl );
385 // check the tab items
386 const UnoPoint aOwnScreenPos( getLocationOnScreen() );
387 const ::Point aRequestedScreenPoint( i_rPoint.X + aOwnScreenPos.X, i_rPoint.Y + aOwnScreenPos.Y );
389 for ( size_t i=0; i<m_pImpl->getPanelDeck()->GetPanelCount(); ++i )
391 const ::Rectangle aItemScreenRect( m_pImpl->getTabBar()->GetItemScreenRect(i) );
392 if ( aItemScreenRect.IsInside( aRequestedScreenPoint ) )
393 return m_pImpl->getAccessiblePanelItem(i);
396 // check the scroll buttons
397 const ::Point aRequestedClientPoint( VCLUnoHelper::ConvertToVCLPoint( i_rPoint ) );
399 const bool bHasScrollBack = m_pImpl->getTabBar()->GetScrollButton( false ).IsVisible();
400 if ( bHasScrollBack && lcl_covers( m_pImpl->getTabBar()->GetScrollButton( false ), aRequestedClientPoint ) )
401 return m_pImpl->getTabBar()->GetScrollButton( false ).GetAccessible();
403 const bool bHasScrollForward = m_pImpl->getTabBar()->GetScrollButton( true ).IsVisible();
404 if ( bHasScrollForward && lcl_covers( m_pImpl->getTabBar()->GetScrollButton( true ), aRequestedClientPoint ) )
405 return m_pImpl->getTabBar()->GetScrollButton( true ).GetAccessible();
407 // no hit
408 return NULL;
411 //------------------------------------------------------------------------------------------------------------------
412 void SAL_CALL AccessibleToolPanelTabBar::disposing()
414 AccessibleToolPanelTabBar_Base::disposing();
415 m_pImpl->dispose();
418 //------------------------------------------------------------------------------------------------------------------
419 Reference< XAccessible > AccessibleToolPanelTabBar::GetChildAccessible( const VclWindowEvent& i_rVclWindowEvent )
421 // don't let the base class generate any A11Y events from VclWindowEvent, we completely manage those
422 // A11Y events ourself
423 (void)i_rVclWindowEvent;
424 return NULL;
427 //------------------------------------------------------------------------------------------------------------------
428 void AccessibleToolPanelTabBar::FillAccessibleStateSet( ::utl::AccessibleStateSetHelper& i_rStateSet )
430 AccessibleToolPanelTabBar_Base::FillAccessibleStateSet( i_rStateSet );
431 i_rStateSet.AddState( AccessibleStateType::FOCUSABLE );
433 ENSURE_OR_RETURN_VOID( !m_pImpl->isDisposed(), "AccessibleToolPanelTabBar::FillAccessibleStateSet: already disposed!" );
434 if ( m_pImpl->getTabBar()->IsVertical() )
435 i_rStateSet.AddState( AccessibleStateType::VERTICAL );
436 else
437 i_rStateSet.AddState( AccessibleStateType::HORIZONTAL );
440 //......................................................................................................................
441 } // namespace accessibility
442 //......................................................................................................................
444 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */