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