Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / accessibility / source / standard / vclxaccessibletoolbox.cxx
bloba1a2d5b03d543400218e799227af324ae451030d
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 .
19 #include <string.h>
21 #include <standard/vclxaccessibletoolbox.hxx>
22 #include <standard/vclxaccessibletoolboxitem.hxx>
23 #include <toolkit/helper/convert.hxx>
25 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
26 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
27 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
28 #include <o3tl/safeint.hxx>
29 #include <vcl/toolbox.hxx>
30 #include <vcl/vclevent.hxx>
31 #include <comphelper/accessiblecontexthelper.hxx>
32 #include <comphelper/accessiblewrapper.hxx>
33 #include <comphelper/processfactory.hxx>
34 #include <comphelper/servicehelper.hxx>
35 #include <comphelper/types.hxx>
37 using namespace ::comphelper;
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star::accessibility;
43 namespace
46 // = OToolBoxWindowItemContext
48 /** XAccessibleContext implementation for a toolbox item which is represented by a VCL Window
50 class OToolBoxWindowItemContext final : public OAccessibleContextWrapper
52 sal_Int32 m_nIndexInParent;
53 public:
54 OToolBoxWindowItemContext(sal_Int32 _nIndexInParent,
55 const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
56 const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
57 const css::uno::Reference< css::accessibility::XAccessible >& _rxOwningAccessible,
58 const css::uno::Reference< css::accessibility::XAccessible >& _rxParentAccessible
59 ) : OAccessibleContextWrapper(
60 _rxContext,
61 _rxInnerAccessibleContext,
62 _rxOwningAccessible,
63 _rxParentAccessible )
64 ,m_nIndexInParent(_nIndexInParent)
67 virtual sal_Int64 SAL_CALL getAccessibleIndexInParent( ) override;
71 sal_Int64 SAL_CALL OToolBoxWindowItemContext::getAccessibleIndexInParent( )
73 ::osl::MutexGuard aGuard( m_aMutex );
74 return m_nIndexInParent;
78 // = OToolBoxWindowItem
80 /** XAccessible implementation for a toolbox item which is represented by a VCL Window
82 class OToolBoxWindowItem : public OAccessibleWrapper
84 private:
85 sal_Int32 m_nIndexInParent;
87 public:
88 sal_Int32 getIndexInParent() const { return m_nIndexInParent; }
89 void setIndexInParent( sal_Int32 _nNewIndex ) { m_nIndexInParent = _nNewIndex; }
91 public:
92 OToolBoxWindowItem(sal_Int32 _nIndexInParent,
93 const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
94 const css::uno::Reference< css::accessibility::XAccessible >& _rxInnerAccessible,
95 const css::uno::Reference< css::accessibility::XAccessible >& _rxParentAccessible
96 ) : OAccessibleWrapper(
97 _rxContext,
98 _rxInnerAccessible,
99 _rxParentAccessible)
100 ,m_nIndexInParent(_nIndexInParent)
104 protected:
105 // OAccessibleWrapper
106 virtual rtl::Reference<OAccessibleContextWrapper> createAccessibleContext(
107 const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerContext
108 ) override;
111 rtl::Reference<OAccessibleContextWrapper> OToolBoxWindowItem::createAccessibleContext(
112 const Reference< XAccessibleContext >& _rxInnerContext )
114 return new OToolBoxWindowItemContext( m_nIndexInParent, getComponentContext(), _rxInnerContext, this, getParent() );
118 // VCLXAccessibleToolBox
120 VCLXAccessibleToolBox::VCLXAccessibleToolBox( VCLXWindow* pVCLXWindow ) :
122 ImplInheritanceHelper( pVCLXWindow )
127 VCLXAccessibleToolBox::~VCLXAccessibleToolBox()
131 VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( ToolBox::ImplToolItems::size_type _nPos )
133 VCLXAccessibleToolBoxItem* pItem = nullptr;
134 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
135 if ( pToolBox )
137 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
138 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
139 // returns only toolbox buttons, not windows
140 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is())
141 pItem = static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
144 return pItem;
147 void VCLXAccessibleToolBox::UpdateFocus_Impl()
149 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
150 if( !pToolBox )
151 return;
153 // submit events only if toolbox has the focus to avoid sending events due to mouse move
154 bool bHasFocus = false;
155 if ( pToolBox->HasFocus() )
156 bHasFocus = true;
157 else
159 // check for subtoolbar, i.e. check if our parent is a toolbar
160 ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
161 // subtoolbars never get the focus as key input is just forwarded, so check if the parent toolbar has it
162 if ( pToolBoxParent && pToolBoxParent->HasFocus() )
163 bHasFocus = true;
166 if ( !bHasFocus )
167 return;
169 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
170 sal_uInt16 nFocusCount = 0;
171 for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
173 ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
175 if ( rxChild.is() )
177 VCLXAccessibleToolBoxItem* pItem =
178 static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
179 if ( pItem->HasFocus() && nItemId != nHighlightItemId )
181 // reset the old focused item
182 pItem->SetFocus( false );
183 nFocusCount++;
185 if ( nItemId == nHighlightItemId )
187 // set the new focused item
188 pItem->SetFocus( true );
189 nFocusCount++;
192 // both items changed?
193 if ( nFocusCount > 1 )
194 break;
198 void VCLXAccessibleToolBox::ReleaseFocus_Impl( ToolBox::ImplToolItems::size_type _nPos )
200 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
201 if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
203 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
204 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
205 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
207 VCLXAccessibleToolBoxItem* pItem =
208 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
209 if ( pItem->HasFocus() )
210 pItem->SetFocus( false );
215 void VCLXAccessibleToolBox::UpdateChecked_Impl( ToolBox::ImplToolItems::size_type _nPos )
217 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
218 if ( !pToolBox )
219 return;
221 ToolBoxItemId nFocusId = pToolBox->GetItemId( _nPos );
222 VCLXAccessibleToolBoxItem* pFocusItem = nullptr;
224 for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
226 ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
228 VCLXAccessibleToolBoxItem* pItem =
229 static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
230 pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
231 if ( nItemId == nFocusId )
232 pFocusItem = pItem;
234 //Solution:If the position is not a child item,the focus should not be called
235 if ( pFocusItem && _nPos != ToolBox::ITEM_NOTFOUND )
236 pFocusItem->SetFocus( true );
239 void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( ToolBox::ImplToolItems::size_type _nPos )
241 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
242 if ( !pToolBox )
243 return;
245 ToolBoxItemId nItemId = pToolBox->GetItemId( _nPos );
247 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
248 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
249 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
251 VCLXAccessibleToolBoxItem* pItem =
252 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
253 if ( pItem )
254 pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET );
258 void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator const & _rMapPos,
259 bool _bNotifyRemoval )
261 Reference< XAccessible > xItemAcc( _rMapPos->second );
262 if ( !xItemAcc.is() )
263 return;
265 if ( _bNotifyRemoval )
267 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any( xItemAcc ), Any() );
270 auto pWindowItem = dynamic_cast<OToolBoxWindowItem*>(xItemAcc.get());
271 if ( !pWindowItem )
273 static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() )->ReleaseToolBox();
274 ::comphelper::disposeComponent( xItemAcc );
276 else
278 Reference< XAccessibleContext > xContext( pWindowItem->getContextNoCreate() );
279 ::comphelper::disposeComponent( xContext );
283 void VCLXAccessibleToolBox::UpdateItem_Impl( ToolBox::ImplToolItems::size_type _nPos)
285 if ( _nPos < m_aAccessibleChildren.size() )
287 UpdateAllItems_Impl();
288 return;
291 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
292 if ( !pToolBox )
293 return;
295 // adjust the "index-in-parent"s
296 ToolBoxItemsMap::iterator aIndexAdjust = m_aAccessibleChildren.upper_bound( _nPos );
297 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
298 while ( m_aAccessibleChildren.end() != aIndexAdjust )
300 Reference< XAccessible > xItemAcc( aIndexAdjust->second );
302 auto pWindowItem = dynamic_cast<OToolBoxWindowItem*>(xItemAcc.get());
303 if ( !pWindowItem )
305 VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() );
306 if ( pItem )
308 sal_Int32 nIndex = pItem->getIndexInParent( );
309 nIndex++;
310 pItem->setIndexInParent( nIndex );
313 else
315 sal_Int32 nIndex = pWindowItem->getIndexInParent( );
316 nIndex++;
317 pWindowItem->setIndexInParent( nIndex );
320 ++aIndexAdjust;
323 // TODO: we should make this dependent on the existence of event listeners
324 // with the current implementation, we always create accessible object
325 Any aNewChild( getAccessibleChild( static_cast<sal_Int64>(_nPos) ) );
326 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
327 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewChild );
330 void VCLXAccessibleToolBox::UpdateAllItems_Impl()
332 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
333 if ( !pToolBox )
334 return;
336 // deregister the old items
337 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
338 aIter != m_aAccessibleChildren.end(); ++aIter )
340 implReleaseToolboxItem( aIter, true );
342 m_aAccessibleChildren.clear();
344 // register the new items
345 ToolBox::ImplToolItems::size_type i, nCount = pToolBox->GetItemCount();
346 for ( i = 0; i < nCount; ++i )
348 Any aNewValue;
349 aNewValue <<= getAccessibleChild(i);
350 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
354 void VCLXAccessibleToolBox::UpdateCustomPopupItemp_Impl( vcl::Window* pWindow, bool bOpen )
356 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
357 if( !(pWindow && pToolBox) )
358 return;
360 const ToolBoxItemId nDownItem = pToolBox->GetDownItemId();
361 if ( !nDownItem )
362 // No item is currently in down state.
363 // Moreover, calling GetItemPos with 0 will find a separator if there is any.
364 return;
366 Reference< XAccessible > xChild( pWindow->GetAccessible() );
367 if( xChild.is() )
369 Reference< XAccessible > xChildItem( getAccessibleChild(pToolBox->GetItemPos(nDownItem)));
370 VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
372 pItem->SetChild( xChild );
373 pItem->NotifyChildEvent( xChild, bOpen );
377 void VCLXAccessibleToolBox::UpdateItemName_Impl( ToolBox::ImplToolItems::size_type _nPos )
379 VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
380 if ( pItem )
381 pItem->NameChanged();
384 void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( ToolBox::ImplToolItems::size_type _nPos )
386 VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
387 if ( pItem )
388 pItem->ToggleEnableState();
391 void VCLXAccessibleToolBox::HandleSubToolBarEvent( const VclWindowEvent& rVclWindowEvent )
393 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
394 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
395 if ( !(pChildWindow
396 && pToolBox
397 && pToolBox == pChildWindow->GetParent()
398 && pChildWindow->GetType() == WindowType::TOOLBOX) )
399 return;
401 const ToolBoxItemId nCurItemId( pToolBox->GetCurItemId() );
402 if ( !nCurItemId )
403 // No item is currently active (might happen when opening the overflow popup).
404 // Moreover, calling GetItemPos with 0 will find a separator if there is any.
405 return;
407 ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( nCurItemId );
408 Reference< XAccessible > xItem = getAccessibleChild( nIndex );
409 if ( xItem.is() )
411 Reference< XAccessible > xChild = pChildWindow->GetAccessible();
412 VCLXAccessibleToolBoxItem* pItem =
413 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
414 pItem->SetChild( xChild );
415 pItem->NotifyChildEvent( xChild, true/*_bShow*/ );
419 void VCLXAccessibleToolBox::ReleaseSubToolBox( ToolBox* _pSubToolBox )
421 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
422 if ( !pToolBox )
423 return;
425 ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
426 if ( nIndex == ToolBox::ITEM_NOTFOUND )
427 return; // not found
429 Reference< XAccessible > xItem = getAccessibleChild( nIndex );
430 if ( !xItem.is() )
431 return;
433 Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
434 VCLXAccessibleToolBoxItem* pItem =
435 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
436 if ( pItem->GetChild() == xChild )
438 pItem->SetChild( Reference< XAccessible >() );
439 pItem->NotifyChildEvent( xChild, false );
443 void VCLXAccessibleToolBox::FillAccessibleStateSet( sal_Int64& rStateSet )
445 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
447 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
448 if ( pToolBox )
450 rStateSet |= AccessibleStateType::FOCUSABLE;
451 if ( pToolBox->IsHorizontal() )
452 rStateSet |= AccessibleStateType::HORIZONTAL;
453 else
454 rStateSet |= AccessibleStateType::VERTICAL;
458 void VCLXAccessibleToolBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
460 // to prevent an early release of the toolbox (VclEventId::ObjectDying)
461 Reference< XAccessibleContext > xHoldAlive = this;
463 switch ( rVclWindowEvent.GetId() )
465 case VclEventId::ToolboxClick:
466 case VclEventId::ToolboxSelect:
468 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
469 if ( rVclWindowEvent.GetData() )
471 UpdateChecked_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
472 UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
474 else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != ToolBox::ITEM_NOTFOUND )
476 UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
477 UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
479 break;
481 case VclEventId::ToolboxDoubleClick:
482 case VclEventId::ToolboxActivate:
483 case VclEventId::ToolboxDeactivate:
484 //case VclEventId::ToolboxSelect:
485 break;
487 case VclEventId::ToolboxItemUpdated:
489 if ( rVclWindowEvent.GetData() )
491 UpdateChecked_Impl( ToolBox::ITEM_NOTFOUND );
492 UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
494 break;
497 case VclEventId::ToolboxHighlight:
498 UpdateFocus_Impl();
499 break;
501 case VclEventId::ToolboxHighlightOff:
502 ReleaseFocus_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
503 break;
505 case VclEventId::ToolboxItemAdded :
506 UpdateItem_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
507 break;
509 case VclEventId::ToolboxItemRemoved :
510 case VclEventId::ToolboxAllItemsChanged :
512 UpdateAllItems_Impl();
513 break;
516 case VclEventId::ToolboxItemWindowChanged:
518 auto nPos = static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
519 ToolBoxItemsMap::iterator aAccessiblePos( m_aAccessibleChildren.find( nPos ) );
520 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
521 if ( m_aAccessibleChildren.end() != aAccessiblePos )
523 implReleaseToolboxItem( aAccessiblePos, false );
524 m_aAccessibleChildren.erase (aAccessiblePos);
527 Any aNewValue;
528 aNewValue <<= getAccessibleChild(nPos);
529 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
530 break;
532 case VclEventId::ToolboxItemTextChanged :
533 UpdateItemName_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
534 break;
536 case VclEventId::ToolboxItemEnabled :
537 case VclEventId::ToolboxItemDisabled :
539 UpdateItemEnabled_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
540 break;
543 case VclEventId::DropdownOpen:
544 case VclEventId::DropdownClose:
546 UpdateCustomPopupItemp_Impl( static_cast< vcl::Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VclEventId::DropdownOpen );
547 break;
550 case VclEventId::ObjectDying :
552 // if this toolbox is a subtoolbox, we have to release it from its parent
553 VclPtr< vcl::Window > pWin = GetAs< vcl::Window >();
554 if ( pWin && pWin->GetParent() &&
555 pWin->GetParent()->GetType() == WindowType::TOOLBOX )
557 auto pParentAccContext = pWin->GetParent()->GetAccessible()->getAccessibleContext();
558 VCLXAccessibleToolBox* pParent = static_cast< VCLXAccessibleToolBox* >( pParentAccContext.get() );
559 if ( pParent )
560 pParent->ReleaseSubToolBox(static_cast<ToolBox *>(pWin.get()));
563 // dispose all items
564 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
565 aIter != m_aAccessibleChildren.end(); ++aIter )
567 implReleaseToolboxItem( aIter, false );
569 m_aAccessibleChildren.clear();
571 [[fallthrough]]; // call base class
574 default:
575 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
579 void VCLXAccessibleToolBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
581 switch ( rVclWindowEvent.GetId() )
583 case VclEventId::WindowShow: // send create on show for direct accessible children
585 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
586 if ( xReturn.is() )
587 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), Any(xReturn) );
588 else
589 HandleSubToolBarEvent( rVclWindowEvent );
591 break;
593 default:
594 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
599 // XComponent
600 void SAL_CALL VCLXAccessibleToolBox::disposing()
602 VCLXAccessibleComponent::disposing();
604 // release the items
605 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
606 aIter != m_aAccessibleChildren.end(); ++aIter )
608 implReleaseToolboxItem( aIter, false );
610 m_aAccessibleChildren.clear();
613 // XServiceInfo
614 OUString VCLXAccessibleToolBox::getImplementationName()
616 return "com.sun.star.comp.toolkit.AccessibleToolBox";
619 Sequence< OUString > VCLXAccessibleToolBox::getSupportedServiceNames()
621 return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
622 Sequence<OUString>{"com.sun.star.accessibility.AccessibleToolBox"});
625 // XAccessibleContext
626 sal_Int64 SAL_CALL VCLXAccessibleToolBox::getAccessibleChildCount( )
628 comphelper::OExternalLockGuard aGuard( this );
629 return implGetAccessibleChildCount();
632 sal_Int64 VCLXAccessibleToolBox::implGetAccessibleChildCount( )
634 sal_Int64 nCount = 0;
635 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
636 if ( pToolBox )
637 nCount = pToolBox->GetItemCount();
639 return nCount;
642 Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleChild( sal_Int64 i )
644 comphelper::OExternalLockGuard aGuard( this );
646 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
647 if ( (!pToolBox) || i < 0 || o3tl::make_unsigned(i) >= pToolBox->GetItemCount() )
648 throw IndexOutOfBoundsException();
650 Reference< XAccessible > xChild;
651 // search for the child
652 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
653 if ( m_aAccessibleChildren.end() == aIter )
655 ToolBoxItemId nItemId = pToolBox->GetItemId( i );
656 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
657 vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
658 // not found -> create a new child
659 rtl::Reference<VCLXAccessibleToolBoxItem> pChild = new VCLXAccessibleToolBoxItem( pToolBox, i );
660 Reference< XAccessible> xParent = pChild;
661 if ( pItemWindow )
663 xChild = new OToolBoxWindowItem(0,::comphelper::getProcessComponentContext(),pItemWindow->GetAccessible(),xParent);
664 pItemWindow->SetAccessible(xChild);
665 pChild->SetChild( xChild );
667 xChild = pChild;
668 if ( nHighlightItemId > ToolBoxItemId(0) && nItemId == nHighlightItemId )
669 pChild->SetFocus( true );
670 if ( pToolBox->IsItemChecked( nItemId ) )
671 pChild->SetChecked( true );
672 if ( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET )
673 pChild->SetIndeterminate( true );
674 m_aAccessibleChildren.emplace( i, xChild );
676 else
678 // found it
679 xChild = aIter->second;
681 return xChild;
684 Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleAtPoint( const awt::Point& _rPoint )
686 comphelper::OExternalLockGuard aGuard( this );
688 Reference< XAccessible > xAccessible;
689 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
690 if ( pToolBox )
692 ToolBox::ImplToolItems::size_type nItemPos = pToolBox->GetItemPos( VCLPoint( _rPoint ) );
693 if ( nItemPos != ToolBox::ITEM_NOTFOUND )
694 xAccessible = getAccessibleChild( nItemPos );
697 return xAccessible;
700 Reference< XAccessible > VCLXAccessibleToolBox::GetItemWindowAccessible( const VclWindowEvent& rVclWindowEvent )
702 Reference< XAccessible > xReturn;
703 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
704 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
705 if ( pChildWindow && pToolBox )
707 ToolBox::ImplToolItems::size_type nCount = pToolBox->GetItemCount();
708 for (ToolBox::ImplToolItems::size_type i = 0 ; i < nCount && !xReturn.is() ; ++i)
710 ToolBoxItemId nItemId = pToolBox->GetItemId( i );
711 vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
712 if ( pItemWindow == pChildWindow )
713 xReturn = getAccessibleChild(i);
716 return xReturn;
719 Reference< XAccessible > VCLXAccessibleToolBox::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
721 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
723 if ( !xReturn.is() )
724 xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
725 return xReturn;
728 // XAccessibleSelection
729 void VCLXAccessibleToolBox::selectAccessibleChild( sal_Int64 nChildIndex )
731 OExternalLockGuard aGuard( this );
733 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
734 if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
735 throw IndexOutOfBoundsException();
737 pToolBox->ChangeHighlight( nChildIndex );
740 sal_Bool VCLXAccessibleToolBox::isAccessibleChildSelected( sal_Int64 nChildIndex )
742 OExternalLockGuard aGuard( this );
743 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
744 if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
745 throw IndexOutOfBoundsException();
747 if ( pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nChildIndex ) )
748 return true;
749 else
750 return false;
753 void VCLXAccessibleToolBox::clearAccessibleSelection( )
755 OExternalLockGuard aGuard( this );
756 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
757 pToolBox -> LoseFocus();
760 void VCLXAccessibleToolBox::selectAllAccessibleChildren( )
762 OExternalLockGuard aGuard( this );
763 // intentionally empty. makes no sense for a toolbox
766 sal_Int64 VCLXAccessibleToolBox::getSelectedAccessibleChildCount( )
768 OExternalLockGuard aGuard( this );
770 sal_Int64 nRet = 0;
771 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
772 if (pToolBox)
774 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
775 for ( size_t i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
777 if ( nHighlightItemId == pToolBox->GetItemId( i ) )
779 nRet = 1;
780 break; // a toolbox can only have (n)one selected child
785 return nRet;
788 Reference< XAccessible > VCLXAccessibleToolBox::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex )
790 OExternalLockGuard aGuard( this );
791 if ( nSelectedChildIndex != 0 )
792 throw IndexOutOfBoundsException();
794 Reference< XAccessible > xChild;
795 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
796 if (pToolBox)
798 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
799 for (ToolBox::ImplToolItems::size_type i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
801 if ( nHighlightItemId == pToolBox->GetItemId( i ) )
803 xChild = getAccessibleChild( i );
804 break;
809 if (!xChild)
810 throw IndexOutOfBoundsException();
812 return xChild;
815 void VCLXAccessibleToolBox::deselectAccessibleChild( sal_Int64 nChildIndex )
817 OExternalLockGuard aGuard( this );
818 if ( nChildIndex < 0 || nChildIndex >= implGetAccessibleChildCount() )
819 throw IndexOutOfBoundsException();
820 clearAccessibleSelection(); // a toolbox can only have (n)one selected child
823 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */