/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: vclxaccessiblelist.cxx,v $ * $Revision: 1.4 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_accessibility.hxx" #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::accessibility; using namespace ::accessibility; namespace { void checkSelection_Impl( sal_Int32 _nIndex, const IComboListBoxHelper& _rListBox, sal_Bool bSelected ) throw (::com::sun::star::lang::IndexOutOfBoundsException) { sal_Int32 nCount = bSelected ? (sal_Int32)_rListBox.GetSelectEntryCount() : (sal_Int32)_rListBox.GetEntryCount(); if ( _nIndex < 0 || _nIndex >= nCount ) throw ::com::sun::star::lang::IndexOutOfBoundsException(); } } VCLXAccessibleList::VCLXAccessibleList (VCLXWindow* pVCLWindow, BoxType aBoxType, const Reference< XAccessible >& _xParent) : VCLXAccessibleComponent (pVCLWindow), m_aBoxType (aBoxType), m_nVisibleLineCount (0), m_nIndexInParent (DEFAULT_INDEX_IN_PARENT), m_nLastTopEntry ( 0 ), m_nLastSelectedPos ( LISTBOX_ENTRY_NOTFOUND ), m_bDisableProcessEvent ( false ), m_bVisible ( true ), m_xParent ( _xParent ) { // Because combo boxes and list boxes have the no common interface for // methods with identical signature we have to write down twice the // same code. switch (m_aBoxType) { case COMBOBOX: { ComboBox* pBox = static_cast(GetWindow()); if ( pBox != NULL ) m_pListBoxHelper = new VCLListBoxHelper (*pBox); break; } case LISTBOX: { ListBox* pBox = static_cast(GetWindow()); if ( pBox != NULL ) m_pListBoxHelper = new VCLListBoxHelper (*pBox); break; } } UpdateVisibleLineCount(); USHORT nCount = static_cast(getAccessibleChildCount()); m_aAccessibleChildren.reserve(nCount); } // ----------------------------------------------------------------------------- VCLXAccessibleList::~VCLXAccessibleList (void) { delete m_pListBoxHelper; } // ----------------------------------------------------------------------------- void VCLXAccessibleList::SetIndexInParent (sal_Int32 nIndex) { m_nIndexInParent = nIndex; } // ----------------------------------------------------------------------------- void SAL_CALL VCLXAccessibleList::disposing (void) { VCLXAccessibleComponent::disposing(); // Dispose all items in the list. clearItems(); delete m_pListBoxHelper; m_pListBoxHelper = NULL; } // ----------------------------------------------------------------------------- void VCLXAccessibleList::clearItems() { // ListItems::iterator aEnd = m_aAccessibleChildren.end(); // for (ListItems::iterator aIter = m_aAccessibleChildren.begin(); aIter != aEnd; ++aIter) // ::comphelper::disposeComponent(*aIter); // Clear the list itself and delete all the rest. ListItems().swap(m_aAccessibleChildren); // clear and minimize } // ----------------------------------------------------------------------------- void VCLXAccessibleList::FillAccessibleStateSet (utl::AccessibleStateSetHelper& rStateSet) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet ); // check if our list should be visible if ( m_pListBoxHelper && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN && !m_pListBoxHelper->IsInDropDown() ) { rStateSet.RemoveState (AccessibleStateType::VISIBLE); rStateSet.RemoveState (AccessibleStateType::SHOWING); m_bVisible = false; } // Both the combo box and list box are handled identical in the // following but for some reason they don't have a common interface for // the methods used. if ( m_pListBoxHelper ) { if ( m_pListBoxHelper->IsMultiSelectionEnabled() ) rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE); rStateSet.AddState (AccessibleStateType::FOCUSABLE); // All children are transient. rStateSet.AddState (AccessibleStateType::MANAGES_DESCENDANTS); } } // ----------------------------------------------------------------------------- void VCLXAccessibleList::notifyVisibleStates(sal_Bool _bSetNew ) { m_bVisible = _bSetNew ? true : false; Any aOldValue, aNewValue; (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::VISIBLE; NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); (_bSetNew ? aNewValue : aOldValue ) <<= AccessibleStateType::SHOWING; NotifyAccessibleEvent( AccessibleEventId::STATE_CHANGED, aOldValue, aNewValue ); ListItems::iterator aIter = m_aAccessibleChildren.begin(); ListItems::iterator aEnd = m_aAccessibleChildren.end(); UpdateVisibleLineCount(); // adjust the index inside the VCLXAccessibleListItem for (;aIter != aEnd ; ++aIter) { Reference< XAccessible > xHold = *aIter; VCLXAccessibleListItem* pItem = static_cast(xHold.get()); if ( pItem ) { USHORT nTopEntry = 0; if ( m_pListBoxHelper ) nTopEntry = m_pListBoxHelper->GetTopEntry(); USHORT nPos = (USHORT)(aIter - m_aAccessibleChildren.begin()); sal_Bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) ); pItem->SetVisible( m_bVisible && bVisible ); } } } // ----------------------------------------------------------------------------- void VCLXAccessibleList::ProcessWindowEvent (const VclWindowEvent& rVclWindowEvent) { // Create a reference to this object to prevent an early release of the // listbox (VCLEVENT_OBJECT_DYING). Reference< XAccessible > xTemp = this; switch ( rVclWindowEvent.GetId() ) { case VCLEVENT_DROPDOWN_OPEN: notifyVisibleStates(sal_True); break; case VCLEVENT_DROPDOWN_CLOSE: notifyVisibleStates(sal_False); break; case VCLEVENT_LISTBOX_SCROLLED: case VCLEVENT_COMBOBOX_SCROLLED: UpdateEntryRange_Impl(); break; case VCLEVENT_LISTBOX_SELECT: if ( !m_bDisableProcessEvent ) UpdateSelection_Impl(); break; // The selection events VCLEVENT_COMBOBOX_SELECT and // VCLEVENT_COMBOBOX_DESELECT are not handled here because here we // have no access to the edit field. Its text is necessary to // identify the currently selected item. case VCLEVENT_OBJECT_DYING: { dispose(); VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent); break; } case VCLEVENT_LISTBOX_ITEMREMOVED: case VCLEVENT_COMBOBOX_ITEMREMOVED: HandleChangedItemList (false, reinterpret_cast( rVclWindowEvent.GetData())); break; case VCLEVENT_LISTBOX_ITEMADDED: case VCLEVENT_COMBOBOX_ITEMADDED: HandleChangedItemList (true, reinterpret_cast( rVclWindowEvent.GetData())); break; case VCLEVENT_CONTROL_GETFOCUS: VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent); if ( m_pListBoxHelper ) { uno::Any aOldValue, aNewValue; USHORT nPos = m_pListBoxHelper->GetSelectEntryPos(); if ( nPos == LISTBOX_ENTRY_NOTFOUND ) nPos = m_pListBoxHelper->GetTopEntry(); if ( nPos != LISTBOX_ENTRY_NOTFOUND ) aNewValue <<= CreateChild(nPos); NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue ); } break; default: VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent); } } // ----------------------------------------------------------------------------- /** To find out which item is currently selected and to update the SELECTED state of the associated accessibility objects accordingly we exploit the fact that the */ void VCLXAccessibleList::UpdateSelection (::rtl::OUString sTextOfSelectedItem) { if ( m_aBoxType == COMBOBOX ) { ComboBox* pBox = static_cast(GetWindow()); if ( pBox != NULL ) { // Find the index of the selected item inside the VCL control... USHORT nIndex = pBox->GetEntryPos (XubString(sTextOfSelectedItem)); // ...and then find the associated accessibility object. if ( nIndex == LISTBOX_ENTRY_NOTFOUND ) nIndex = 0; UpdateSelection_Impl(nIndex); } } } // ----------------------------------------------------------------------------- void VCLXAccessibleList::adjustEntriesIndexInParent(ListItems::iterator& _aBegin,::std::mem_fun_t& _rMemFun) { ListItems::iterator aIter = _aBegin; ListItems::iterator aEnd = m_aAccessibleChildren.end(); // adjust the index inside the VCLXAccessibleListItem for (;aIter != aEnd ; ++aIter) { Reference< XAccessible > xHold = *aIter; VCLXAccessibleListItem* pItem = static_cast(xHold.get()); if ( pItem ) _rMemFun(pItem); } } // ----------------------------------------------------------------------------- Reference VCLXAccessibleList::CreateChild (sal_Int32 i) { Reference xChild; USHORT nPos = static_cast(i); if ( nPos >= m_aAccessibleChildren.size() ) { m_aAccessibleChildren.resize(nPos + 1); // insert into the container xChild = new VCLXAccessibleListItem(m_pListBoxHelper, i, this); m_aAccessibleChildren[nPos] = xChild; } else { xChild = m_aAccessibleChildren[nPos]; // check if position is empty and can be used else we have to adjust all entries behind this if ( xChild.is() ) { ListItems::iterator aIter = m_aAccessibleChildren.begin() + nPos; ::std::mem_fun_t aTemp(&VCLXAccessibleListItem::IncrementIndexInParent); adjustEntriesIndexInParent( aIter, aTemp); } else { xChild = new VCLXAccessibleListItem(m_pListBoxHelper, i, this); m_aAccessibleChildren[nPos] = xChild; } } if ( xChild.is() ) { // Just add the SELECTED state. BOOL bNowSelected = FALSE; if ( m_pListBoxHelper ) bNowSelected = m_pListBoxHelper->IsEntryPosSelected ((USHORT)i); VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >(xChild.get()); pItem->SetSelected( bNowSelected ); // Set the child's VISIBLE state. UpdateVisibleLineCount(); USHORT nTopEntry = 0; if ( m_pListBoxHelper ) nTopEntry = m_pListBoxHelper->GetTopEntry(); sal_Bool bVisible = ( nPos>=nTopEntry && nPos<( nTopEntry + m_nVisibleLineCount ) ); pItem->SetVisible( m_bVisible && bVisible ); } return xChild; } // ----------------------------------------------------------------------------- void VCLXAccessibleList::HandleChangedItemList (bool bItemInserted, sal_Int32 nIndex) { if ( !bItemInserted ) { if ( nIndex == -1 ) // special handling here { clearItems(); } else { if ( nIndex >= 0 && static_cast(nIndex) < m_aAccessibleChildren.size() ) { ListItems::iterator aIter = m_aAccessibleChildren.erase(m_aAccessibleChildren.begin()+nIndex); ::std::mem_fun_t aTemp(&VCLXAccessibleListItem::DecrementIndexInParent); adjustEntriesIndexInParent( aIter, aTemp ); } } } else getAccessibleChild(nIndex); NotifyAccessibleEvent ( AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any()); } // ----------------------------------------------------------------------------- IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleList, VCLXAccessibleComponent, VCLXAccessibleList_BASE) IMPLEMENT_FORWARD_XTYPEPROVIDER2(VCLXAccessibleList, VCLXAccessibleComponent, VCLXAccessibleList_BASE) //===== XAccessible ========================================================= Reference SAL_CALL VCLXAccessibleList::getAccessibleContext (void) throw (RuntimeException) { return this; } // ----------------------------------------------------------------------------- //===== XAccessibleContext ================================================== sal_Int32 SAL_CALL VCLXAccessibleList::getAccessibleChildCount (void) throw (RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); sal_Int32 nCount = 0; if ( m_pListBoxHelper ) nCount = m_pListBoxHelper->GetEntryCount(); return nCount; } // ----------------------------------------------------------------------------- Reference SAL_CALL VCLXAccessibleList::getAccessibleChild (sal_Int32 i) throw (IndexOutOfBoundsException, RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); if ( i < 0 || i >= getAccessibleChildCount() ) throw IndexOutOfBoundsException(); Reference< XAccessible > xChild; // search for the child if ( static_cast(i) >= m_aAccessibleChildren.size() ) xChild = CreateChild (i); else { xChild = m_aAccessibleChildren[i]; if ( !xChild.is() ) xChild = CreateChild (i); } OSL_ENSURE( xChild.is(), "VCLXAccessibleList::getAccessibleChild: returning empty child!" ); return xChild; } // ----------------------------------------------------------------------------- Reference< XAccessible > SAL_CALL VCLXAccessibleList::getAccessibleParent( ) throw (RuntimeException) { ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); return m_xParent; } // ----------------------------------------------------------------------------- sal_Int32 SAL_CALL VCLXAccessibleList::getAccessibleIndexInParent (void) throw (::com::sun::star::uno::RuntimeException) { if (m_nIndexInParent != DEFAULT_INDEX_IN_PARENT) return m_nIndexInParent; else return VCLXAccessibleComponent::getAccessibleIndexInParent(); } // ----------------------------------------------------------------------------- sal_Int16 SAL_CALL VCLXAccessibleList::getAccessibleRole (void) throw (RuntimeException) { return AccessibleRole::LIST; } // ----------------------------------------------------------------------------- //===== XAccessibleComponent ================================================ sal_Bool SAL_CALL VCLXAccessibleList::contains( const awt::Point& rPoint ) throw (RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); sal_Bool bInside = sal_False; Window* pListBox = GetWindow(); if ( pListBox ) { Rectangle aRect( Point(0,0), pListBox->GetSizePixel() ); bInside = aRect.IsInside( VCLPoint( rPoint ) ); } return bInside; } // ----------------------------------------------------------------------------- Reference< XAccessible > SAL_CALL VCLXAccessibleList::getAccessibleAt( const awt::Point& rPoint ) throw (RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); Reference< XAccessible > xChild; if ( m_pListBoxHelper ) { UpdateVisibleLineCount(); if ( contains( rPoint ) && m_nVisibleLineCount > 0 ) { Point aPos = VCLPoint( rPoint ); USHORT nEndPos = m_pListBoxHelper->GetTopEntry() + (USHORT)m_nVisibleLineCount; for ( USHORT i = m_pListBoxHelper->GetTopEntry(); i < nEndPos; ++i ) { if ( m_pListBoxHelper->GetBoundingRectangle(i).IsInside( aPos ) ) { xChild = getAccessibleChild(i); break; } } } } return xChild; } // ----------------------------------------------------------------------------- //===== XServiceInfo ========================================================== ::rtl::OUString VCLXAccessibleList::getImplementationName (void) throw (RuntimeException) { return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.toolkit.AccessibleList")); } // ----------------------------------------------------------------------------- Sequence< ::rtl::OUString > VCLXAccessibleList::getSupportedServiceNames (void) throw (RuntimeException) { Sequence< ::rtl::OUString > aNames = VCLXAccessibleComponent::getSupportedServiceNames(); sal_Int32 nLength = aNames.getLength(); aNames.realloc( nLength + 1 ); aNames[nLength] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleList")); return aNames; } // ----------------------------------------------------------------------------- void VCLXAccessibleList::UpdateVisibleLineCount() { if ( m_pListBoxHelper ) { if ( (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN ) m_nVisibleLineCount = m_pListBoxHelper->GetDisplayLineCount(); else { USHORT nCols = 0, nLines = 0; m_pListBoxHelper->GetMaxVisColumnsAndLines (nCols, nLines); m_nVisibleLineCount = nLines; } } } // ----------------------------------------------------------------------------- void VCLXAccessibleList::UpdateEntryRange_Impl() { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); sal_Int32 nTop = m_nLastTopEntry; if ( m_pListBoxHelper ) nTop = m_pListBoxHelper->GetTopEntry(); if ( nTop != m_nLastTopEntry ) { UpdateVisibleLineCount(); sal_Int32 nBegin = Min( m_nLastTopEntry, nTop ); sal_Int32 nEnd = Max( m_nLastTopEntry + m_nVisibleLineCount, nTop + m_nVisibleLineCount ); for (USHORT i = static_cast(nBegin); (i <= static_cast(nEnd)); ++i) { sal_Bool bVisible = ( i >= nTop && i < ( nTop + m_nVisibleLineCount ) ); Reference< XAccessible > xHold; if ( i < m_aAccessibleChildren.size() ) xHold = m_aAccessibleChildren[i]; else if ( bVisible ) xHold = CreateChild(i); if ( xHold.is() ) static_cast< VCLXAccessibleListItem* >( xHold.get() )->SetVisible( m_bVisible && bVisible ); } } m_nLastTopEntry = nTop; } // ----------------------------------------------------------------------------- BOOL VCLXAccessibleList::checkEntrySelected(USHORT _nPos,Any& _rNewValue,Reference< XAccessible >& _rxNewAcc) { OSL_ENSURE(m_pListBoxHelper,"Helper is not valid!"); BOOL bNowSelected = FALSE; if ( m_pListBoxHelper ) { bNowSelected = m_pListBoxHelper->IsEntryPosSelected (_nPos); if ( bNowSelected ) { _rxNewAcc = CreateChild(_nPos); _rNewValue <<= _rxNewAcc; } } return bNowSelected; } // ----------------------------------------------------------------------------- void VCLXAccessibleList::UpdateSelection_Impl(USHORT) { uno::Any aOldValue, aNewValue; { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); Reference< XAccessible > xNewAcc; if ( m_pListBoxHelper ) { USHORT i=0; for ( ListItems::iterator aIter = m_aAccessibleChildren.begin(); aIter != m_aAccessibleChildren.end(); ++aIter,++i) { Reference< XAccessible > xHold = *aIter; if ( xHold.is() ) { VCLXAccessibleListItem* pItem = static_cast< VCLXAccessibleListItem* >( xHold.get() ); // Retrieve the item's index from the list entry. BOOL bNowSelected = m_pListBoxHelper->IsEntryPosSelected (i); if ( bNowSelected && !pItem->IsSelected() ) { xNewAcc = *aIter; aNewValue <<= xNewAcc; } else if ( pItem->IsSelected() ) m_nLastSelectedPos = i; pItem->SetSelected( bNowSelected ); } else { // it could happen that a child was not created before checkEntrySelected(i,aNewValue,xNewAcc); } } USHORT nCount = m_pListBoxHelper->GetEntryCount(); if ( i < nCount ) // here we have to check the if any other listbox entry is selected { for (; i < nCount && !checkEntrySelected(i,aNewValue,xNewAcc) ;++i ) ; } if ( xNewAcc.is() && GetWindow()->HasFocus() ) { if ( m_nLastSelectedPos != LISTBOX_ENTRY_NOTFOUND ) aOldValue <<= getAccessibleChild( (sal_Int32)m_nLastSelectedPos ); aNewValue <<= xNewAcc; } } } if ( aNewValue.hasValue() || aOldValue.hasValue() ) NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue ); NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); } // ----------------------------------------------------------------------------- // XAccessibleSelection // ----------------------------------------------------------------------------- void SAL_CALL VCLXAccessibleList::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) { sal_Bool bNotify = sal_False; { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); if ( m_pListBoxHelper ) { checkSelection_Impl(nChildIndex,*m_pListBoxHelper,sal_False); m_pListBoxHelper->SelectEntryPos( (USHORT)nChildIndex, TRUE ); // call the select handler, don't handle events in this time m_bDisableProcessEvent = true; m_pListBoxHelper->Select(); m_bDisableProcessEvent = false; bNotify = sal_True; } } if ( bNotify ) UpdateSelection_Impl(); } // ----------------------------------------------------------------------------- sal_Bool SAL_CALL VCLXAccessibleList::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); sal_Bool bRet = sal_False; if ( m_pListBoxHelper ) { checkSelection_Impl(nChildIndex,*m_pListBoxHelper,sal_False); bRet = m_pListBoxHelper->IsEntryPosSelected( (USHORT)nChildIndex ); } return bRet; } // ----------------------------------------------------------------------------- void SAL_CALL VCLXAccessibleList::clearAccessibleSelection( ) throw (RuntimeException) { sal_Bool bNotify = sal_False; { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); if ( m_pListBoxHelper ) { m_pListBoxHelper->SetNoSelection(); bNotify = sal_True; } } if ( bNotify ) UpdateSelection_Impl(); } // ----------------------------------------------------------------------------- void SAL_CALL VCLXAccessibleList::selectAllAccessibleChildren( ) throw (RuntimeException) { sal_Bool bNotify = sal_False; { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); if ( m_pListBoxHelper ) { USHORT nCount = m_pListBoxHelper->GetEntryCount(); for ( USHORT i = 0; i < nCount; ++i ) m_pListBoxHelper->SelectEntryPos( i, TRUE ); // call the select handler, don't handle events in this time m_bDisableProcessEvent = true; m_pListBoxHelper->Select(); m_bDisableProcessEvent = false; bNotify = sal_True; } } if ( bNotify ) UpdateSelection_Impl(); } // ----------------------------------------------------------------------------- sal_Int32 SAL_CALL VCLXAccessibleList::getSelectedAccessibleChildCount( ) throw (RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); sal_Int32 nCount = 0; if ( m_pListBoxHelper ) nCount = m_pListBoxHelper->GetSelectEntryCount(); return nCount; } // ----------------------------------------------------------------------------- Reference< XAccessible > SAL_CALL VCLXAccessibleList::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); if ( m_pListBoxHelper ) { checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,sal_True); return getAccessibleChild( (sal_Int32)m_pListBoxHelper->GetSelectEntryPos( (USHORT)nSelectedChildIndex ) ); } return NULL; } // ----------------------------------------------------------------------------- void SAL_CALL VCLXAccessibleList::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) { sal_Bool bNotify = sal_False; { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); if ( m_pListBoxHelper ) { checkSelection_Impl(nSelectedChildIndex,*m_pListBoxHelper,sal_False); m_pListBoxHelper->SelectEntryPos( (USHORT)nSelectedChildIndex, FALSE ); // call the select handler, don't handle events in this time m_bDisableProcessEvent = true; m_pListBoxHelper->Select(); m_bDisableProcessEvent = false; bNotify = sal_True; } } if ( bNotify ) UpdateSelection_Impl(); } // ----------------------------------------------------------------------------- // accessibility::XAccessibleComponent awt::Rectangle VCLXAccessibleList::implGetBounds() throw (uno::RuntimeException) { awt::Rectangle aBounds ( 0, 0, 0, 0 ); if ( m_pListBoxHelper && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN ) { if ( m_pListBoxHelper->IsInDropDown() ) aBounds = AWTRectangle(m_pListBoxHelper->GetDropDownPosSizePixel()); } else { // a list has the same bounds as his parent but starts at (0,0) aBounds = VCLXAccessibleComponent::implGetBounds(); aBounds.X = 0; aBounds.Y = 0; if ( m_aBoxType == COMBOBOX ) { ComboBox* pBox = static_cast(GetWindow()); if ( pBox ) { Size aSize = pBox->GetSubEdit()->GetSizePixel(); aBounds.X += aSize.Height(); aBounds.Y += aSize.Width(); aBounds.Height -= aSize.Height(); aBounds.Width -= aSize.Width(); } } } return aBounds; } // ----------------------------------------------------------------------------- awt::Point VCLXAccessibleList::getLocationOnScreen( ) throw (uno::RuntimeException) { vos::OGuard aSolarGuard( Application::GetSolarMutex() ); ::osl::Guard< ::osl::Mutex > aGuard( GetMutex() ); awt::Point aPos; if ( m_pListBoxHelper && (m_pListBoxHelper->GetStyle() & WB_DROPDOWN ) == WB_DROPDOWN ) { if ( m_pListBoxHelper->IsInDropDown() ) aPos = AWTPoint(m_pListBoxHelper->GetDropDownPosSizePixel().TopLeft()); } else { aPos = VCLXAccessibleComponent::getLocationOnScreen(); if ( m_aBoxType == COMBOBOX ) { ComboBox* pBox = static_cast(GetWindow()); if ( pBox ) { aPos.X += pBox->GetSubEdit()->GetSizePixel().Height(); aPos.Y += pBox->GetSubEdit()->GetSizePixel().Width(); } } } return aPos; } // -----------------------------------------------------------------------------