LibreOffice Module accessibility (master) 1
vclxaccessibletoolbox.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19#include <string.h>
20
24
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>
35#include <comphelper/types.hxx>
36
37using namespace ::comphelper;
38using namespace ::com::sun::star;
39using namespace ::com::sun::star::uno;
40using namespace ::com::sun::star::lang;
41using namespace ::com::sun::star::accessibility;
42
43namespace
44{
45
46 // = OToolBoxWindowItemContext
47
50 class OToolBoxWindowItemContext final : public OAccessibleContextWrapper
51 {
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)
65 {
66 }
67 virtual sal_Int64 SAL_CALL getAccessibleIndexInParent( ) override;
68 };
69
70
71 sal_Int64 SAL_CALL OToolBoxWindowItemContext::getAccessibleIndexInParent( )
72 {
73 ::osl::MutexGuard aGuard( m_aMutex );
74 return m_nIndexInParent;
75 }
76
77
78 // = OToolBoxWindowItem
79
82 class OToolBoxWindowItem : public OAccessibleWrapper
83 {
84 private:
85 sal_Int32 m_nIndexInParent;
86
87 public:
88 sal_Int32 getIndexInParent() const { return m_nIndexInParent; }
89 void setIndexInParent( sal_Int32 _nNewIndex ) { m_nIndexInParent = _nNewIndex; }
90
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)
101 {
102 }
103
104 protected:
105 // OAccessibleWrapper
106 virtual rtl::Reference<OAccessibleContextWrapper> createAccessibleContext(
107 const css::uno::Reference< css::accessibility::XAccessibleContext >& _rxInnerContext
108 ) override;
109 };
110
111 rtl::Reference<OAccessibleContextWrapper> OToolBoxWindowItem::createAccessibleContext(
112 const Reference< XAccessibleContext >& _rxInnerContext )
113 {
114 return new OToolBoxWindowItemContext( m_nIndexInParent, getComponentContext(), _rxInnerContext, this, getParent() );
115 }
116}
117
118// VCLXAccessibleToolBox
119
121
122 ImplInheritanceHelper( pVCLXWindow )
123
124{
125}
126
128{
129}
130
131VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( ToolBox::ImplToolItems::size_type _nPos )
132{
133 VCLXAccessibleToolBoxItem* pItem = nullptr;
134 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
135 if ( pToolBox )
136 {
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() );
142 }
143
144 return pItem;
145}
146
148{
149 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
150 if( !pToolBox )
151 return;
152
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
158 {
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;
164 }
165
166 if ( !bHasFocus )
167 return;
168
169 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
170 sal_uInt16 nFocusCount = 0;
171 for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
172 {
173 ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
174
175 if ( rxChild.is() )
176 {
178 static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
179 if ( pItem->HasFocus() && nItemId != nHighlightItemId )
180 {
181 // reset the old focused item
182 pItem->SetFocus( false );
183 nFocusCount++;
184 }
185 if ( nItemId == nHighlightItemId )
186 {
187 // set the new focused item
188 pItem->SetFocus( true );
189 nFocusCount++;
190 }
191 }
192 // both items changed?
193 if ( nFocusCount > 1 )
194 break;
195 }
196}
197
198void VCLXAccessibleToolBox::ReleaseFocus_Impl( ToolBox::ImplToolItems::size_type _nPos )
199{
200 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
201 if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
202 {
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() )
206 {
208 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
209 if ( pItem->HasFocus() )
210 pItem->SetFocus( false );
211 }
212 }
213}
214
215void VCLXAccessibleToolBox::UpdateChecked_Impl( ToolBox::ImplToolItems::size_type _nPos )
216{
217 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
218 if ( !pToolBox )
219 return;
220
221 ToolBoxItemId nFocusId = pToolBox->GetItemId( _nPos );
222 VCLXAccessibleToolBoxItem* pFocusItem = nullptr;
223
224 for ( const auto& [rPos, rxChild] : m_aAccessibleChildren )
225 {
226 ToolBoxItemId nItemId = pToolBox->GetItemId( rPos );
227
229 static_cast< VCLXAccessibleToolBoxItem* >( rxChild.get() );
230 pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
231 if ( nItemId == nFocusId )
232 pFocusItem = pItem;
233 }
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 );
237}
238
239void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( ToolBox::ImplToolItems::size_type _nPos )
240{
241 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
242 if ( !pToolBox )
243 return;
244
245 ToolBoxItemId nItemId = pToolBox->GetItemId( _nPos );
246
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() )
250 {
252 static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
253 if ( pItem )
254 pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == TRISTATE_INDET );
255 }
256}
257
258void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator const & _rMapPos,
259 bool _bNotifyRemoval )
260{
261 Reference< XAccessible > xItemAcc( _rMapPos->second );
262 if ( !xItemAcc.is() )
263 return;
264
265 if ( _bNotifyRemoval )
266 {
267 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any( xItemAcc ), Any() );
268 }
269
270 auto pWindowItem = dynamic_cast<OToolBoxWindowItem*>(xItemAcc.get());
271 if ( !pWindowItem )
272 {
273 static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() )->ReleaseToolBox();
274 ::comphelper::disposeComponent( xItemAcc );
275 }
276 else
277 {
278 Reference< XAccessibleContext > xContext( pWindowItem->getContextNoCreate() );
279 ::comphelper::disposeComponent( xContext );
280 }
281}
282
283void VCLXAccessibleToolBox::UpdateItem_Impl( ToolBox::ImplToolItems::size_type _nPos)
284{
285 if ( _nPos < m_aAccessibleChildren.size() )
286 {
288 return;
289 }
290
291 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
292 if ( !pToolBox )
293 return;
294
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 )
299 {
300 Reference< XAccessible > xItemAcc( aIndexAdjust->second );
301
302 auto pWindowItem = dynamic_cast<OToolBoxWindowItem*>(xItemAcc.get());
303 if ( !pWindowItem )
304 {
305 VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() );
306 if ( pItem )
307 {
308 sal_Int32 nIndex = pItem->getIndexInParent( );
309 nIndex++;
310 pItem->setIndexInParent( nIndex );
311 }
312 }
313 else
314 {
315 sal_Int32 nIndex = pWindowItem->getIndexInParent( );
316 nIndex++;
317 pWindowItem->setIndexInParent( nIndex );
318 }
319
320 ++aIndexAdjust;
321 }
322
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 );
328}
329
331{
332 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
333 if ( !pToolBox )
334 return;
335
336 // deregister the old items
337 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
338 aIter != m_aAccessibleChildren.end(); ++aIter )
339 {
340 implReleaseToolboxItem( aIter, true );
341 }
342 m_aAccessibleChildren.clear();
343
344 // register the new items
345 ToolBox::ImplToolItems::size_type i, nCount = pToolBox->GetItemCount();
346 for ( i = 0; i < nCount; ++i )
347 {
348 Any aNewValue;
349 aNewValue <<= getAccessibleChild(i);
350 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
351 }
352}
353
355{
356 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
357 if( !(pWindow && pToolBox) )
358 return;
359
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;
365
366 Reference< XAccessible > xChild( pWindow->GetAccessible() );
367 if( xChild.is() )
368 {
369 Reference< XAccessible > xChildItem( getAccessibleChild(pToolBox->GetItemPos(nDownItem)));
370 VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
371
372 pItem->SetChild( xChild );
373 pItem->NotifyChildEvent( xChild, bOpen );
374 }
375}
376
377void VCLXAccessibleToolBox::UpdateItemName_Impl( ToolBox::ImplToolItems::size_type _nPos )
378{
380 if ( pItem )
381 pItem->NameChanged();
382}
383
384void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( ToolBox::ImplToolItems::size_type _nPos )
385{
387 if ( pItem )
388 pItem->ToggleEnableState();
389}
390
392{
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;
400
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;
406
407 ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( nCurItemId );
409 if ( xItem.is() )
410 {
411 Reference< XAccessible > xChild = pChildWindow->GetAccessible();
413 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
414 pItem->SetChild( xChild );
415 pItem->NotifyChildEvent( xChild, true/*_bShow*/ );
416 }
417}
418
420{
421 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
422 if ( !pToolBox )
423 return;
424
425 ToolBox::ImplToolItems::size_type nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
427 return; // not found
428
430 if ( !xItem.is() )
431 return;
432
433 Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
435 static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
436 if ( pItem->GetChild() == xChild )
437 {
439 pItem->NotifyChildEvent( xChild, false );
440 }
441}
442
444{
445 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
446
447 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
448 if ( pToolBox )
449 {
450 rStateSet |= AccessibleStateType::FOCUSABLE;
451 if ( pToolBox->IsHorizontal() )
452 rStateSet |= AccessibleStateType::HORIZONTAL;
453 else
454 rStateSet |= AccessibleStateType::VERTICAL;
455 }
456}
457
459{
460 // to prevent an early release of the toolbox (VclEventId::ObjectDying)
461 Reference< XAccessibleContext > xHoldAlive = this;
462
463 switch ( rVclWindowEvent.GetId() )
464 {
465 case VclEventId::ToolboxClick:
466 case VclEventId::ToolboxSelect:
467 {
468 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
469 if ( rVclWindowEvent.GetData() )
470 {
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())) );
473 }
474 else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != ToolBox::ITEM_NOTFOUND )
475 {
476 UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
477 UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
478 }
479 break;
480 }
481 case VclEventId::ToolboxDoubleClick:
482 case VclEventId::ToolboxActivate:
483 case VclEventId::ToolboxDeactivate:
484 //case VclEventId::ToolboxSelect:
485 break;
486
487 case VclEventId::ToolboxItemUpdated:
488 {
489 if ( rVclWindowEvent.GetData() )
490 {
492 UpdateIndeterminate_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
493 }
494 break;
495 }
496
497 case VclEventId::ToolboxHighlight:
499 break;
500
501 case VclEventId::ToolboxHighlightOff:
502 ReleaseFocus_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
503 break;
504
505 case VclEventId::ToolboxItemAdded :
506 UpdateItem_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
507 break;
508
509 case VclEventId::ToolboxItemRemoved :
510 case VclEventId::ToolboxAllItemsChanged :
511 {
513 break;
514 }
515
516 case VclEventId::ToolboxItemWindowChanged:
517 {
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 )
522 {
523 implReleaseToolboxItem( aAccessiblePos, false );
524 m_aAccessibleChildren.erase (aAccessiblePos);
525 }
526
527 Any aNewValue;
528 aNewValue <<= getAccessibleChild(nPos);
529 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
530 break;
531 }
532 case VclEventId::ToolboxItemTextChanged :
533 UpdateItemName_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
534 break;
535
536 case VclEventId::ToolboxItemEnabled :
537 case VclEventId::ToolboxItemDisabled :
538 {
539 UpdateItemEnabled_Impl( static_cast<ToolBox::ImplToolItems::size_type>(reinterpret_cast<sal_IntPtr>(rVclWindowEvent.GetData())) );
540 break;
541 }
542
543 case VclEventId::DropdownOpen:
544 case VclEventId::DropdownClose:
545 {
546 UpdateCustomPopupItemp_Impl( static_cast< vcl::Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VclEventId::DropdownOpen );
547 break;
548 }
549
550 case VclEventId::ObjectDying :
551 {
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 )
556 {
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()));
561 }
562
563 // dispose all items
564 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
565 aIter != m_aAccessibleChildren.end(); ++aIter )
566 {
567 implReleaseToolboxItem( aIter, false );
568 }
569 m_aAccessibleChildren.clear();
570
571 [[fallthrough]]; // call base class
572 }
573
574 default:
575 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
576 }
577}
578
580{
581 switch ( rVclWindowEvent.GetId() )
582 {
583 case VclEventId::WindowShow: // send create on show for direct accessible children
584 {
585 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
586 if ( xReturn.is() )
587 NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), Any(xReturn) );
588 else
589 HandleSubToolBarEvent( rVclWindowEvent );
590 }
591 break;
592
593 default:
594 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
595
596 }
597}
598
599// XComponent
601{
602 VCLXAccessibleComponent::disposing();
603
604 // release the items
605 for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
606 aIter != m_aAccessibleChildren.end(); ++aIter )
607 {
608 implReleaseToolboxItem( aIter, false );
609 }
610 m_aAccessibleChildren.clear();
611}
612
613// XServiceInfo
615{
616 return "com.sun.star.comp.toolkit.AccessibleToolBox";
617}
618
620{
621 return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
622 Sequence<OUString>{"com.sun.star.accessibility.AccessibleToolBox"});
623}
624
625// XAccessibleContext
627{
628 comphelper::OExternalLockGuard aGuard( this );
630}
631
633 {
634 sal_Int64 nCount = 0;
635 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
636 if ( pToolBox )
637 nCount = pToolBox->GetItemCount();
638
639 return nCount;
640}
641
643{
644 comphelper::OExternalLockGuard aGuard( this );
645
646 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
647 if ( (!pToolBox) || i < 0 || o3tl::make_unsigned(i) >= pToolBox->GetItemCount() )
648 throw IndexOutOfBoundsException();
649
651 // search for the child
652 ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
653 if ( m_aAccessibleChildren.end() == aIter )
654 {
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
660 Reference< XAccessible> xParent = pChild;
661 if ( pItemWindow )
662 {
663 xChild = new OToolBoxWindowItem(0,::comphelper::getProcessComponentContext(),pItemWindow->GetAccessible(),xParent);
664 pItemWindow->SetAccessible(xChild);
665 pChild->SetChild( xChild );
666 }
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 );
675 }
676 else
677 {
678 // found it
679 xChild = aIter->second;
680 }
681 return xChild;
682}
683
685{
686 comphelper::OExternalLockGuard aGuard( this );
687
688 Reference< XAccessible > xAccessible;
689 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
690 if ( pToolBox )
691 {
692 ToolBox::ImplToolItems::size_type nItemPos = pToolBox->GetItemPos( VCLPoint( _rPoint ) );
693 if ( nItemPos != ToolBox::ITEM_NOTFOUND )
694 xAccessible = getAccessibleChild( nItemPos );
695 }
696
697 return xAccessible;
698}
699
701{
703 vcl::Window* pChildWindow = static_cast<vcl::Window *>(rVclWindowEvent.GetData());
704 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
705 if ( pChildWindow && pToolBox )
706 {
707 ToolBox::ImplToolItems::size_type nCount = pToolBox->GetItemCount();
708 for (ToolBox::ImplToolItems::size_type i = 0 ; i < nCount && !xReturn.is() ; ++i)
709 {
710 ToolBoxItemId nItemId = pToolBox->GetItemId( i );
711 vcl::Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
712 if ( pItemWindow == pChildWindow )
713 xReturn = getAccessibleChild(i);
714 }
715 }
716 return xReturn;
717}
718
720{
721 Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
722
723 if ( !xReturn.is() )
724 xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
725 return xReturn;
726}
727
728// XAccessibleSelection
730{
731 OExternalLockGuard aGuard( this );
732
733 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
734 if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
735 throw IndexOutOfBoundsException();
736
737 pToolBox->ChangeHighlight( nChildIndex );
738}
739
741{
742 OExternalLockGuard aGuard( this );
743 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
744 if ( (!pToolBox) || nChildIndex < 0 || o3tl::make_unsigned(nChildIndex) >= pToolBox->GetItemCount() )
745 throw IndexOutOfBoundsException();
746
747 if ( pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nChildIndex ) )
748 return true;
749 else
750 return false;
751}
752
754{
755 OExternalLockGuard aGuard( this );
756 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
757 pToolBox -> LoseFocus();
758}
759
761{
762 OExternalLockGuard aGuard( this );
763 // intentionally empty. makes no sense for a toolbox
764}
765
767{
768 OExternalLockGuard aGuard( this );
769
770 sal_Int64 nRet = 0;
771 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
772 if (pToolBox)
773 {
774 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
775 for ( size_t i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
776 {
777 if ( nHighlightItemId == pToolBox->GetItemId( i ) )
778 {
779 nRet = 1;
780 break; // a toolbox can only have (n)one selected child
781 }
782 }
783 }
784
785 return nRet;
786}
787
789{
790 OExternalLockGuard aGuard( this );
791 if ( nSelectedChildIndex != 0 )
792 throw IndexOutOfBoundsException();
793
795 VclPtr< ToolBox > pToolBox = GetAs< ToolBox >();
796 if (pToolBox)
797 {
798 ToolBoxItemId nHighlightItemId = pToolBox->GetHighlightItemId();
799 for (ToolBox::ImplToolItems::size_type i = 0, nCount = pToolBox->GetItemCount(); i < nCount; i++ )
800 {
801 if ( nHighlightItemId == pToolBox->GetItemId( i ) )
802 {
803 xChild = getAccessibleChild( i );
804 break;
805 }
806 }
807 }
808
809 if (!xChild)
810 throw IndexOutOfBoundsException();
811
812 return xChild;
813}
814
816{
817 OExternalLockGuard aGuard( this );
818 if ( nChildIndex < 0 || nChildIndex >= implGetAccessibleChildCount() )
819 throw IndexOutOfBoundsException();
820 clearAccessibleSelection(); // a toolbox can only have (n)one selected child
821}
822
823/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static constexpr auto ITEM_NOTFOUND
void SetIndeterminate(bool _bIndeterminate)
void setIndexInParent(sal_Int32 _nNewIndex)
const css::uno::Reference< css::accessibility::XAccessible > & GetChild() const
void NotifyChildEvent(const css::uno::Reference< css::accessibility::XAccessible > &_xChild, bool _bShow)
void SetChild(const css::uno::Reference< css::accessibility::XAccessible > &_xChild)
virtual ~VCLXAccessibleToolBox() override
void ReleaseFocus_Impl(ToolBox::ImplToolItems::size_type _nPos)
void UpdateChecked_Impl(ToolBox::ImplToolItems::size_type _nPos)
virtual void SAL_CALL selectAllAccessibleChildren() override
void UpdateIndeterminate_Impl(ToolBox::ImplToolItems::size_type _nPos)
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
void HandleSubToolBarEvent(const VclWindowEvent &rVclWindowEvent)
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int64 i) override
virtual void SAL_CALL disposing() override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getSelectedAccessibleChild(sal_Int64 nSelectedChildIndex) override
void UpdateItemName_Impl(ToolBox::ImplToolItems::size_type _nPos)
virtual sal_Bool SAL_CALL isAccessibleChildSelected(sal_Int64 nChildIndex) override
virtual void ProcessWindowChildEvent(const VclWindowEvent &rVclWindowEvent) override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &aPoint) override
virtual void FillAccessibleStateSet(sal_Int64 &rStateSet) override
VCLXAccessibleToolBox(VCLXWindow *pVCLXWindow)
css::uno::Reference< css::accessibility::XAccessible > GetItemWindowAccessible(const VclWindowEvent &rVclWindowEvent)
void UpdateItem_Impl(ToolBox::ImplToolItems::size_type _nPos)
virtual void ProcessWindowEvent(const VclWindowEvent &rVclWindowEvent) override
virtual css::uno::Reference< css::accessibility::XAccessible > GetChildAccessible(const VclWindowEvent &rVclWindowEvent) override
virtual void SAL_CALL selectAccessibleChild(sal_Int64 nChildIndex) override
void UpdateCustomPopupItemp_Impl(vcl::Window *pWindow, bool bOpen)
VCLXAccessibleToolBoxItem * GetItem_Impl(ToolBox::ImplToolItems::size_type _nPos)
virtual sal_Int64 SAL_CALL getAccessibleChildCount() override
virtual sal_Int64 SAL_CALL getSelectedAccessibleChildCount() override
virtual void SAL_CALL clearAccessibleSelection() override
void UpdateItemEnabled_Impl(ToolBox::ImplToolItems::size_type _nPos)
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL deselectAccessibleChild(sal_Int64 nChildIndex) override
void implReleaseToolboxItem(ToolBoxItemsMap::iterator const &_rMapPos, bool _bNotifyRemoval)
void ReleaseSubToolBox(ToolBox *_pSubToolBox)
ToolBoxItemsMap m_aAccessibleChildren
reference_type * get() const
VclEventId GetId() const
void * GetData() const
vcl::Window * GetParent() const
WindowType GetType() const
void SetAccessible(const css::uno::Reference< css::accessibility::XAccessible > &)
bool HasFocus() const
css::uno::Reference< css::accessibility::XAccessible > GetAccessible(bool bCreate=true)
inline ::Point VCLPoint(const css::awt::Point &rAWTPoint)
int nCount
TRISTATE_INDET
sal_Int32 nIndex
sal_uInt16 nPos
css::uno::Sequence< T > concatSequences(const css::uno::Sequence< T > &rS1, const Ss &... rSn)
Reference< XComponentContext > getComponentContext(Reference< XMultiServiceFactory > const &factory)
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
unsigned char sal_Bool
sal_Int32 _nPos