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/sequence.hxx>
31 #include <comphelper/types.hxx>
32 #include <o3tl/safeint.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vcl/toolkit/combobox.hxx>
35 #include <vcl/toolkit/lstbox.hxx>
36 #include <vcl/unohelp.hxx>
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
;
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(vcl::Window
* pWindow
, BoxType aBoxType
,
57 const Reference
< XAccessible
>& _xParent
)
58 : ImplInheritanceHelper (pWindow
),
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();
111 m_pListBoxHelper
.reset();
114 void VCLXAccessibleList::disposeChildren()
116 // Dispose all items in the list.
117 for (rtl::Reference
<VCLXAccessibleListItem
>& rxChild
: m_aAccessibleChildren
)
123 m_aAccessibleChildren
.clear();
127 void VCLXAccessibleList::FillAccessibleStateSet (sal_Int64
& rStateSet
)
129 SolarMutexGuard aSolarGuard
;
131 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet
);
132 // check if our list should be visible
133 if ( m_pListBoxHelper
134 && (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
135 && !m_pListBoxHelper
->IsInDropDown() )
137 rStateSet
&= ~AccessibleStateType::VISIBLE
;
138 rStateSet
&= ~AccessibleStateType::SHOWING
;
142 // Both the combo box and list box are handled identical in the
143 // following but for some reason they don't have a common interface for
145 if ( m_pListBoxHelper
)
147 if ( m_pListBoxHelper
->IsMultiSelectionEnabled() )
148 rStateSet
|= AccessibleStateType::MULTI_SELECTABLE
;
149 rStateSet
|= AccessibleStateType::FOCUSABLE
;
150 // All children are transient.
151 rStateSet
|= AccessibleStateType::MANAGES_DESCENDANTS
;
155 void VCLXAccessibleList::notifyVisibleStates(bool _bSetNew
)
157 m_bVisible
= _bSetNew
;
158 Any aOldValue
, aNewValue
;
159 (_bSetNew
? aNewValue
: aOldValue
) <<= AccessibleStateType::VISIBLE
;
160 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED
, aOldValue
, aNewValue
);
161 (_bSetNew
? aNewValue
: aOldValue
) <<= AccessibleStateType::SHOWING
;
162 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED
, aOldValue
, aNewValue
);
164 auto aIter
= m_aAccessibleChildren
.begin();
165 UpdateVisibleLineCount();
166 // adjust the index inside the VCLXAccessibleListItem
167 for ( ; aIter
!= m_aAccessibleChildren
.end(); )
169 rtl::Reference
<VCLXAccessibleListItem
> xChild
= *aIter
;
172 aIter
= m_aAccessibleChildren
.erase(aIter
);
176 const sal_Int32 nTopEntry
= m_pListBoxHelper
? m_pListBoxHelper
->GetTopEntry() : 0;
177 const sal_Int32 nPos
= static_cast<sal_Int32
>(aIter
- m_aAccessibleChildren
.begin());
178 bool bVisible
= ( nPos
>=nTopEntry
&& nPos
<( nTopEntry
+ m_nVisibleLineCount
) );
179 xChild
->SetVisible(m_bVisible
&& bVisible
);
186 void VCLXAccessibleList::UpdateSelection_Acc (std::u16string_view
/*sTextOfSelectedItem*/, bool b_IsDropDownList
)
188 if ( m_aBoxType
!= COMBOBOX
)
191 /* FIXME: is there something missing here? nIndex is unused. Looks like
192 * copy-paste from VCLXAccessibleList::UpdateSelection() */
193 // VclPtr< ComboBox > pBox = GetAs< ComboBox >();
196 // // Find the index of the selected item inside the VCL control...
197 // sal_Int32 nIndex = pBox->GetEntryPos(sTextOfSelectedItem);
198 // // ...and then find the associated accessibility object.
199 // if ( nIndex == LISTBOX_ENTRY_NOTFOUND )
201 UpdateSelection_Impl_Acc(b_IsDropDownList
);
206 void VCLXAccessibleList::UpdateSelection_Impl_Acc(bool bHasDropDownList
)
208 uno::Any aOldValue
, aNewValue
;
211 SolarMutexGuard aSolarGuard
;
212 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
213 Reference
< XAccessible
> xNewAcc
;
214 if ( m_pListBoxHelper
)
217 m_nCurSelectedPos
= LISTBOX_ENTRY_NOTFOUND
;
218 for (const rtl::Reference
<VCLXAccessibleListItem
>& rxChild
: m_aAccessibleChildren
)
222 // Retrieve the item's index from the list entry.
223 bool bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected (i
);
225 m_nCurSelectedPos
= i
;
227 if (bNowSelected
&& !rxChild
->IsSelected())
230 aNewValue
<<= xNewAcc
;
232 else if (rxChild
->IsSelected())
233 m_nLastSelectedPos
= i
;
235 rxChild
->SetSelected(bNowSelected
);
238 { // it could happen that a child was not created before
239 checkEntrySelected(i
,aNewValue
,xNewAcc
);
243 const sal_Int32 nCount
= m_pListBoxHelper
->GetEntryCount();
244 if ( i
< nCount
) // here we have to check the if any other listbox entry is selected
246 for (; i
< nCount
&& !checkEntrySelected(i
,aNewValue
,xNewAcc
) ;++i
)
249 if ( xNewAcc
.is() && GetWindow()->HasFocus() )
251 if ( m_nLastSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
)
252 aOldValue
<<= getAccessibleChild( m_nLastSelectedPos
);
253 aNewValue
<<= xNewAcc
;
258 // since an active descendant is the UI element with keyboard focus, only send
259 // ACTIVE_DESCENDANT_CHANGED if the listbox/combobox has focus
260 vcl::Window
* pWindow
= GetWindow();
262 const bool bFocused
= pWindow
->HasChildPathFocus();
264 if (m_aBoxType
== COMBOBOX
)
266 //VCLXAccessibleDropDownComboBox
267 //when in list is dropped down, xText = NULL
268 if (bHasDropDownList
&& m_pListBoxHelper
&& m_pListBoxHelper
->IsInDropDown())
270 if ( aNewValue
.hasValue() || aOldValue
.hasValue() )
274 NotifyAccessibleEvent(
275 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
280 NotifyListItem(aNewValue
);
285 //VCLXAccessibleComboBox
286 NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED
, uno::Any(), uno::Any() );
289 else if (m_aBoxType
== LISTBOX
)
291 if ( aNewValue
.hasValue() || aOldValue
.hasValue() )
295 NotifyAccessibleEvent(
296 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
301 NotifyListItem(aNewValue
);
306 void VCLXAccessibleList::NotifyListItem(css::uno::Any
const & val
)
308 Reference
< XAccessible
> xCurItem
;
312 VCLXAccessibleListItem
* pCurItem
= static_cast< VCLXAccessibleListItem
* >(xCurItem
.get());
315 pCurItem
->NotifyAccessibleEvent(AccessibleEventId::SELECTION_CHANGED
,Any(),Any());
320 void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent
& rVclWindowEvent
, bool b_IsDropDownList
)
322 switch ( rVclWindowEvent
.GetId() )
324 case VclEventId::DropdownSelect
:
325 case VclEventId::ListboxSelect
:
326 if ( !m_bDisableProcessEvent
)
327 UpdateSelection_Impl_Acc(b_IsDropDownList
);
329 case VclEventId::WindowGetFocus
:
331 case VclEventId::ControlGetFocus
:
333 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
334 if (m_aBoxType
== COMBOBOX
&& b_IsDropDownList
)
336 //VCLXAccessibleDropDownComboBox
338 else if (m_aBoxType
== LISTBOX
&& b_IsDropDownList
)
341 else if ( m_aBoxType
== LISTBOX
&& !b_IsDropDownList
)
343 if ( m_pListBoxHelper
)
347 sal_Int32 nPos
= m_nCurSelectedPos
; //m_pListBoxHelper->GetSelectedEntryPos();
349 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
350 nPos
= m_pListBoxHelper
->GetTopEntry();
351 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
352 aNewValue
<<= uno::Reference
<XAccessible
>(CreateChild(nPos
));
353 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
366 void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent
& rVclWindowEvent
)
368 // Create a reference to this object to prevent an early release of the
369 // listbox (VclEventId::ObjectDying).
370 Reference
< XAccessible
> xHoldAlive
= this;
372 switch ( rVclWindowEvent
.GetId() )
374 case VclEventId::DropdownOpen
:
375 notifyVisibleStates(true);
377 case VclEventId::DropdownClose
:
378 notifyVisibleStates(false);
380 case VclEventId::ListboxScrolled
:
381 UpdateEntryRange_Impl();
384 // The selection events VclEventId::ComboboxSelect and
385 // VclEventId::ComboboxDeselect are not handled here because here we
386 // have no access to the edit field. Its text is necessary to
387 // identify the currently selected item.
389 case VclEventId::ObjectDying
:
393 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
397 case VclEventId::ListboxItemRemoved
:
398 case VclEventId::ComboboxItemRemoved
:
399 case VclEventId::ListboxItemAdded
:
400 case VclEventId::ComboboxItemAdded
:
401 HandleChangedItemList();
403 case VclEventId::ControlGetFocus
:
405 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
406 // Added by IBM Symphony Acc team to handle the list item focus when List control get focus
407 bool b_IsDropDownList
= true;
408 if (m_pListBoxHelper
)
409 b_IsDropDownList
= ((m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
);
410 if ( m_aBoxType
== LISTBOX
&& !b_IsDropDownList
)
412 if ( m_pListBoxHelper
)
416 sal_Int32 nPos
= m_nCurSelectedPos
;
418 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
419 nPos
= m_pListBoxHelper
->GetTopEntry();
420 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
421 aNewValue
<<= Reference
<XAccessible
>(CreateChild(nPos
));
422 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
431 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
435 void VCLXAccessibleList::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper
& rRelationSet
)
437 VclPtr
< ListBox
> pBox
= GetAs
< ListBox
>();
438 if( m_aBoxType
== LISTBOX
)
440 if (m_pListBoxHelper
&& (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) != WB_DROPDOWN
)
442 uno::Sequence
<uno::Reference
<css::accessibility::XAccessible
>> aSequence
{ pBox
->GetAccessible() };
443 rRelationSet
.AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType_MEMBER_OF
, aSequence
) );
448 VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet
);
453 /** To find out which item is currently selected and to update the SELECTED
454 state of the associated accessibility objects accordingly we exploit the
457 void VCLXAccessibleList::UpdateSelection (std::u16string_view sTextOfSelectedItem
)
459 if ( m_aBoxType
!= COMBOBOX
)
462 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
465 // Find the index of the selected item inside the VCL control...
466 sal_Int32 nIndex
= pBox
->GetEntryPos(sTextOfSelectedItem
);
467 // ...and then find the associated accessibility object.
468 if ( nIndex
== LISTBOX_ENTRY_NOTFOUND
)
470 UpdateSelection_Impl(nIndex
);
475 rtl::Reference
<VCLXAccessibleListItem
> VCLXAccessibleList::CreateChild(sal_Int32 nPos
)
477 rtl::Reference
<VCLXAccessibleListItem
> xChild
;
479 if ( o3tl::make_unsigned(nPos
) >= m_aAccessibleChildren
.size() )
481 m_aAccessibleChildren
.resize(nPos
+ 1);
483 // insert into the container
484 xChild
= new VCLXAccessibleListItem(nPos
, this);
485 m_aAccessibleChildren
[nPos
] = xChild
;
489 xChild
= m_aAccessibleChildren
[nPos
];
490 // check if position is empty and can be used else we have to adjust all entries behind this
493 xChild
= new VCLXAccessibleListItem(nPos
, this);
494 m_aAccessibleChildren
[nPos
] = xChild
;
500 // Just add the SELECTED state.
501 bool bNowSelected
= false;
502 if ( m_pListBoxHelper
)
503 bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected(nPos
);
505 m_nCurSelectedPos
= nPos
;
506 xChild
->SetSelected(bNowSelected
);
508 // Set the child's VISIBLE state.
509 UpdateVisibleLineCount();
510 const sal_Int32 nTopEntry
= m_pListBoxHelper
? m_pListBoxHelper
->GetTopEntry() : 0;
511 bool bVisible
= ( nPos
>=nTopEntry
&& nPos
<( nTopEntry
+ m_nVisibleLineCount
) );
512 xChild
->SetVisible(m_bVisible
&& bVisible
);
519 void VCLXAccessibleList::HandleChangedItemList()
522 NotifyAccessibleEvent (
523 AccessibleEventId::INVALIDATE_ALL_CHILDREN
,
529 Reference
<XAccessibleContext
> SAL_CALL
530 VCLXAccessibleList::getAccessibleContext()
536 // XAccessibleContext
538 sal_Int64 SAL_CALL
VCLXAccessibleList::getAccessibleChildCount()
540 SolarMutexGuard aSolarGuard
;
541 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
542 return implGetAccessibleChildCount();
545 sal_Int64
VCLXAccessibleList::implGetAccessibleChildCount()
547 sal_Int32 nCount
= 0;
548 if ( m_pListBoxHelper
)
549 nCount
= m_pListBoxHelper
->GetEntryCount();
554 Reference
<XAccessible
> SAL_CALL
VCLXAccessibleList::getAccessibleChild (sal_Int64 i
)
556 SolarMutexGuard aSolarGuard
;
557 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
559 if ( i
< 0 || i
>= getAccessibleChildCount() )
560 throw IndexOutOfBoundsException();
562 Reference
< XAccessible
> xChild
;
563 // search for the child
564 if ( o3tl::make_unsigned(i
) >= m_aAccessibleChildren
.size() )
565 xChild
= CreateChild (i
);
568 xChild
= m_aAccessibleChildren
[i
];
570 xChild
= CreateChild (i
);
572 OSL_ENSURE( xChild
.is(), "VCLXAccessibleList::getAccessibleChild: returning empty child!" );
576 Reference
< XAccessible
> SAL_CALL
VCLXAccessibleList::getAccessibleParent( )
578 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
583 sal_Int64 SAL_CALL
VCLXAccessibleList::getAccessibleIndexInParent()
585 if (m_nIndexInParent
!= DEFAULT_INDEX_IN_PARENT
)
586 return m_nIndexInParent
;
588 return VCLXAccessibleComponent::getAccessibleIndexInParent();
591 sal_Int16 SAL_CALL
VCLXAccessibleList::getAccessibleRole()
593 return AccessibleRole::LIST
;
597 OUString
VCLXAccessibleList::getImplementationName()
599 return u
"com.sun.star.comp.toolkit.AccessibleList"_ustr
;
602 Sequence
< OUString
> VCLXAccessibleList::getSupportedServiceNames()
604 return comphelper::concatSequences(VCLXAccessibleComponent::getSupportedServiceNames(),
605 std::initializer_list
<OUString
>{u
"com.sun.star.accessibility.AccessibleList"_ustr
});
608 void VCLXAccessibleList::UpdateVisibleLineCount()
610 if ( m_pListBoxHelper
)
612 if ( (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
)
613 m_nVisibleLineCount
= m_pListBoxHelper
->GetDisplayLineCount();
616 sal_uInt16 nCols
= 0,
618 m_pListBoxHelper
->GetMaxVisColumnsAndLines (nCols
, nLines
);
619 m_nVisibleLineCount
= nLines
;
624 void VCLXAccessibleList::UpdateEntryRange_Impl()
626 SolarMutexGuard aSolarGuard
;
627 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
629 sal_Int32 nTop
= m_nLastTopEntry
;
631 if ( m_pListBoxHelper
)
632 nTop
= m_pListBoxHelper
->GetTopEntry();
633 if ( nTop
!= m_nLastTopEntry
)
635 UpdateVisibleLineCount();
636 sal_Int32 nBegin
= std::min( m_nLastTopEntry
, nTop
);
637 sal_Int32 nEnd
= std::max( m_nLastTopEntry
+ m_nVisibleLineCount
, nTop
+ m_nVisibleLineCount
);
638 for (sal_Int32 i
= nBegin
; (i
<= nEnd
); ++i
)
640 bool bVisible
= ( i
>= nTop
&& i
< ( nTop
+ m_nVisibleLineCount
) );
641 rtl::Reference
<VCLXAccessibleListItem
> xChild
;
642 if ( o3tl::make_unsigned(i
) < m_aAccessibleChildren
.size() )
643 xChild
= m_aAccessibleChildren
[i
];
645 xChild
= CreateChild(i
);
648 xChild
->SetVisible(m_bVisible
&& bVisible
);
652 m_nLastTopEntry
= nTop
;
655 bool VCLXAccessibleList::checkEntrySelected(sal_Int32 _nPos
,Any
& _rNewValue
,Reference
< XAccessible
>& _rxNewAcc
)
657 OSL_ENSURE(m_pListBoxHelper
,"Helper is not valid!");
658 bool bNowSelected
= false;
659 if ( m_pListBoxHelper
)
661 bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected (_nPos
);
664 _rxNewAcc
= CreateChild(_nPos
);
665 _rNewValue
<<= _rxNewAcc
;
672 void VCLXAccessibleList::UpdateSelection_Impl(sal_Int32
)
674 uno::Any aOldValue
, aNewValue
;
677 SolarMutexGuard aSolarGuard
;
678 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
679 Reference
< XAccessible
> xNewAcc
;
681 if ( m_pListBoxHelper
)
684 m_nCurSelectedPos
= LISTBOX_ENTRY_NOTFOUND
;
685 for (const rtl::Reference
<VCLXAccessibleListItem
>& rxChild
: m_aAccessibleChildren
)
689 // Retrieve the item's index from the list entry.
690 bool bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected (i
);
692 m_nCurSelectedPos
= i
;
694 if (bNowSelected
&& !rxChild
->IsSelected())
697 aNewValue
<<= xNewAcc
;
699 else if (rxChild
->IsSelected())
700 m_nLastSelectedPos
= i
;
702 rxChild
->SetSelected(bNowSelected
);
705 { // it could happen that a child was not created before
706 checkEntrySelected(i
,aNewValue
,xNewAcc
);
710 const sal_Int32 nCount
= m_pListBoxHelper
->GetEntryCount();
711 if ( i
< nCount
) // here we have to check the if any other listbox entry is selected
713 for (; i
< nCount
&& !checkEntrySelected(i
,aNewValue
,xNewAcc
) ;++i
)
716 if ( xNewAcc
.is() && GetWindow()->HasFocus() )
718 if ( m_nLastSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
)
719 aOldValue
<<= getAccessibleChild( m_nLastSelectedPos
);
720 aNewValue
<<= xNewAcc
;
722 if (m_pListBoxHelper
->IsInDropDown())
724 if ( aNewValue
.hasValue() || aOldValue
.hasValue() )
725 NotifyAccessibleEvent(
726 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
729 //the SELECTION_CHANGED is not necessary
730 //NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
737 // XAccessibleSelection
739 void SAL_CALL
VCLXAccessibleList::selectAccessibleChild( sal_Int64 nChildIndex
)
741 bool bNotify
= false;
744 SolarMutexGuard aSolarGuard
;
745 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
747 if ( m_pListBoxHelper
)
749 checkSelection_Impl(nChildIndex
,*m_pListBoxHelper
,false);
751 m_pListBoxHelper
->SelectEntryPos( static_cast<sal_uInt16
>(nChildIndex
) );
752 // call the select handler, don't handle events in this time
753 m_bDisableProcessEvent
= true;
754 m_pListBoxHelper
->Select();
755 m_bDisableProcessEvent
= false;
761 UpdateSelection_Impl();
764 sal_Bool SAL_CALL
VCLXAccessibleList::isAccessibleChildSelected( sal_Int64 nChildIndex
)
766 SolarMutexGuard aSolarGuard
;
767 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
770 if ( m_pListBoxHelper
)
772 checkSelection_Impl(nChildIndex
,*m_pListBoxHelper
,false);
774 bRet
= m_pListBoxHelper
->IsEntryPosSelected( static_cast<sal_uInt16
>(nChildIndex
) );
779 void SAL_CALL
VCLXAccessibleList::clearAccessibleSelection( )
781 bool bNotify
= false;
784 SolarMutexGuard aSolarGuard
;
785 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
787 if ( m_pListBoxHelper
)
789 m_pListBoxHelper
->SetNoSelection();
795 UpdateSelection_Impl();
798 void SAL_CALL
VCLXAccessibleList::selectAllAccessibleChildren( )
800 bool bNotify
= false;
803 SolarMutexGuard aSolarGuard
;
804 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
806 if ( m_pListBoxHelper
)
808 const sal_Int32 nCount
= m_pListBoxHelper
->GetEntryCount();
809 for ( sal_Int32 i
= 0; i
< nCount
; ++i
)
810 m_pListBoxHelper
->SelectEntryPos( i
);
811 // call the select handler, don't handle events in this time
812 m_bDisableProcessEvent
= true;
813 m_pListBoxHelper
->Select();
814 m_bDisableProcessEvent
= false;
820 UpdateSelection_Impl();
823 sal_Int64 SAL_CALL
VCLXAccessibleList::getSelectedAccessibleChildCount( )
825 SolarMutexGuard aSolarGuard
;
826 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
828 sal_Int64 nCount
= 0;
829 if ( m_pListBoxHelper
)
830 nCount
= m_pListBoxHelper
->GetSelectedEntryCount();
834 Reference
< XAccessible
> SAL_CALL
VCLXAccessibleList::getSelectedAccessibleChild( sal_Int64 nSelectedChildIndex
)
836 SolarMutexGuard aSolarGuard
;
837 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
839 if ( m_pListBoxHelper
)
841 checkSelection_Impl(nSelectedChildIndex
,*m_pListBoxHelper
,true);
842 return getAccessibleChild( m_pListBoxHelper
->GetSelectedEntryPos( static_cast<sal_uInt16
>(nSelectedChildIndex
) ) );
848 void SAL_CALL
VCLXAccessibleList::deselectAccessibleChild( sal_Int64 nSelectedChildIndex
)
850 bool bNotify
= false;
853 SolarMutexGuard aSolarGuard
;
854 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
856 if ( m_pListBoxHelper
)
858 checkSelection_Impl(nSelectedChildIndex
,*m_pListBoxHelper
,false);
860 m_pListBoxHelper
->SelectEntryPos( static_cast<sal_uInt16
>(nSelectedChildIndex
), false );
861 // call the select handler, don't handle events in this time
862 m_bDisableProcessEvent
= true;
863 m_pListBoxHelper
->Select();
864 m_bDisableProcessEvent
= false;
870 UpdateSelection_Impl();
873 awt::Rectangle
VCLXAccessibleList::implGetBounds()
875 awt::Rectangle
aBounds ( 0, 0, 0, 0 );
876 if ( m_pListBoxHelper
877 && (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
)
879 if ( m_pListBoxHelper
->IsInDropDown() )
880 aBounds
= vcl::unohelper::ConvertToAWTRect(m_pListBoxHelper
->GetDropDownPosSizePixel());
884 // a list has the same bounds as his parent but starts at (0,0)
885 aBounds
= VCLXAccessibleComponent::implGetBounds();
888 if ( m_aBoxType
== COMBOBOX
)
890 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
893 Size aSize
= pBox
->GetSubEdit()->GetSizePixel();
894 aBounds
.Y
+= aSize
.Height();
895 aBounds
.Height
-= aSize
.Height();
903 awt::Point
VCLXAccessibleList::getLocationOnScreen( )
905 SolarMutexGuard aSolarGuard
;
906 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
909 if ( m_pListBoxHelper
910 && (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
)
912 if ( m_pListBoxHelper
->IsInDropDown() )
913 aPos
= vcl::unohelper::ConvertToAWTPoint(
914 m_pListBoxHelper
->GetDropDownPosSizePixel().TopLeft());
918 aPos
= VCLXAccessibleComponent::getLocationOnScreen();
919 if ( m_aBoxType
== COMBOBOX
)
921 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
924 aPos
.Y
+= pBox
->GetSubEdit()->GetSizePixel().Height();
932 bool VCLXAccessibleList::IsInDropDown() const
934 return m_pListBoxHelper
->IsInDropDown();
938 void VCLXAccessibleList::HandleDropOpen()
940 if ( !m_bDisableProcessEvent
)
941 UpdateSelection_Impl();
942 if (m_nCurSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
&&
943 m_nLastSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
)
945 Reference
< XAccessible
> xChild
= getAccessibleChild(m_nCurSelectedPos
);
949 aNewValue
<<= xChild
;
950 NotifyAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, uno::Any(), aNewValue
);
955 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */