CppunitTest_sc_tiledrendering2: move to tiledrendering folder
[LibreOffice.git] / accessibility / source / standard / vclxaccessibletoolbox.cxx
blob9d4cb3aaf2034242434f3a05e51247675daed062
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/vclunohelper.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 return m_nIndexInParent;
77 // = OToolBoxWindowItem
79 /** XAccessible implementation for a toolbox item which is represented by a VCL Window
81 class OToolBoxWindowItem : public OAccessibleWrapper
83 private:
84 sal_Int32 m_nIndexInParent;
86 public:
87 OToolBoxWindowItem(sal_Int32 _nIndexInParent,
88 const css::uno::Reference< css::uno::XComponentContext >& _rxContext,
89 const css::uno::Reference< css::accessibility::XAccessible >& _rxInnerAccessible,
90 const css::uno::Reference< css::accessibility::XAccessible >& _rxParentAccessible
91 ) : OAccessibleWrapper(
92 _rxContext,
93 _rxInnerAccessible,
94 _rxParentAccessible)
95 ,m_nIndexInParent(_nIndexInParent)
99 protected:
100 // OAccessibleWrapper
101 virtual rtl::Reference<OAccessibleContextWrapper> createAccessibleContext(
102 const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerContext
103 ) override;
106 rtl::Reference<OAccessibleContextWrapper> OToolBoxWindowItem::createAccessibleContext(
107 const Reference< XAccessibleContext >& _rxInnerContext )
109 return new OToolBoxWindowItemContext( m_nIndexInParent, getComponentContext(), _rxInnerContext, this, getParent() );
113 // VCLXAccessibleToolBox
115 VCLXAccessibleToolBox::VCLXAccessibleToolBox( VCLXWindow* pVCLXWindow ) :
117 ImplInheritanceHelper( pVCLXWindow )
122 VCLXAccessibleToolBox::~VCLXAccessibleToolBox()
126 VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( ToolBox::ImplToolItems::size_type _nPos )
128 VCLXAccessibleToolBoxItem* pItem = nullptr;
129 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
130 if ( pToolBox )
132 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
133 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
134 // returns only toolbox buttons, not windows
135 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is())
136 pItem = aIter->second.get();
139 return pItem;
142 void VCLXAccessibleToolBox::UpdateFocus_Impl()
144 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
145 if( !pToolBox )
146 return;
148 // submit events only if toolbox has the focus to avoid sending events due to mouse move
149 bool bHasFocus = false;
150 if ( pToolBox->HasFocus() )
151 bHasFocus = true;
152 else
154 // check for subtoolbar, i.e. check if our parent is a toolbar
155 ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
156 // subtoolbars never get the focus as key input is just forwarded, so check if the parent toolbar has it
157 if ( pToolBoxParent && pToolBoxParent->HasFocus() )
158 bHasFocus = true;
161 if ( !bHasFocus )
162 return;
164 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
165 sal_uInt16 nFocusCount = 0;
166 for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
168 ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
170 if ( rxChild.is() )
172 VCLXAccessibleToolBoxItem* pItem = rxChild.get();
173 if ( pItem->HasFocus() && nItemId != nHighlightItemId )
175 // reset the old focused item
176 pItem->SetFocus( false );
177 nFocusCount++;
179 if ( nItemId == nHighlightItemId )
181 // set the new focused item
182 pItem->SetFocus( true );
183 nFocusCount++;
186 // both items changed?
187 if ( nFocusCount > 1 )
188 break;
192 void VCLXAccessibleToolBox::ReleaseFocus_Impl( ToolBox::ImplToolItems::size_type _nPos )
194 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
195 if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
197 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
198 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
199 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
201 VCLXAccessibleToolBoxItem* pItem = aIter->second.get();
202 if ( pItem->HasFocus() )
203 pItem->SetFocus( false );
208 void VCLXAccessibleToolBox::UpdateChecked_Impl( ToolBox::ImplToolItems::size_type _nPos )
210 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
211 if ( !pToolBox )
212 return;
214 ToolBoxItemId nFocusId = pToolBox->GetItemId( _nPos );
215 VCLXAccessibleToolBoxItem* pFocusItem = nullptr;
217 for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
219 ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
221 VCLXAccessibleToolBoxItem* pItem = rxChild.get();
222 pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
223 if ( nItemId == nFocusId )
224 pFocusItem = pItem;
226 //Solution:If the position is not a child item,the focus should not be called
227 if ( pFocusItem && _nPos != ToolBox::ITEM_NOTFOUND )
228 pFocusItem->SetFocus( true );
231 void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( ToolBox::ImplToolItems::size_type _nPos )
233 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
234 if ( !pToolBox )
235 return;
237 ToolBoxItemId nItemId = pToolBox->GetItemId( _nPos );
239 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
240 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
241 if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
243 VCLXAccessibleToolBoxItem* pItem = aIter->second.get();
244 if ( pItem )
245 pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET );
249 void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator const & _rMapPos,
250 bool _bNotifyRemoval )
252 rtl::Reference<VCLXAccessibleToolBoxItem> xItemAcc(_rMapPos->second);
253 if ( !xItemAcc.is() )
254 return;
256 if ( _bNotifyRemoval )
258 NotifyAccessibleEvent(AccessibleEventId::CHILD, Any(Reference<XAccessible>(xItemAcc)), Any());
261 xItemAcc->ReleaseToolBox();
262 xItemAcc->dispose();
265 void VCLXAccessibleToolBox::UpdateItem_Impl( ToolBox::ImplToolItems::size_type _nPos)
267 if ( _nPos < m_aAccessibleChildren.size() )
269 UpdateAllItems_Impl();
270 return;
273 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
274 if ( !pToolBox )
275 return;
277 // adjust the "index-in-parent"s
278 ToolBoxItemsMap::iterator aIndexAdjust = m_aAccessibleChildren.upper_bound( _nPos );
279 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
280 while ( m_aAccessibleChildren.end() != aIndexAdjust )
282 rtl::Reference<VCLXAccessibleToolBoxItem> xItem(aIndexAdjust->second);
283 if (xItem.is())
285 sal_Int32 nIndex = xItem->getIndexInParent();
286 nIndex++;
287 xItem->setIndexInParent(nIndex);
290 ++aIndexAdjust;
293 // TODO: we should make this dependent on the existence of event listeners
294 // with the current implementation, we always create accessible object
295 Any aNewChild( getAccessibleChild( static_cast<sal_Int64>(_nPos) ) );
296 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
297 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewChild );
300 void VCLXAccessibleToolBox::UpdateAllItems_Impl()
302 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
303 if ( !pToolBox )
304 return;
306 // deregister the old items
307 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
308 aIter != m_aAccessibleChildren.end(); ++aIter )
310 implReleaseToolboxItem( aIter, true );
312 m_aAccessibleChildren.clear();
314 // register the new items
315 ToolBox::ImplToolItems::size_type i, nCount = pToolBox->GetItemCount();
316 for ( i = 0; i < nCount; ++i )
318 Any aNewValue;
319 aNewValue <<= getAccessibleChild(i);
320 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
324 void VCLXAccessibleToolBox::UpdateCustomPopupItemp_Impl( vcl::Window* pWindow, bool bOpen )
326 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
327 if( !(pWindow && pToolBox) )
328 return;
330 const ToolBoxItemId nDownItem = pToolBox->GetDownItemId();
331 if ( !nDownItem )
332 // No item is currently in down state.
333 // Moreover, calling GetItemPos with 0 will find a separator if there is any.
334 return;
336 Reference< XAccessible > xChild( pWindow->GetAccessible() );
337 if( xChild.is() )
339 Reference< XAccessible > xChildItem( getAccessibleChild(pToolBox->GetItemPos(nDownItem)));
340 VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
342 pItem->SetChild( xChild );
343 pItem->NotifyChildEvent( xChild, bOpen );
347 void VCLXAccessibleToolBox::UpdateItemName_Impl( ToolBox::ImplToolItems::size_type _nPos )
349 VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
350 if ( pItem )
351 pItem->NameChanged();
354 void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( ToolBox::ImplToolItems::size_type _nPos )
356 VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos );
357 if ( pItem )
358 pItem->ToggleEnableState();
361 void VCLXAccessibleToolBox::HandleSubToolBarEvent( const VclWindowEvent& rVclWindowEvent )
363 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
364 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
365 if ( !(pChildWindow
366 && pToolBox
367 && pToolBox == pChildWindow->GetParent()
368 && pChildWindow->GetType() == WindowType::TOOLBOX) )
369 return;
371 const ToolBoxItemId nCurItemId( pToolBox->GetCurItemId() );
372 if ( !nCurItemId )
373 // No item is currently active (might happen when opening the overflow popup).
374 // Moreover, calling GetItemPos with 0 will find a separator if there is any.
375 return;
377 ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( nCurItemId );
378 Reference< XAccessible > xItem = getAccessibleChild( nIndex );
379 if ( xItem.is() )
381 Reference< XAccessible > xChild = pChildWindow->GetAccessible();
382 VCLXAccessibleToolBoxItem* pItem =
383 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
384 pItem->SetChild( xChild );
385 pItem->NotifyChildEvent( xChild, true/*_bShow*/ );
389 void VCLXAccessibleToolBox::ReleaseSubToolBox( ToolBox* _pSubToolBox )
391 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
392 if ( !pToolBox )
393 return;
395 ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
396 if ( nIndex == ToolBox::ITEM_NOTFOUND )
397 return; // not found
399 Reference< XAccessible > xItem = getAccessibleChild( nIndex );
400 if ( !xItem.is() )
401 return;
403 Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
404 VCLXAccessibleToolBoxItem* pItem =
405 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
406 if ( pItem->GetChild() == xChild )
408 pItem->SetChild( Reference< XAccessible >() );
409 pItem->NotifyChildEvent( xChild, false );
413 void VCLXAccessibleToolBox::FillAccessibleStateSet( sal_Int64& rStateSet )
415 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
417 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
418 if ( pToolBox )
420 rStateSet |= AccessibleStateType::FOCUSABLE;
421 if ( pToolBox->IsHorizontal() )
422 rStateSet |= AccessibleStateType::HORIZONTAL;
423 else
424 rStateSet |= AccessibleStateType::VERTICAL;
428 void VCLXAccessibleToolBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
430 // to prevent an early release of the toolbox (VclEventId::ObjectDying)
431 Reference< XAccessibleContext > xHoldAlive = this;
433 switch ( rVclWindowEvent.GetId() )
435 case VclEventId::ToolboxClick:
436 case VclEventId::ToolboxSelect:
438 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
439 if ( rVclWindowEvent.GetData() )
441 UpdateChecked_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
442 UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
444 else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != ToolBox::ITEM_NOTFOUND )
446 UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
447 UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
449 break;
451 case VclEventId::ToolboxDoubleClick:
452 case VclEventId::ToolboxActivate:
453 case VclEventId::ToolboxDeactivate:
454 //case VclEventId::ToolboxSelect:
455 break;
457 case VclEventId::ToolboxItemUpdated:
459 if ( rVclWindowEvent.GetData() )
461 UpdateChecked_Impl( ToolBox::ITEM_NOTFOUND );
462 UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
464 break;
467 case VclEventId::ToolboxHighlight:
468 UpdateFocus_Impl();
469 break;
471 case VclEventId::ToolboxHighlightOff:
472 ReleaseFocus_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
473 break;
475 case VclEventId::ToolboxItemAdded :
476 UpdateItem_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
477 break;
479 case VclEventId::ToolboxItemRemoved :
480 case VclEventId::ToolboxAllItemsChanged :
482 UpdateAllItems_Impl();
483 break;
486 case VclEventId::ToolboxItemWindowChanged:
488 auto nPos = static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData()));
489 ToolBoxItemsMap::iterator aAccessiblePos( m_aAccessibleChildren.find( nPos ) );
490 //TODO: ToolBox::ImplToolItems::size_type -> sal_Int32!
491 if ( m_aAccessibleChildren.end() != aAccessiblePos )
493 implReleaseToolboxItem( aAccessiblePos, false );
494 m_aAccessibleChildren.erase (aAccessiblePos);
497 Any aNewValue;
498 aNewValue <<= getAccessibleChild(nPos);
499 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
500 break;
502 case VclEventId::ToolboxItemTextChanged :
503 UpdateItemName_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
504 break;
506 case VclEventId::ToolboxItemEnabled :
507 case VclEventId::ToolboxItemDisabled :
509 UpdateItemEnabled_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
510 break;
513 case VclEventId::DropdownOpen:
514 case VclEventId::DropdownClose:
516 UpdateCustomPopupItemp_Impl( static_cast< vcl::Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VclEventId::DropdownOpen );
517 break;
520 case VclEventId::ObjectDying :
522 // if this toolbox is a subtoolbox, we have to release it from its parent
523 VclPtr< vcl::Window > pWin = GetAs< vcl::Window >();
524 if ( pWin && pWin->GetParent() &&
525 pWin->GetParent()->GetType() == WindowType::TOOLBOX )
527 auto pParentAccContext = pWin->GetParent()->GetAccessible()->getAccessibleContext();
528 VCLXAccessibleToolBox* pParent = static_cast< VCLXAccessibleToolBox* >( pParentAccContext.get() );
529 if ( pParent )
530 pParent->ReleaseSubToolBox(static_cast<ToolBox *>(pWin.get()));
533 // dispose all items
534 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
535 aIter != m_aAccessibleChildren.end(); ++aIter )
537 implReleaseToolboxItem( aIter, false );
539 m_aAccessibleChildren.clear();
541 [[fallthrough]]; // call base class
544 default:
545 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
549 void VCLXAccessibleToolBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
551 switch ( rVclWindowEvent.GetId() )
553 case VclEventId::WindowShow: // send create on show for direct accessible children
555 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
556 if ( xReturn.is() )
557 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), Any(xReturn) );
558 else
559 HandleSubToolBarEvent( rVclWindowEvent );
561 break;
563 default:
564 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
569 // XComponent
570 void SAL_CALL VCLXAccessibleToolBox::disposing()
572 VCLXAccessibleComponent::disposing();
574 // release the items
575 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
576 aIter != m_aAccessibleChildren.end(); ++aIter )
578 implReleaseToolboxItem( aIter, false );
580 m_aAccessibleChildren.clear();
583 // XServiceInfo
584 OUString VCLXAccessibleToolBox::getImplementationName()
586 return u"com.sun.star.comp.toolkit.AccessibleToolBox"_ustr;
589 Sequence< OUString > VCLXAccessibleToolBox::getSupportedServiceNames()
591 return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
592 Sequence<OUString>{u"com.sun.star.accessibility.AccessibleToolBox"_ustr});
595 // XAccessibleContext
596 sal_Int64 SAL_CALL VCLXAccessibleToolBox::getAccessibleChildCount( )
598 comphelper::OExternalLockGuard aGuard( this );
599 return implGetAccessibleChildCount();
602 sal_Int64 VCLXAccessibleToolBox::implGetAccessibleChildCount( )
604 sal_Int64 nCount = 0;
605 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
606 if ( pToolBox )
607 nCount = pToolBox->GetItemCount();
609 return nCount;
612 Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleChild( sal_Int64 i )
614 comphelper::OExternalLockGuard aGuard( this );
616 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
617 if ( (!pToolBox) || i < 0 || o3tl::make_unsigned(i) >= pToolBox->GetItemCount() )
618 throw IndexOutOfBoundsException();
620 rtl::Reference< VCLXAccessibleToolBoxItem > xChild;
621 // search for the child
622 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
623 if ( m_aAccessibleChildren.end() == aIter )
625 ToolBoxItemId nItemId = pToolBox->GetItemId( i );
626 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
627 vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
628 // not found -> create a new child
629 xChild = new VCLXAccessibleToolBoxItem( pToolBox, i );
630 if ( pItemWindow )
632 Reference< XAccessible> xParent = xChild;
633 auto const xInnerAcc(pItemWindow->GetAccessible());
634 if (xInnerAcc) // else child is being disposed - avoid crashing
636 rtl::Reference<OToolBoxWindowItem> xChild2(new OToolBoxWindowItem(0,
637 ::comphelper::getProcessComponentContext(), xInnerAcc, xParent));
638 pItemWindow->SetAccessible(xChild2);
639 xChild->SetChild( xChild2 );
642 if ( nHighlightItemId > ToolBoxItemId(0) && nItemId == nHighlightItemId )
643 xChild->SetFocus( true );
644 if ( pToolBox->IsItemChecked( nItemId ) )
645 xChild->SetChecked( true );
646 if ( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET )
647 xChild->SetIndeterminate( true );
648 m_aAccessibleChildren.emplace( i, xChild );
650 else
652 // found it
653 xChild = aIter->second;
655 return xChild;
658 Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleAtPoint( const awt::Point& _rPoint )
660 comphelper::OExternalLockGuard aGuard( this );
662 Reference< XAccessible > xAccessible;
663 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
664 if ( pToolBox )
666 ToolBox::ImplToolItems::size_type nItemPos
667 = pToolBox->GetItemPos(VCLUnoHelper::ConvertToVCLPoint(_rPoint));
668 if ( nItemPos != ToolBox::ITEM_NOTFOUND )
669 xAccessible = getAccessibleChild( nItemPos );
672 return xAccessible;
675 Reference< XAccessible > VCLXAccessibleToolBox::GetItemWindowAccessible( const VclWindowEvent& rVclWindowEvent )
677 Reference< XAccessible > xReturn;
678 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
679 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
680 if ( pChildWindow && pToolBox )
682 ToolBox::ImplToolItems::size_type nCount = pToolBox->GetItemCount();
683 for (ToolBox::ImplToolItems::size_type i = 0 ; i < nCount && !xReturn.is() ; ++i)
685 ToolBoxItemId nItemId = pToolBox->GetItemId( i );
686 vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
687 if ( pItemWindow == pChildWindow )
688 xReturn = getAccessibleChild(i);
691 return xReturn;
694 Reference< XAccessible > VCLXAccessibleToolBox::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
696 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
698 if ( !xReturn.is() )
699 xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
700 return xReturn;
703 // XAccessibleSelection
704 void VCLXAccessibleToolBox::selectAccessibleChild( sal_Int64 nChildIndex )
706 OExternalLockGuard aGuard( this );
708 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
709 if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
710 throw IndexOutOfBoundsException();
712 pToolBox->ChangeHighlight( nChildIndex );
715 sal_Bool VCLXAccessibleToolBox::isAccessibleChildSelected( sal_Int64 nChildIndex )
717 OExternalLockGuard aGuard( this );
718 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
719 if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
720 throw IndexOutOfBoundsException();
722 if ( pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nChildIndex ) )
723 return true;
724 else
725 return false;
728 void VCLXAccessibleToolBox::clearAccessibleSelection( )
730 OExternalLockGuard aGuard( this );
731 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
732 pToolBox -> LoseFocus();
735 void VCLXAccessibleToolBox::selectAllAccessibleChildren( )
737 OExternalLockGuard aGuard( this );
738 // intentionally empty. makes no sense for a toolbox
741 sal_Int64 VCLXAccessibleToolBox::getSelectedAccessibleChildCount( )
743 OExternalLockGuard aGuard( this );
745 sal_Int64 nRet = 0;
746 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
747 if (pToolBox)
749 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
750 for ( size_t i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
752 if ( nHighlightItemId == pToolBox->GetItemId( i ) )
754 nRet = 1;
755 break; // a toolbox can only have (n)one selected child
760 return nRet;
763 Reference< XAccessible > VCLXAccessibleToolBox::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex )
765 OExternalLockGuard aGuard( this );
766 if ( nSelectedChildIndex != 0 )
767 throw IndexOutOfBoundsException();
769 Reference< XAccessible > xChild;
770 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
771 if (pToolBox)
773 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
774 for (ToolBox::ImplToolItems::size_type i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
776 if ( nHighlightItemId == pToolBox->GetItemId( i ) )
778 xChild = getAccessibleChild( i );
779 break;
784 if (!xChild)
785 throw IndexOutOfBoundsException();
787 return xChild;
790 void VCLXAccessibleToolBox::deselectAccessibleChild( sal_Int64 nChildIndex )
792 OExternalLockGuard aGuard( this );
793 if ( nChildIndex < 0 || nChildIndex >= implGetAccessibleChildCount() )
794 throw IndexOutOfBoundsException();
795 clearAccessibleSelection(); // a toolbox can only have (n)one selected child
798 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */