bump product version to 7.6.3.2-android
[LibreOffice.git] / accessibility / source / standard / vclxaccessiblelist.cxx
blob101c5815c0ac7adf930dab03eadc86dd4c1244f4
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 .
20 #include <standard/vclxaccessiblelist.hxx>
21 #include <standard/vclxaccessiblelistitem.hxx>
22 #include <helper/listboxhelper.hxx>
24 #include <unotools/accessiblerelationsethelper.hxx>
25 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
26 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
27 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
28 #include <com/sun/star/accessibility/AccessibleRole.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <comphelper/types.hxx>
31 #include <o3tl/safeint.hxx>
32 #include <vcl/svapp.hxx>
33 #include <vcl/toolkit/combobox.hxx>
34 #include <vcl/toolkit/lstbox.hxx>
35 #include <toolkit/helper/convert.hxx>
37 using namespace ::com::sun::star;
38 using namespace ::com::sun::star::uno;
39 using namespace ::com::sun::star::lang;
40 using namespace ::com::sun::star::beans;
41 using namespace ::com::sun::star::accessibility;
42 using namespace ::accessibility;
44 namespace
46 /// @throws css::lang::IndexOutOfBoundsException
47 void checkSelection_Impl( sal_Int64 _nIndex, const IComboListBoxHelper& _rListBox, bool bSelected )
49 sal_Int32 nCount = bSelected ? _rListBox.GetSelectedEntryCount()
50 : _rListBox.GetEntryCount();
51 if ( _nIndex < 0 || _nIndex >= nCount )
52 throw css::lang::IndexOutOfBoundsException();
56 VCLXAccessibleList::VCLXAccessibleList (VCLXWindow* pVCLWindow, BoxType aBoxType,
57 const Reference< XAccessible >& _xParent)
58 : ImplInheritanceHelper (pVCLWindow),
59 m_aBoxType (aBoxType),
60 m_nVisibleLineCount (0),
61 m_nIndexInParent (DEFAULT_INDEX_IN_PARENT),
62 m_nLastTopEntry ( 0 ),
63 m_nLastSelectedPos ( LISTBOX_ENTRY_NOTFOUND ),
64 m_bDisableProcessEvent ( false ),
65 m_bVisible ( true ),
66 m_nCurSelectedPos ( LISTBOX_ENTRY_NOTFOUND ),
67 m_xParent ( _xParent )
69 // Because combo boxes and list boxes don't have a common interface for
70 // methods with identical signature we have to write down twice the
71 // same code.
72 switch (m_aBoxType)
74 case COMBOBOX:
76 VclPtr< ComboBox > pBox = GetAs< ComboBox >();
77 if ( pBox )
78 m_pListBoxHelper.reset( new VCLListBoxHelper<ComboBox> (*pBox) );
79 break;
82 case LISTBOX:
84 VclPtr< ListBox > pBox = GetAs< ListBox >();
85 if ( pBox )
86 m_pListBoxHelper.reset( new VCLListBoxHelper<ListBox> (*pBox) );
87 break;
90 UpdateVisibleLineCount();
91 if(m_pListBoxHelper)
93 m_nCurSelectedPos=m_pListBoxHelper->GetSelectedEntryPos(0);
95 sal_uInt16 nCount = static_cast<sal_uInt16>(getAccessibleChildCount());
96 m_aAccessibleChildren.reserve(nCount);
100 void VCLXAccessibleList::SetIndexInParent (sal_Int32 nIndex)
102 m_nIndexInParent = nIndex;
106 void SAL_CALL VCLXAccessibleList::disposing()
108 VCLXAccessibleComponent::disposing();
110 // Dispose all items in the list.
111 for (Reference<XAccessible>& rxChild : m_aAccessibleChildren)
112 comphelper::disposeComponent(rxChild);
114 m_aAccessibleChildren.clear();
116 m_pListBoxHelper.reset();
120 void VCLXAccessibleList::FillAccessibleStateSet (sal_Int64& rStateSet)
122 SolarMutexGuard aSolarGuard;
124 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
125 // check if our list should be visible
126 if ( m_pListBoxHelper
127 && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN
128 && !m_pListBoxHelper->IsInDropDown() )
130 rStateSet &= ~AccessibleStateType::VISIBLE;
131 rStateSet &= ~AccessibleStateType::SHOWING;
132 m_bVisible = false;
135 // Both the combo box and list box are handled identical in the
136 // following but for some reason they don't have a common interface for
137 // the methods used.
138 if ( m_pListBoxHelper )
140 if ( m_pListBoxHelper->IsMultiSelectionEnabled() )
141 rStateSet |= AccessibleStateType::MULTI_SELECTABLE;
142 rStateSet |= AccessibleStateType::FOCUSABLE;
143 // All children are transient.
144 rStateSet |= AccessibleStateType::MANAGES_DESCENDANTS;
148 void VCLXAccessibleList::notifyVisibleStates(bool _bSetNew )
150 m_bVisible = _bSetNew;
151 Any aOldValue, aNewValue;
152 (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::VISIBLE;
153 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
154 (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::SHOWING;
155 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue );
157 ListItems::iterator aIter = m_aAccessibleChildren.begin();
158 UpdateVisibleLineCount();
159 // adjust the index inside the VCLXAccessibleListItem
160 for ( ; aIter != m_aAccessibleChildren.end(); )
162 Reference<XAccessible> xChild = *aIter;
163 if (!xChild.is())
165 aIter = m_aAccessibleChildren.erase(aIter);
167 else
169 VCLXAccessibleListItem* pItem = static_cast<VCLXAccessibleListItem*>(xChild.get());
170 const sal_Int32 nTopEntry = m_pListBoxHelper ? m_pListBoxHelper->GetTopEntry() : 0;
171 const sal_Int32 nPos = static_cast<sal_Int32>(aIter - m_aAccessibleChildren.begin());
172 bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) );
173 pItem->SetVisible( m_bVisible && bVisible );
174 ++aIter;
180 void VCLXAccessibleList::UpdateSelection_Acc (std::u16string_view /*sTextOfSelectedItem*/, bool b_IsDropDownList)
182 if ( m_aBoxType != COMBOBOX )
183 return;
185 /* FIXME: is there something missing here? nIndex is unused. Looks like
186 * copy-paste from VCLXAccessibleList::UpdateSelection() */
187 // VclPtr< ComboBox > pBox = GetAs< ComboBox >();
188 // if ( pBox )
189 // {
190 // // Find the index of the selected item inside the VCL control...
191 // sal_Int32 nIndex = pBox->GetEntryPos(sTextOfSelectedItem);
192 // // ...and then find the associated accessibility object.
193 // if ( nIndex == LISTBOX_ENTRY_NOTFOUND )
194 // nIndex = 0;
195 UpdateSelection_Impl_Acc(b_IsDropDownList);
196 // }
200 void VCLXAccessibleList::UpdateSelection_Impl_Acc(bool bHasDropDownList)
202 uno::Any aOldValue, aNewValue;
205 SolarMutexGuard aSolarGuard;
206 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
207 Reference< XAccessible > xNewAcc;
208 if ( m_pListBoxHelper )
210 sal_Int32 i=0;
211 m_nCurSelectedPos = LISTBOX_ENTRY_NOTFOUND;
212 for (const Reference<XAccessible>& rxChild : m_aAccessibleChildren)
214 if (rxChild.is())
216 VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >(rxChild.get() );
217 // Retrieve the item's index from the list entry.
218 bool bNowSelected = m_pListBoxHelper->IsEntryPosSelected (i);
219 if (bNowSelected)
220 m_nCurSelectedPos = i;
222 if ( bNowSelected && !pItem->IsSelected() )
224 xNewAcc = rxChild;
225 aNewValue <<= xNewAcc;
227 else if ( pItem->IsSelected() )
228 m_nLastSelectedPos = i;
230 pItem->SetSelected( bNowSelected );
232 else
233 { // it could happen that a child was not created before
234 checkEntrySelected(i,aNewValue,xNewAcc);
236 ++i;
238 const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
239 if ( i < nCount ) // here we have to check the if any other listbox entry is selected
241 for (; i < nCount && !checkEntrySelected(i,aNewValue,xNewAcc) ;++i )
244 if ( xNewAcc.is() && GetWindow()->HasFocus() )
246 if ( m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND )
247 aOldValue <<= getAccessibleChild( m_nLastSelectedPos );
248 aNewValue <<= xNewAcc;
253 if (m_aBoxType == COMBOBOX)
255 //VCLXAccessibleDropDownComboBox
256 //when in list is dropped down, xText = NULL
257 if (bHasDropDownList && m_pListBoxHelper && m_pListBoxHelper->IsInDropDown())
259 if ( aNewValue.hasValue() || aOldValue.hasValue() )
261 NotifyAccessibleEvent(
262 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
263 aOldValue,
264 aNewValue );
266 NotifyListItem(aNewValue);
269 else
271 //VCLXAccessibleComboBox
272 NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, uno::Any(), uno::Any() );
275 else if (m_aBoxType == LISTBOX)
277 if ( aNewValue.hasValue() || aOldValue.hasValue() )
279 NotifyAccessibleEvent(
280 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
281 aOldValue,
282 aNewValue );
284 NotifyListItem(aNewValue);
289 void VCLXAccessibleList::NotifyListItem(css::uno::Any const & val)
291 Reference< XAccessible > xCurItem;
292 val >>= xCurItem;
293 if (xCurItem.is())
295 VCLXAccessibleListItem* pCurItem = static_cast< VCLXAccessibleListItem* >(xCurItem.get());
296 if (pCurItem)
298 pCurItem->NotifyAccessibleEvent(AccessibleEventId::SELECTION_CHANGED,Any(),Any());
303 void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent, bool b_IsDropDownList)
305 switch ( rVclWindowEvent.GetId() )
307 case VclEventId::DropdownSelect:
308 case VclEventId::ListboxSelect:
309 if ( !m_bDisableProcessEvent )
310 UpdateSelection_Impl_Acc(b_IsDropDownList);
311 break;
312 case VclEventId::WindowGetFocus:
313 break;
314 case VclEventId::ControlGetFocus:
316 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
317 if (m_aBoxType == COMBOBOX && b_IsDropDownList)
319 //VCLXAccessibleDropDownComboBox
321 else if (m_aBoxType == LISTBOX && b_IsDropDownList)
324 else if ( m_aBoxType == LISTBOX && !b_IsDropDownList)
326 if ( m_pListBoxHelper )
328 uno::Any aOldValue,
329 aNewValue;
330 sal_Int32 nPos = m_nCurSelectedPos; //m_pListBoxHelper->GetSelectedEntryPos();
332 if ( nPos == LISTBOX_ENTRY_NOTFOUND )
333 nPos = m_pListBoxHelper->GetTopEntry();
334 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
335 aNewValue <<= CreateChild(nPos);
336 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
337 aOldValue,
338 aNewValue );
342 break;
343 default:
344 break;
349 void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent)
351 // Create a reference to this object to prevent an early release of the
352 // listbox (VclEventId::ObjectDying).
353 Reference< XAccessible > xHoldAlive = this;
355 switch ( rVclWindowEvent.GetId() )
357 case VclEventId::DropdownOpen:
358 notifyVisibleStates(true);
359 break;
360 case VclEventId::DropdownClose:
361 notifyVisibleStates(false);
362 break;
363 case VclEventId::ListboxScrolled:
364 UpdateEntryRange_Impl();
365 break;
367 // The selection events VclEventId::ComboboxSelect and
368 // VclEventId::ComboboxDeselect are not handled here because here we
369 // have no access to the edit field. Its text is necessary to
370 // identify the currently selected item.
372 case VclEventId::ObjectDying:
374 dispose();
376 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
377 break;
380 case VclEventId::ListboxItemRemoved:
381 case VclEventId::ComboboxItemRemoved:
382 case VclEventId::ListboxItemAdded:
383 case VclEventId::ComboboxItemAdded:
384 HandleChangedItemList();
385 break;
386 case VclEventId::ControlGetFocus:
388 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
389 // Added by IBM Symphony Acc team to handle the list item focus when List control get focus
390 bool b_IsDropDownList = true;
391 if (m_pListBoxHelper)
392 b_IsDropDownList = ((m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN);
393 if ( m_aBoxType == LISTBOX && !b_IsDropDownList )
395 if ( m_pListBoxHelper )
397 uno::Any aOldValue,
398 aNewValue;
399 sal_Int32 nPos = m_nCurSelectedPos;
401 if ( nPos == LISTBOX_ENTRY_NOTFOUND )
402 nPos = m_pListBoxHelper->GetTopEntry();
403 if ( nPos != LISTBOX_ENTRY_NOTFOUND )
404 aNewValue <<= CreateChild(nPos);
405 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
406 aOldValue,
407 aNewValue );
411 break;
413 default:
414 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent);
418 void VCLXAccessibleList::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper& rRelationSet )
420 VclPtr< ListBox > pBox = GetAs< ListBox >();
421 if( m_aBoxType == LISTBOX )
423 if (m_pListBoxHelper && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) != WB_DROPDOWN)
425 uno::Sequence< uno::Reference< uno::XInterface > > aSequence { pBox->GetAccessible() };
426 rRelationSet.AddRelation( com::sun::star::accessibility::AccessibleRelation( com::sun::star::accessibility::AccessibleRelationType::MEMBER_OF, aSequence ) );
429 else
431 VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet);
436 /** To find out which item is currently selected and to update the SELECTED
437 state of the associated accessibility objects accordingly we exploit the
438 fact that the
440 void VCLXAccessibleList::UpdateSelection (std::u16string_view sTextOfSelectedItem)
442 if ( m_aBoxType != COMBOBOX )
443 return;
445 VclPtr< ComboBox > pBox = GetAs< ComboBox >();
446 if ( pBox )
448 // Find the index of the selected item inside the VCL control...
449 sal_Int32 nIndex = pBox->GetEntryPos(sTextOfSelectedItem);
450 // ...and then find the associated accessibility object.
451 if ( nIndex == LISTBOX_ENTRY_NOTFOUND )
452 nIndex = 0;
453 UpdateSelection_Impl(nIndex);
458 Reference<XAccessible> VCLXAccessibleList::CreateChild (sal_Int32 nPos)
460 Reference<XAccessible> xChild;
462 if ( o3tl::make_unsigned(nPos) >= m_aAccessibleChildren.size() )
464 m_aAccessibleChildren.resize(nPos + 1);
466 // insert into the container
467 xChild = new VCLXAccessibleListItem(nPos, this);
468 m_aAccessibleChildren[nPos] = xChild;
470 else
472 xChild = m_aAccessibleChildren[nPos];
473 // check if position is empty and can be used else we have to adjust all entries behind this
474 if (!xChild.is())
476 xChild = new VCLXAccessibleListItem(nPos, this);
477 m_aAccessibleChildren[nPos] = xChild;
481 if ( xChild.is() )
483 // Just add the SELECTED state.
484 bool bNowSelected = false;
485 if ( m_pListBoxHelper )
486 bNowSelected = m_pListBoxHelper->IsEntryPosSelected(nPos);
487 if (bNowSelected)
488 m_nCurSelectedPos = nPos;
489 VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >(xChild.get());
490 pItem->SetSelected( bNowSelected );
492 // Set the child's VISIBLE state.
493 UpdateVisibleLineCount();
494 const sal_Int32 nTopEntry = m_pListBoxHelper ? m_pListBoxHelper->GetTopEntry() : 0;
495 bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) );
496 pItem->SetVisible( m_bVisible && bVisible );
499 return xChild;
503 void VCLXAccessibleList::HandleChangedItemList()
505 m_aAccessibleChildren.clear();
506 NotifyAccessibleEvent (
507 AccessibleEventId::INVALIDATE_ALL_CHILDREN,
508 Any(), Any());
511 // XAccessible
513 Reference<XAccessibleContext> SAL_CALL
514 VCLXAccessibleList::getAccessibleContext()
516 return this;
520 // XAccessibleContext
522 sal_Int64 SAL_CALL VCLXAccessibleList::getAccessibleChildCount()
524 SolarMutexGuard aSolarGuard;
525 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
526 return implGetAccessibleChildCount();
529 sal_Int64 VCLXAccessibleList::implGetAccessibleChildCount()
531 sal_Int32 nCount = 0;
532 if ( m_pListBoxHelper )
533 nCount = m_pListBoxHelper->GetEntryCount();
535 return nCount;
538 Reference<XAccessible> SAL_CALL VCLXAccessibleList::getAccessibleChild (sal_Int64 i)
540 SolarMutexGuard aSolarGuard;
541 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
543 if ( i < 0 || i >= getAccessibleChildCount() )
544 throw IndexOutOfBoundsException();
546 Reference< XAccessible > xChild;
547 // search for the child
548 if ( o3tl::make_unsigned(i) >= m_aAccessibleChildren.size() )
549 xChild = CreateChild (i);
550 else
552 xChild = m_aAccessibleChildren[i];
553 if ( !xChild.is() )
554 xChild = CreateChild (i);
556 OSL_ENSURE( xChild.is(), "VCLXAccessibleList::getAccessibleChild: returning empty child!" );
557 return xChild;
560 Reference< XAccessible > SAL_CALL VCLXAccessibleList::getAccessibleParent( )
562 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
564 return m_xParent;
567 sal_Int64 SAL_CALL VCLXAccessibleList::getAccessibleIndexInParent()
569 if (m_nIndexInParent != DEFAULT_INDEX_IN_PARENT)
570 return m_nIndexInParent;
571 else
572 return VCLXAccessibleComponent::getAccessibleIndexInParent();
575 sal_Int16 SAL_CALL VCLXAccessibleList::getAccessibleRole()
577 return AccessibleRole::LIST;
580 // XServiceInfo
581 OUString VCLXAccessibleList::getImplementationName()
583 return "com.sun.star.comp.toolkit.AccessibleList";
586 Sequence< OUString > VCLXAccessibleList::getSupportedServiceNames()
588 return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
589 Sequence<OUString>{"com.sun.star.accessibility.AccessibleList"});
592 void VCLXAccessibleList::UpdateVisibleLineCount()
594 if ( m_pListBoxHelper )
596 if ( (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
597 m_nVisibleLineCount = m_pListBoxHelper->GetDisplayLineCount();
598 else
600 sal_uInt16 nCols = 0,
601 nLines = 0;
602 m_pListBoxHelper->GetMaxVisColumnsAndLines (nCols, nLines);
603 m_nVisibleLineCount = nLines;
608 void VCLXAccessibleList::UpdateEntryRange_Impl()
610 SolarMutexGuard aSolarGuard;
611 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
613 sal_Int32 nTop = m_nLastTopEntry;
615 if ( m_pListBoxHelper )
616 nTop = m_pListBoxHelper->GetTopEntry();
617 if ( nTop != m_nLastTopEntry )
619 UpdateVisibleLineCount();
620 sal_Int32 nBegin = std::min( m_nLastTopEntry, nTop );
621 sal_Int32 nEnd = std::max( m_nLastTopEntry + m_nVisibleLineCount, nTop + m_nVisibleLineCount );
622 for (sal_Int32 i = nBegin; (i <= nEnd); ++i)
624 bool bVisible = ( i >= nTop && i < ( nTop + m_nVisibleLineCount ) );
625 Reference< XAccessible > xHold;
626 if ( o3tl::make_unsigned(i) < m_aAccessibleChildren.size() )
627 xHold = m_aAccessibleChildren[i];
628 else if ( bVisible )
629 xHold = CreateChild(i);
631 if ( xHold.is() )
632 static_cast< VCLXAccessibleListItem* >( xHold.get() )->SetVisible( m_bVisible && bVisible );
636 m_nLastTopEntry = nTop;
639 bool VCLXAccessibleList::checkEntrySelected(sal_Int32 _nPos,Any& _rNewValue,Reference< XAccessible >& _rxNewAcc)
641 OSL_ENSURE(m_pListBoxHelper,"Helper is not valid!");
642 bool bNowSelected = false;
643 if ( m_pListBoxHelper )
645 bNowSelected = m_pListBoxHelper->IsEntryPosSelected (_nPos);
646 if ( bNowSelected )
648 _rxNewAcc = CreateChild(_nPos);
649 _rNewValue <<= _rxNewAcc;
652 return bNowSelected;
656 void VCLXAccessibleList::UpdateSelection_Impl(sal_Int32)
658 uno::Any aOldValue, aNewValue;
661 SolarMutexGuard aSolarGuard;
662 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
663 Reference< XAccessible > xNewAcc;
665 if ( m_pListBoxHelper )
667 sal_Int32 i=0;
668 m_nCurSelectedPos = LISTBOX_ENTRY_NOTFOUND;
669 for (const Reference<XAccessible>& rxChild : m_aAccessibleChildren )
671 if (rxChild.is())
673 VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >( rxChild.get() );
674 // Retrieve the item's index from the list entry.
675 bool bNowSelected = m_pListBoxHelper->IsEntryPosSelected (i);
676 if (bNowSelected)
677 m_nCurSelectedPos = i;
679 if ( bNowSelected && !pItem->IsSelected() )
681 xNewAcc = rxChild;
682 aNewValue <<= xNewAcc;
684 else if ( pItem->IsSelected() )
685 m_nLastSelectedPos = i;
687 pItem->SetSelected( bNowSelected );
689 else
690 { // it could happen that a child was not created before
691 checkEntrySelected(i,aNewValue,xNewAcc);
693 ++i;
695 const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
696 if ( i < nCount ) // here we have to check the if any other listbox entry is selected
698 for (; i < nCount && !checkEntrySelected(i,aNewValue,xNewAcc) ;++i )
701 if ( xNewAcc.is() && GetWindow()->HasFocus() )
703 if ( m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND )
704 aOldValue <<= getAccessibleChild( m_nLastSelectedPos );
705 aNewValue <<= xNewAcc;
707 if (m_pListBoxHelper->IsInDropDown())
709 if ( aNewValue.hasValue() || aOldValue.hasValue() )
710 NotifyAccessibleEvent(
711 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED,
712 aOldValue,
713 aNewValue );
714 //the SELECTION_CHANGED is not necessary
715 //NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
722 // XAccessibleSelection
724 void SAL_CALL VCLXAccessibleList::selectAccessibleChild( sal_Int64 nChildIndex )
726 bool bNotify = false;
729 SolarMutexGuard aSolarGuard;
730 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
732 if ( m_pListBoxHelper )
734 checkSelection_Impl(nChildIndex,*m_pListBoxHelper,false);
736 m_pListBoxHelper->SelectEntryPos( static_cast<sal_uInt16>(nChildIndex) );
737 // call the select handler, don't handle events in this time
738 m_bDisableProcessEvent = true;
739 m_pListBoxHelper->Select();
740 m_bDisableProcessEvent = false;
741 bNotify = true;
745 if ( bNotify )
746 UpdateSelection_Impl();
749 sal_Bool SAL_CALL VCLXAccessibleList::isAccessibleChildSelected( sal_Int64 nChildIndex )
751 SolarMutexGuard aSolarGuard;
752 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
754 bool bRet = false;
755 if ( m_pListBoxHelper )
757 checkSelection_Impl(nChildIndex,*m_pListBoxHelper,false);
759 bRet = m_pListBoxHelper->IsEntryPosSelected( static_cast<sal_uInt16>(nChildIndex) );
761 return bRet;
764 void SAL_CALL VCLXAccessibleList::clearAccessibleSelection( )
766 bool bNotify = false;
769 SolarMutexGuard aSolarGuard;
770 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
772 if ( m_pListBoxHelper )
774 m_pListBoxHelper->SetNoSelection();
775 bNotify = true;
779 if ( bNotify )
780 UpdateSelection_Impl();
783 void SAL_CALL VCLXAccessibleList::selectAllAccessibleChildren( )
785 bool bNotify = false;
788 SolarMutexGuard aSolarGuard;
789 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
791 if ( m_pListBoxHelper )
793 const sal_Int32 nCount = m_pListBoxHelper->GetEntryCount();
794 for ( sal_Int32 i = 0; i < nCount; ++i )
795 m_pListBoxHelper->SelectEntryPos( i );
796 // call the select handler, don't handle events in this time
797 m_bDisableProcessEvent = true;
798 m_pListBoxHelper->Select();
799 m_bDisableProcessEvent = false;
800 bNotify = true;
804 if ( bNotify )
805 UpdateSelection_Impl();
808 sal_Int64 SAL_CALL VCLXAccessibleList::getSelectedAccessibleChildCount( )
810 SolarMutexGuard aSolarGuard;
811 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
813 sal_Int64 nCount = 0;
814 if ( m_pListBoxHelper )
815 nCount = m_pListBoxHelper->GetSelectedEntryCount();
816 return nCount;
819 Reference< XAccessible > SAL_CALL VCLXAccessibleList::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex )
821 SolarMutexGuard aSolarGuard;
822 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
824 if ( m_pListBoxHelper )
826 checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,true);
827 return getAccessibleChild( m_pListBoxHelper->GetSelectedEntryPos( static_cast<sal_uInt16>(nSelectedChildIndex) ) );
830 return nullptr;
833 void SAL_CALL VCLXAccessibleList::deselectAccessibleChild( sal_Int64 nSelectedChildIndex )
835 bool bNotify = false;
838 SolarMutexGuard aSolarGuard;
839 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
841 if ( m_pListBoxHelper )
843 checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,false);
845 m_pListBoxHelper->SelectEntryPos( static_cast<sal_uInt16>(nSelectedChildIndex), false );
846 // call the select handler, don't handle events in this time
847 m_bDisableProcessEvent = true;
848 m_pListBoxHelper->Select();
849 m_bDisableProcessEvent = false;
850 bNotify = true;
854 if ( bNotify )
855 UpdateSelection_Impl();
858 awt::Rectangle VCLXAccessibleList::implGetBounds()
860 awt::Rectangle aBounds ( 0, 0, 0, 0 );
861 if ( m_pListBoxHelper
862 && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
864 if ( m_pListBoxHelper->IsInDropDown() )
865 aBounds = AWTRectangle(m_pListBoxHelper->GetDropDownPosSizePixel());
867 else
869 // a list has the same bounds as his parent but starts at (0,0)
870 aBounds = VCLXAccessibleComponent::implGetBounds();
871 aBounds.X = 0;
872 aBounds.Y = 0;
873 if ( m_aBoxType == COMBOBOX )
875 VclPtr< ComboBox > pBox = GetAs< ComboBox >();
876 if ( pBox )
878 Size aSize = pBox->GetSubEdit()->GetSizePixel();
879 aBounds.Y += aSize.Height();
880 aBounds.Height -= aSize.Height();
884 return aBounds;
888 awt::Point VCLXAccessibleList::getLocationOnScreen( )
890 SolarMutexGuard aSolarGuard;
891 ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() );
893 awt::Point aPos;
894 if ( m_pListBoxHelper
895 && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN )
897 if ( m_pListBoxHelper->IsInDropDown() )
898 aPos = AWTPoint(m_pListBoxHelper->GetDropDownPosSizePixel().TopLeft());
900 else
902 aPos = VCLXAccessibleComponent::getLocationOnScreen();
903 if ( m_aBoxType == COMBOBOX )
905 VclPtr< ComboBox > pBox = GetAs< ComboBox >();
906 if ( pBox )
908 aPos.Y += pBox->GetSubEdit()->GetSizePixel().Height();
912 return aPos;
916 bool VCLXAccessibleList::IsInDropDown() const
918 return m_pListBoxHelper->IsInDropDown();
922 void VCLXAccessibleList::HandleDropOpen()
924 if ( !m_bDisableProcessEvent )
925 UpdateSelection_Impl();
926 if (m_nCurSelectedPos != LISTBOX_ENTRY_NOTFOUND &&
927 m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND)
929 Reference< XAccessible > xChild = getAccessibleChild(m_nCurSelectedPos);
930 if(xChild.is())
932 uno::Any aNewValue;
933 aNewValue <<= xChild;
934 NotifyAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, uno::Any(), aNewValue );
939 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */