diff options
Diffstat (limited to 'svx/source/form/fmshell.cxx')
-rw-r--r-- | svx/source/form/fmshell.cxx | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/svx/source/form/fmshell.cxx b/svx/source/form/fmshell.cxx index c40841f221..4a9a859c0e 100644 --- a/svx/source/form/fmshell.cxx +++ b/svx/source/form/fmshell.cxx @@ -78,6 +78,7 @@ #include <svx/fmglob.hxx> #include <svl/eitem.hxx> #include <tools/shl.hxx> +#include <tools/diagnose_ex.h> #include <svx/svdpage.hxx> #include <svx/fmmodel.hxx> #include <svx/dialmgr.hxx> @@ -98,6 +99,8 @@ #include <svx/svxdlg.hxx> //CHINA001 #include <svx/dialogs.hrc> //CHINA001 +#include "svx/sdrobjectfilter.hxx" + #define HANDLE_SQL_ERRORS( action, successflag, context, message ) \ try \ { \ @@ -544,7 +547,7 @@ void FmFormShell::Execute(SfxRequest &rReq) case SID_FM_SCROLLBAR: case SID_FM_SPINBUTTON: { - SFX_REQUEST_ARG( rReq, pGrabFocusItem, SfxBoolItem, SID_FM_GRABCONTROLFOCUS, sal_False ); + SFX_REQUEST_ARG( rReq, pGrabFocusItem, SfxBoolItem, SID_FM_TOGGLECONTROLFOCUS, sal_False ); if ( pGrabFocusItem && pGrabFocusItem->GetValue() ) { // see below SfxViewShell* pShell = GetViewShell(); @@ -572,9 +575,9 @@ void FmFormShell::Execute(SfxRequest &rReq) { // #99013# if selected with control key, return focus to current view // do this asynchron, so that the creation can be finished first - // reusing the SID_FM_GRABCONTROLFOCUS is somewhat hacky ... which it wouldn't if it would have another + // reusing the SID_FM_TOGGLECONTROLFOCUS is somewhat hacky ... which it wouldn't if it would have another // name, so I do not really have a big problem with this .... - SfxBoolItem aGrabFocusIndicatorItem( SID_FM_GRABCONTROLFOCUS, sal_True ); + SfxBoolItem aGrabFocusIndicatorItem( SID_FM_TOGGLECONTROLFOCUS, sal_True ); GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( nSlot, SFX_CALLMODE_ASYNCHRON, &aGrabFocusIndicatorItem, NULL ); } @@ -595,11 +598,27 @@ void FmFormShell::Execute(SfxRequest &rReq) } break; - case SID_FM_GRABCONTROLFOCUS: + case SID_FM_TOGGLECONTROLFOCUS: { FmFormView* pFormView = GetFormView(); - if ( pFormView ) + if ( !pFormView ) + break; + + // if we execute this ourself, then either the application does not implement an own handling for this, + // of we're on the top of the dispatcher stack, which means a control has the focus. + // In the latter case, we put the focus to the document window, otherwise, we focus the first control + const bool bHasControlFocus = GetImpl()->HasControlFocus(); + if ( bHasControlFocus ) + { + const OutputDevice* pDevice = GetCurrentViewDevice(); + Window* pWindow = dynamic_cast< Window* >( const_cast< OutputDevice* >( pDevice ) ); + if ( pWindow ) + pWindow->GrabFocus(); + } + else + { pFormView->GrabFirstControlFocus( ); + } } break; @@ -1353,6 +1372,78 @@ namespace } //------------------------------------------------------------------------ +void FmFormShell::ToggleControlFocus( const SdrUnoObj& i_rUnoObject, const SdrView& i_rView, OutputDevice& i_rDevice ) const +{ + try + { + // check if the focus currently is in a control + // Well, okay, do it the other way 'round: Check whether the current control of the active controller + // actually has the focus. This should be equivalent. + const bool bHasControlFocus = GetImpl()->HasControlFocus(); + + if ( bHasControlFocus ) + { + Window* pWindow( dynamic_cast< Window* >( &i_rDevice ) ); + OSL_ENSURE( pWindow, "FmFormShell::ToggleControlFocus: I need a Window, really!" ); + if ( pWindow ) + pWindow->GrabFocus(); + } + else + { + Reference< XControl > xControl; + GetFormControl( i_rUnoObject.GetUnoControlModel(), i_rView, i_rDevice, xControl ); + Reference< XWindow > xControlWindow( xControl, UNO_QUERY ); + if ( xControlWindow.is() ) + xControlWindow->setFocus(); + } + } + catch( const Exception& ) + { + DBG_UNHANDLED_EXCEPTION(); + } +} + +//------------------------------------------------------------------------ +namespace +{ + class FocusableControlsFilter : public ::svx::ISdrObjectFilter + { + public: + FocusableControlsFilter( const SdrView& i_rView, const OutputDevice& i_rDevice ) + :m_rView( i_rView ) + ,m_rDevice( i_rDevice ) + { + } + + public: + virtual bool includeObject( const SdrObject& i_rObject ) const + { + const SdrUnoObj* pUnoObj = dynamic_cast< const SdrUnoObj* >( &i_rObject ); + if ( !pUnoObj ) + return false; + + Reference< XControl > xControl = pUnoObj->GetUnoControl( m_rView, m_rDevice ); + return FmXFormView::isFocusable( xControl ); + } + + private: + const SdrView& m_rView; + const OutputDevice& m_rDevice; + }; +} + +//------------------------------------------------------------------------ +::std::auto_ptr< ::svx::ISdrObjectFilter > FmFormShell::CreateFocusableControlFilter( const SdrView& i_rView, const OutputDevice& i_rDevice ) const +{ + ::std::auto_ptr< ::svx::ISdrObjectFilter > pFilter; + + if ( !i_rView.IsDesignMode() ) + pFilter.reset( new FocusableControlsFilter( i_rView, i_rDevice ) ); + + return pFilter; +} + +//------------------------------------------------------------------------ SdrUnoObj* FmFormShell::GetFormControl( const Reference< XControlModel >& _rxModel, const SdrView& _rView, const OutputDevice& _rDevice, Reference< XControl >& _out_rxControl ) const { if ( !_rxModel.is() ) |