1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
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 ),
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
76 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
78 m_pListBoxHelper
.reset( new VCLListBoxHelper
<ComboBox
> (*pBox
) );
84 VclPtr
< ListBox
> pBox
= GetAs
< ListBox
>();
86 m_pListBoxHelper
.reset( new VCLListBoxHelper
<ListBox
> (*pBox
) );
90 UpdateVisibleLineCount();
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
;
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
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
;
165 aIter
= m_aAccessibleChildren
.erase(aIter
);
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
);
180 void VCLXAccessibleList::UpdateSelection_Acc (std::u16string_view
/*sTextOfSelectedItem*/, bool b_IsDropDownList
)
182 if ( m_aBoxType
!= COMBOBOX
)
185 /* FIXME: is there something missing here? nIndex is unused. Looks like
186 * copy-paste from VCLXAccessibleList::UpdateSelection() */
187 // VclPtr< ComboBox > pBox = GetAs< ComboBox >();
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 )
195 UpdateSelection_Impl_Acc(b_IsDropDownList
);
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
)
211 m_nCurSelectedPos
= LISTBOX_ENTRY_NOTFOUND
;
212 for (const Reference
<XAccessible
>& rxChild
: m_aAccessibleChildren
)
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
);
220 m_nCurSelectedPos
= i
;
222 if ( bNowSelected
&& !pItem
->IsSelected() )
225 aNewValue
<<= xNewAcc
;
227 else if ( pItem
->IsSelected() )
228 m_nLastSelectedPos
= i
;
230 pItem
->SetSelected( bNowSelected
);
233 { // it could happen that a child was not created before
234 checkEntrySelected(i
,aNewValue
,xNewAcc
);
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
,
266 NotifyListItem(aNewValue
);
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
,
284 NotifyListItem(aNewValue
);
289 void VCLXAccessibleList::NotifyListItem(css::uno::Any
const & val
)
291 Reference
< XAccessible
> xCurItem
;
295 VCLXAccessibleListItem
* pCurItem
= static_cast< VCLXAccessibleListItem
* >(xCurItem
.get());
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
);
312 case VclEventId::WindowGetFocus
:
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
)
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
,
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);
360 case VclEventId::DropdownClose
:
361 notifyVisibleStates(false);
363 case VclEventId::ListboxScrolled
:
364 UpdateEntryRange_Impl();
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
:
376 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
380 case VclEventId::ListboxItemRemoved
:
381 case VclEventId::ComboboxItemRemoved
:
382 case VclEventId::ListboxItemAdded
:
383 case VclEventId::ComboboxItemAdded
:
384 HandleChangedItemList();
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
)
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
,
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
) );
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
440 void VCLXAccessibleList::UpdateSelection (std::u16string_view sTextOfSelectedItem
)
442 if ( m_aBoxType
!= COMBOBOX
)
445 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
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
)
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
;
472 xChild
= m_aAccessibleChildren
[nPos
];
473 // check if position is empty and can be used else we have to adjust all entries behind this
476 xChild
= new VCLXAccessibleListItem(nPos
, this);
477 m_aAccessibleChildren
[nPos
] = xChild
;
483 // Just add the SELECTED state.
484 bool bNowSelected
= false;
485 if ( m_pListBoxHelper
)
486 bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected(nPos
);
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
);
503 void VCLXAccessibleList::HandleChangedItemList()
505 m_aAccessibleChildren
.clear();
506 NotifyAccessibleEvent (
507 AccessibleEventId::INVALIDATE_ALL_CHILDREN
,
513 Reference
<XAccessibleContext
> SAL_CALL
514 VCLXAccessibleList::getAccessibleContext()
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();
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
);
552 xChild
= m_aAccessibleChildren
[i
];
554 xChild
= CreateChild (i
);
556 OSL_ENSURE( xChild
.is(), "VCLXAccessibleList::getAccessibleChild: returning empty child!" );
560 Reference
< XAccessible
> SAL_CALL
VCLXAccessibleList::getAccessibleParent( )
562 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
567 sal_Int64 SAL_CALL
VCLXAccessibleList::getAccessibleIndexInParent()
569 if (m_nIndexInParent
!= DEFAULT_INDEX_IN_PARENT
)
570 return m_nIndexInParent
;
572 return VCLXAccessibleComponent::getAccessibleIndexInParent();
575 sal_Int16 SAL_CALL
VCLXAccessibleList::getAccessibleRole()
577 return AccessibleRole::LIST
;
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();
600 sal_uInt16 nCols
= 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
];
629 xHold
= CreateChild(i
);
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
);
648 _rxNewAcc
= CreateChild(_nPos
);
649 _rNewValue
<<= _rxNewAcc
;
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
)
668 m_nCurSelectedPos
= LISTBOX_ENTRY_NOTFOUND
;
669 for (const Reference
<XAccessible
>& rxChild
: m_aAccessibleChildren
)
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
);
677 m_nCurSelectedPos
= i
;
679 if ( bNowSelected
&& !pItem
->IsSelected() )
682 aNewValue
<<= xNewAcc
;
684 else if ( pItem
->IsSelected() )
685 m_nLastSelectedPos
= i
;
687 pItem
->SetSelected( bNowSelected
);
690 { // it could happen that a child was not created before
691 checkEntrySelected(i
,aNewValue
,xNewAcc
);
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
,
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;
746 UpdateSelection_Impl();
749 sal_Bool SAL_CALL
VCLXAccessibleList::isAccessibleChildSelected( sal_Int64 nChildIndex
)
751 SolarMutexGuard aSolarGuard
;
752 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
755 if ( m_pListBoxHelper
)
757 checkSelection_Impl(nChildIndex
,*m_pListBoxHelper
,false);
759 bRet
= m_pListBoxHelper
->IsEntryPosSelected( static_cast<sal_uInt16
>(nChildIndex
) );
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();
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;
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();
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
) ) );
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;
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());
869 // a list has the same bounds as his parent but starts at (0,0)
870 aBounds
= VCLXAccessibleComponent::implGetBounds();
873 if ( m_aBoxType
== COMBOBOX
)
875 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
878 Size aSize
= pBox
->GetSubEdit()->GetSizePixel();
879 aBounds
.Y
+= aSize
.Height();
880 aBounds
.Height
-= aSize
.Height();
888 awt::Point
VCLXAccessibleList::getLocationOnScreen( )
890 SolarMutexGuard aSolarGuard
;
891 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
894 if ( m_pListBoxHelper
895 && (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
)
897 if ( m_pListBoxHelper
->IsInDropDown() )
898 aPos
= AWTPoint(m_pListBoxHelper
->GetDropDownPosSizePixel().TopLeft());
902 aPos
= VCLXAccessibleComponent::getLocationOnScreen();
903 if ( m_aBoxType
== COMBOBOX
)
905 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
908 aPos
.Y
+= pBox
->GetSubEdit()->GetSizePixel().Height();
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
);
933 aNewValue
<<= xChild
;
934 NotifyAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, uno::Any(), aNewValue
);
939 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */