1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <fmvwimp.hxx>
21 #include <svx/fmshell.hxx>
22 #include <svx/fmtools.hxx>
23 #include <fmservs.hxx>
24 #include <fmprop.hxx>
25 #include <fmpgeimp.hxx>
26 #include <fmundo.hxx>
27 #include <vcl/waitobj.hxx>
28 #include <com/sun/star/form/XLoadable.hpp>
29 #include <com/sun/star/container/XNamed.hpp>
30 #include <com/sun/star/sdbcx/Privilege.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/beans/XMultiPropertySet.hpp>
33 #include <com/sun/star/beans/XFastPropertySet.hpp>
34 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
35 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #include <com/sun/star/container/XNameContainer.hpp>
37 #include <com/sun/star/awt/XTabControllerModel.hpp>
38 #include <sfx2/viewfrm.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/weld.hxx>
41 #include <svl/whiter.hxx>
42 #include <sfx2/app.hxx>
43 #include <svl/intitem.hxx>
44 #include <svl/stritem.hxx>
45 #include <svl/visitem.hxx>
46 #include <unotools/moduleoptions.hxx>
47 #include <sfx2/objface.hxx>
48 #include <sfx2/request.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include <sfx2/objsh.hxx>
51 #include <svx/svdobj.hxx>
52 #include <svx/fmpage.hxx>
53 #include <svx/svditer.hxx>
54 #include <fmobj.hxx>
55 
56 #include <svx/svxids.hrc>
57 
58 #include <fmexch.hxx>
59 #include <svx/fmglob.hxx>
60 #include <svl/eitem.hxx>
61 #include <tools/diagnose_ex.h>
62 #include <svx/svdpage.hxx>
63 #include <svx/fmmodel.hxx>
64 #include <fmshimp.hxx>
65 #include <svx/svdpagv.hxx>
66 #include <sfx2/objitem.hxx>
67 #include <sfx2/viewsh.hxx>
68 #include <fmexpl.hxx>
69 #include <formcontrolling.hxx>
70 #include <svl/numuno.hxx>
71 #include <connectivity/dbtools.hxx>
72 #include <comphelper/types.hxx>
73 #include <fmdocumentclassification.hxx>
74 #include <formtoolbars.hxx>
75 
76 #include <svx/svxdlg.hxx>
77 
78 #include <svx/sdrobjectfilter.hxx>
79 
80 #define ShellClass_FmFormShell
81 #include <svxslots.hxx>
82 
83 #include <tbxform.hxx>
84 #include <com/sun/star/beans/PropertyValue.hpp>
85 
86 #include <memory>
87 
88 // is used for Invalidate -> maintain it as well
89 // sort ascending !!!!!!
90 sal_uInt16 const ControllerSlotMap[] =    // slots of the controller
91 {
92     SID_FM_CONFIG,
93     SID_FM_PUSHBUTTON,
94     SID_FM_RADIOBUTTON,
95     SID_FM_CHECKBOX,
96     SID_FM_FIXEDTEXT,
97     SID_FM_GROUPBOX,
98     SID_FM_EDIT,
99     SID_FM_LISTBOX,
100     SID_FM_COMBOBOX,
101     SID_FM_DBGRID,
102     SID_FM_IMAGEBUTTON,
103     SID_FM_FILECONTROL,
104     SID_FM_NAVIGATIONBAR,
105     SID_FM_CTL_PROPERTIES,
106     SID_FM_PROPERTIES,
107     SID_FM_TAB_DIALOG,
108     SID_FM_ADD_FIELD,
109     SID_FM_DESIGN_MODE,
110     SID_FM_SHOW_FMEXPLORER,
111     SID_FM_SHOW_PROPERTIES,
112     SID_FM_FMEXPLORER_CONTROL,
113     SID_FM_DATEFIELD,
114     SID_FM_TIMEFIELD,
115     SID_FM_NUMERICFIELD,
116     SID_FM_CURRENCYFIELD,
117     SID_FM_PATTERNFIELD,
118     SID_FM_OPEN_READONLY,
119     SID_FM_IMAGECONTROL,
120     SID_FM_USE_WIZARDS,
121     SID_FM_FORMATTEDFIELD,
122     SID_FM_FILTER_NAVIGATOR,
123     SID_FM_AUTOCONTROLFOCUS,
124     SID_FM_SCROLLBAR,
125     SID_FM_SPINBUTTON,
126     SID_FM_SHOW_DATANAVIGATOR,
127     SID_FM_DATANAVIGATOR_CONTROL,
128 
129     0
130 };
131 
132 using namespace ::com::sun::star::uno;
133 using namespace ::com::sun::star::awt;
134 using namespace ::com::sun::star::sdbc;
135 using namespace ::com::sun::star::sdbcx;
136 using namespace ::com::sun::star::beans;
137 using namespace ::com::sun::star::form;
138 using namespace ::com::sun::star::form::runtime;
139 using namespace ::svxform;
140 
FmDesignModeChangedHint(bool bDesMode)141 FmDesignModeChangedHint::FmDesignModeChangedHint( bool bDesMode )
142     :m_bDesignMode( bDesMode )
143 {
144 }
145 
146 
~FmDesignModeChangedHint()147 FmDesignModeChangedHint::~FmDesignModeChangedHint()
148 {
149 }
150 
SFX_IMPL_INTERFACE(FmFormShell,SfxShell)151 SFX_IMPL_INTERFACE(FmFormShell, SfxShell)
152 
153 void FmFormShell::InitInterface_Impl()
154 {
155     GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_NAVIGATION, SfxVisibilityFlags::Standard|SfxVisibilityFlags::ReadonlyDoc,
156                                             ToolbarId::SvxTbx_Form_Navigation,
157                                             SfxShellFeature::FormShowDatabaseBar);
158 
159     GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_NAVIGATION, SfxVisibilityFlags::Standard|SfxVisibilityFlags::ReadonlyDoc,
160                                             ToolbarId::SvxTbx_Form_Filter,
161                                             SfxShellFeature::FormShowFilterBar);
162 
163     GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Standard | SfxVisibilityFlags::ReadonlyDoc,
164                                             ToolbarId::SvxTbx_Text_Control_Attributes,
165                                             SfxShellFeature::FormShowTextControlBar);
166 
167     GetStaticInterface()->RegisterChildWindow(SID_FM_ADD_FIELD, false, SfxShellFeature::FormShowField);
168     GetStaticInterface()->RegisterChildWindow(SID_FM_SHOW_PROPERTIES, false, SfxShellFeature::FormShowProperies);
169     GetStaticInterface()->RegisterChildWindow(SID_FM_SHOW_FMEXPLORER, false, SfxShellFeature::FormShowExplorer);
170     GetStaticInterface()->RegisterChildWindow(SID_FM_FILTER_NAVIGATOR, false, SfxShellFeature::FormShowFilterNavigator);
171     GetStaticInterface()->RegisterChildWindow(SID_FM_SHOW_DATANAVIGATOR, false, SfxShellFeature::FormShowDataNavigator);
172 
173     GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Standard,
174                                             ToolbarId::SvxTbx_Controls,
175                                             SfxShellFeature::FormTBControls);
176 
177     GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT, SfxVisibilityFlags::Standard,
178                                             ToolbarId::SvxTbx_FormDesign,
179                                             SfxShellFeature::FormTBDesign);
180 }
181 
182 
FmFormShell(SfxViewShell * _pParent,FmFormView * pView)183 FmFormShell::FmFormShell( SfxViewShell* _pParent, FmFormView* pView )
184             :SfxShell(_pParent)
185             ,m_pImpl(new FmXFormShell(*this, _pParent->GetViewFrame()))
186             ,m_pFormView( pView )
187             ,m_pFormModel( nullptr )
188             ,m_nLastSlot( 0 )
189             ,m_bDesignMode( true )
190             ,m_bHasForms(false)
191 {
192     SetPool( &SfxGetpApp()->GetPool() );
193     SetName( "Form" );
194 
195     SetView(m_pFormView);
196 }
197 
198 
~FmFormShell()199 FmFormShell::~FmFormShell()
200 {
201     if ( m_pFormView )
202         SetView( nullptr );
203 
204     m_pImpl->dispose();
205 }
206 
207 
NotifyMarkListChanged(FmFormView * pWhichView)208 void FmFormShell::NotifyMarkListChanged(FmFormView* pWhichView)
209 {
210     FmNavViewMarksChanged aChangeNotification(pWhichView);
211     Broadcast(aChangeNotification);
212 }
213 
214 
PrepareClose(bool bUI)215 bool FmFormShell::PrepareClose(bool bUI)
216 {
217     if (GetImpl()->didPrepareClose_Lock())
218         // we already did a PrepareClose for the current modifications of the current form
219         return true;
220 
221     bool bResult = true;
222     // Save the data records, not in DesignMode and FilterMode
223     if (!m_bDesignMode && !GetImpl()->isInFilterMode_Lock() &&
224         m_pFormView && m_pFormView->GetActualOutDev() &&
225         m_pFormView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
226     {
227         SdrPageView* pCurPageView = m_pFormView->GetSdrPageView();
228 
229         // sal_uInt16 nPos = pCurPageView ? pCurPageView->GetWinList().Find((OutputDevice*)m_pFormView->GetActualOutDev()) : SDRPAGEVIEWWIN_NOTFOUND;
230         SdrPageWindow* pWindow = pCurPageView ? pCurPageView->FindPageWindow(*const_cast<OutputDevice*>(m_pFormView->GetActualOutDev())) : nullptr;
231 
232         if(pWindow)
233         {
234             // First, the current contents of the controls are stored.
235             // If everything has gone smoothly, the modified records are stored.
236             if (GetImpl()->getActiveController_Lock().is())
237             {
238                 const svx::ControllerFeatures& rController = GetImpl()->getActiveControllerFeatures_Lock();
239                 if ( rController->commitCurrentControl() )
240                 {
241                     const bool bModified = rController->isModifiedRow();
242 
243                     if ( bModified && bUI )
244                     {
245                         SfxViewShell* pShell = GetViewShell();
246                         vcl::Window* pShellWnd = pShell ? pShell->GetWindow() : nullptr;
247                         weld::Widget* pFrameWeld = pShellWnd ? pShellWnd->GetFrameWeld() : nullptr;
248                         std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pFrameWeld, "svx/ui/savemodifieddialog.ui"));
249                         std::unique_ptr<weld::MessageDialog> xQry(xBuilder->weld_message_dialog("SaveModifiedDialog"));
250                         switch (xQry->run())
251                         {
252                             case RET_YES:
253                                 bResult = rController->commitCurrentRecord( );
254                                 [[fallthrough]];
255                             case RET_NO:
256                                 GetImpl()->didPrepareClose_Lock(true);
257                                 break;
258 
259                             case RET_CANCEL:
260                                 return false;
261                         }
262                     }
263                 }
264             }
265         }
266     }
267     return bResult;
268 }
269 
270 
impl_setDesignMode(bool bDesign)271 void FmFormShell::impl_setDesignMode(bool bDesign)
272 {
273     if (m_pFormView)
274     {
275         if (!bDesign)
276             m_nLastSlot = SID_FM_DESIGN_MODE;
277 
278         GetImpl()->SetDesignMode_Lock(bDesign);
279         // my m_bDesignMode is also set by the Impl ...
280     }
281     else
282     {
283         m_bHasForms = false;
284         m_bDesignMode = bDesign;
285         UIFeatureChanged();
286     }
287 
288     GetViewShell()->GetViewFrame()->GetBindings().Invalidate(ControllerSlotMap);
289 }
290 
291 
HasUIFeature(SfxShellFeature nFeature) const292 bool FmFormShell::HasUIFeature(SfxShellFeature nFeature) const
293 {
294     assert((nFeature & ~SfxShellFeature::FormMask) == SfxShellFeature::NONE);
295     bool bResult = false;
296     if (nFeature & SfxShellFeature::FormShowDatabaseBar)
297     {
298         // only if forms are also available
299         bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar_Lock() && !GetImpl()->isInFilterMode_Lock();
300     }
301     else if (nFeature & SfxShellFeature::FormShowFilterBar)
302     {
303         // only if forms are also available
304         bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar_Lock() && GetImpl()->isInFilterMode_Lock();
305     }
306     else if (nFeature & SfxShellFeature::FormShowFilterNavigator)
307     {
308         bResult = !m_bDesignMode && GetImpl()->hasDatabaseBar_Lock() && GetImpl()->isInFilterMode_Lock();
309     }
310     else if (nFeature & SfxShellFeature::FormShowField)
311     {
312         bResult = m_bDesignMode && m_pFormView && m_bHasForms;
313     }
314     else if (nFeature & SfxShellFeature::FormShowProperies)
315     {
316         bResult = m_bDesignMode && m_pFormView && m_bHasForms;
317     }
318     else if (nFeature & SfxShellFeature::FormShowExplorer)
319     {
320         bResult = m_bDesignMode; // OJ #101593# && m_pFormView && m_bHasForms;
321     }
322     else if (nFeature & SfxShellFeature::FormShowTextControlBar)
323     {
324         bResult = !GetImpl()->IsReadonlyDoc_Lock() && m_pImpl->IsActiveControl_Lock(true);
325     }
326     else if (nFeature & SfxShellFeature::FormShowDataNavigator)
327     {
328         bResult = GetImpl()->isEnhancedForm_Lock();
329     }
330     else if (  (nFeature & SfxShellFeature::FormTBControls)
331             || (nFeature & SfxShellFeature::FormTBDesign)
332             )
333     {
334         bResult = true;
335     }
336 
337     return bResult;
338 }
339 
340 
Execute(SfxRequest & rReq)341 void FmFormShell::Execute(SfxRequest &rReq)
342 {
343     sal_uInt16 nSlot = rReq.GetSlot();
344 
345 
346     // set MasterSlot
347     switch( nSlot )
348     {
349         case SID_FM_PUSHBUTTON:
350         case SID_FM_RADIOBUTTON:
351         case SID_FM_CHECKBOX:
352         case SID_FM_FIXEDTEXT:
353         case SID_FM_GROUPBOX:
354         case SID_FM_LISTBOX:
355         case SID_FM_COMBOBOX:
356         case SID_FM_NAVIGATIONBAR:
357         case SID_FM_EDIT:
358         case SID_FM_DBGRID:
359         case SID_FM_IMAGEBUTTON:
360         case SID_FM_IMAGECONTROL:
361         case SID_FM_FILECONTROL:
362         case SID_FM_DATEFIELD:
363         case SID_FM_TIMEFIELD:
364         case SID_FM_NUMERICFIELD:
365         case SID_FM_CURRENCYFIELD:
366         case SID_FM_PATTERNFIELD:
367         case SID_FM_FORMATTEDFIELD:
368         case SID_FM_SCROLLBAR:
369         case SID_FM_SPINBUTTON:
370             m_nLastSlot = nSlot;
371             break;
372     }
373 
374 
375     // set the Identifier and Inventor of the Uno control
376     sal_uInt16 nIdentifier = 0;
377     switch( nSlot )
378     {
379         case SID_FM_CHECKBOX:
380             nIdentifier = OBJ_FM_CHECKBOX;
381             break;
382         case SID_FM_PUSHBUTTON:
383             nIdentifier = OBJ_FM_BUTTON;
384             break;
385         case SID_FM_FIXEDTEXT:
386             nIdentifier = OBJ_FM_FIXEDTEXT;
387             break;
388         case SID_FM_LISTBOX:
389             nIdentifier = OBJ_FM_LISTBOX;
390             break;
391         case SID_FM_EDIT:
392             nIdentifier = OBJ_FM_EDIT;
393             break;
394         case SID_FM_RADIOBUTTON:
395             nIdentifier = OBJ_FM_RADIOBUTTON;
396             break;
397         case SID_FM_GROUPBOX:
398             nIdentifier = OBJ_FM_GROUPBOX;
399             break;
400         case SID_FM_COMBOBOX:
401             nIdentifier = OBJ_FM_COMBOBOX;
402             break;
403         case SID_FM_NAVIGATIONBAR:
404             nIdentifier = OBJ_FM_NAVIGATIONBAR;
405             break;
406         case SID_FM_DBGRID:
407             nIdentifier = OBJ_FM_GRID;
408             break;
409         case SID_FM_IMAGEBUTTON:
410             nIdentifier = OBJ_FM_IMAGEBUTTON;
411             break;
412         case SID_FM_IMAGECONTROL:
413             nIdentifier = OBJ_FM_IMAGECONTROL;
414             break;
415         case SID_FM_FILECONTROL:
416             nIdentifier = OBJ_FM_FILECONTROL;
417             break;
418         case SID_FM_DATEFIELD:
419             nIdentifier = OBJ_FM_DATEFIELD;
420             break;
421         case SID_FM_TIMEFIELD:
422             nIdentifier = OBJ_FM_TIMEFIELD;
423             break;
424         case SID_FM_NUMERICFIELD:
425             nIdentifier = OBJ_FM_NUMERICFIELD;
426             break;
427         case SID_FM_CURRENCYFIELD:
428             nIdentifier = OBJ_FM_CURRENCYFIELD;
429             break;
430         case SID_FM_PATTERNFIELD:
431             nIdentifier = OBJ_FM_PATTERNFIELD;
432             break;
433         case SID_FM_FORMATTEDFIELD:
434             nIdentifier = OBJ_FM_FORMATTEDFIELD;
435             break;
436         case SID_FM_SCROLLBAR:
437             nIdentifier = OBJ_FM_SCROLLBAR;
438             break;
439         case SID_FM_SPINBUTTON:
440             nIdentifier = OBJ_FM_SPINBUTTON;
441             break;
442     }
443 
444     switch ( nSlot )
445     {
446         case SID_FM_CHECKBOX:
447         case SID_FM_PUSHBUTTON:
448         case SID_FM_FIXEDTEXT:
449         case SID_FM_LISTBOX:
450         case SID_FM_EDIT:
451         case SID_FM_RADIOBUTTON:
452         case SID_FM_COMBOBOX:
453         case SID_FM_NAVIGATIONBAR:
454         case SID_FM_GROUPBOX:
455         case SID_FM_DBGRID:
456         case SID_FM_IMAGEBUTTON:
457         case SID_FM_IMAGECONTROL:
458         case SID_FM_FILECONTROL:
459         case SID_FM_DATEFIELD:
460         case SID_FM_TIMEFIELD:
461         case SID_FM_NUMERICFIELD:
462         case SID_FM_CURRENCYFIELD:
463         case SID_FM_PATTERNFIELD:
464         case SID_FM_FORMATTEDFIELD:
465         case SID_FM_SCROLLBAR:
466         case SID_FM_SPINBUTTON:
467         {
468             const SfxBoolItem* pGrabFocusItem = rReq.GetArg<SfxBoolItem>(SID_FM_TOGGLECONTROLFOCUS);
469             if ( pGrabFocusItem && pGrabFocusItem->GetValue() )
470             {   // see below
471                 SfxViewShell* pShell = GetViewShell();
472                 vcl::Window* pShellWnd = pShell ? pShell->GetWindow() : nullptr;
473                 if ( pShellWnd )
474                     pShellWnd->GrabFocus();
475                 break;
476             }
477 
478             SfxUInt16Item aIdentifierItem( SID_FM_CONTROL_IDENTIFIER, nIdentifier );
479             SfxUInt32Item aInventorItem( SID_FM_CONTROL_INVENTOR, sal_uInt32(SdrInventor::FmForm) );
480             const SfxPoolItem* pArgs[] =
481             {
482                 &aIdentifierItem, &aInventorItem, nullptr
483             };
484             const SfxPoolItem* pInternalArgs[] =
485             {
486                 nullptr
487             };
488 
489             GetViewShell()->GetViewFrame()->GetDispatcher()->Execute( SID_FM_CREATE_CONTROL, SfxCallMode::ASYNCHRON,
490                                       pArgs, rReq.GetModifier(), pInternalArgs );
491 
492             if ( rReq.GetModifier() & KEY_MOD1 )
493             {
494                 //  #99013# if selected with control key, return focus to current view
495                 // do this asynchron, so that the creation can be finished first
496                 // reusing the SID_FM_TOGGLECONTROLFOCUS is somewhat hacky... which it wouldn't if it would have another
497                 // name, so I do not really have a big problem with this...
498                 SfxBoolItem aGrabFocusIndicatorItem( SID_FM_TOGGLECONTROLFOCUS, true );
499                 GetViewShell()->GetViewFrame()->GetDispatcher()->ExecuteList(
500                         nSlot, SfxCallMode::ASYNCHRON,
501                         { &aGrabFocusIndicatorItem });
502             }
503 
504             rReq.Done();
505         }   break;
506     }
507 
508     // individual actions
509     switch( nSlot )
510     {
511         case SID_FM_FORM_DESIGN_TOOLS:
512         {
513             FormToolboxes aToolboxAccess(GetImpl()->getHostFrame_Lock());
514             aToolboxAccess.toggleToolbox( nSlot );
515             rReq.Done();
516         }
517         break;
518 
519         case SID_FM_TOGGLECONTROLFOCUS:
520         {
521             FmFormView* pFormView = GetFormView();
522             if ( !pFormView )
523                 break;
524 
525             // if we execute this ourself, then either the application does not implement an own handling for this,
526             // of we're on the top of the dispatcher stack, which means a control has the focus.
527             // In the latter case, we put the focus to the document window, otherwise, we focus the first control
528             const bool bHasControlFocus = GetImpl()->HasControlFocus_Lock();
529             if ( bHasControlFocus )
530             {
531                 if (m_pFormView)
532                 {
533                     const OutputDevice* pDevice = m_pFormView->GetActualOutDev();
534                     vcl::Window* pWindow = dynamic_cast< vcl::Window* >( const_cast< OutputDevice* >( pDevice ) );
535                     if ( pWindow )
536                         pWindow->GrabFocus();
537                 }
538             }
539             else
540             {
541                 pFormView->GrabFirstControlFocus( );
542             }
543         }
544         break;
545 
546         case SID_FM_VIEW_AS_GRID:
547             GetImpl()->CreateExternalView_Lock();
548             break;
549         case SID_FM_CONVERTTO_EDIT          :
550         case SID_FM_CONVERTTO_BUTTON            :
551         case SID_FM_CONVERTTO_FIXEDTEXT     :
552         case SID_FM_CONVERTTO_LISTBOX       :
553         case SID_FM_CONVERTTO_CHECKBOX      :
554         case SID_FM_CONVERTTO_RADIOBUTTON   :
555         case SID_FM_CONVERTTO_GROUPBOX      :
556         case SID_FM_CONVERTTO_COMBOBOX      :
557         case SID_FM_CONVERTTO_IMAGEBUTTON   :
558         case SID_FM_CONVERTTO_FILECONTROL   :
559         case SID_FM_CONVERTTO_DATE          :
560         case SID_FM_CONVERTTO_TIME          :
561         case SID_FM_CONVERTTO_NUMERIC       :
562         case SID_FM_CONVERTTO_CURRENCY      :
563         case SID_FM_CONVERTTO_PATTERN       :
564         case SID_FM_CONVERTTO_IMAGECONTROL  :
565         case SID_FM_CONVERTTO_FORMATTED     :
566         case SID_FM_CONVERTTO_SCROLLBAR     :
567         case SID_FM_CONVERTTO_SPINBUTTON    :
568         case SID_FM_CONVERTTO_NAVIGATIONBAR :
569             GetImpl()->executeControlConversionSlot_Lock(FmXFormShell::SlotToIdent(nSlot));
570             // after the conversion, re-determine the selection, since the
571             // selected object has changed
572             GetImpl()->SetSelection_Lock(GetFormView()->GetMarkedObjectList());
573             break;
574         case SID_FM_LEAVE_CREATE:
575             m_nLastSlot = 0;
576             rReq.Done();
577             break;
578         case SID_FM_SHOW_PROPERTY_BROWSER:
579         {
580             const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(SID_FM_SHOW_PROPERTIES);
581             bool bShow = true;
582             if ( pShowItem )
583                 bShow = pShowItem->GetValue();
584             GetImpl()->ShowSelectionProperties_Lock(bShow);
585 
586             rReq.Done();
587         } break;
588 
589         case SID_FM_PROPERTIES:
590         {
591             // display the PropertyBrowser
592             const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(nSlot);
593             bool bShow = pShowItem == nullptr || pShowItem->GetValue();
594 
595             InterfaceBag aOnlyTheForm;
596             aOnlyTheForm.insert(Reference<XInterface>(GetImpl()->getCurrentForm_Lock(), UNO_QUERY));
597             GetImpl()->setCurrentSelection_Lock(aOnlyTheForm);
598 
599             GetImpl()->ShowSelectionProperties_Lock(bShow);
600 
601             rReq.Done();
602         }   break;
603 
604         case SID_FM_CTL_PROPERTIES:
605         {
606             const SfxBoolItem* pShowItem = rReq.GetArg<SfxBoolItem>(nSlot);
607             bool bShow = pShowItem == nullptr || pShowItem->GetValue();
608 
609             OSL_ENSURE( GetImpl()->onlyControlsAreMarked_Lock(), "FmFormShell::Execute: ControlProperties should be disabled!" );
610             if ( bShow )
611                 GetImpl()->selectLastMarkedControls_Lock();
612             GetImpl()->ShowSelectionProperties_Lock(bShow);
613 
614             rReq.Done();
615         }   break;
616         case SID_FM_SHOW_PROPERTIES:
617         case SID_FM_ADD_FIELD:
618         case SID_FM_FILTER_NAVIGATOR:
619         case SID_FM_SHOW_DATANAVIGATOR :
620         {
621             GetViewShell()->GetViewFrame()->ChildWindowExecute( rReq );
622             rReq.Done();
623         }   break;
624         case SID_FM_SHOW_FMEXPLORER:
625         {
626             if (!m_pFormView)   // force setting the view
627                 GetViewShell()->GetViewFrame()->GetDispatcher()->Execute(SID_CREATE_SW_DRAWVIEW);
628 
629             GetViewShell()->GetViewFrame()->ChildWindowExecute(rReq);
630             rReq.Done();
631         }
632         break;
633 
634         case SID_FM_TAB_DIALOG:
635         {
636             GetImpl()->ExecuteTabOrderDialog_Lock(
637                 Reference<XTabControllerModel>(GetImpl()->getCurrentForm_Lock(), UNO_QUERY));
638             rReq.Done();
639         }
640         break;
641 
642         case SID_FM_DESIGN_MODE:
643         {
644             const SfxBoolItem* pDesignItem = rReq.GetArg<SfxBoolItem>(nSlot);
645             bool bDesignMode = pDesignItem ? pDesignItem->GetValue() : !m_bDesignMode;
646             SetDesignMode( bDesignMode );
647             if ( m_bDesignMode == bDesignMode )
648                 rReq.Done();
649 
650             m_nLastSlot = SID_FM_DESIGN_MODE;
651         }
652         break;
653 
654         case SID_FM_AUTOCONTROLFOCUS:
655         {
656             FmFormModel* pModel = GetFormModel();
657             DBG_ASSERT(pModel, "FmFormShell::Execute : invalid call !");
658                 // should have been disabled in GetState if we don't have a FormModel
659             pModel->SetAutoControlFocus( !pModel->GetAutoControlFocus() );
660             GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_AUTOCONTROLFOCUS);
661         }
662         break;
663         case SID_FM_OPEN_READONLY:
664         {
665             FmFormModel* pModel = GetFormModel();
666             DBG_ASSERT(pModel, "FmFormShell::Execute : invalid call !");
667                 // should have been disabled in GetState if we don't have a FormModel
668             pModel->SetOpenInDesignMode( !pModel->GetOpenInDesignMode() );
669             GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_OPEN_READONLY);
670         }
671         break;
672         case SID_FM_USE_WIZARDS:
673         {
674             GetImpl()->SetWizardUsing_Lock(!GetImpl()->GetWizardUsing_Lock());
675             GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_USE_WIZARDS);
676         }
677         break;
678         case SID_FM_SEARCH:
679         {
680             const svx::ControllerFeatures& rController = GetImpl()->getActiveControllerFeatures_Lock();
681             if ( rController->commitCurrentControl() && rController->commitCurrentRecord() )
682                 GetImpl()->ExecuteSearch_Lock();
683             rReq.Done();
684         }
685         break;
686 
687         case SID_FM_RECORD_FIRST:
688         case SID_FM_RECORD_PREV:
689         case SID_FM_RECORD_NEXT:
690         case SID_FM_RECORD_LAST:
691         case SID_FM_RECORD_NEW:
692         case SID_FM_REFRESH:
693         case SID_FM_REFRESH_FORM_CONTROL:
694         case SID_FM_RECORD_DELETE:
695         case SID_FM_RECORD_UNDO:
696         case SID_FM_RECORD_SAVE:
697         case SID_FM_REMOVE_FILTER_SORT:
698         case SID_FM_SORTDOWN:
699         case SID_FM_SORTUP:
700         case SID_FM_AUTOFILTER:
701         case SID_FM_ORDERCRIT:
702         case SID_FM_FORM_FILTERED:
703         {
704             GetImpl()->ExecuteFormSlot_Lock(nSlot);
705             rReq.Done();
706         }
707         break;
708 
709         case SID_FM_RECORD_ABSOLUTE:
710         {
711             const svx::ControllerFeatures& rController = GetImpl()->getNavControllerFeatures_Lock();
712             sal_Int32 nRecord = -1;
713 
714             const SfxItemSet* pArgs = rReq.GetArgs();
715             if ( pArgs )
716             {
717                 const SfxPoolItem* pItem;
718                 if ( ( pArgs->GetItemState( FN_PARAM_1, true, &pItem ) ) == SfxItemState::SET )
719                 {
720                     const SfxInt32Item* pTypedItem = dynamic_cast<const SfxInt32Item* >( pItem );
721                     if ( pTypedItem )
722                         nRecord = std::max( pTypedItem->GetValue(), sal_Int32(0) );
723                 }
724             }
725             else
726             {
727                 SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
728                 ScopedVclPtr<AbstractFmInputRecordNoDialog> dlg(pFact->CreateFmInputRecordNoDialog(rReq.GetFrameWeld()));
729                 dlg->SetValue( rController->getCursor()->getRow() );
730                 if ( dlg->Execute() == RET_OK )
731                     nRecord = dlg->GetValue();
732 
733                 rReq.AppendItem( SfxInt32Item( FN_PARAM_1, nRecord ) );
734             }
735 
736             if ( nRecord != -1 )
737                 rController->execute( nSlot, "Position", makeAny( nRecord ) );
738 
739             rReq.Done();
740         }   break;
741         case SID_FM_FILTER_EXECUTE:
742         case SID_FM_FILTER_EXIT:
743         {
744             bool bCancelled = ( SID_FM_FILTER_EXIT == nSlot );
745             bool bReopenNavigator = false;
746 
747             if ( !bCancelled )
748             {
749                 // if the filter navigator is still open, we need to close it, so it can possibly
750                 // commit it's most recent changes
751                 if ( GetViewShell() && GetViewShell()->GetViewFrame() )
752                     if ( GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_FILTER_NAVIGATOR ) )
753                     {
754                         GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR );
755                         bReopenNavigator = true;
756                     }
757 
758                 Reference<runtime::XFormController> const xController(GetImpl()->getActiveController_Lock());
759 
760                 if  (   GetViewShell()->GetViewFrame()->HasChildWindow( SID_FM_FILTER_NAVIGATOR )
761                         // closing the window was denied, for instance because of an invalid criterion
762 
763                     ||  (   xController.is()
764                         &&  !GetImpl()->getActiveControllerFeatures_Lock()->commitCurrentControl()
765                         )
766                         // committing the controller was denied
767                     )
768                 {
769                     rReq.Done();
770                     break;
771                 }
772             }
773 
774             GetImpl()->stopFiltering_Lock(!bCancelled);
775             rReq.Done();
776 
777             if ( bReopenNavigator )
778                 // we closed the navigator only to implicitly commit it (as we do not have another
779                 // direct wire to it), but to the user, it should look as it was always open
780                 GetViewShell()->GetViewFrame()->ToggleChildWindow( SID_FM_FILTER_NAVIGATOR );
781         }
782         break;
783 
784         case SID_FM_FILTER_START:
785         {
786             GetImpl()->startFiltering_Lock();
787             rReq.Done();
788 
789             // initially open the filter navigator, the whole form based filter is pretty useless without it
790             SfxBoolItem aIdentifierItem( SID_FM_FILTER_NAVIGATOR, true );
791             GetViewShell()->GetViewFrame()->GetDispatcher()->ExecuteList(
792                     SID_FM_FILTER_NAVIGATOR, SfxCallMode::ASYNCHRON,
793                     { &aIdentifierItem });
794         }   break;
795     }
796 }
797 
798 
GetState(SfxItemSet & rSet)799 void FmFormShell::GetState(SfxItemSet &rSet)
800 {
801     SfxWhichIter aIter( rSet );
802     sal_uInt16 nWhich = aIter.FirstWhich();
803     while ( nWhich )
804     {
805         switch( nWhich )
806         {
807             case SID_FM_FORM_DESIGN_TOOLS:
808             {
809                 FormToolboxes aToolboxAccess(GetImpl()->getHostFrame_Lock());
810                 rSet.Put( SfxBoolItem( nWhich, aToolboxAccess.isToolboxVisible( nWhich ) ) );
811             }
812             break;
813 
814             case SID_FM_FILTER_EXECUTE:
815             case SID_FM_FILTER_EXIT:
816                 if (!GetImpl()->isInFilterMode_Lock())
817                     rSet.DisableItem( nWhich );
818                 break;
819 
820             case SID_FM_USE_WIZARDS:
821                 if  ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
822                     rSet.Put( SfxVisibilityItem( nWhich, false ) );
823                 else if (!GetFormModel())
824                     rSet.DisableItem( nWhich );
825                 else
826                     rSet.Put(SfxBoolItem(nWhich, GetImpl()->GetWizardUsing_Lock()));
827                 break;
828             case SID_FM_AUTOCONTROLFOCUS:
829                 if (!GetFormModel())
830                     rSet.DisableItem( nWhich );
831                 else
832                     rSet.Put( SfxBoolItem(nWhich, GetFormModel()->GetAutoControlFocus() ) );
833                 break;
834             case SID_FM_OPEN_READONLY:
835                 if (!GetFormModel())
836                     rSet.DisableItem( nWhich );
837                 else
838                     rSet.Put( SfxBoolItem(nWhich, GetFormModel()->GetOpenInDesignMode() ) );
839                 break;
840 
841             case SID_FM_NAVIGATIONBAR:
842             case SID_FM_DBGRID:
843                 if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
844                 {
845                     rSet.Put( SfxVisibilityItem( nWhich, false ) );
846                     break;
847                 }
848                 [[fallthrough]];
849 
850             case SID_FM_SCROLLBAR:
851             case SID_FM_IMAGECONTROL:
852             case SID_FM_FILECONTROL:
853             case SID_FM_CURRENCYFIELD:
854             case SID_FM_PATTERNFIELD:
855             case SID_FM_IMAGEBUTTON:
856             case SID_FM_RADIOBUTTON:
857             case SID_FM_COMBOBOX:
858             case SID_FM_GROUPBOX:
859             case SID_FM_CHECKBOX:
860             case SID_FM_PUSHBUTTON:
861             case SID_FM_FIXEDTEXT:
862             case SID_FM_LISTBOX:
863             case SID_FM_EDIT:
864             case SID_FM_DATEFIELD:
865             case SID_FM_TIMEFIELD:
866             case SID_FM_NUMERICFIELD:
867             case SID_FM_FORMATTEDFIELD:
868             case SID_FM_SPINBUTTON:
869                 if (!m_bDesignMode)
870                     rSet.DisableItem( nWhich );
871                 else
872                 {
873                     bool bLayerLocked = false;
874                     if (m_pFormView)
875                     {
876                         // If the css::drawing::Layer is locked, the slots must be disabled. #36897
877                         SdrPageView* pPV = m_pFormView->GetSdrPageView();
878                         if (pPV != nullptr)
879                             bLayerLocked = pPV->IsLayerLocked(m_pFormView->GetActiveLayer());
880                     }
881                     if (bLayerLocked)
882                         rSet.DisableItem( nWhich );
883                     else
884                         rSet.Put( SfxBoolItem(nWhich, (nWhich==m_nLastSlot)) );
885                 }
886                 break;
887             case SID_FM_FILTER_NAVIGATOR_CONTROL:
888             {
889                 if (GetImpl()->isInFilterMode_Lock())
890                     rSet.Put(SfxObjectItem(nWhich, this));
891                 else
892                     rSet.Put(SfxObjectItem(nWhich));
893             }   break;
894             case SID_FM_FIELDS_CONTROL:
895             case SID_FM_PROPERTY_CONTROL:
896             {
897                 if (!m_bDesignMode || !m_pFormView || !m_bHasForms)
898                     rSet.Put(SfxObjectItem(nWhich));
899                 else
900                     rSet.Put(SfxObjectItem(nWhich, this));
901 
902             }   break;
903             case SID_FM_FMEXPLORER_CONTROL:
904             case SID_FM_DATANAVIGATOR_CONTROL :
905             {
906                 if (!m_bDesignMode || !m_pFormView)
907                     rSet.Put(SfxObjectItem(nWhich));
908                 else
909                     rSet.Put(SfxObjectItem(nWhich, this));
910 
911             }   break;
912             case SID_FM_ADD_FIELD:
913             case SID_FM_SHOW_FMEXPLORER:
914             case SID_FM_SHOW_PROPERTIES:
915             case SID_FM_FILTER_NAVIGATOR:
916             case SID_FM_SHOW_DATANAVIGATOR:
917             {
918                 if ( GetViewShell()->GetViewFrame()->KnowsChildWindow(nWhich) )
919                     rSet.Put( SfxBoolItem( nWhich, GetViewShell()->GetViewFrame()->HasChildWindow(nWhich)) );
920                 else
921                     rSet.DisableItem(nWhich);
922             }   break;
923 
924             case SID_FM_SHOW_PROPERTY_BROWSER:
925             {
926                 rSet.Put(SfxBoolItem(nWhich, GetImpl()->IsPropBrwOpen_Lock()));
927             }
928             break;
929 
930             case SID_FM_CTL_PROPERTIES:
931             {
932                 // potentially, give the Impl the opportunity to update its
933                 // current objects which are aligned with the current MarkList
934                 if (GetImpl()->IsSelectionUpdatePending_Lock())
935                     GetImpl()->ForceUpdateSelection_Lock();
936 
937                 if (!m_pFormView || !m_bDesignMode || !GetImpl()->onlyControlsAreMarked_Lock())
938                     rSet.DisableItem( nWhich );
939                 else
940                 {
941                     bool const bChecked = GetImpl()->IsPropBrwOpen_Lock() && !GetImpl()->isSolelySelected_Lock(GetImpl()->getCurrentForm_Lock());
942                         // if the property browser is open, and only controls are marked, and the current selection
943                         // does not consist of only the current form, then the current selection is the (composition of)
944                         // the currently marked controls
945                     rSet.Put( SfxBoolItem( nWhich, bChecked ) );
946                 }
947             }   break;
948 
949             case SID_FM_PROPERTIES:
950             {
951                 // potentially, give the Impl the opportunity to update its
952                 // current objects which are aligned with the current MarkList
953                 if (GetImpl()->IsSelectionUpdatePending_Lock())
954                     GetImpl()->ForceUpdateSelection_Lock();
955 
956                 if (!m_pFormView || !m_bDesignMode || !GetImpl()->getCurrentForm_Lock().is())
957                     rSet.DisableItem( nWhich );
958                 else
959                 {
960                     bool const bChecked = GetImpl()->IsPropBrwOpen_Lock() && GetImpl()->isSolelySelected_Lock(GetImpl()->getCurrentForm_Lock());
961                     rSet.Put(SfxBoolItem(nWhich, bChecked));
962                 }
963             }   break;
964             case SID_FM_TAB_DIALOG:
965                 // potentially, give the Impl the opportunity to update its
966                 // current objects which are aligned with the current MarkList
967                 if (GetImpl()->IsSelectionUpdatePending_Lock())
968                     GetImpl()->ForceUpdateSelection_Lock();
969 
970                 if (!m_pFormView || !m_bDesignMode || !GetImpl()->getCurrentForm_Lock().is() )
971                     rSet.DisableItem( nWhich );
972                 break;
973             case SID_FM_DESIGN_MODE:
974                 if (!m_pFormView || GetImpl()->IsReadonlyDoc_Lock())
975                     rSet.DisableItem( nWhich );
976                 else
977                     rSet.Put( SfxBoolItem(nWhich, m_bDesignMode) );
978                 break;
979             case SID_FM_SEARCH:
980             case SID_FM_RECORD_FIRST:
981             case SID_FM_RECORD_NEXT:
982             case SID_FM_RECORD_PREV:
983             case SID_FM_RECORD_LAST:
984             case SID_FM_RECORD_NEW:
985             case SID_FM_RECORD_DELETE:
986             case SID_FM_RECORD_ABSOLUTE:
987             case SID_FM_RECORD_TOTAL:
988             case SID_FM_RECORD_SAVE:
989             case SID_FM_RECORD_UNDO:
990             case SID_FM_FORM_FILTERED:
991             case SID_FM_REMOVE_FILTER_SORT:
992             case SID_FM_SORTUP:
993             case SID_FM_SORTDOWN:
994             case SID_FM_ORDERCRIT:
995             case SID_FM_FILTER_START:
996             case SID_FM_AUTOFILTER:
997             case SID_FM_REFRESH:
998             case SID_FM_REFRESH_FORM_CONTROL:
999             case SID_FM_VIEW_AS_GRID:
1000                 GetFormState(rSet,nWhich);
1001                 break;
1002 
1003             case SID_FM_CHANGECONTROLTYPE:
1004             {
1005                 if ( !m_pFormView || !m_bDesignMode )
1006                     rSet.DisableItem( nWhich );
1007                 else
1008                 {
1009                     if (!GetImpl()->canConvertCurrentSelectionToControl_Lock("ConvertToFixed"))
1010                         // if it cannot be converted to a fixed text, it is no single control
1011                         rSet.DisableItem( nWhich );
1012                 }
1013             } break;
1014 
1015             case SID_FM_CONVERTTO_FILECONTROL   :
1016             case SID_FM_CONVERTTO_CURRENCY      :
1017             case SID_FM_CONVERTTO_PATTERN       :
1018             case SID_FM_CONVERTTO_IMAGECONTROL  :
1019             case SID_FM_CONVERTTO_SCROLLBAR     :
1020             case SID_FM_CONVERTTO_NAVIGATIONBAR :
1021             case SID_FM_CONVERTTO_IMAGEBUTTON   :
1022             case SID_FM_CONVERTTO_EDIT          :
1023             case SID_FM_CONVERTTO_BUTTON        :
1024             case SID_FM_CONVERTTO_FIXEDTEXT     :
1025             case SID_FM_CONVERTTO_LISTBOX       :
1026             case SID_FM_CONVERTTO_CHECKBOX      :
1027             case SID_FM_CONVERTTO_RADIOBUTTON   :
1028             case SID_FM_CONVERTTO_GROUPBOX      :
1029             case SID_FM_CONVERTTO_COMBOBOX      :
1030             case SID_FM_CONVERTTO_DATE          :
1031             case SID_FM_CONVERTTO_TIME          :
1032             case SID_FM_CONVERTTO_NUMERIC       :
1033             case SID_FM_CONVERTTO_FORMATTED     :
1034             case SID_FM_CONVERTTO_SPINBUTTON    :
1035             {
1036                 if (!m_pFormView || !m_bDesignMode || !GetImpl()->canConvertCurrentSelectionToControl_Lock(FmXFormShell::SlotToIdent(nWhich)))
1037                     rSet.DisableItem( nWhich );
1038                 else
1039                 {
1040                     rSet.Put( SfxBoolItem( nWhich, false ) );
1041                     // just to have a defined state (available and not checked)
1042                 }
1043             }
1044             break;
1045         }
1046         nWhich = aIter.NextWhich();
1047     }
1048 }
1049 
1050 
GetFormState(SfxItemSet & rSet,sal_uInt16 nWhich)1051 void FmFormShell::GetFormState(SfxItemSet &rSet, sal_uInt16 nWhich)
1052 {
1053     if  (   !GetImpl()->getNavController_Lock().is()
1054         ||  !isRowSetAlive(GetImpl()->getNavController_Lock()->getModel())
1055         ||  !m_pFormView
1056         ||  m_bDesignMode
1057         ||  !GetImpl()->getActiveForm_Lock().is()
1058         ||  GetImpl()->isInFilterMode_Lock()
1059         )
1060         rSet.DisableItem(nWhich);
1061     else
1062     {
1063         bool bEnable = false;
1064         try
1065         {
1066             switch (nWhich)
1067             {
1068             case SID_FM_VIEW_AS_GRID:
1069                 if (GetImpl()->getHostFrame_Lock().is() && GetImpl()->getNavController_Lock().is())
1070                 {
1071                     bEnable = true;
1072                     bool bDisplayingCurrent =
1073                         GetImpl()->getInternalForm_Lock(
1074                             Reference<XForm>(GetImpl()->getNavController_Lock()->getModel(), UNO_QUERY)
1075                         ) == GetImpl()->getExternallyDisplayedForm_Lock();
1076                     rSet.Put(SfxBoolItem(nWhich, bDisplayingCurrent));
1077                 }
1078                 break;
1079 
1080             case SID_FM_SEARCH:
1081             {
1082                 Reference<css::beans::XPropertySet> const xNavSet(GetImpl()->getActiveForm_Lock(), UNO_QUERY);
1083                 sal_Int32 nCount = ::comphelper::getINT32(xNavSet->getPropertyValue(FM_PROP_ROWCOUNT));
1084                 bEnable = nCount != 0;
1085             }   break;
1086             case SID_FM_RECORD_ABSOLUTE:
1087             case SID_FM_RECORD_TOTAL:
1088             {
1089                 FeatureState aState;
1090                 GetImpl()->getNavControllerFeatures_Lock()->getState( nWhich, aState );
1091                 if ( SID_FM_RECORD_ABSOLUTE == nWhich )
1092                 {
1093                     sal_Int32 nPosition = 0;
1094                     aState.State >>= nPosition;
1095                     rSet.Put( SfxInt32Item( nWhich, nPosition ) );
1096                 }
1097                 else if ( SID_FM_RECORD_TOTAL == nWhich )
1098                 {
1099                     OUString sTotalCount;
1100                     aState.State >>= sTotalCount;
1101                     rSet.Put( SfxStringItem( nWhich, sTotalCount ) );
1102                 }
1103                 bEnable = aState.Enabled;
1104             }
1105             break;
1106 
1107             // first, prev, next, last, and absolute affect the nav controller, not the
1108             // active controller
1109             case SID_FM_RECORD_FIRST:
1110             case SID_FM_RECORD_PREV:
1111             case SID_FM_RECORD_NEXT:
1112             case SID_FM_RECORD_LAST:
1113             case SID_FM_RECORD_NEW:
1114             case SID_FM_RECORD_SAVE:
1115             case SID_FM_RECORD_UNDO:
1116             case SID_FM_RECORD_DELETE:
1117             case SID_FM_REFRESH:
1118             case SID_FM_REFRESH_FORM_CONTROL:
1119             case SID_FM_REMOVE_FILTER_SORT:
1120             case SID_FM_SORTUP:
1121             case SID_FM_SORTDOWN:
1122             case SID_FM_AUTOFILTER:
1123             case SID_FM_ORDERCRIT:
1124                 bEnable = GetImpl()->IsFormSlotEnabled( nWhich, nullptr );
1125                 break;
1126 
1127             case SID_FM_FORM_FILTERED:
1128             {
1129                 FeatureState aState;
1130                 bEnable = GetImpl()->IsFormSlotEnabled( nWhich, &aState );
1131 
1132                 rSet.Put( SfxBoolItem( nWhich, ::comphelper::getBOOL( aState.State ) ) );
1133             }
1134             break;
1135 
1136             case SID_FM_FILTER_START:
1137                 bEnable = GetImpl()->getActiveControllerFeatures_Lock()->canDoFormFilter();
1138                 break;
1139             }
1140         }
1141         catch( const Exception& )
1142         {
1143             OSL_FAIL( "FmFormShell::GetFormState: caught an exception while determining the state!" );
1144         }
1145         if (!bEnable)
1146             rSet.DisableItem(nWhich);
1147     }
1148 }
1149 
1150 
GetCurPage() const1151 FmFormPage* FmFormShell::GetCurPage() const
1152 {
1153     FmFormPage* pP = nullptr;
1154     if (m_pFormView && m_pFormView->GetSdrPageView())
1155         pP = dynamic_cast<FmFormPage*>( m_pFormView->GetSdrPageView()->GetPage() );
1156     return pP;
1157 }
1158 
1159 
SetView(FmFormView * _pView)1160 void FmFormShell::SetView( FmFormView* _pView )
1161 {
1162     if ( m_pFormView )
1163     {
1164         if ( IsActive() )
1165             GetImpl()->viewDeactivated_Lock(*m_pFormView);
1166 
1167         m_pFormView->SetFormShell( nullptr, FmFormView::FormShellAccess() );
1168         m_pFormView = nullptr;
1169         m_pFormModel = nullptr;
1170     }
1171 
1172     if ( !_pView )
1173         return;
1174 
1175     m_pFormView = _pView;
1176     m_pFormView->SetFormShell( this, FmFormView::FormShellAccess() );
1177     m_pFormModel = static_cast<FmFormModel*>(m_pFormView->GetModel());
1178 
1179     impl_setDesignMode( m_pFormView->IsDesignMode() );
1180 
1181     // We activate our view if we are activated ourself, but sometimes the Activate precedes the SetView.
1182     // But here we know both the view and our activation state so we at least are able to pass the latter
1183     // to the former.
1184     // FS - 30.06.99 - 67308
1185     if ( IsActive() )
1186         GetImpl()->viewActivated_Lock(*m_pFormView);
1187 }
1188 
1189 
DetermineForms(bool bInvalidate)1190 void FmFormShell::DetermineForms(bool bInvalidate)
1191 {
1192     // are there forms on the current page
1193     bool bForms = GetImpl()->hasForms_Lock();
1194     if (bForms != m_bHasForms)
1195     {
1196         m_bHasForms = bForms;
1197         if (bInvalidate)
1198             UIFeatureChanged();
1199     }
1200 }
1201 
1202 
GetY2KState(sal_uInt16 & nReturn)1203 bool FmFormShell::GetY2KState(sal_uInt16& nReturn)
1204 {
1205     return GetImpl()->GetY2KState_Lock(nReturn);
1206 }
1207 
1208 
SetY2KState(sal_uInt16 n)1209 void FmFormShell::SetY2KState(sal_uInt16 n)
1210 {
1211     GetImpl()->SetY2KState_Lock(n);
1212 }
1213 
1214 
Activate(bool bMDI)1215 void FmFormShell::Activate(bool bMDI)
1216 {
1217     SfxShell::Activate(bMDI);
1218 
1219     if ( m_pFormView )
1220         GetImpl()->viewActivated_Lock(*m_pFormView, true);
1221 }
1222 
1223 
Deactivate(bool bMDI)1224 void FmFormShell::Deactivate(bool bMDI)
1225 {
1226     SfxShell::Deactivate(bMDI);
1227 
1228     if ( m_pFormView )
1229         GetImpl()->viewDeactivated_Lock(*m_pFormView, false);
1230 }
1231 
1232 
ExecuteTextAttribute(SfxRequest & _rReq)1233 void FmFormShell::ExecuteTextAttribute( SfxRequest& _rReq )
1234 {
1235     m_pImpl->ExecuteTextAttribute_Lock(_rReq);
1236 }
1237 
1238 
GetTextAttributeState(SfxItemSet & _rSet)1239 void FmFormShell::GetTextAttributeState( SfxItemSet& _rSet )
1240 {
1241     m_pImpl->GetTextAttributeState_Lock(_rSet);
1242 }
1243 
1244 
IsActiveControl() const1245 bool FmFormShell::IsActiveControl() const
1246 {
1247     return m_pImpl->IsActiveControl_Lock(false);
1248 }
1249 
1250 
ForgetActiveControl()1251 void FmFormShell::ForgetActiveControl()
1252 {
1253     m_pImpl->ForgetActiveControl_Lock();
1254 }
1255 
1256 
SetControlActivationHandler(const Link<LinkParamNone *,void> & _rHdl)1257 void FmFormShell::SetControlActivationHandler( const Link<LinkParamNone*,void>& _rHdl )
1258 {
1259     m_pImpl->SetControlActivationHandler_Lock(_rHdl);
1260 }
1261 
1262 
1263 namespace
1264 {
lcl_findUnoObject(const SdrObjList & _rObjList,const Reference<XControlModel> & _rxModel)1265     SdrUnoObj* lcl_findUnoObject( const SdrObjList& _rObjList, const Reference< XControlModel >& _rxModel )
1266     {
1267         SdrObjListIter aIter( &_rObjList );
1268         while ( aIter.IsMore() )
1269         {
1270             SdrObject* pObject = aIter.Next();
1271             SdrUnoObj* pUnoObject = dynamic_cast<SdrUnoObj*>( pObject  );
1272             if ( !pUnoObject )
1273                 continue;
1274 
1275             Reference< XControlModel > xControlModel = pUnoObject->GetUnoControlModel();
1276             if ( !xControlModel.is() )
1277                 continue;
1278 
1279             if ( _rxModel == xControlModel )
1280                 return pUnoObject;
1281         }
1282         return nullptr;
1283     }
1284 }
1285 
1286 
ToggleControlFocus(const SdrUnoObj & i_rUnoObject,const SdrView & i_rView,OutputDevice & i_rDevice) const1287 void FmFormShell::ToggleControlFocus( const SdrUnoObj& i_rUnoObject, const SdrView& i_rView, OutputDevice& i_rDevice ) const
1288 {
1289     try
1290     {
1291         // check if the focus currently is in a control
1292         // Well, okay, do it the other way 'round: Check whether the current control of the active controller
1293         // actually has the focus. This should be equivalent.
1294         const bool bHasControlFocus = GetImpl()->HasControlFocus_Lock();
1295 
1296         if ( bHasControlFocus )
1297         {
1298             vcl::Window* pWindow( dynamic_cast< vcl::Window* >( &i_rDevice ) );
1299             OSL_ENSURE( pWindow, "FmFormShell::ToggleControlFocus: I need a Window, really!" );
1300             if ( pWindow )
1301                 pWindow->GrabFocus();
1302         }
1303         else
1304         {
1305             Reference< XControl > xControl;
1306             GetFormControl( i_rUnoObject.GetUnoControlModel(), i_rView, i_rDevice, xControl );
1307             Reference< XWindow > xControlWindow( xControl, UNO_QUERY );
1308             if ( xControlWindow.is() )
1309                 xControlWindow->setFocus();
1310         }
1311     }
1312     catch( const Exception& )
1313     {
1314         DBG_UNHANDLED_EXCEPTION("svx");
1315     }
1316 }
1317 
1318 
1319 namespace
1320 {
1321     class FocusableControlsFilter : public svx::ISdrObjectFilter
1322     {
1323     public:
FocusableControlsFilter(const SdrView & i_rView,const OutputDevice & i_rDevice)1324         FocusableControlsFilter( const SdrView& i_rView, const OutputDevice& i_rDevice )
1325             :m_rView( i_rView )
1326             ,m_rDevice( i_rDevice )
1327         {
1328         }
1329 
1330     public:
includeObject(const SdrObject & i_rObject) const1331         virtual bool    includeObject( const SdrObject& i_rObject ) const override
1332         {
1333             const SdrUnoObj* pUnoObj = dynamic_cast< const SdrUnoObj* >( &i_rObject );
1334             if ( !pUnoObj )
1335                 return false;
1336 
1337             Reference< XControl > xControl = pUnoObj->GetUnoControl( m_rView, m_rDevice );
1338             return FmXFormView::isFocusable( xControl );
1339         }
1340 
1341     private:
1342         const SdrView&      m_rView;
1343         const OutputDevice& m_rDevice;
1344     };
1345 }
1346 
1347 
CreateFocusableControlFilter(const SdrView & i_rView,const OutputDevice & i_rDevice)1348 ::std::unique_ptr< svx::ISdrObjectFilter > FmFormShell::CreateFocusableControlFilter( const SdrView& i_rView, const OutputDevice& i_rDevice )
1349 {
1350     ::std::unique_ptr< svx::ISdrObjectFilter > pFilter;
1351 
1352     if ( !i_rView.IsDesignMode() )
1353         pFilter.reset( new FocusableControlsFilter( i_rView, i_rDevice ) );
1354 
1355     return pFilter;
1356 }
1357 
1358 
GetFormControl(const Reference<XControlModel> & _rxModel,const SdrView & _rView,const OutputDevice & _rDevice,Reference<XControl> & _out_rxControl) const1359 SdrUnoObj* FmFormShell::GetFormControl( const Reference< XControlModel >& _rxModel, const SdrView& _rView, const OutputDevice& _rDevice, Reference< XControl >& _out_rxControl ) const
1360 {
1361     if ( !_rxModel.is() )
1362         return nullptr;
1363 
1364     // we can only retrieve controls for SdrObjects which belong to page which is actually displayed in the given view
1365     SdrPageView* pPageView = _rView.GetSdrPageView();
1366     SdrPage* pPage = pPageView ? pPageView->GetPage() : nullptr;
1367     OSL_ENSURE( pPage, "FmFormShell::GetFormControl: no page displayed in the given view!" );
1368     if ( !pPage )
1369         return nullptr;
1370 
1371     SdrUnoObj* pUnoObject = lcl_findUnoObject( *pPage, _rxModel );
1372     if ( pUnoObject )
1373     {
1374         _out_rxControl = pUnoObject->GetUnoControl( _rView, _rDevice );
1375         return pUnoObject;
1376     }
1377 
1378 #if OSL_DEBUG_LEVEL > 0
1379     // perhaps we are fed with a control model which lives on a page other than the one displayed
1380     // in the given view. This is worth being reported as error, in non-product builds.
1381     FmFormModel* pModel = GetFormModel();
1382     if ( pModel )
1383     {
1384         sal_uInt16 pageCount = pModel->GetPageCount();
1385         for ( sal_uInt16 page = 0; page < pageCount; ++page )
1386         {
1387             pPage = pModel->GetPage( page );
1388             OSL_ENSURE( pPage, "FmFormShell::GetFormControl: NULL page encountered!" );
1389             if  ( !pPage )
1390                 continue;
1391 
1392             pUnoObject = lcl_findUnoObject( *pPage, _rxModel );
1393             OSL_ENSURE( !pUnoObject, "FmFormShell::GetFormControl: the given control model belongs to a wrong page (displayed elsewhere)!" );
1394         }
1395     }
1396 #else
1397     (void) this; // avoid loplugin:staticmethods
1398 #endif
1399 
1400     return nullptr;
1401 }
1402 
1403 
GetFormController(const Reference<XForm> & _rxForm,const SdrView & _rView,const OutputDevice & _rDevice)1404 Reference< runtime::XFormController > FmFormShell::GetFormController( const Reference< XForm >& _rxForm, const SdrView& _rView, const OutputDevice& _rDevice )
1405 {
1406     const FmFormView* pFormView = dynamic_cast< const FmFormView* >( &_rView );
1407     if ( !pFormView )
1408         return nullptr;
1409 
1410     return pFormView->GetFormController( _rxForm, _rDevice );
1411 }
1412 
1413 
SetDesignMode(bool _bDesignMode)1414 void FmFormShell::SetDesignMode( bool _bDesignMode )
1415 {
1416     if ( _bDesignMode == m_bDesignMode )
1417         return;
1418 
1419     FmFormModel* pModel = GetFormModel();
1420     if (pModel)
1421         // Switch off the undo environment for the time of the transition. This ensures that
1422         // one can also change non-transient properties there. (It should be done with
1423         // caution, however, and it should always be reversed when one switches the mode back.
1424         // An example is the setting of the maximum text length by the OEditModel on its control.)
1425         pModel->GetUndoEnv().Lock();
1426 
1427     // then the actual switch
1428     if ( m_bDesignMode || PrepareClose() )
1429         impl_setDesignMode(!m_bDesignMode );
1430 
1431     // and my undo environment back on
1432     if ( pModel )
1433         pModel->GetUndoEnv().UnLock();
1434 }
1435 
1436 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1437