blob: 6c245d322cbd8d5cf329f8c9a29c6865f0f99b34 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_accessibility.hxx"
// includes --------------------------------------------------------------
#include <accessibility/standard/vclxaccessibletoolbox.hxx>
#include <accessibility/standard/vclxaccessibletoolboxitem.hxx>
#include <toolkit/helper/convert.hxx>
#include <unotools/accessiblestatesethelper.hxx>
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <com/sun/star/lang/XUnoTunnel.hpp>
#include <tools/debug.hxx>
#include <vcl/toolbox.hxx>
#include <comphelper/accessiblewrapper.hxx>
#include <comphelper/processfactory.hxx>
using namespace ::comphelper;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::accessibility;
namespace
{
// =========================================================================
// = OToolBoxWindowItemContext
// =========================================================================
/** XAccessibleContext implementation for a toolbox item which is represented by a VCL Window
*/
class OToolBoxWindowItemContext : public OAccessibleContextWrapper
{
sal_Int32 m_nIndexInParent;
public:
OToolBoxWindowItemContext(sal_Int32 _nIndexInParent,
const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerAccessibleContext,
const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxOwningAccessible,
const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
) : OAccessibleContextWrapper(
_rxORB,
_rxInnerAccessibleContext,
_rxOwningAccessible,
_rxParentAccessible )
,m_nIndexInParent(_nIndexInParent)
{
}
virtual sal_Int32 SAL_CALL getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException);
};
// -------------------------------------------------------------------------
sal_Int32 SAL_CALL OToolBoxWindowItemContext::getAccessibleIndexInParent( ) throw (::com::sun::star::uno::RuntimeException)
{
::osl::MutexGuard aGuard( m_aMutex );
return m_nIndexInParent;
}
// =========================================================================
// = OToolBoxWindowItem
// =========================================================================
typedef ::cppu::ImplHelper1 < XUnoTunnel
> OToolBoxWindowItem_Base;
/** XAccessible implementation for a toolbox item which is represented by a VCL Window
*/
class OToolBoxWindowItem
:public OAccessibleWrapper
,public OToolBoxWindowItem_Base
{
private:
sal_Int32 m_nIndexInParent;
public:
inline sal_Int32 getIndexInParent() const { return m_nIndexInParent; }
inline void setIndexInParent( sal_Int32 _nNewIndex ) { m_nIndexInParent = _nNewIndex; }
static sal_Bool isWindowItem( const Reference< XAccessible >& _rxAcc, OToolBoxWindowItem** /* [out] */ _ppImplementation = NULL );
public:
OToolBoxWindowItem(sal_Int32 _nIndexInParent,
const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxInnerAccessible,
const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& _rxParentAccessible
) : OAccessibleWrapper(
_rxORB,
_rxInnerAccessible,
_rxParentAccessible)
,m_nIndexInParent(_nIndexInParent)
{
}
protected:
// XInterface
DECLARE_XINTERFACE( )
DECLARE_XTYPEPROVIDER( )
// OAccessibleWrapper
virtual OAccessibleContextWrapper* createAccessibleContext(
const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext >& _rxInnerContext
);
// XUnoTunnel
virtual sal_Int64 SAL_CALL getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw (RuntimeException);
static Sequence< sal_Int8 > getUnoTunnelImplementationId();
};
// -------------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
IMPLEMENT_FORWARD_XTYPEPROVIDER2( OToolBoxWindowItem, OAccessibleWrapper, OToolBoxWindowItem_Base )
// -------------------------------------------------------------------------
OAccessibleContextWrapper* OToolBoxWindowItem::createAccessibleContext(
const Reference< XAccessibleContext >& _rxInnerContext )
{
return new OToolBoxWindowItemContext( m_nIndexInParent,getORB(), _rxInnerContext, this, getParent() );
}
//--------------------------------------------------------------------
sal_Bool OToolBoxWindowItem::isWindowItem( const Reference< XAccessible >& _rxAcc, OToolBoxWindowItem** /* [out] */ _ppImplementation )
{
OToolBoxWindowItem* pImplementation = NULL;
Reference< XUnoTunnel > xTunnel( _rxAcc, UNO_QUERY );
if ( xTunnel.is() )
pImplementation = reinterpret_cast< OToolBoxWindowItem* >( xTunnel->getSomething( getUnoTunnelImplementationId() ) );
if ( _ppImplementation )
*_ppImplementation = pImplementation;
return NULL != pImplementation;
}
//--------------------------------------------------------------------
Sequence< sal_Int8 > OToolBoxWindowItem::getUnoTunnelImplementationId()
{
static ::cppu::OImplementationId * pId = 0;
if (! pId)
{
::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
if (! pId)
{
static ::cppu::OImplementationId aId;
pId = &aId;
}
}
return pId->getImplementationId();
}
//--------------------------------------------------------------------
sal_Int64 SAL_CALL OToolBoxWindowItem::getSomething( const Sequence< sal_Int8 >& _rId ) throw (RuntimeException)
{
if ( ( 16 == _rId.getLength() )
&& ( 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), _rId.getConstArray(), 16 ) )
)
return reinterpret_cast< sal_Int64>( this );
return 0;
}
}
DBG_NAME(VCLXAccessibleToolBox)
// -----------------------------------------------------------------------------
// VCLXAccessibleToolBox
// -----------------------------------------------------------------------------
VCLXAccessibleToolBox::VCLXAccessibleToolBox( VCLXWindow* pVCLXWindow ) :
VCLXAccessibleComponent( pVCLXWindow )
{
DBG_CTOR(VCLXAccessibleToolBox,NULL);
}
// -----------------------------------------------------------------------------
VCLXAccessibleToolBox::~VCLXAccessibleToolBox()
{
DBG_DTOR(VCLXAccessibleToolBox,NULL);
}
// -----------------------------------------------------------------------------
VCLXAccessibleToolBoxItem* VCLXAccessibleToolBox::GetItem_Impl( sal_Int32 _nPos, bool _bMustHaveFocus )
{
VCLXAccessibleToolBoxItem* pItem = NULL;
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox && ( !_bMustHaveFocus || pToolBox->HasFocus() ) )
{
ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
// returns only toolbox buttons, not windows
if ( aIter != m_aAccessibleChildren.end() && aIter->second.is())
pItem = static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
}
return pItem;
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateFocus_Impl()
{
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if( !pToolBox )
return;
// submit events only if toolbox has the focus to avoid sending events due to mouse move
sal_Bool bHasFocus = sal_False;
if ( pToolBox->HasFocus() )
bHasFocus = sal_True;
else
{
// check for subtoolbar, i.e. check if our parent is a toolbar
ToolBox* pToolBoxParent = dynamic_cast< ToolBox* >( pToolBox->GetParent() );
// subtoolbars never get the focus as key input is just forwarded, so check if the parent toolbar has it
if ( pToolBoxParent && pToolBoxParent->HasFocus() )
bHasFocus = sal_True;
}
if ( bHasFocus )
{
sal_uInt16 nHighlightItemId = pToolBox->GetHighlightItemId();
sal_uInt16 nFocusCount = 0;
for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
aIter != m_aAccessibleChildren.end(); ++aIter )
{
sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)aIter->first );
if ( aIter->second.is() )
{
VCLXAccessibleToolBoxItem* pItem =
static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
if ( pItem->HasFocus() && nItemId != nHighlightItemId )
{
// reset the old focused item
pItem->SetFocus( sal_False );
nFocusCount++;
}
if ( nItemId == nHighlightItemId )
{
// set the new focused item
pItem->SetFocus( sal_True );
nFocusCount++;
}
}
// both items changed?
if ( nFocusCount > 1 )
break;
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::ReleaseFocus_Impl( sal_Int32 _nPos )
{
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox ) // #107124#, do not check for focus because this message is also handled in losefocus
{
ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
{
VCLXAccessibleToolBoxItem* pItem =
static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
if ( pItem->HasFocus() )
pItem->SetFocus( sal_False );
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateChecked_Impl( sal_Int32 _nPos )
{
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
sal_uInt16 nFocusId = pToolBox->GetItemId( (sal_uInt16)_nPos );
VCLXAccessibleToolBoxItem* pFocusItem = NULL;
for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
aIter != m_aAccessibleChildren.end(); ++aIter )
{
sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)aIter->first );
VCLXAccessibleToolBoxItem* pItem =
static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
pItem->SetChecked( pToolBox->IsItemChecked( nItemId ) );
if ( nItemId == nFocusId )
pFocusItem = pItem;
}
//Solution:If the position is not a child item,the focus should not be called
if ( pFocusItem && (sal_uInt16)_nPos != TOOLBOX_ITEM_NOTFOUND )
pFocusItem->SetFocus( sal_True );
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateIndeterminate_Impl( sal_Int32 _nPos )
{
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)_nPos );
ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find( _nPos );
if ( aIter != m_aAccessibleChildren.end() && aIter->second.is() )
{
VCLXAccessibleToolBoxItem* pItem =
static_cast< VCLXAccessibleToolBoxItem* >( aIter->second.get() );
if ( pItem )
pItem->SetIndeterminate( pToolBox->GetItemState( nItemId ) == STATE_DONTKNOW );
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::implReleaseToolboxItem( ToolBoxItemsMap::iterator& _rMapPos,
bool _bNotifyRemoval, bool _bDispose )
{
Reference< XAccessible > xItemAcc( _rMapPos->second );
if ( !xItemAcc.is() )
return;
if ( _bNotifyRemoval )
{
NotifyAccessibleEvent( AccessibleEventId::CHILD, makeAny( xItemAcc ), Any() );
}
OToolBoxWindowItem* pWindowItem = NULL;
if ( !OToolBoxWindowItem::isWindowItem( xItemAcc, &pWindowItem ) )
{
static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() )->ReleaseToolBox();
if ( _bDispose )
::comphelper::disposeComponent( xItemAcc );
}
else
{
if ( _bDispose )
{
if ( pWindowItem )
{
Reference< XAccessibleContext > xContext( pWindowItem->getContextNoCreate() );
::comphelper::disposeComponent( xContext );
}
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateItem_Impl( sal_Int32 _nPos, sal_Bool _bItemAdded )
{
if ( _nPos < sal_Int32( m_aAccessibleChildren.size() ) )
{
UpdateAllItems_Impl();
return;
}
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
if ( !_bItemAdded )
{ // the item was removed
// -> destroy the old item
ToolBoxItemsMap::iterator aItemPos = m_aAccessibleChildren.find( _nPos );
if ( m_aAccessibleChildren.end() != aItemPos )
{
implReleaseToolboxItem( aItemPos, true, true );
m_aAccessibleChildren.erase( aItemPos );
}
}
// adjust the "index-in-parent"s
ToolBoxItemsMap::iterator aIndexAdjust = m_aAccessibleChildren.upper_bound( _nPos );
while ( m_aAccessibleChildren.end() != aIndexAdjust )
{
Reference< XAccessible > xItemAcc( aIndexAdjust->second );
OToolBoxWindowItem* pWindowItem = NULL;
if ( !OToolBoxWindowItem::isWindowItem( xItemAcc, &pWindowItem ) )
{
VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xItemAcc.get() );
if ( pItem )
{
sal_Int32 nIndex = pItem->getIndexInParent( );
nIndex += _bItemAdded ? +1 : -1;
pItem->setIndexInParent( nIndex );
}
}
else
{
if ( pWindowItem )
{
sal_Int32 nIndex = pWindowItem->getIndexInParent( );
nIndex += _bItemAdded ? +1 : -1;
pWindowItem->setIndexInParent( nIndex );
}
}
++aIndexAdjust;
}
if ( _bItemAdded )
{
// TODO: we should make this dependent on the existence of event listeners
// with the current implementation, we always create accessible object
Any aNewChild = makeAny( getAccessibleChild( (sal_Int32)_nPos ) );
NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewChild );
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateAllItems_Impl()
{
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
// deregister the old items
for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
aIter != m_aAccessibleChildren.end(); ++aIter )
{
implReleaseToolboxItem( aIter, true, true );
}
m_aAccessibleChildren.clear();
// register the new items
sal_uInt16 i, nCount = pToolBox->GetItemCount();
for ( i = 0; i < nCount; ++i )
{
Any aNewValue;
aNewValue <<= getAccessibleChild( (sal_Int32)i );;
NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateCustomPopupItemp_Impl( Window* pWindow, bool bOpen )
{
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if( pWindow && pToolBox )
{
Reference< XAccessible > xChild( pWindow->GetAccessible() );
if( xChild.is() )
{
Reference< XAccessible > xChildItem( getAccessibleChild( static_cast< sal_Int32 >( pToolBox->GetItemPos( pToolBox->GetDownItemId() ) ) ) );
VCLXAccessibleToolBoxItem* pItem = static_cast< VCLXAccessibleToolBoxItem* >( xChildItem.get() );
pItem->SetChild( xChild );
pItem->NotifyChildEvent( xChild, bOpen );
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateItemName_Impl( sal_Int32 _nPos )
{
VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos, false );
if ( pItem )
pItem->NameChanged();
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::UpdateItemEnabled_Impl( sal_Int32 _nPos )
{
VCLXAccessibleToolBoxItem* pItem = GetItem_Impl( _nPos, false );
if ( pItem )
pItem->ToggleEnableState();
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::HandleSubToolBarEvent( const VclWindowEvent& rVclWindowEvent, bool _bShow )
{
Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pChildWindow
&& pToolBox
&& pToolBox == pChildWindow->GetParent()
&& pChildWindow->GetType() == WINDOW_TOOLBOX )
{
sal_Int32 nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
Reference< XAccessible > xItem = getAccessibleChild( nIndex );
if ( xItem.is() )
{
Reference< XAccessible > xChild = pChildWindow->GetAccessible();
VCLXAccessibleToolBoxItem* pItem =
static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
pItem->SetChild( xChild );
pItem->NotifyChildEvent( xChild, _bShow );
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::ReleaseSubToolBox( ToolBox* _pSubToolBox )
{
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
sal_Int32 nIndex = pToolBox->GetItemPos( pToolBox->GetCurItemId() );
Reference< XAccessible > xItem = getAccessibleChild( nIndex );
if ( xItem.is() )
{
Reference< XAccessible > xChild = _pSubToolBox->GetAccessible();
VCLXAccessibleToolBoxItem* pItem =
static_cast< VCLXAccessibleToolBoxItem* >( xItem.get() );
if ( pItem->GetChild() == xChild )
{
pItem->SetChild( Reference< XAccessible >() );
pItem->NotifyChildEvent( xChild, false );
}
}
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet )
{
VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet );
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
rStateSet.AddState( AccessibleStateType::FOCUSABLE );
if ( pToolBox->IsHorizontal() )
rStateSet.AddState( AccessibleStateType::HORIZONTAL );
else
rStateSet.AddState( AccessibleStateType::VERTICAL );
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
{
// to prevent an early release of the toolbox (VCLEVENT_OBJECT_DYING)
Reference< XAccessibleContext > xTemp = this;
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
switch ( rVclWindowEvent.GetId() )
{
case VCLEVENT_TOOLBOX_CLICK:
case VCLEVENT_TOOLBOX_SELECT:
{
if ( rVclWindowEvent.GetData() )
{
UpdateChecked_Impl( (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData() );
UpdateIndeterminate_Impl( (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData() );
}
else if( pToolBox->GetItemPos(pToolBox->GetCurItemId()) != TOOLBOX_ITEM_NOTFOUND )
{
UpdateChecked_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
UpdateIndeterminate_Impl( pToolBox->GetItemPos(pToolBox->GetCurItemId()) );
}
break;
}
case VCLEVENT_TOOLBOX_DOUBLECLICK:
case VCLEVENT_TOOLBOX_ACTIVATE:
case VCLEVENT_TOOLBOX_DEACTIVATE:
//case VCLEVENT_TOOLBOX_SELECT:
break;
// IA2 CWS. MT: Still using VCLEVENT_TOOLBOX_CLICK, see comment in vcl/source/window/toolbox2.cxx
/*
case VCLEVENT_TOOLBOX_ITEMUPDATED:
{
if ( rVclWindowEvent.GetData() )
{
UpdateChecked_Impl( TOOLBOX_ITEM_NOTFOUND );
UpdateIndeterminate_Impl( (sal_Int32)rVclWindowEvent.GetData() );
}
break;
}
*/
case VCLEVENT_TOOLBOX_HIGHLIGHT:
UpdateFocus_Impl();
break;
case VCLEVENT_TOOLBOX_HIGHLIGHTOFF:
ReleaseFocus_Impl( (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData() );
break;
case VCLEVENT_TOOLBOX_ITEMADDED :
// UpdateItem_Impl( (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData(), VCLEVENT_TOOLBOX_ITEMADDED == rVclWindowEvent.GetId() );
UpdateItem_Impl( (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData(), sal_True );
break;
case VCLEVENT_TOOLBOX_ITEMREMOVED :
case VCLEVENT_TOOLBOX_ALLITEMSCHANGED :
{
UpdateAllItems_Impl();
break;
}
case VCLEVENT_TOOLBOX_ITEMWINDOWCHANGED:
{
sal_Int32 nPos = (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData();
ToolBoxItemsMap::iterator aAccessiblePos( m_aAccessibleChildren.find( nPos ) );
if ( m_aAccessibleChildren.end() != aAccessiblePos )
{
implReleaseToolboxItem( aAccessiblePos, false, true );
m_aAccessibleChildren.erase (aAccessiblePos);
}
Any aNewValue;
aNewValue <<= getAccessibleChild(nPos);
NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), aNewValue );
break;
}
case VCLEVENT_TOOLBOX_ITEMTEXTCHANGED :
UpdateItemName_Impl( (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData() );
break;
case VCLEVENT_TOOLBOX_ITEMENABLED :
case VCLEVENT_TOOLBOX_ITEMDISABLED :
{
UpdateItemEnabled_Impl( (sal_Int32)(sal_IntPtr)rVclWindowEvent.GetData() );
break;
}
case VCLEVENT_DROPDOWN_OPEN:
case VCLEVENT_DROPDOWN_CLOSE:
{
UpdateCustomPopupItemp_Impl( static_cast< Window* >( rVclWindowEvent.GetData() ), rVclWindowEvent.GetId() == VCLEVENT_DROPDOWN_OPEN );
break;
}
case VCLEVENT_OBJECT_DYING :
{
// if this toolbox is a subtoolbox, we have to relese it from its parent
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox && pToolBox->GetParent() &&
pToolBox->GetParent()->GetType() == WINDOW_TOOLBOX )
{
VCLXAccessibleToolBox* pParent = static_cast< VCLXAccessibleToolBox* >(
pToolBox->GetParent()->GetAccessible()->getAccessibleContext().get() );
if ( pParent )
pParent->ReleaseSubToolBox( pToolBox );
}
// dispose all items
for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
aIter != m_aAccessibleChildren.end(); ++aIter )
{
implReleaseToolboxItem( aIter, false, true );
}
m_aAccessibleChildren.clear();
//!!! no break to call base class
}
default:
VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
}
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent )
{
switch ( rVclWindowEvent.GetId() )
{
case VCLEVENT_WINDOW_SHOW: // send create on show for direct accessible children
{
Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
if ( xReturn.is() )
NotifyAccessibleEvent( AccessibleEventId::CHILD, Any(), makeAny(xReturn) );
else
HandleSubToolBarEvent( rVclWindowEvent, true );
}
break;
default:
VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent );
}
}
// -----------------------------------------------------------------------------
// XInterface
// -----------------------------------------------------------------------------
IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
// -----------------------------------------------------------------------------
// XTypeProvider
// -----------------------------------------------------------------------------
IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleToolBox, VCLXAccessibleComponent, VCLXAccessibleToolBox_BASE )
// -----------------------------------------------------------------------------
// XComponent
// -----------------------------------------------------------------------------
void SAL_CALL VCLXAccessibleToolBox::disposing()
{
VCLXAccessibleComponent::disposing();
// release the items
for ( ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.begin();
aIter != m_aAccessibleChildren.end(); ++aIter )
{
implReleaseToolboxItem( aIter, false, true );
}
m_aAccessibleChildren.clear();
}
// -----------------------------------------------------------------------------
// XServiceInfo
// -----------------------------------------------------------------------------
::rtl::OUString VCLXAccessibleToolBox::getImplementationName() throw (RuntimeException)
{
return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleToolBox" );
}
// -----------------------------------------------------------------------------
Sequence< ::rtl::OUString > VCLXAccessibleToolBox::getSupportedServiceNames() throw (RuntimeException)
{
Sequence< ::rtl::OUString > aNames = VCLXAccessibleComponent::getSupportedServiceNames();
sal_Int32 nLength = aNames.getLength();
aNames.realloc( nLength + 1 );
aNames[nLength] = ::rtl::OUString::createFromAscii( "com.sun.star.accessibility.AccessibleToolBox" );
return aNames;
}
// -----------------------------------------------------------------------------
// XAccessibleContext
// -----------------------------------------------------------------------------
sal_Int32 SAL_CALL VCLXAccessibleToolBox::getAccessibleChildCount( ) throw (RuntimeException)
{
comphelper::OExternalLockGuard aGuard( this );
sal_Int32 nCount = 0;
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
nCount = pToolBox->GetItemCount();
return nCount;
}
// -----------------------------------------------------------------------------
Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException)
{
if ( i < 0 || i >= getAccessibleChildCount() )
throw IndexOutOfBoundsException();
comphelper::OExternalLockGuard aGuard( this );
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
Reference< XAccessible > xChild;
// search for the child
ToolBoxItemsMap::iterator aIter = m_aAccessibleChildren.find(i);
if ( m_aAccessibleChildren.end() == aIter )
{
sal_uInt16 nItemId = pToolBox->GetItemId( (sal_uInt16)i );
sal_uInt16 nHighlightItemId = pToolBox->GetHighlightItemId();
Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
// not found -> create a new child
VCLXAccessibleToolBoxItem* pChild = new VCLXAccessibleToolBoxItem( pToolBox, i );
Reference< XAccessible> xParent = pChild;
if ( pItemWindow )
{
xChild = new OToolBoxWindowItem(0,::comphelper::getProcessServiceFactory(),pItemWindow->GetAccessible(),xParent);
pItemWindow->SetAccessible(xChild);
pChild->SetChild( xChild );
}
xChild = pChild;
if ( nHighlightItemId > 0 && nItemId == nHighlightItemId )
pChild->SetFocus( sal_True );
if ( pToolBox->IsItemChecked( nItemId ) )
pChild->SetChecked( sal_True );
if ( pToolBox->GetItemState( nItemId ) == STATE_DONTKNOW )
pChild->SetIndeterminate( true );
m_aAccessibleChildren.insert( ToolBoxItemsMap::value_type( i, xChild ) );
}
else
{
// found it
xChild = aIter->second;
}
return xChild;
}
return NULL;
}
// -----------------------------------------------------------------------------
Reference< XAccessible > SAL_CALL VCLXAccessibleToolBox::getAccessibleAtPoint( const awt::Point& _rPoint ) throw (RuntimeException)
{
comphelper::OExternalLockGuard aGuard( this );
Reference< XAccessible > xAccessible;
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pToolBox )
{
sal_uInt16 nItemPos = pToolBox->GetItemPos( VCLPoint( _rPoint ) );
if ( nItemPos != TOOLBOX_ITEM_NOTFOUND )
xAccessible = getAccessibleChild( nItemPos );
}
return xAccessible;
}
// -----------------------------------------------------------------------------
Reference< XAccessible > VCLXAccessibleToolBox::GetItemWindowAccessible( const VclWindowEvent& rVclWindowEvent )
{
Reference< XAccessible > xReturn;
Window* pChildWindow = (Window *) rVclWindowEvent.GetData();
ToolBox* pToolBox = static_cast< ToolBox* >( GetWindow() );
if ( pChildWindow && pToolBox )
{
sal_uInt16 nCount = pToolBox->GetItemCount();
for (sal_uInt16 i = 0 ; i < nCount && !xReturn.is() ; ++i)
{
sal_uInt16 nItemId = pToolBox->GetItemId( i );
Window* pItemWindow = pToolBox->GetItemWindow( nItemId );
if ( pItemWindow == pChildWindow )
xReturn = getAccessibleChild(i);
}
}
return xReturn;
}
// -----------------------------------------------------------------------------
Reference< XAccessible > VCLXAccessibleToolBox::GetChildAccessible( const VclWindowEvent& rVclWindowEvent )
{
Reference< XAccessible > xReturn = GetItemWindowAccessible(rVclWindowEvent);
if ( !xReturn.is() )
xReturn = VCLXAccessibleComponent::GetChildAccessible(rVclWindowEvent);
return xReturn;
}
// -----------------------------------------------------------------------------
// XAccessibleSelection
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
OExternalLockGuard aGuard( this );
if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
throw IndexOutOfBoundsException();
ToolBox * pToolBox = static_cast < ToolBox * > ( GetWindow() );
sal_uInt16 nPos = static_cast < sal_uInt16 > (nChildIndex);
pToolBox->ChangeHighlight( nPos );
}
// -----------------------------------------------------------------------------
sal_Bool VCLXAccessibleToolBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
OExternalLockGuard aGuard( this );
if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
throw IndexOutOfBoundsException();
ToolBox * pToolBox = static_cast < ToolBox * > ( GetWindow() );
sal_uInt16 nPos = static_cast < sal_uInt16 > (nChildIndex);
if ( pToolBox != NULL && pToolBox->GetHighlightItemId() == pToolBox->GetItemId( nPos ) )
return sal_True;
else
return sal_False;
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::clearAccessibleSelection( ) throw (RuntimeException)
{
OExternalLockGuard aGuard( this );
ToolBox * pToolBox = static_cast < ToolBox * > ( GetWindow() );
pToolBox -> LoseFocus();
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::selectAllAccessibleChildren( ) throw (RuntimeException)
{
OExternalLockGuard aGuard( this );
// intentionally empty. makes no sense for a toolbox
}
// -----------------------------------------------------------------------------
sal_Int32 VCLXAccessibleToolBox::getSelectedAccessibleChildCount( ) throw (RuntimeException)
{
OExternalLockGuard aGuard( this );
sal_Int32 nRet = 0;
for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
{
if ( isAccessibleChildSelected( i ) )
{
nRet = 1;
break; // a toolbox can only have (n)one selected child
}
}
return nRet;
}
// -----------------------------------------------------------------------------
Reference< XAccessible > VCLXAccessibleToolBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
OExternalLockGuard aGuard( this );
if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
throw IndexOutOfBoundsException();
Reference< XAccessible > xChild;
for ( sal_Int32 i = 0, j = 0, nCount = getAccessibleChildCount(); i < nCount; i++ )
{
if ( isAccessibleChildSelected( i ) && ( j++ == nSelectedChildIndex ) )
{
xChild = getAccessibleChild( i );
break;
}
}
return xChild;
}
// -----------------------------------------------------------------------------
void VCLXAccessibleToolBox::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
{
OExternalLockGuard aGuard( this );
if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() )
throw IndexOutOfBoundsException();
clearAccessibleSelection(); // a toolbox can only have (n)one selected child
}
// -----------------------------------------------------------------------------