/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * 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_toolkit.hxx" #include #include #include #include #include #include #include #include #include //........................................................................ namespace toolkit { //........................................................................ using ::comphelper::OContextEntryGuard; 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; //==================================================================== //= OAccessibleControlContext //==================================================================== //-------------------------------------------------------------------- OAccessibleControlContext::OAccessibleControlContext() :OAccessibleControlContext_Base( ) { // nothing to do here, we have a late ctor } //-------------------------------------------------------------------- OAccessibleControlContext::~OAccessibleControlContext() { ensureDisposed(); } //-------------------------------------------------------------------- IMPLEMENT_FORWARD_XINTERFACE3( OAccessibleControlContext, OAccessibleControlContext_Base, OAccessibleImplementationAccess, OAccessibleControlContext_IBase ) IMPLEMENT_FORWARD_XTYPEPROVIDER3( OAccessibleControlContext, OAccessibleControlContext_Base, OAccessibleImplementationAccess, OAccessibleControlContext_IBase ) // (order matters: the first is the class name, the second is the class doing the ref counting) //-------------------------------------------------------------------- void OAccessibleControlContext::Init( const Reference< XAccessible >& _rxCreator ) SAL_THROW( ( Exception ) ) { OContextEntryGuard aGuard( this ); // retrieve the model of the control OSL_ENSURE( !m_xControlModel.is(), "OAccessibleControlContext::Init: already know a control model....!???" ); Reference< awt::XControl > xControl( _rxCreator, UNO_QUERY ); if ( xControl.is() ) m_xControlModel = m_xControlModel.query( xControl->getModel() ); OSL_ENSURE( m_xControlModel.is(), "OAccessibleControlContext::Init: invalid creator (no control, or control without model!" ); if ( !m_xControlModel.is() ) throw DisposedException(); // caught by the caller (the create method) // start listening at the model startModelListening(); // announce the XAccessible to our base class OAccessibleControlContext_Base::lateInit( _rxCreator ); } //-------------------------------------------------------------------- OAccessibleControlContext* OAccessibleControlContext::create( const Reference< XAccessible >& _rxCreator ) SAL_THROW( ( ) ) { OAccessibleControlContext* pNew = NULL; try { pNew = new OAccessibleControlContext; pNew->Init( _rxCreator ); } catch( const Exception& ) { OSL_ENSURE( sal_False, "OAccessibleControlContext::create: caught an exception from the late ctor!" ); } return pNew; } //-------------------------------------------------------------------- void OAccessibleControlContext::startModelListening( ) SAL_THROW( ( Exception ) ) { Reference< XComponent > xModelComp( m_xControlModel, UNO_QUERY ); OSL_ENSURE( xModelComp.is(), "OAccessibleControlContext::startModelListening: invalid model!" ); if ( xModelComp.is() ) xModelComp->addEventListener( this ); } //-------------------------------------------------------------------- void OAccessibleControlContext::stopModelListening( ) SAL_THROW( ( Exception ) ) { Reference< XComponent > xModelComp( m_xControlModel, UNO_QUERY ); OSL_ENSURE( xModelComp.is(), "OAccessibleControlContext::stopModelListening: invalid model!" ); if ( xModelComp.is() ) xModelComp->removeEventListener( this ); } //-------------------------------------------------------------------- sal_Int32 SAL_CALL OAccessibleControlContext::getAccessibleChildCount( ) throw (RuntimeException) { // we do not have children return 0; } //-------------------------------------------------------------------- Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleChild( sal_Int32 ) throw (IndexOutOfBoundsException, RuntimeException) { // we do not have children throw IndexOutOfBoundsException(); } //-------------------------------------------------------------------- Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleParent( ) throw (RuntimeException) { OContextEntryGuard aGuard( this ); OSL_ENSURE( implGetForeignControlledParent().is(), "OAccessibleControlContext::getAccessibleParent: somebody forgot to set a parent!" ); // this parent of us is foreign controlled - somebody has to set it using the OAccessibleImplementationAccess // class, before integrating our instance into an AccessibleDocumentModel return implGetForeignControlledParent(); } //-------------------------------------------------------------------- sal_Int16 SAL_CALL OAccessibleControlContext::getAccessibleRole( ) throw (RuntimeException) { return AccessibleRole::SHAPE; } //-------------------------------------------------------------------- ::rtl::OUString SAL_CALL OAccessibleControlContext::getAccessibleDescription( ) throw (RuntimeException) { OContextEntryGuard aGuard( this ); return getModelStringProperty( "HelpText" ); } //-------------------------------------------------------------------- ::rtl::OUString SAL_CALL OAccessibleControlContext::getAccessibleName( ) throw (RuntimeException) { OContextEntryGuard aGuard( this ); return getModelStringProperty( "Name" ); } //-------------------------------------------------------------------- Reference< XAccessibleRelationSet > SAL_CALL OAccessibleControlContext::getAccessibleRelationSet( ) throw (RuntimeException) { return NULL; } //-------------------------------------------------------------------- Reference< XAccessibleStateSet > SAL_CALL OAccessibleControlContext::getAccessibleStateSet( ) throw (RuntimeException) { ::osl::MutexGuard aGuard( GetMutex() ); // no OContextEntryGuard here, as we do not want to throw an exception in case we're not alive anymore ::utl::AccessibleStateSetHelper* pStateSet = NULL; if ( isAlive() ) { // no own states, only the ones which are foreign controlled pStateSet = new ::utl::AccessibleStateSetHelper( implGetForeignControlledStates() ); } else { // only the DEFUNC state if we're already disposed pStateSet = new ::utl::AccessibleStateSetHelper; pStateSet->AddState( AccessibleStateType::DEFUNC ); } return pStateSet; } //-------------------------------------------------------------------- void SAL_CALL OAccessibleControlContext::disposing( const EventObject& #if OSL_DEBUG_LEVEL > 0 _rSource #endif ) throw ( RuntimeException ) { OSL_ENSURE( Reference< XPropertySet >( _rSource.Source, UNO_QUERY ).get() == m_xControlModel.get(), "OAccessibleControlContext::disposing: where did this come from?" ); stopModelListening( ); m_xControlModel.clear(); m_xModelPropsInfo.clear(); OAccessibleControlContext_Base::disposing(); } //-------------------------------------------------------------------- ::rtl::OUString OAccessibleControlContext::getModelStringProperty( const sal_Char* _pPropertyName ) { ::rtl::OUString sReturn; try { if ( !m_xModelPropsInfo.is() && m_xControlModel.is() ) m_xModelPropsInfo = m_xControlModel->getPropertySetInfo(); ::rtl::OUString sPropertyName( ::rtl::OUString::createFromAscii( _pPropertyName ) ); if ( m_xModelPropsInfo.is() && m_xModelPropsInfo->hasPropertyByName( sPropertyName ) ) m_xControlModel->getPropertyValue( sPropertyName ) >>= sReturn; } catch( const Exception& ) { OSL_ENSURE( sal_False, "OAccessibleControlContext::getModelStringProperty: caught an exception!" ); } return sReturn; } //-------------------------------------------------------------------- Window* OAccessibleControlContext::implGetWindow( Reference< awt::XWindow >* _pxUNOWindow ) const { Reference< awt::XControl > xControl( getAccessibleCreator(), UNO_QUERY ); Reference< awt::XWindow > xWindow; if ( xControl.is() ) xWindow = xWindow.query( xControl->getPeer() ); Window* pWindow = xWindow.is() ? VCLUnoHelper::GetWindow( xWindow ) : NULL; if ( _pxUNOWindow ) *_pxUNOWindow = xWindow; return pWindow; } //-------------------------------------------------------------------- awt::Rectangle SAL_CALL OAccessibleControlContext::implGetBounds( ) throw (RuntimeException) { SolarMutexGuard aSolarGuard; // want to do some VCL stuff here ... OContextEntryGuard aGuard( this ); OSL_ENSURE( sal_False, "OAccessibleControlContext::implGetBounds: performance issue: forced to calc the size myself!" ); // In design mode (and this is what this class is for), the surrounding shape (if any) should handle this call // The problem is that in design mode, our size may not be correct (in the drawing layer, controls are // positioned/sized for painting only), and that calculation of our position is expensive // what we know (or can obtain from somewhere): // * the PosSize of our peer, relative to it's parent window // * the parent window which the PosSize is relative to // * our foreign controlled accessible parent // from this info, we can determine the the position of our peer relative to the foreign parent // our control Reference< awt::XWindow > xWindow; Window* pVCLWindow = implGetWindow( &xWindow ); awt::Rectangle aBounds( 0, 0, 0, 0 ); if ( xWindow.is() ) { // ugly, but .... though the XWindow has a getPosSize, it is impossible to determine the // parent which this position/size is relative to. This means we must tunnel UNO and ask the // implementation Window* pVCLParent = pVCLWindow ? pVCLWindow->GetParent() : NULL; // the relative location of the window ::Point aWindowRelativePos( 0, 0); if ( pVCLWindow ) aWindowRelativePos = pVCLWindow->GetPosPixel(); // the screnn position of the "window parent" of the control ::Point aVCLParentScreenPos( 0, 0 ); if ( pVCLParent ) aVCLParentScreenPos = pVCLParent->GetPosPixel(); // the screen position of the "accessible parent" of the control Reference< XAccessible > xParentAcc( implGetForeignControlledParent() ); Reference< XAccessibleComponent > xParentAccComponent; if ( xParentAcc.is() ) xParentAccComponent = xParentAccComponent.query( xParentAcc->getAccessibleContext() ); awt::Point aAccParentScreenPos( 0, 0 ); if ( xParentAccComponent.is() ) aAccParentScreenPos = xParentAccComponent->getLocationOnScreen(); // now the size of the control aBounds = xWindow->getPosSize(); // correct the pos aBounds.X = aWindowRelativePos.X() + aVCLParentScreenPos.X() - aAccParentScreenPos.X; aBounds.Y = aWindowRelativePos.Y() + aVCLParentScreenPos.Y() - aAccParentScreenPos.Y; } return aBounds; } //-------------------------------------------------------------------- Reference< XAccessible > SAL_CALL OAccessibleControlContext::getAccessibleAtPoint( const awt::Point& /* _rPoint */ ) throw (RuntimeException) { // no children at all return NULL; } //-------------------------------------------------------------------- void SAL_CALL OAccessibleControlContext::grabFocus( ) throw (RuntimeException) { OSL_ENSURE( sal_False, "OAccessibleControlContext::grabFocus: !isFocusTraversable, but grabFocus!" ); } //-------------------------------------------------------------------- Any SAL_CALL OAccessibleControlContext::getAccessibleKeyBinding( ) throw (RuntimeException) { // we do not have any key bindings to activate a UNO control in design mode return Any(); } //-------------------------------------------------------------------- sal_Int32 SAL_CALL OAccessibleControlContext::getForeground( ) throw (::com::sun::star::uno::RuntimeException) { SolarMutexGuard aSolarGuard; // want to do some VCL stuff here ... OContextEntryGuard aGuard( this ); Window* pWindow = implGetWindow( ); sal_Int32 nColor = 0; if ( pWindow ) { if ( pWindow->IsControlForeground() ) nColor = pWindow->GetControlForeground().GetColor(); else { Font aFont; if ( pWindow->IsControlFont() ) aFont = pWindow->GetControlFont(); else aFont = pWindow->GetFont(); nColor = aFont.GetColor().GetColor(); } } return nColor; } //-------------------------------------------------------------------- sal_Int32 SAL_CALL OAccessibleControlContext::getBackground( ) throw (::com::sun::star::uno::RuntimeException) { SolarMutexGuard aSolarGuard; // want to do some VCL stuff here ... OContextEntryGuard aGuard( this ); Window* pWindow = implGetWindow( ); sal_Int32 nColor = 0; if ( pWindow ) { if ( pWindow->IsControlBackground() ) nColor = pWindow->GetControlBackground().GetColor(); else nColor = pWindow->GetBackground().GetColor().GetColor(); } return nColor; } //........................................................................ } //namespace toolkit //........................................................................ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */