diff options
Diffstat (limited to 'svx/source/form/fmshell.cxx')
-rw-r--r-- | svx/source/form/fmshell.cxx | 1416 |
1 files changed, 1416 insertions, 0 deletions
diff --git a/svx/source/form/fmshell.cxx b/svx/source/form/fmshell.cxx new file mode 100644 index 0000000000..423bbb7c25 --- /dev/null +++ b/svx/source/form/fmshell.cxx @@ -0,0 +1,1416 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * 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 . + */ + +#include <fmvwimp.hxx> +#include <svx/fmshell.hxx> +#include <svx/fmtools.hxx> +#include <fmprop.hxx> +#include <fmundo.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/awt/XTabControllerModel.hpp> +#include <sfx2/viewfrm.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svl/whiter.hxx> +#include <sfx2/app.hxx> +#include <svl/intitem.hxx> +#include <svl/stritem.hxx> +#include <svl/visitem.hxx> +#include <unotools/moduleoptions.hxx> +#include <sfx2/objface.hxx> +#include <sfx2/request.hxx> +#include <sfx2/dispatch.hxx> +#include <svx/svdobj.hxx> +#include <svx/fmpage.hxx> +#include <svx/svditer.hxx> + +#include <svx/svxids.hrc> + +#include <svx/svdobjkind.hxx> +#include <svl/eitem.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <svx/svdpage.hxx> +#include <svx/fmmodel.hxx> +#include <fmshimp.hxx> +#include <svx/svdpagv.hxx> +#include <sfx2/objitem.hxx> +#include <sfx2/viewsh.hxx> +#include <fmexpl.hxx> +#include <formcontrolling.hxx> +#include <comphelper/types.hxx> +#include <fmdocumentclassification.hxx> +#include <formtoolbars.hxx> + +#include <svx/svxdlg.hxx> + +#include <svx/sdrobjectfilter.hxx> + +#define ShellClass_FmFormShell +#include <svxslots.hxx> + +#include <memory> + +// is used for Invalidate -> maintain it as well +// sort ascending !!!!!! +sal_uInt16 const ControllerSlotMap[] = // slots of the controller +{ + SID_FM_CONFIG, + SID_FM_PUSHBUTTON, + SID_FM_RADIOBUTTON, + SID_FM_CHECKBOX, + SID_FM_FIXEDTEXT, + SID_FM_GROUPBOX, + SID_FM_EDIT, + SID_FM_LISTBOX, + SID_FM_COMBOBOX, + SID_FM_DBGRID, + SID_FM_IMAGEBUTTON, + SID_FM_FILECONTROL, + SID_FM_NAVIGATIONBAR, + SID_FM_CTL_PROPERTIES, + SID_FM_PROPERTIES, + SID_FM_TAB_DIALOG, + SID_FM_ADD_FIELD, + SID_FM_DESIGN_MODE, + SID_FM_SHOW_FMEXPLORER, + SID_FM_SHOW_PROPERTIES, + SID_FM_FMEXPLORER_CONTROL, + SID_FM_DATEFIELD, + SID_FM_TIMEFIELD, + SID_FM_NUMERICFIELD, + SID_FM_CURRENCYFIELD, + SID_FM_PATTERNFIELD, + SID_FM_OPEN_READONLY, + SID_FM_IMAGECONTROL, + SID_FM_USE_WIZARDS, + SID_FM_FORMATTEDFIELD, + SID_FM_FILTER_NAVIGATOR, + SID_FM_AUTOCONTROLFOCUS, + SID_FM_SCROLLBAR, + SID_FM_SPINBUTTON, + SID_FM_SHOW_DATANAVIGATOR, + SID_FM_DATANAVIGATOR_CONTROL, + + 0 +}; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::sdbcx; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::form; +using namespace ::com::sun::star::form::runtime; +using namespace ::svxform; + +FmDesignModeChangedHint::FmDesignModeChangedHint( bool bDesMode ) + :m_bDesignMode( bDesMode ) +{ +} + + +FmDesignModeChangedHint::~FmDesignModeChangedHint() +{ +} + +SFX_IMPL_INTERFACE(FmFormShell, SfxShell) + +void FmFormShell::InitInterface_Impl() +{ + GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_NAVIGATION, SfxVisibilityFlags::Standard|SfxVisibilityFlags::ReadonlyDoc, + ToolbarId::SvxTbx_Form_Navigation, + SfxShellFeature::FormShowDatabaseBar); + + GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_NAVIGATION, SfxVisibilityFlags::Standard|SfxVisibilityFlags::ReadonlyDoc, + ToolbarId::SvxTbx_Form_Filter, + SfxShellFeature::FormShowFilterBar); + + GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Standard | SfxVisibilityFlags::ReadonlyDoc, + ToolbarId::SvxTbx_Text_Control_Attributes, + SfxShellFeature::FormShowTextControlBar); + + GetStaticInterface()->RegisterChildWindow(SID_FM_ADD_FIELD, false, SfxShellFeature::FormShowField); + GetStaticInterface()->RegisterChildWindow(SID_FM_SHOW_PROPERTIES, false, SfxShellFeature::FormShowProperties); + GetStaticInterface()->RegisterChildWindow(SID_FM_SHOW_FMEXPLORER, false, SfxShellFeature::FormShowExplorer); + GetStaticInterface()->RegisterChildWindow(SID_FM_FILTER_NAVIGATOR, false, SfxShellFeature::FormShowFilterNavigator); + GetStaticInterface()->RegisterChildWindow(SID_FM_SHOW_DATANAVIGATOR, false, SfxShellFeature::FormShowDataNavigator); + + GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Standard, + ToolbarId::SvxTbx_Controls, + SfxShellFeature::FormTBControls); + + GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Standard, + ToolbarId::SvxTbx_FormDesign, + SfxShellFeature::FormTBDesign); +} + + +FmFormShell::FmFormShell( SfxViewShell* _pParent, FmFormView* pView ) + :SfxShell(_pParent) + ,m_pImpl(new FmXFormShell(*this, &_pParent->GetViewFrame())) + ,m_pFormView( pView ) + ,m_pFormModel( nullptr ) + ,m_nLastSlot( 0 ) + ,m_bDesignMode( true ) + ,m_bHasForms(false) +{ + SetPool( &SfxGetpApp()->GetPool() ); + SetName( "Form" ); + + SetView(m_pFormView); +} + + +FmFormShell::~FmFormShell() +{ + if ( m_pFormView ) + SetView( nullptr ); + + m_pImpl->dispose(); +} + + +void FmFormShell::NotifyMarkListChanged(FmFormView* pWhichView) +{ + FmNavViewMarksChanged aChangeNotification(pWhichView); + Broadcast(aChangeNotification); +} + + +bool FmFormShell::PrepareClose(bool bUI) +{ + if (GetImpl()->didPrepareClose_Lock()) + // we already made a PrepareClose for the current modifications of the current form + return true; + + bool bResult = true; + // Save the data records, not in DesignMode and FilterMode + if (!m_bDesignMode && !GetImpl()->isInFilterMode_Lock() && + m_pFormView && m_pFormView->GetActualOutDev() && + m_pFormView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW) + { + SdrPageView* pCurPageView = m_pFormView->GetSdrPageView(); + + // sal_uInt16 nPos = pCurPageView ? pCurPageView->GetWinList().Find((OutputDevice*)m_pFormView->GetActualOutDev()) : SDRPAGEVIEWWIN_NOTFOUND; + SdrPageWindow* pWindow = pCurPageView ? pCurPageView->FindPageWindow(*const_cast<OutputDevice*>(m_pFormView->GetActualOutDev())) : nullptr; + + if(pWindow) + { + // First, the current contents of the controls are stored. + // If everything has gone smoothly, the modified records are stored. + if (GetImpl()->getActiveController_Lock().is()) + { + const svx::ControllerFeatures& rController = GetImpl()->getActiveControllerFeatures_Lock(); + if ( rController->commitCurrentControl() ) + { + const bool bModified = rController->isModifiedRow(); + + if ( bModified && bUI ) + { + SfxViewShell* pShell = GetViewShell(); + vcl::Window* pShellWnd = pShell ? pShell->GetWindow() : nullptr; + weld::Widget* pFrameWeld = pShellWnd ? pShellWnd->GetFrameWeld() : nullptr; + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pFrameWeld, "svx/ui/savemodifieddialog.ui")); + std::unique_ptr<weld::MessageDialog> xQry(xBuilder->weld_message_dialog("SaveModifiedDialog")); + switch (xQry->run()) + { + case RET_YES: + bResult = rController->commitCurrentRecord( ); + [[fallthrough]]; + case RET_NO: + GetImpl()->didPrepareClose_Lock(true); + break; + + case RET_CANCEL: + return false; + } + } + } + } + } + } + return bResult; +} + + +void FmFormShell::impl_setDesignMode(bool bDesign) +{ + if (m_pFormView) + { + if (!bDesign) + m_nLastSlot = SID_FM_DESIGN_MODE; + + GetImpl()->SetDesignMode_Lock(bDesign); + // my m_bDesignMode is also set by the Impl ... + } + else + { + m_bHasForms = false; + m_bDesignMode = bDesign; + UIFeatureChanged(); + } + + GetViewShell()->GetViewFrame().GetBindings().Invalidate(ControllerSlotMap); +} + +bool FmFormShell::HasUIFeature(SfxShellFeature nFeature) const +{ + assert((nFeature & ~SfxShellFeature::FormMask) == SfxShellFeature::NONE); + bool bResult = false; + if (nFeature & SfxShellFeature::FormShowDatabaseBar) + { + // only if forms are also available + bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar_Lock() && !GetImpl()->isInFilterMode_Lock(); + } + else if (nFeature & SfxShellFeature::FormShowFilterBar) + { + // only if forms are also available + bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar_Lock() && GetImpl()->isInFilterMode_Lock(); + } + else if (nFeature & SfxShellFeature::FormShowFilterNavigator) + { + bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar_Lock() && GetImpl()->isInFilterMode_Lock(); + } + else if (nFeature & SfxShellFeature::FormShowField) + { + bResult = m_bDesignMode && m_pFormView && m_bHasForms; + } + else if (nFeature & SfxShellFeature::FormShowProperties) + { + bResult = m_bDesignMode && m_pFormView && m_bHasForms; + } + else if (nFeature & SfxShellFeature::FormShowExplorer) + { + bResult = m_bDesignMode; // OJ #101593# && m_pFormView && m_bHasForms; + } + else if (nFeature & SfxShellFeature::FormShowTextControlBar) + { + bResult = !GetImpl()->IsReadonlyDoc_Lock() && m_pImpl->IsActiveControl_Lock(true); + } + else if (nFeature & SfxShellFeature::FormShowDataNavigator) + { + bResult = GetImpl()->isEnhancedForm_Lock(); + } + else if ( (nFeature & SfxShellFeature::FormTBControls) + || (nFeature & SfxShellFeature::FormTBDesign) + ) + { + bResult = true; + } + + return bResult; +} + + +void FmFormShell::Execute(SfxRequest &rReq) +{ + sal_uInt16 nSlot = rReq.GetSlot(); + + + // set MasterSlot + switch( nSlot ) + { + case SID_FM_PUSHBUTTON: + case SID_FM_RADIOBUTTON: + case SID_FM_CHECKBOX: + case SID_FM_FIXEDTEXT: + case SID_FM_GROUPBOX: + case SID_FM_LISTBOX: + case SID_FM_COMBOBOX: + case SID_FM_NAVIGATIONBAR: + case SID_FM_EDIT: + case SID_FM_DBGRID: + case SID_FM_IMAGEBUTTON: + case SID_FM_IMAGECONTROL: + case SID_FM_FILECONTROL: + case SID_FM_DATEFIELD: + case SID_FM_TIMEFIELD: + case SID_FM_NUMERICFIELD: + case SID_FM_CURRENCYFIELD: + case SID_FM_PATTERNFIELD: + case SID_FM_FORMATTEDFIELD: + case SID_FM_SCROLLBAR: + case SID_FM_SPINBUTTON: + m_nLastSlot = nSlot; + break; + } + + + // set the Identifier and Inventor of the Uno control + SdrObjKind nIdentifier = SdrObjKind::NONE; + switch( nSlot ) + { + case SID_FM_CHECKBOX: + nIdentifier = SdrObjKind::FormCheckbox; + break; + case SID_FM_PUSHBUTTON: + nIdentifier = SdrObjKind::FormButton; + break; + case SID_FM_FIXEDTEXT: + nIdentifier = SdrObjKind::FormFixedText; + break; + case SID_FM_LISTBOX: + nIdentifier = SdrObjKind::FormListbox; + break; + case SID_FM_EDIT: + nIdentifier = SdrObjKind::FormEdit; + break; + case SID_FM_RADIOBUTTON: + nIdentifier = SdrObjKind::FormRadioButton; + break; + case SID_FM_GROUPBOX: + nIdentifier = SdrObjKind::FormGroupBox; + break; + case SID_FM_COMBOBOX: + nIdentifier = SdrObjKind::FormCombobox; + break; + case SID_FM_NAVIGATIONBAR: + nIdentifier = SdrObjKind::FormNavigationBar; + break; + case SID_FM_DBGRID: + nIdentifier = SdrObjKind::FormGrid; + break; + case SID_FM_IMAGEBUTTON: + nIdentifier = SdrObjKind::FormImageButton; + break; + case SID_FM_IMAGECONTROL: + nIdentifier = SdrObjKind::FormImageControl; + break; + case SID_FM_FILECONTROL: + nIdentifier = SdrObjKind::FormFileControl; + break; + case SID_FM_DATEFIELD: + nIdentifier = SdrObjKind::FormDateField; + break; + case SID_FM_TIMEFIELD: + nIdentifier = SdrObjKind::FormTimeField; + break; + case SID_FM_NUMERICFIELD: + nIdentifier = SdrObjKind::FormNumericField; + break; + case SID_FM_CURRENCYFIELD: + nIdentifier = SdrObjKind::FormCurrencyField; + break; + case SID_FM_PATTERNFIELD: + nIdentifier = SdrObjKind::FormPatternField; + break; + case SID_FM_FORMATTEDFIELD: + nIdentifier = SdrObjKind::FormFormattedField; + break; + case SID_FM_SCROLLBAR: + nIdentifier = SdrObjKind::FormScrollbar; + break; + case SID_FM_SPINBUTTON: + nIdentifier = SdrObjKind::FormSpinButton; + break; + } + + switch ( nSlot ) + { + case SID_FM_CHECKBOX: + case SID_FM_PUSHBUTTON: + case SID_FM_FIXEDTEXT: + case SID_FM_LISTBOX: + case SID_FM_EDIT: + case SID_FM_RADIOBUTTON: + case SID_FM_COMBOBOX: + case SID_FM_NAVIGATIONBAR: + case SID_FM_GROUPBOX: + case SID_FM_DBGRID: + case SID_FM_IMAGEBUTTON: + case SID_FM_IMAGECONTROL: + case SID_FM_FILECONTROL: + case SID_FM_DATEFIELD: + case SID_FM_TIMEFIELD: + case SID_FM_NUMERICFIELD: + case SID_FM_CURRENCYFIELD: + case SID_FM_PATTERNFIELD: + case SID_FM_FORMATTEDFIELD: + case SID_FM_SCROLLBAR: + case SID_FM_SPINBUTTON: + { + const SfxBoolItem* pGrabFocusItem = rReq.GetArg<SfxBoolItem>(SID_FM_TOGGLECONTROLFOCUS); + if ( pGrabFocusItem && pGrabFocusItem->GetValue() ) + { // see below + SfxViewShell* pShell = GetViewShell(); + vcl::Window* pShellWnd = pShell ? pShell->GetWindow() : nullptr; + if ( pShellWnd ) + pShellWnd->GrabFocus(); + break; + } + + SfxUInt16Item aIdentifierItem( SID_FM_CONTROL_IDENTIFIER, static_cast<sal_uInt16>(nIdentifier) ); + SfxUInt32Item aInventorItem( SID_FM_CONTROL_INVENTOR, sal_uInt32(SdrInventor::FmForm) ); + const SfxPoolItem* pArgs[] = + { + &aIdentifierItem, &aInventorItem, nullptr + }; + const SfxPoolItem* pInternalArgs[] = + { + nullptr + }; + + GetViewShell()->GetViewFrame().GetDispatcher()->Execute( SID_FM_CREATE_CONTROL, SfxCallMode::ASYNCHRON, + pArgs, rReq.GetModifier(), pInternalArgs ); + + if ( rReq.GetModifier() & KEY_MOD1 ) + { + // #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_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_TOGGLECONTROLFOCUS, true ); + GetViewShell()->GetViewFrame().GetDispatcher()->ExecuteList( + nSlot, SfxCallMode::ASYNCHRON, + { &aGrabFocusIndicatorItem }); + } + + rReq.Done(); + } break; + } + + // individual actions + switch( nSlot ) + { + case SID_FM_FORM_DESIGN_TOOLS: + { + FormToolboxes aToolboxAccess(GetImpl()->getHostFrame_Lock()); + aToolboxAccess.toggleToolbox( nSlot ); + rReq.Done(); + } + break; + + case SID_FM_TOGGLECONTROLFOCUS: + { + FmFormView* pFormView = GetFormView(); + 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_Lock(); + if ( bHasControlFocus ) + { + if (m_pFormView) + { + const OutputDevice* pDevice = m_pFormView->GetActualOutDev(); + vcl::Window* pWindow = pDevice->GetOwnerWindow(); + if ( pWindow ) + pWindow->GrabFocus(); + } + } + else + { + pFormView->GrabFirstControlFocus( ); + } + } + break; + + case SID_FM_VIEW_AS_GRID: + GetImpl()->CreateExternalView_Lock(); + break; + case SID_FM_CONVERTTO_EDIT : + case SID_FM_CONVERTTO_BUTTON : + case SID_FM_CONVERTTO_FIXEDTEXT : + case SID_FM_CONVERTTO_LISTBOX : + case SID_FM_CONVERTTO_CHECKBOX : + case SID_FM_CONVERTTO_RADIOBUTTON : + case SID_FM_CONVERTTO_GROUPBOX : + case SID_FM_CONVERTTO_COMBOBOX : + case SID_FM_CONVERTTO_IMAGEBUTTON : + case SID_FM_CONVERTTO_FILECONTROL : + case SID_FM_CONVERTTO_DATE : + case SID_FM_CONVERTTO_TIME : + case SID_FM_CONVERTTO_NUMERIC : + case SID_FM_CONVERTTO_CURRENCY : + case SID_FM_CONVERTTO_PATTERN : + case SID_FM_CONVERTTO_IMAGECONTROL : + case SID_FM_CONVERTTO_FORMATTED : + case SID_FM_CONVERTTO_SCROLLBAR : + case SID_FM_CONVERTTO_SPINBUTTON : + case SID_FM_CONVERTTO_NAVIGATIONBAR : + GetImpl()->executeControlConversionSlot_Lock(FmXFormShell::SlotToIdent(nSlot)); + // after the conversion, re-determine the selection, since the + // selected object has changed + GetImpl()->SetSelection_Lock(GetFormView()->GetMarkedObjectList()); + break; + case SID_FM_LEAVE_CREATE: + m_nLastSlot = 0; + rReq.Done(); + break; + case SID_FM_SHOW_PROPERTY_BROWSER: + { + const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(SID_FM_SHOW_PROPERTIES); + bool bShow = true; + if ( pShowItem ) + bShow = pShowItem->GetValue(); + GetImpl()->ShowSelectionProperties_Lock(bShow); + + rReq.Done(); + } break; + + case SID_FM_PROPERTIES: + { + // display the PropertyBrowser + const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(nSlot); + bool bShow = pShowItem == nullptr || pShowItem->GetValue(); + + InterfaceBag aOnlyTheForm; + aOnlyTheForm.insert(Reference<XInterface>(GetImpl()->getCurrentForm_Lock(), UNO_QUERY)); + GetImpl()->setCurrentSelection_Lock(std::move(aOnlyTheForm)); + + GetImpl()->ShowSelectionProperties_Lock(bShow); + + rReq.Done(); + } break; + + case SID_FM_CTL_PROPERTIES: + { + const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(nSlot); + bool bShow = pShowItem == nullptr || pShowItem->GetValue(); + + OSL_ENSURE( GetImpl()->onlyControlsAreMarked_Lock(), "FmFormShell::Execute: ControlProperties should be disabled!" ); + if ( bShow ) + GetImpl()->selectLastMarkedControls_Lock(); + GetImpl()->ShowSelectionProperties_Lock(bShow); + + rReq.Done(); + } break; + case SID_FM_SHOW_PROPERTIES: + case SID_FM_ADD_FIELD: + case SID_FM_FILTER_NAVIGATOR: + case SID_FM_SHOW_DATANAVIGATOR : + { + GetViewShell()->GetViewFrame().ToggleChildWindow(nSlot); + rReq.Done(); + } break; + case SID_FM_SHOW_FMEXPLORER: + { + if (!m_pFormView) // force setting the view + GetViewShell()->GetViewFrame().GetDispatcher()->Execute(SID_CREATE_SW_DRAWVIEW); + + GetViewShell()->GetViewFrame().ChildWindowExecute(rReq); + rReq.Done(); + } + break; + + case SID_FM_TAB_DIALOG: + { + GetImpl()->ExecuteTabOrderDialog_Lock( + Reference<XTabControllerModel>(GetImpl()->getCurrentForm_Lock(), UNO_QUERY)); + rReq.Done(); + } + break; + + case SID_FM_DESIGN_MODE: + { + const SfxBoolItem* pDesignItem = rReq.GetArg<SfxBoolItem>(nSlot); + bool bDesignMode = pDesignItem ? pDesignItem->GetValue() : !m_bDesignMode; + SetDesignMode( bDesignMode ); + if ( m_bDesignMode == bDesignMode ) + rReq.Done(); + + m_nLastSlot = SID_FM_DESIGN_MODE; + } + break; + + case SID_FM_AUTOCONTROLFOCUS: + { + FmFormModel* pModel = GetFormModel(); + DBG_ASSERT(pModel, "FmFormShell::Execute : invalid call !"); + // should have been disabled in GetState if we don't have a FormModel + pModel->SetAutoControlFocus( !pModel->GetAutoControlFocus() ); + GetViewShell()->GetViewFrame().GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS); + } + break; + case SID_FM_OPEN_READONLY: + { + FmFormModel* pModel = GetFormModel(); + DBG_ASSERT(pModel, "FmFormShell::Execute : invalid call !"); + // should have been disabled in GetState if we don't have a FormModel + pModel->SetOpenInDesignMode( !pModel->GetOpenInDesignMode() ); + GetViewShell()->GetViewFrame().GetBindings().Invalidate(SID_FM_OPEN_READONLY); + } + break; + case SID_FM_USE_WIZARDS: + { + GetImpl()->SetWizardUsing_Lock(!GetImpl()->GetWizardUsing_Lock()); + GetViewShell()->GetViewFrame().GetBindings().Invalidate(SID_FM_USE_WIZARDS); + } + break; + case SID_FM_SEARCH: + { + const svx::ControllerFeatures& rController = GetImpl()->getActiveControllerFeatures_Lock(); + if ( rController->commitCurrentControl() && rController->commitCurrentRecord() ) + GetImpl()->ExecuteSearch_Lock(); + rReq.Done(); + } + break; + + case SID_FM_RECORD_FIRST: + case SID_FM_RECORD_PREV: + case SID_FM_RECORD_NEXT: + case SID_FM_RECORD_LAST: + case SID_FM_RECORD_NEW: + case SID_FM_REFRESH: + case SID_FM_REFRESH_FORM_CONTROL: + case SID_FM_RECORD_DELETE: + case SID_FM_RECORD_UNDO: + case SID_FM_RECORD_SAVE: + case SID_FM_REMOVE_FILTER_SORT: + case SID_FM_SORTDOWN: + case SID_FM_SORTUP: + case SID_FM_AUTOFILTER: + case SID_FM_ORDERCRIT: + case SID_FM_FORM_FILTERED: + { + GetImpl()->ExecuteFormSlot_Lock(nSlot); + rReq.Done(); + } + break; + + case SID_FM_RECORD_ABSOLUTE: + { + const svx::ControllerFeatures& rController = GetImpl()->getNavControllerFeatures_Lock(); + sal_Int32 nRecord = -1; + + const SfxItemSet* pArgs = rReq.GetArgs(); + if ( pArgs ) + { + const SfxPoolItem* pItem; + if ( ( pArgs->GetItemState( FN_PARAM_1, true, &pItem ) ) == SfxItemState::SET ) + { + const SfxInt32Item* pTypedItem = dynamic_cast<const SfxInt32Item* >( pItem ); + if ( pTypedItem ) + nRecord = std::max( pTypedItem->GetValue(), sal_Int32(0) ); + } + } + else + { + SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractFmInputRecordNoDialog> dlg(pFact->CreateFmInputRecordNoDialog(rReq.GetFrameWeld())); + dlg->SetValue( rController->getCursor()->getRow() ); + if ( dlg->Execute() == RET_OK ) + nRecord = dlg->GetValue(); + + rReq.AppendItem( SfxInt32Item( TypedWhichId<SfxInt32Item>(FN_PARAM_1), nRecord ) ); + } + + if ( nRecord != -1 ) + rController->execute( nSlot, "Position", Any( nRecord ) ); + + rReq.Done(); + } break; + case SID_FM_FILTER_EXECUTE: + case SID_FM_FILTER_EXIT: + { + bool bCancelled = ( SID_FM_FILTER_EXIT == nSlot ); + bool bReopenNavigator = false; + + if ( !bCancelled ) + { + // if the filter navigator is still open, we need to close it, so it can possibly + // commit it's most recent changes + if (GetViewShell()) + if ( GetViewShell()->GetViewFrame().HasChildWindow( SID_FM_FILTER_NAVIGATOR ) ) + { + GetViewShell()->GetViewFrame().ToggleChildWindow( SID_FM_FILTER_NAVIGATOR ); + bReopenNavigator = true; + } + + Reference<runtime::XFormController> const xController(GetImpl()->getActiveController_Lock()); + + if ( GetViewShell()->GetViewFrame().HasChildWindow( SID_FM_FILTER_NAVIGATOR ) + // closing the window was denied, for instance because of an invalid criterion + + || ( xController.is() + && !GetImpl()->getActiveControllerFeatures_Lock()->commitCurrentControl() + ) + // committing the controller was denied + ) + { + rReq.Done(); + break; + } + } + + GetImpl()->stopFiltering_Lock(!bCancelled); + rReq.Done(); + + if ( bReopenNavigator ) + // we closed the navigator only to implicitly commit it (as we do not have another + // direct wire to it), but to the user, it should look as it was always open + GetViewShell()->GetViewFrame().ToggleChildWindow( SID_FM_FILTER_NAVIGATOR ); + } + break; + + case SID_FM_FILTER_START: + { + GetImpl()->startFiltering_Lock(); + rReq.Done(); + + // initially open the filter navigator, the whole form based filter is pretty useless without it + SfxBoolItem aIdentifierItem( SID_FM_FILTER_NAVIGATOR, true ); + GetViewShell()->GetViewFrame().GetDispatcher()->ExecuteList( + SID_FM_FILTER_NAVIGATOR, SfxCallMode::ASYNCHRON, + { &aIdentifierItem }); + } break; + } +} + + +void FmFormShell::GetState(SfxItemSet &rSet) +{ + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich = aIter.FirstWhich(); + while ( nWhich ) + { + switch( nWhich ) + { + case SID_FM_FORM_DESIGN_TOOLS: + { + FormToolboxes aToolboxAccess(GetImpl()->getHostFrame_Lock()); + rSet.Put( SfxBoolItem( nWhich, aToolboxAccess.isToolboxVisible( nWhich ) ) ); + } + break; + + case SID_FM_FILTER_EXECUTE: + case SID_FM_FILTER_EXIT: + if (!GetImpl()->isInFilterMode_Lock()) + rSet.DisableItem( nWhich ); + break; + + case SID_FM_USE_WIZARDS: + if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) ) + rSet.Put( SfxVisibilityItem( nWhich, false ) ); + else if (!GetFormModel()) + rSet.DisableItem( nWhich ); + else + rSet.Put(SfxBoolItem(nWhich, GetImpl()->GetWizardUsing_Lock())); + break; + case SID_FM_AUTOCONTROLFOCUS: + if (!GetFormModel()) + rSet.DisableItem( nWhich ); + else + rSet.Put( SfxBoolItem(nWhich, GetFormModel()->GetAutoControlFocus() ) ); + break; + case SID_FM_OPEN_READONLY: + if (!GetFormModel()) + rSet.DisableItem( nWhich ); + else + rSet.Put( SfxBoolItem(nWhich, GetFormModel()->GetOpenInDesignMode() ) ); + break; + + case SID_FM_NAVIGATIONBAR: + case SID_FM_DBGRID: + if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) ) + { + rSet.Put( SfxVisibilityItem( nWhich, false ) ); + break; + } + [[fallthrough]]; + + case SID_FM_SCROLLBAR: + case SID_FM_IMAGECONTROL: + case SID_FM_FILECONTROL: + case SID_FM_CURRENCYFIELD: + case SID_FM_PATTERNFIELD: + case SID_FM_IMAGEBUTTON: + case SID_FM_RADIOBUTTON: + case SID_FM_COMBOBOX: + case SID_FM_GROUPBOX: + case SID_FM_CHECKBOX: + case SID_FM_PUSHBUTTON: + case SID_FM_FIXEDTEXT: + case SID_FM_LISTBOX: + case SID_FM_EDIT: + case SID_FM_DATEFIELD: + case SID_FM_TIMEFIELD: + case SID_FM_NUMERICFIELD: + case SID_FM_FORMATTEDFIELD: + case SID_FM_SPINBUTTON: + if (!m_bDesignMode) + rSet.DisableItem( nWhich ); + else + { + bool bLayerLocked = false; + if (m_pFormView) + { + // If the css::drawing::Layer is locked, the slots must be disabled. #36897 + SdrPageView* pPV = m_pFormView->GetSdrPageView(); + if (pPV != nullptr) + bLayerLocked = pPV->IsLayerLocked(m_pFormView->GetActiveLayer()); + } + if (bLayerLocked) + rSet.DisableItem( nWhich ); + else + rSet.Put( SfxBoolItem(nWhich, (nWhich==m_nLastSlot)) ); + } + break; + case SID_FM_FILTER_NAVIGATOR_CONTROL: + { + if (GetImpl()->isInFilterMode_Lock()) + rSet.Put(SfxObjectItem(nWhich, this)); + else + rSet.Put(SfxObjectItem(nWhich)); + } break; + case SID_FM_FIELDS_CONTROL: + case SID_FM_PROPERTY_CONTROL: + { + if (!m_bDesignMode || !m_pFormView || !m_bHasForms) + rSet.Put(SfxObjectItem(nWhich)); + else + rSet.Put(SfxObjectItem(nWhich, this)); + + } break; + case SID_FM_FMEXPLORER_CONTROL: + case SID_FM_DATANAVIGATOR_CONTROL : + { + if (!m_bDesignMode || !m_pFormView) + rSet.Put(SfxObjectItem(nWhich)); + else + rSet.Put(SfxObjectItem(nWhich, this)); + + } break; + case SID_FM_ADD_FIELD: + case SID_FM_SHOW_FMEXPLORER: + case SID_FM_SHOW_PROPERTIES: + case SID_FM_FILTER_NAVIGATOR: + case SID_FM_SHOW_DATANAVIGATOR: + { + if ( GetViewShell()->GetViewFrame().KnowsChildWindow(nWhich) ) + rSet.Put( SfxBoolItem( nWhich, GetViewShell()->GetViewFrame().HasChildWindow(nWhich)) ); + else + rSet.DisableItem(nWhich); + } break; + + case SID_FM_SHOW_PROPERTY_BROWSER: + { + rSet.Put(SfxBoolItem(nWhich, GetImpl()->IsPropBrwOpen_Lock())); + } + break; + + case SID_FM_CTL_PROPERTIES: + { + // potentially, give the Impl the opportunity to update its + // current objects which are aligned with the current MarkList + if (GetImpl()->IsSelectionUpdatePending_Lock()) + GetImpl()->ForceUpdateSelection_Lock(); + + if (!m_pFormView || !m_bDesignMode || !GetImpl()->onlyControlsAreMarked_Lock()) + rSet.DisableItem( nWhich ); + else + { + bool const bChecked = GetImpl()->IsPropBrwOpen_Lock() && !GetImpl()->isSolelySelected_Lock(GetImpl()->getCurrentForm_Lock()); + // if the property browser is open, and only controls are marked, and the current selection + // does not consist of only the current form, then the current selection is the (composition of) + // the currently marked controls + rSet.Put( SfxBoolItem( nWhich, bChecked ) ); + } + } break; + + case SID_FM_PROPERTIES: + { + // potentially, give the Impl the opportunity to update its + // current objects which are aligned with the current MarkList + if (GetImpl()->IsSelectionUpdatePending_Lock()) + GetImpl()->ForceUpdateSelection_Lock(); + + if (!m_pFormView || !m_bDesignMode || !GetImpl()->getCurrentForm_Lock().is()) + rSet.DisableItem( nWhich ); + else + { + bool const bChecked = GetImpl()->IsPropBrwOpen_Lock() && GetImpl()->isSolelySelected_Lock(GetImpl()->getCurrentForm_Lock()); + rSet.Put(SfxBoolItem(nWhich, bChecked)); + } + } break; + case SID_FM_TAB_DIALOG: + // potentially, give the Impl the opportunity to update its + // current objects which are aligned with the current MarkList + if (GetImpl()->IsSelectionUpdatePending_Lock()) + GetImpl()->ForceUpdateSelection_Lock(); + + if (!m_pFormView || !m_bDesignMode || !GetImpl()->getCurrentForm_Lock().is() ) + rSet.DisableItem( nWhich ); + break; + case SID_FM_DESIGN_MODE: + if (!m_pFormView || GetImpl()->IsReadonlyDoc_Lock()) + rSet.DisableItem( nWhich ); + else + rSet.Put( SfxBoolItem(nWhich, m_bDesignMode) ); + break; + case SID_FM_SEARCH: + case SID_FM_RECORD_FIRST: + case SID_FM_RECORD_NEXT: + case SID_FM_RECORD_PREV: + case SID_FM_RECORD_LAST: + case SID_FM_RECORD_NEW: + case SID_FM_RECORD_DELETE: + case SID_FM_RECORD_ABSOLUTE: + case SID_FM_RECORD_TOTAL: + case SID_FM_RECORD_SAVE: + case SID_FM_RECORD_UNDO: + case SID_FM_FORM_FILTERED: + case SID_FM_REMOVE_FILTER_SORT: + case SID_FM_SORTUP: + case SID_FM_SORTDOWN: + case SID_FM_ORDERCRIT: + case SID_FM_FILTER_START: + case SID_FM_AUTOFILTER: + case SID_FM_REFRESH: + case SID_FM_REFRESH_FORM_CONTROL: + case SID_FM_VIEW_AS_GRID: + GetFormState(rSet,nWhich); + break; + + case SID_FM_CHANGECONTROLTYPE: + { + if ( !m_pFormView || !m_bDesignMode ) + rSet.DisableItem( nWhich ); + else + { + if (!GetImpl()->canConvertCurrentSelectionToControl_Lock(u"ConvertToFixed")) + // if it cannot be converted to a fixed text, it is no single control + rSet.DisableItem( nWhich ); + } + } break; + + case SID_FM_CONVERTTO_FILECONTROL : + case SID_FM_CONVERTTO_CURRENCY : + case SID_FM_CONVERTTO_PATTERN : + case SID_FM_CONVERTTO_IMAGECONTROL : + case SID_FM_CONVERTTO_SCROLLBAR : + case SID_FM_CONVERTTO_NAVIGATIONBAR : + case SID_FM_CONVERTTO_IMAGEBUTTON : + case SID_FM_CONVERTTO_EDIT : + case SID_FM_CONVERTTO_BUTTON : + case SID_FM_CONVERTTO_FIXEDTEXT : + case SID_FM_CONVERTTO_LISTBOX : + case SID_FM_CONVERTTO_CHECKBOX : + case SID_FM_CONVERTTO_RADIOBUTTON : + case SID_FM_CONVERTTO_GROUPBOX : + case SID_FM_CONVERTTO_COMBOBOX : + case SID_FM_CONVERTTO_DATE : + case SID_FM_CONVERTTO_TIME : + case SID_FM_CONVERTTO_NUMERIC : + case SID_FM_CONVERTTO_FORMATTED : + case SID_FM_CONVERTTO_SPINBUTTON : + { + if (!m_pFormView || !m_bDesignMode || !GetImpl()->canConvertCurrentSelectionToControl_Lock(FmXFormShell::SlotToIdent(nWhich))) + rSet.DisableItem( nWhich ); + else + { + rSet.Put( SfxBoolItem( nWhich, false ) ); + // just to have a defined state (available and not checked) + } + } + break; + } + nWhich = aIter.NextWhich(); + } +} + + +void FmFormShell::GetFormState(SfxItemSet &rSet, sal_uInt16 nWhich) +{ + if ( !GetImpl()->getNavController_Lock().is() + || !isRowSetAlive(GetImpl()->getNavController_Lock()->getModel()) + || !m_pFormView + || m_bDesignMode + || !GetImpl()->getActiveForm_Lock().is() + || GetImpl()->isInFilterMode_Lock() + ) + rSet.DisableItem(nWhich); + else + { + bool bEnable = false; + try + { + switch (nWhich) + { + case SID_FM_VIEW_AS_GRID: + if (GetImpl()->getHostFrame_Lock().is() && GetImpl()->getNavController_Lock().is()) + { + bEnable = true; + bool bDisplayingCurrent = + GetImpl()->getInternalForm_Lock( + Reference<XForm>(GetImpl()->getNavController_Lock()->getModel(), UNO_QUERY) + ) == GetImpl()->getExternallyDisplayedForm_Lock(); + rSet.Put(SfxBoolItem(nWhich, bDisplayingCurrent)); + } + break; + + case SID_FM_SEARCH: + { + Reference<css::beans::XPropertySet> const xNavSet(GetImpl()->getActiveForm_Lock(), UNO_QUERY); + sal_Int32 nCount = ::comphelper::getINT32(xNavSet->getPropertyValue(FM_PROP_ROWCOUNT)); + bEnable = nCount != 0; + } break; + case SID_FM_RECORD_ABSOLUTE: + case SID_FM_RECORD_TOTAL: + { + FeatureState aState; + GetImpl()->getNavControllerFeatures_Lock()->getState( nWhich, aState ); + if ( SID_FM_RECORD_ABSOLUTE == nWhich ) + { + sal_Int32 nPosition = 0; + aState.State >>= nPosition; + rSet.Put( SfxInt32Item( SID_FM_RECORD_ABSOLUTE, nPosition ) ); + } + else if ( SID_FM_RECORD_TOTAL == nWhich ) + { + OUString sTotalCount; + aState.State >>= sTotalCount; + rSet.Put( SfxStringItem( nWhich, sTotalCount ) ); + } + bEnable = aState.Enabled; + } + break; + + // first, prev, next, last, and absolute affect the nav controller, not the + // active controller + case SID_FM_RECORD_FIRST: + case SID_FM_RECORD_PREV: + case SID_FM_RECORD_NEXT: + case SID_FM_RECORD_LAST: + case SID_FM_RECORD_NEW: + case SID_FM_RECORD_SAVE: + case SID_FM_RECORD_UNDO: + case SID_FM_RECORD_DELETE: + case SID_FM_REFRESH: + case SID_FM_REFRESH_FORM_CONTROL: + case SID_FM_REMOVE_FILTER_SORT: + case SID_FM_SORTUP: + case SID_FM_SORTDOWN: + case SID_FM_AUTOFILTER: + case SID_FM_ORDERCRIT: + bEnable = GetImpl()->IsFormSlotEnabled( nWhich, nullptr ); + break; + + case SID_FM_FORM_FILTERED: + { + FeatureState aState; + bEnable = GetImpl()->IsFormSlotEnabled( nWhich, &aState ); + + rSet.Put( SfxBoolItem( nWhich, ::comphelper::getBOOL( aState.State ) ) ); + } + break; + + case SID_FM_FILTER_START: + bEnable = GetImpl()->getActiveControllerFeatures_Lock()->canDoFormFilter(); + break; + } + } + catch( const Exception& ) + { + TOOLS_WARN_EXCEPTION("svx.form", "caught an exception while determining the state!"); + } + if (!bEnable) + rSet.DisableItem(nWhich); + } +} + + +FmFormPage* FmFormShell::GetCurPage() const +{ + FmFormPage* pP = nullptr; + if (m_pFormView && m_pFormView->GetSdrPageView()) + pP = dynamic_cast<FmFormPage*>( m_pFormView->GetSdrPageView()->GetPage() ); + return pP; +} + + +void FmFormShell::SetView( FmFormView* _pView ) +{ + if ( m_pFormView ) + { + if ( IsActive() ) + GetImpl()->viewDeactivated_Lock(*m_pFormView); + + m_pFormView->SetFormShell( nullptr, FmFormView::FormShellAccess() ); + m_pFormView = nullptr; + m_pFormModel = nullptr; + } + + if ( !_pView ) + return; + + m_pFormView = _pView; + m_pFormView->SetFormShell( this, FmFormView::FormShellAccess() ); + m_pFormModel = static_cast<FmFormModel*>(&m_pFormView->GetModel()); + + impl_setDesignMode( m_pFormView->IsDesignMode() ); + + // We activate our view if we are activated ourself, but sometimes the Activate precedes the SetView. + // But here we know both the view and our activation state so we at least are able to pass the latter + // to the former. + // FS - 30.06.99 - 67308 + if ( IsActive() ) + GetImpl()->viewActivated_Lock(*m_pFormView); +} + + +void FmFormShell::DetermineForms(bool bInvalidate) +{ + // are there forms on the current page + bool bForms = GetImpl()->hasForms_Lock(); + if (bForms != m_bHasForms) + { + m_bHasForms = bForms; + if (bInvalidate) + UIFeatureChanged(); + } +} + + +bool FmFormShell::GetY2KState(sal_uInt16& nReturn) +{ + return GetImpl()->GetY2KState_Lock(nReturn); +} + + +void FmFormShell::SetY2KState(sal_uInt16 n) +{ + GetImpl()->SetY2KState_Lock(n); +} + + +void FmFormShell::Activate(bool bMDI) +{ + SfxShell::Activate(bMDI); + + if ( m_pFormView ) + GetImpl()->viewActivated_Lock(*m_pFormView, true); +} + + +void FmFormShell::Deactivate(bool bMDI) +{ + SfxShell::Deactivate(bMDI); + + if ( m_pFormView ) + GetImpl()->viewDeactivated_Lock(*m_pFormView, false); +} + + +void FmFormShell::ExecuteTextAttribute( SfxRequest& _rReq ) +{ + m_pImpl->ExecuteTextAttribute_Lock(_rReq); +} + + +void FmFormShell::GetTextAttributeState( SfxItemSet& _rSet ) +{ + m_pImpl->GetTextAttributeState_Lock(_rSet); +} + + +bool FmFormShell::IsActiveControl() const +{ + return m_pImpl->IsActiveControl_Lock(false); +} + + +void FmFormShell::ForgetActiveControl() +{ + m_pImpl->ForgetActiveControl_Lock(); +} + + +void FmFormShell::SetControlActivationHandler( const Link<LinkParamNone*,void>& _rHdl ) +{ + m_pImpl->SetControlActivationHandler_Lock(_rHdl); +} + + +namespace +{ + SdrUnoObj* lcl_findUnoObject( const SdrObjList& _rObjList, const Reference< XControlModel >& _rxModel ) + { + SdrObjListIter aIter( &_rObjList ); + while ( aIter.IsMore() ) + { + SdrObject* pObject = aIter.Next(); + SdrUnoObj* pUnoObject = dynamic_cast<SdrUnoObj*>( pObject ); + if ( !pUnoObject ) + continue; + + Reference< XControlModel > xControlModel = pUnoObject->GetUnoControlModel(); + if ( !xControlModel.is() ) + continue; + + if ( _rxModel == xControlModel ) + return pUnoObject; + } + return nullptr; + } +} + + +void FmFormShell::ToggleControlFocus( const SdrUnoObj& i_rUnoObject, const SdrView& i_rView, const 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_Lock(); + + if ( bHasControlFocus ) + { + vcl::Window* pWindow = i_rDevice.GetOwnerWindow(); + 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("svx"); + } +} + + +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 override + { + 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::unique_ptr< svx::ISdrObjectFilter > FmFormShell::CreateFocusableControlFilter( const SdrView& i_rView, const OutputDevice& i_rDevice ) +{ + ::std::unique_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() ) + return nullptr; + + // we can only retrieve controls for SdrObjects which belong to page which is actually displayed in the given view + SdrPageView* pPageView = _rView.GetSdrPageView(); + SdrPage* pPage = pPageView ? pPageView->GetPage() : nullptr; + OSL_ENSURE( pPage, "FmFormShell::GetFormControl: no page displayed in the given view!" ); + if ( !pPage ) + return nullptr; + + SdrUnoObj* pUnoObject = lcl_findUnoObject( *pPage, _rxModel ); + if ( pUnoObject ) + { + _out_rxControl = pUnoObject->GetUnoControl( _rView, _rDevice ); + return pUnoObject; + } + +#if OSL_DEBUG_LEVEL > 0 + // perhaps we are fed with a control model which lives on a page other than the one displayed + // in the given view. This is worth being reported as error, in non-product builds. + FmFormModel* pModel = GetFormModel(); + if ( pModel ) + { + sal_uInt16 pageCount = pModel->GetPageCount(); + for ( sal_uInt16 page = 0; page < pageCount; ++page ) + { + pPage = pModel->GetPage( page ); + OSL_ENSURE( pPage, "FmFormShell::GetFormControl: NULL page encountered!" ); + if ( !pPage ) + continue; + + pUnoObject = lcl_findUnoObject( *pPage, _rxModel ); + OSL_ENSURE( !pUnoObject, "FmFormShell::GetFormControl: the given control model belongs to a wrong page (displayed elsewhere)!" ); + } + } +#else + (void) this; // avoid loplugin:staticmethods +#endif + + return nullptr; +} + + +Reference< runtime::XFormController > FmFormShell::GetFormController( const Reference< XForm >& _rxForm, const SdrView& _rView, const OutputDevice& _rDevice ) +{ + const FmFormView* pFormView = dynamic_cast< const FmFormView* >( &_rView ); + if ( !pFormView ) + return nullptr; + + return pFormView->GetFormController( _rxForm, _rDevice ); +} + + +void FmFormShell::SetDesignMode( bool _bDesignMode ) +{ + if ( _bDesignMode == m_bDesignMode ) + return; + + FmFormModel* pModel = GetFormModel(); + if (pModel) + // Switch off the undo environment for the time of the transition. This ensures that + // one can also change non-transient properties there. (It should be done with + // caution, however, and it should always be reversed when one switches the mode back. + // An example is the setting of the maximum text length by the OEditModel on its control.) + pModel->GetUndoEnv().Lock(); + + // then the actual switch + if ( m_bDesignMode || PrepareClose() ) + impl_setDesignMode(!m_bDesignMode ); + + // and my undo environment back on + if ( pModel ) + pModel->GetUndoEnv().UnLock(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |