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 <accessibility/standard/vclxaccessiblelist.hxx>
21 #include <accessibility/standard/vclxaccessiblelistitem.hxx>
22 #include <accessibility/helper/listboxhelper.hxx>
24 #include <unotools/accessiblerelationsethelper.hxx>
25 #include <unotools/accessiblestatesethelper.hxx>
26 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
27 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
29 #include <com/sun/star/accessibility/AccessibleRole.hpp>
30 #include <vcl/svapp.hxx>
31 #include <vcl/combobox.hxx>
32 #include <vcl/lstbox.hxx>
33 #include <toolkit/helper/convert.hxx>
35 using namespace ::com::sun::star
;
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::lang
;
38 using namespace ::com::sun::star::beans
;
39 using namespace ::com::sun::star::accessibility
;
40 using namespace ::accessibility
;
44 void checkSelection_Impl( sal_Int32 _nIndex
, const IComboListBoxHelper
& _rListBox
, bool bSelected
)
45 throw (::com::sun::star::lang::IndexOutOfBoundsException
)
47 sal_Int32 nCount
= bSelected
? (sal_Int32
)_rListBox
.GetSelectEntryCount()
48 : (sal_Int32
)_rListBox
.GetEntryCount();
49 if ( _nIndex
< 0 || _nIndex
>= nCount
)
50 throw ::com::sun::star::lang::IndexOutOfBoundsException();
54 VCLXAccessibleList::VCLXAccessibleList (VCLXWindow
* pVCLWindow
, BoxType aBoxType
,
55 const Reference
< XAccessible
>& _xParent
)
56 : VCLXAccessibleComponent (pVCLWindow
),
57 m_aBoxType (aBoxType
),
59 m_nVisibleLineCount (0),
60 m_nIndexInParent (DEFAULT_INDEX_IN_PARENT
),
61 m_nLastTopEntry ( 0 ),
62 m_nLastSelectedPos ( LISTBOX_ENTRY_NOTFOUND
),
63 m_bDisableProcessEvent ( false ),
65 m_nCurSelectedPos ( LISTBOX_ENTRY_NOTFOUND
),
66 m_xParent ( _xParent
)
68 // Because combo boxes and list boxes don't have a common interface for
69 // methods with identical signature we have to write down twice the
75 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
77 m_pListBoxHelper
= new VCLListBoxHelper
<ComboBox
> (*pBox
);
83 VclPtr
< ListBox
> pBox
= GetAs
< ListBox
>();
85 m_pListBoxHelper
= new VCLListBoxHelper
<ListBox
> (*pBox
);
89 UpdateVisibleLineCount();
92 m_nCurSelectedPos
=m_pListBoxHelper
->GetSelectEntryPos();
94 sal_uInt16 nCount
= static_cast<sal_uInt16
>(getAccessibleChildCount());
95 m_aAccessibleChildren
.reserve(nCount
);
99 VCLXAccessibleList::~VCLXAccessibleList()
101 delete m_pListBoxHelper
;
105 void VCLXAccessibleList::SetIndexInParent (sal_Int32 nIndex
)
107 m_nIndexInParent
= nIndex
;
111 void SAL_CALL
VCLXAccessibleList::disposing()
113 VCLXAccessibleComponent::disposing();
115 // Dispose all items in the list.
118 delete m_pListBoxHelper
;
119 m_pListBoxHelper
= NULL
;
123 void VCLXAccessibleList::clearItems()
125 // Clear the list itself and delete all the rest.
126 ListItems().swap(m_aAccessibleChildren
); // clear and minimize
130 void VCLXAccessibleList::FillAccessibleStateSet (utl::AccessibleStateSetHelper
& rStateSet
)
132 SolarMutexGuard aSolarGuard
;
134 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet
);
135 // check if our list should be visible
136 if ( m_pListBoxHelper
137 && (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
138 && !m_pListBoxHelper
->IsInDropDown() )
140 rStateSet
.RemoveState (AccessibleStateType::VISIBLE
);
141 rStateSet
.RemoveState (AccessibleStateType::SHOWING
);
145 // Both the combo box and list box are handled identical in the
146 // following but for some reason they don't have a common interface for
148 if ( m_pListBoxHelper
)
150 if ( m_pListBoxHelper
->IsMultiSelectionEnabled() )
151 rStateSet
.AddState( AccessibleStateType::MULTI_SELECTABLE
);
152 rStateSet
.AddState (AccessibleStateType::FOCUSABLE
);
153 // All children are transient.
154 rStateSet
.AddState (AccessibleStateType::MANAGES_DESCENDANTS
);
158 void VCLXAccessibleList::notifyVisibleStates(bool _bSetNew
)
160 m_bVisible
= _bSetNew
;
161 Any aOldValue
, aNewValue
;
162 (_bSetNew
? aNewValue
: aOldValue
) <<= AccessibleStateType::VISIBLE
;
163 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED
, aOldValue
, aNewValue
);
164 (_bSetNew
? aNewValue
: aOldValue
) <<= AccessibleStateType::SHOWING
;
165 NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED
, aOldValue
, aNewValue
);
167 ListItems::iterator aIter
= m_aAccessibleChildren
.begin();
168 ListItems::iterator aEnd
= m_aAccessibleChildren
.end();
169 UpdateVisibleLineCount();
170 // adjust the index inside the VCLXAccessibleListItem
171 for (;aIter
!= aEnd
; ++aIter
)
173 Reference
< XAccessible
> xHold
= *aIter
;
174 VCLXAccessibleListItem
* pItem
= static_cast<VCLXAccessibleListItem
*>(xHold
.get());
177 sal_uInt16 nTopEntry
= 0;
178 if ( m_pListBoxHelper
)
179 nTopEntry
= m_pListBoxHelper
->GetTopEntry();
180 sal_uInt16 nPos
= (sal_uInt16
)(aIter
- m_aAccessibleChildren
.begin());
181 bool bVisible
= ( nPos
>=nTopEntry
&& nPos
<( nTopEntry
+ m_nVisibleLineCount
) );
182 pItem
->SetVisible( m_bVisible
&& bVisible
);
188 void VCLXAccessibleList::UpdateSelection_Acc (const ::rtl::OUString
& sTextOfSelectedItem
, bool b_IsDropDownList
)
190 if ( m_aBoxType
== COMBOBOX
)
192 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
195 // Find the index of the selected item inside the VCL control...
196 sal_Int32 nIndex
= pBox
->GetEntryPos(sTextOfSelectedItem
);
197 // ...and then find the associated accessibility object.
198 if ( nIndex
== LISTBOX_ENTRY_NOTFOUND
)
200 /* FIXME: is there something missing here? nIndex is unused. Looks
201 * like copy-paste from VCLXAccessibleList::UpdateSelection() */
202 UpdateSelection_Impl_Acc(b_IsDropDownList
);
208 void VCLXAccessibleList::UpdateSelection_Impl_Acc(bool bHasDropDownList
)
210 uno::Any aOldValue
, aNewValue
;
213 SolarMutexGuard aSolarGuard
;
214 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
215 Reference
< XAccessible
> xNewAcc
;
216 if ( m_pListBoxHelper
)
219 m_nCurSelectedPos
= LISTBOX_ENTRY_NOTFOUND
;
220 for ( ListItems::iterator aIter
= m_aAccessibleChildren
.begin();
221 aIter
!= m_aAccessibleChildren
.end(); ++aIter
,++i
)
223 Reference
< XAccessible
> xHold
= *aIter
;
226 VCLXAccessibleListItem
* pItem
= static_cast< VCLXAccessibleListItem
* >( xHold
.get() );
227 // Retrieve the item's index from the list entry.
228 bool bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected (i
);
230 m_nCurSelectedPos
= i
;
232 if ( bNowSelected
&& !pItem
->IsSelected() )
235 aNewValue
<<= xNewAcc
;
237 else if ( pItem
->IsSelected() )
238 m_nLastSelectedPos
= i
;
240 pItem
->SetSelected( bNowSelected
);
243 { // it could happen that a child was not created before
244 checkEntrySelected(i
,aNewValue
,xNewAcc
);
247 sal_uInt16 nCount
= m_pListBoxHelper
->GetEntryCount();
248 if ( i
< nCount
) // here we have to check the if any other listbox entry is selected
250 for (; i
< nCount
&& !checkEntrySelected(i
,aNewValue
,xNewAcc
) ;++i
)
253 if ( xNewAcc
.is() && GetWindow()->HasFocus() )
255 if ( m_nLastSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
)
256 aOldValue
<<= getAccessibleChild( (sal_Int32
)m_nLastSelectedPos
);
257 aNewValue
<<= xNewAcc
;
262 if (m_aBoxType
== COMBOBOX
)
264 //VCLXAccessibleDropDownComboBox
265 //when in list is dropped down, xText = NULL
266 if (bHasDropDownList
&& m_pListBoxHelper
&& m_pListBoxHelper
->IsInDropDown())
268 if ( aNewValue
.hasValue() || aOldValue
.hasValue() )
270 NotifyAccessibleEvent(
271 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
275 NotifyListItem(aNewValue
);
280 //VCLXAccessibleComboBox
281 NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED
, uno::Any(), uno::Any() );
284 else if (m_aBoxType
== LISTBOX
)
286 if ( aNewValue
.hasValue() || aOldValue
.hasValue() )
288 NotifyAccessibleEvent(
289 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
293 NotifyListItem(aNewValue
);
298 void VCLXAccessibleList::NotifyListItem(::com::sun::star::uno::Any
& val
)
300 Reference
< XAccessible
> xCurItem
;
304 VCLXAccessibleListItem
* pCurItem
= static_cast< VCLXAccessibleListItem
* >(xCurItem
.get());
307 pCurItem
->NotifyAccessibleEvent(AccessibleEventId::SELECTION_CHANGED
,Any(),Any());
312 void VCLXAccessibleList::UpdateFocus_Impl_Acc (sal_uInt16 nPos
,bool b_IsDropDownList
)
314 if (!(m_aBoxType
== LISTBOX
&& !b_IsDropDownList
))
318 Reference
<XAccessible
> xChild
= CreateChild(nPos
);
323 m_nCurSelectedPos
= nPos
;
324 uno::Any aOldValue
, aNewValue
;
325 aNewValue
<<= xChild
;
327 NotifyAccessibleEvent(
328 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
334 void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent
& rVclWindowEvent
, bool b_IsDropDownList
)
336 switch ( rVclWindowEvent
.GetId() )
338 case VCLEVENT_DROPDOWN_SELECT
:
339 case VCLEVENT_LISTBOX_SELECT
:
340 if ( !m_bDisableProcessEvent
)
341 UpdateSelection_Impl_Acc(b_IsDropDownList
);
343 case VCLEVENT_LISTBOX_FOCUSITEMCHANGED
:
344 if ( !m_bDisableProcessEvent
)
345 UpdateFocus_Impl_Acc((sal_uInt16
)reinterpret_cast<sal_uIntPtr
>(rVclWindowEvent
.GetData()),b_IsDropDownList
);
347 case VCLEVENT_WINDOW_GETFOCUS
:
349 case VCLEVENT_CONTROL_GETFOCUS
:
351 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
352 if (m_aBoxType
== COMBOBOX
&& b_IsDropDownList
)
354 //VCLXAccessibleDropDownComboBox
356 else if (m_aBoxType
== LISTBOX
&& b_IsDropDownList
)
359 else if ( m_aBoxType
== LISTBOX
&& !b_IsDropDownList
)
361 if ( m_pListBoxHelper
)
365 sal_Int32 nPos
= m_nCurSelectedPos
; //m_pListBoxHelper->GetSelectEntryPos();
367 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
368 nPos
= m_pListBoxHelper
->GetTopEntry();
369 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
370 aNewValue
<<= CreateChild(nPos
);
371 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
384 void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent
& rVclWindowEvent
)
386 // Create a reference to this object to prevent an early release of the
387 // listbox (VCLEVENT_OBJECT_DYING).
388 Reference
< XAccessible
> xTemp
= this;
390 switch ( rVclWindowEvent
.GetId() )
392 case VCLEVENT_DROPDOWN_OPEN
:
393 notifyVisibleStates(true);
395 case VCLEVENT_DROPDOWN_CLOSE
:
396 notifyVisibleStates(false);
398 case VCLEVENT_LISTBOX_SCROLLED
:
399 case VCLEVENT_COMBOBOX_SCROLLED
:
400 UpdateEntryRange_Impl();
403 // The selection events VCLEVENT_COMBOBOX_SELECT and
404 // VCLEVENT_COMBOBOX_DESELECT are not handled here because here we
405 // have no access to the edit field. Its text is necessary to
406 // identify the currently selected item.
408 case VCLEVENT_OBJECT_DYING
:
412 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
416 case VCLEVENT_LISTBOX_ITEMREMOVED
:
417 case VCLEVENT_COMBOBOX_ITEMREMOVED
:
418 HandleChangedItemList (false, reinterpret_cast<sal_IntPtr
>(
419 rVclWindowEvent
.GetData()));
422 case VCLEVENT_LISTBOX_ITEMADDED
:
423 case VCLEVENT_COMBOBOX_ITEMADDED
:
424 HandleChangedItemList (true, reinterpret_cast<sal_IntPtr
>(
425 rVclWindowEvent
.GetData()));
427 case VCLEVENT_CONTROL_GETFOCUS
:
429 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
430 // Added by IBM Symphony Acc team to handle the list item focus when List control get focus
431 bool b_IsDropDownList
= true;
432 if (m_pListBoxHelper
)
433 b_IsDropDownList
= ((m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
);
434 if ( m_aBoxType
== LISTBOX
&& !b_IsDropDownList
)
436 if ( m_pListBoxHelper
)
440 sal_Int32 nPos
= m_nCurSelectedPos
;
442 if ( nPos
== LISTBOX_ENTRY_NOTFOUND
)
443 nPos
= m_pListBoxHelper
->GetTopEntry();
444 if ( nPos
!= LISTBOX_ENTRY_NOTFOUND
)
445 aNewValue
<<= CreateChild(nPos
);
446 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
455 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent
);
459 void VCLXAccessibleList::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper
& rRelationSet
)
461 VclPtr
< ListBox
> pBox
= GetAs
< ListBox
>();
462 if( m_aBoxType
== LISTBOX
)
464 if (m_pListBoxHelper
&& (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) != WB_DROPDOWN
)
466 uno::Sequence
< uno::Reference
< uno::XInterface
> > aSequence(1);
467 aSequence
[0] = pBox
->GetAccessible();
468 rRelationSet
.AddRelation( com::sun::star::accessibility::AccessibleRelation( com::sun::star::accessibility::AccessibleRelationType::MEMBER_OF
, aSequence
) );
473 VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet
);
478 /** To find out which item is currently selected and to update the SELECTED
479 state of the associated accessibility objects accordingly we exploit the
482 void VCLXAccessibleList::UpdateSelection (const OUString
& sTextOfSelectedItem
)
484 if ( m_aBoxType
== COMBOBOX
)
486 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
489 // Find the index of the selected item inside the VCL control...
490 sal_Int32 nIndex
= pBox
->GetEntryPos(sTextOfSelectedItem
);
491 // ...and then find the associated accessibility object.
492 if ( nIndex
== LISTBOX_ENTRY_NOTFOUND
)
494 UpdateSelection_Impl(nIndex
);
501 Reference
<XAccessible
> VCLXAccessibleList::CreateChild (sal_Int32 i
)
503 Reference
<XAccessible
> xChild
;
505 sal_uInt16 nPos
= static_cast<sal_uInt16
>(i
);
506 if ( nPos
>= m_aAccessibleChildren
.size() )
508 m_aAccessibleChildren
.resize(nPos
+ 1);
510 // insert into the container
511 xChild
= new VCLXAccessibleListItem(m_pListBoxHelper
, i
, this);
512 m_aAccessibleChildren
[nPos
] = xChild
;
516 xChild
= m_aAccessibleChildren
[nPos
];
517 // check if position is empty and can be used else we have to adjust all entries behind this
520 xChild
= new VCLXAccessibleListItem(m_pListBoxHelper
, i
, this);
521 m_aAccessibleChildren
[nPos
] = xChild
;
527 // Just add the SELECTED state.
528 bool bNowSelected
= false;
529 if ( m_pListBoxHelper
)
530 bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected ((sal_uInt16
)i
);
532 m_nCurSelectedPos
= sal_uInt16(i
);
533 VCLXAccessibleListItem
* pItem
= static_cast< VCLXAccessibleListItem
* >(xChild
.get());
534 pItem
->SetSelected( bNowSelected
);
536 // Set the child's VISIBLE state.
537 UpdateVisibleLineCount();
538 sal_uInt16 nTopEntry
= 0;
539 if ( m_pListBoxHelper
)
540 nTopEntry
= m_pListBoxHelper
->GetTopEntry();
541 bool bVisible
= ( nPos
>=nTopEntry
&& nPos
<( nTopEntry
+ m_nVisibleLineCount
) );
542 pItem
->SetVisible( m_bVisible
&& bVisible
);
549 void VCLXAccessibleList::HandleChangedItemList (bool /*bItemInserted*/, sal_Int32
/*nIndex*/)
552 NotifyAccessibleEvent (
553 AccessibleEventId::INVALIDATE_ALL_CHILDREN
,
558 IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleList
, VCLXAccessibleComponent
, VCLXAccessibleList_BASE
)
559 IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleList
, VCLXAccessibleComponent
, VCLXAccessibleList_BASE
)
563 Reference
<XAccessibleContext
> SAL_CALL
564 VCLXAccessibleList::getAccessibleContext()
565 throw (RuntimeException
, std::exception
)
571 // XAccessibleContext
573 sal_Int32 SAL_CALL
VCLXAccessibleList::getAccessibleChildCount()
574 throw (RuntimeException
, std::exception
)
576 SolarMutexGuard aSolarGuard
;
577 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
579 sal_Int32 nCount
= 0;
580 if ( m_pListBoxHelper
)
581 nCount
= m_pListBoxHelper
->GetEntryCount();
586 Reference
<XAccessible
> SAL_CALL
VCLXAccessibleList::getAccessibleChild (sal_Int32 i
)
587 throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
589 SolarMutexGuard aSolarGuard
;
590 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
592 if ( i
< 0 || i
>= getAccessibleChildCount() )
593 throw IndexOutOfBoundsException();
595 Reference
< XAccessible
> xChild
;
596 // search for the child
597 if ( i
>= static_cast<sal_Int32
>(m_aAccessibleChildren
.size()) )
598 xChild
= CreateChild (i
);
601 xChild
= m_aAccessibleChildren
[i
];
603 xChild
= CreateChild (i
);
605 OSL_ENSURE( xChild
.is(), "VCLXAccessibleList::getAccessibleChild: returning empty child!" );
609 Reference
< XAccessible
> SAL_CALL
VCLXAccessibleList::getAccessibleParent( )
610 throw (RuntimeException
, std::exception
)
612 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
617 sal_Int32 SAL_CALL
VCLXAccessibleList::getAccessibleIndexInParent()
618 throw (::com::sun::star::uno::RuntimeException
, std::exception
)
620 if (m_nIndexInParent
!= DEFAULT_INDEX_IN_PARENT
)
621 return m_nIndexInParent
;
623 return VCLXAccessibleComponent::getAccessibleIndexInParent();
626 sal_Int16 SAL_CALL
VCLXAccessibleList::getAccessibleRole()
627 throw (RuntimeException
, std::exception
)
629 return AccessibleRole::LIST
;
633 OUString
VCLXAccessibleList::getImplementationName()
634 throw (RuntimeException
, std::exception
)
636 return OUString( "com.sun.star.comp.toolkit.AccessibleList" );
639 Sequence
< OUString
> VCLXAccessibleList::getSupportedServiceNames()
640 throw (RuntimeException
, std::exception
)
642 Sequence
< OUString
> aNames
= VCLXAccessibleComponent::getSupportedServiceNames();
643 sal_Int32 nLength
= aNames
.getLength();
644 aNames
.realloc( nLength
+ 1 );
645 aNames
[nLength
] = "com.sun.star.accessibility.AccessibleList";
649 void VCLXAccessibleList::UpdateVisibleLineCount()
651 if ( m_pListBoxHelper
)
653 if ( (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
)
654 m_nVisibleLineCount
= m_pListBoxHelper
->GetDisplayLineCount();
657 sal_uInt16 nCols
= 0,
659 m_pListBoxHelper
->GetMaxVisColumnsAndLines (nCols
, nLines
);
660 m_nVisibleLineCount
= nLines
;
665 void VCLXAccessibleList::UpdateEntryRange_Impl()
667 SolarMutexGuard aSolarGuard
;
668 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
670 sal_Int32 nTop
= m_nLastTopEntry
;
672 if ( m_pListBoxHelper
)
673 nTop
= m_pListBoxHelper
->GetTopEntry();
674 if ( nTop
!= m_nLastTopEntry
)
676 UpdateVisibleLineCount();
677 sal_Int32 nBegin
= std::min( m_nLastTopEntry
, nTop
);
678 sal_Int32 nEnd
= std::max( m_nLastTopEntry
+ m_nVisibleLineCount
, nTop
+ m_nVisibleLineCount
);
679 for (sal_uInt16 i
= static_cast<sal_uInt16
>(nBegin
); (i
<= static_cast<sal_uInt16
>(nEnd
)); ++i
)
681 bool bVisible
= ( i
>= nTop
&& i
< ( nTop
+ m_nVisibleLineCount
) );
682 Reference
< XAccessible
> xHold
;
683 if ( i
< m_aAccessibleChildren
.size() )
684 xHold
= m_aAccessibleChildren
[i
];
686 xHold
= CreateChild(i
);
689 static_cast< VCLXAccessibleListItem
* >( xHold
.get() )->SetVisible( m_bVisible
&& bVisible
);
693 m_nLastTopEntry
= nTop
;
696 bool VCLXAccessibleList::checkEntrySelected(sal_uInt16 _nPos
,Any
& _rNewValue
,Reference
< XAccessible
>& _rxNewAcc
)
698 OSL_ENSURE(m_pListBoxHelper
,"Helper is not valid!");
699 bool bNowSelected
= false;
700 if ( m_pListBoxHelper
)
702 bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected (_nPos
);
705 _rxNewAcc
= CreateChild(_nPos
);
706 _rNewValue
<<= _rxNewAcc
;
713 void VCLXAccessibleList::UpdateSelection_Impl(sal_uInt16
)
715 uno::Any aOldValue
, aNewValue
;
718 SolarMutexGuard aSolarGuard
;
719 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
720 Reference
< XAccessible
> xNewAcc
;
722 if ( m_pListBoxHelper
)
725 m_nCurSelectedPos
= LISTBOX_ENTRY_NOTFOUND
;
726 for ( ListItems::iterator aIter
= m_aAccessibleChildren
.begin();
727 aIter
!= m_aAccessibleChildren
.end(); ++aIter
,++i
)
729 Reference
< XAccessible
> xHold
= *aIter
;
732 VCLXAccessibleListItem
* pItem
= static_cast< VCLXAccessibleListItem
* >( xHold
.get() );
733 // Retrieve the item's index from the list entry.
734 bool bNowSelected
= m_pListBoxHelper
->IsEntryPosSelected (i
);
736 m_nCurSelectedPos
= i
;
738 if ( bNowSelected
&& !pItem
->IsSelected() )
741 aNewValue
<<= xNewAcc
;
743 else if ( pItem
->IsSelected() )
744 m_nLastSelectedPos
= i
;
746 pItem
->SetSelected( bNowSelected
);
749 { // it could happen that a child was not created before
750 checkEntrySelected(i
,aNewValue
,xNewAcc
);
753 sal_uInt16 nCount
= m_pListBoxHelper
->GetEntryCount();
754 if ( i
< nCount
) // here we have to check the if any other listbox entry is selected
756 for (; i
< nCount
&& !checkEntrySelected(i
,aNewValue
,xNewAcc
) ;++i
)
759 if ( xNewAcc
.is() && GetWindow()->HasFocus() )
761 if ( m_nLastSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
)
762 aOldValue
<<= getAccessibleChild( (sal_Int32
)m_nLastSelectedPos
);
763 aNewValue
<<= xNewAcc
;
765 if (m_pListBoxHelper
->IsInDropDown())
767 if ( aNewValue
.hasValue() || aOldValue
.hasValue() )
768 NotifyAccessibleEvent(
769 AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
,
772 //the SELECTION_CHANGED is not necessary
773 //NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() );
780 // XAccessibleSelection
782 void SAL_CALL
VCLXAccessibleList::selectAccessibleChild( sal_Int32 nChildIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
784 bool bNotify
= false;
787 SolarMutexGuard aSolarGuard
;
788 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
790 if ( m_pListBoxHelper
)
792 checkSelection_Impl(nChildIndex
,*m_pListBoxHelper
,false);
794 m_pListBoxHelper
->SelectEntryPos( (sal_uInt16
)nChildIndex
, true );
795 // call the select handler, don't handle events in this time
796 m_bDisableProcessEvent
= true;
797 m_pListBoxHelper
->Select();
798 m_bDisableProcessEvent
= false;
804 UpdateSelection_Impl();
807 sal_Bool SAL_CALL
VCLXAccessibleList::isAccessibleChildSelected( sal_Int32 nChildIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
809 SolarMutexGuard aSolarGuard
;
810 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
813 if ( m_pListBoxHelper
)
815 checkSelection_Impl(nChildIndex
,*m_pListBoxHelper
,false);
817 bRet
= m_pListBoxHelper
->IsEntryPosSelected( (sal_uInt16
)nChildIndex
);
822 void SAL_CALL
VCLXAccessibleList::clearAccessibleSelection( ) throw (RuntimeException
, std::exception
)
824 bool bNotify
= false;
827 SolarMutexGuard aSolarGuard
;
828 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
830 if ( m_pListBoxHelper
)
832 m_pListBoxHelper
->SetNoSelection();
838 UpdateSelection_Impl();
841 void SAL_CALL
VCLXAccessibleList::selectAllAccessibleChildren( ) throw (RuntimeException
, std::exception
)
843 bool bNotify
= false;
846 SolarMutexGuard aSolarGuard
;
847 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
849 if ( m_pListBoxHelper
)
851 sal_uInt16 nCount
= m_pListBoxHelper
->GetEntryCount();
852 for ( sal_uInt16 i
= 0; i
< nCount
; ++i
)
853 m_pListBoxHelper
->SelectEntryPos( i
, true );
854 // call the select handler, don't handle events in this time
855 m_bDisableProcessEvent
= true;
856 m_pListBoxHelper
->Select();
857 m_bDisableProcessEvent
= false;
863 UpdateSelection_Impl();
866 sal_Int32 SAL_CALL
VCLXAccessibleList::getSelectedAccessibleChildCount( ) throw (RuntimeException
, std::exception
)
868 SolarMutexGuard aSolarGuard
;
869 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
871 sal_Int32 nCount
= 0;
872 if ( m_pListBoxHelper
)
873 nCount
= m_pListBoxHelper
->GetSelectEntryCount();
877 Reference
< XAccessible
> SAL_CALL
VCLXAccessibleList::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
879 SolarMutexGuard aSolarGuard
;
880 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
882 if ( m_pListBoxHelper
)
884 checkSelection_Impl(nSelectedChildIndex
,*m_pListBoxHelper
,true);
885 return getAccessibleChild( (sal_Int32
)m_pListBoxHelper
->GetSelectEntryPos( (sal_uInt16
)nSelectedChildIndex
) );
891 void SAL_CALL
VCLXAccessibleList::deselectAccessibleChild( sal_Int32 nSelectedChildIndex
) throw (IndexOutOfBoundsException
, RuntimeException
, std::exception
)
893 bool bNotify
= false;
896 SolarMutexGuard aSolarGuard
;
897 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
899 if ( m_pListBoxHelper
)
901 checkSelection_Impl(nSelectedChildIndex
,*m_pListBoxHelper
,false);
903 m_pListBoxHelper
->SelectEntryPos( (sal_uInt16
)nSelectedChildIndex
, false );
904 // call the select handler, don't handle events in this time
905 m_bDisableProcessEvent
= true;
906 m_pListBoxHelper
->Select();
907 m_bDisableProcessEvent
= false;
913 UpdateSelection_Impl();
916 awt::Rectangle
VCLXAccessibleList::implGetBounds() throw (uno::RuntimeException
)
918 awt::Rectangle
aBounds ( 0, 0, 0, 0 );
919 if ( m_pListBoxHelper
920 && (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
)
922 if ( m_pListBoxHelper
->IsInDropDown() )
923 aBounds
= AWTRectangle(m_pListBoxHelper
->GetDropDownPosSizePixel());
927 // a list has the same bounds as his parent but starts at (0,0)
928 aBounds
= VCLXAccessibleComponent::implGetBounds();
931 if ( m_aBoxType
== COMBOBOX
)
933 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
936 Size aSize
= pBox
->GetSubEdit()->GetSizePixel();
937 aBounds
.Y
+= aSize
.Height();
938 aBounds
.Height
-= aSize
.Height();
946 awt::Point
VCLXAccessibleList::getLocationOnScreen( ) throw (uno::RuntimeException
, std::exception
)
948 SolarMutexGuard aSolarGuard
;
949 ::osl::Guard
< ::osl::Mutex
> aGuard( GetMutex() );
952 if ( m_pListBoxHelper
953 && (m_pListBoxHelper
->GetStyle() & WB_DROPDOWN
) == WB_DROPDOWN
)
955 if ( m_pListBoxHelper
->IsInDropDown() )
956 aPos
= AWTPoint(m_pListBoxHelper
->GetDropDownPosSizePixel().TopLeft());
960 aPos
= VCLXAccessibleComponent::getLocationOnScreen();
961 if ( m_aBoxType
== COMBOBOX
)
963 VclPtr
< ComboBox
> pBox
= GetAs
< ComboBox
>();
966 aPos
.Y
+= pBox
->GetSubEdit()->GetSizePixel().Height();
975 bool VCLXAccessibleList::IsInDropDown()
977 return m_pListBoxHelper
->IsInDropDown();
982 void VCLXAccessibleList::HandleDropOpen()
984 if ( !m_bDisableProcessEvent
)
985 UpdateSelection_Impl();
986 if (m_nCurSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
&&
987 m_nLastSelectedPos
!= LISTBOX_ENTRY_NOTFOUND
)
989 Reference
< XAccessible
> xChild
= getAccessibleChild(m_nCurSelectedPos
);
993 aNewValue
<<= xChild
;
994 NotifyAccessibleEvent(AccessibleEventId::ACTIVE_DESCENDANT_CHANGED
, uno::Any(), aNewValue
);
999 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */