Bump version to 6.4-15
[LibreOffice.git] / svx / source / form / fmview.cxx
blob6c089c44c98cf9ccdbc42333ca75003dd8dcec22
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sfx2/docfile.hxx>
21 #ifdef REFERENCE
22 #undef REFERENCE
23 #endif
24 #include <svtools/ehdl.hxx>
25 #include <unotools/moduleoptions.hxx>
26 #include <com/sun/star/sdb/SQLContext.hpp>
27 #include <com/sun/star/uno/XNamingService.hpp>
28 #include <com/sun/star/sdbc/XConnection.hpp>
29 #include <com/sun/star/sdbc/DataType.hpp>
30 #include <com/sun/star/form/XLoadable.hpp>
31 #include <com/sun/star/form/XReset.hpp>
32 #include <fmvwimp.hxx>
33 #include <sfx2/objsh.hxx>
34 #include <sfx2/viewsh.hxx>
35 #include <sfx2/viewfrm.hxx>
36 #include <sfx2/bindings.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <basic/sbuno.hxx>
39 #include <basic/sbx.hxx>
40 #include <fmobj.hxx>
41 #include <svx/svditer.hxx>
42 #include <svx/svdpagv.hxx>
43 #include <svx/svdogrp.hxx>
44 #include <svx/fmview.hxx>
45 #include <svx/fmmodel.hxx>
46 #include <svx/fmpage.hxx>
47 #include <svx/fmshell.hxx>
48 #include <fmpgeimp.hxx>
49 #include <svx/fmtools.hxx>
50 #include <fmshimp.hxx>
51 #include <fmservs.hxx>
52 #include <fmprop.hxx>
53 #include <fmundo.hxx>
54 #include <svx/dataaccessdescriptor.hxx>
55 #include <comphelper/namedvaluecollection.hxx>
56 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
57 #include <com/sun/star/beans/PropertyValue.hpp>
58 #include <com/sun/star/beans/PropertyState.hpp>
59 #include <com/sun/star/form/FormComponentType.hpp>
60 #include <vcl/svapp.hxx>
61 #include <tools/debug.hxx>
62 #include <tools/diagnose_ex.h>
63 #include <vcl/stdtext.hxx>
64 #include <svx/fmglob.hxx>
65 #include <svx/sdrpagewindow.hxx>
66 #include <svx/sdrpaintwindow.hxx>
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::lang;
71 using namespace ::com::sun::star::sdbc;
72 using namespace ::com::sun::star::sdb;
73 using namespace ::com::sun::star::beans;
74 using namespace ::com::sun::star::container;
75 using namespace ::com::sun::star::form;
76 using namespace ::com::sun::star::util;
77 using namespace ::svxform;
78 using namespace ::svx;
80 FmFormView::FmFormView(
81 SdrModel& rSdrModel,
82 OutputDevice* pOut)
83 : E3dView(rSdrModel, pOut)
85 Init();
88 void FmFormView::Init()
90 pFormShell = nullptr;
91 pImpl = new FmXFormView(this);
93 // set model
94 SdrModel* pModel = GetModel();
96 DBG_ASSERT( dynamic_cast<const FmFormModel*>( pModel) != nullptr, "Wrong model" );
97 if( dynamic_cast<const FmFormModel*>( pModel) == nullptr ) return;
98 FmFormModel* pFormModel = static_cast<FmFormModel*>(pModel);
101 // get DesignMode from model
102 bool bInitDesignMode = pFormModel->GetOpenInDesignMode();
103 if ( pFormModel->OpenInDesignModeIsDefaulted( ) )
104 { // this means that nobody ever explicitly set this on the model, and the model has never
105 // been loaded from a stream.
106 // This means this is a newly created document. This means, we want to have it in design
107 // mode by default (though a newly created model returns true for GetOpenInDesignMode).
108 // We _want_ to have this because it makes a lot of hacks following the original fix
109 DBG_ASSERT( !bInitDesignMode, "FmFormView::Init: doesn't the model default to FALSE anymore?" );
110 // if this asserts, either the on-construction default in the model has changed (then this here
111 // may not be necessary anymore), or we're not dealing with a new document...
112 bInitDesignMode = true;
115 SfxObjectShell* pObjShell = pFormModel->GetObjectShell();
116 if ( pObjShell && pObjShell->GetMedium() )
118 const SfxPoolItem *pItem=nullptr;
119 if ( pObjShell->GetMedium()->GetItemSet()->GetItemState( SID_COMPONENTDATA, false, &pItem ) == SfxItemState::SET )
121 ::comphelper::NamedValueCollection aComponentData( static_cast<const SfxUnoAnyItem*>(pItem)->GetValue() );
122 bInitDesignMode = aComponentData.getOrDefault( "ApplyFormDesignMode", bInitDesignMode );
126 // this will be done in the shell
127 // bDesignMode = !bInitDesignMode; // forces execution of SetDesignMode
128 SetDesignMode( bInitDesignMode );
132 FmFormView::~FmFormView()
134 if( pFormShell )
135 pFormShell->SetView( nullptr );
137 pImpl->notifyViewDying();
141 FmFormPage* FmFormView::GetCurPage()
143 SdrPageView* pPageView = GetSdrPageView();
144 FmFormPage* pCurPage = pPageView ? dynamic_cast<FmFormPage*>( pPageView->GetPage() ) : nullptr;
145 return pCurPage;
149 void FmFormView::MarkListHasChanged()
151 E3dView::MarkListHasChanged();
153 if ( pFormShell && IsDesignMode() )
155 FmFormObj* pObj = getMarkedGrid();
156 if ( pImpl->m_pMarkedGrid && pImpl->m_pMarkedGrid != pObj )
158 pImpl->m_pMarkedGrid = nullptr;
159 if ( pImpl->m_xWindow.is() )
161 pImpl->m_xWindow->removeFocusListener(pImpl.get());
162 pImpl->m_xWindow = nullptr;
164 SetMoveOutside(false);
165 //OLMRefreshAllIAOManagers();
168 pFormShell->GetImpl()->SetSelectionDelayed_Lock();
172 namespace
174 const SdrPageWindow* findPageWindow( const SdrPaintView* _pView, OutputDevice const * _pWindow )
176 SdrPageView* pPageView = _pView->GetSdrPageView();
177 if(pPageView)
179 for ( sal_uInt32 window = 0; window < pPageView->PageWindowCount(); ++window )
181 const SdrPageWindow* pPageWindow = pPageView->GetPageWindow( window );
182 if ( !pPageWindow || &pPageWindow->GetPaintWindow().GetOutputDevice() != _pWindow )
183 continue;
185 return pPageWindow;
188 return nullptr;
193 void FmFormView::AddWindowToPaintView(OutputDevice* pNewWin, vcl::Window* pWindow)
195 E3dView::AddWindowToPaintView(pNewWin, pWindow);
197 if ( !pNewWin )
198 return;
200 // look up the PageViewWindow for the newly inserted window, and care for it
201 // #i39269# / 2004-12-20 / frank.schoenheit@sun.com
202 const SdrPageWindow* pPageWindow = findPageWindow( this, pNewWin );
203 if ( pPageWindow )
204 pImpl->addWindow( *pPageWindow );
208 void FmFormView::DeleteWindowFromPaintView(OutputDevice* pNewWin)
210 const SdrPageWindow* pPageWindow = findPageWindow( this, pNewWin );
211 if ( pPageWindow )
212 pImpl->removeWindow( pPageWindow->GetControlContainer() );
214 E3dView::DeleteWindowFromPaintView(pNewWin);
218 void FmFormView::ChangeDesignMode(bool bDesign)
220 if (bDesign == IsDesignMode())
221 return;
223 FmFormModel* pModel = dynamic_cast<FmFormModel*>( GetModel() );
224 if (pModel)
225 { // For the duration of the transition the Undo-Environment is disabled. This ensures that non-transient Properties can
226 // also be changed (this should be done with care and also reversed before switching the mode back. An example is the
227 // setting of the maximal length of the text by FmXEditModel on its control.)
228 pModel->GetUndoEnv().Lock();
231 // --- 1. deactivate all controls if we are switching to design mode
232 if ( bDesign )
233 DeactivateControls( GetSdrPageView() );
235 // --- 2. simulate a deactivation (the shell will handle some things there ...?)
236 if ( pFormShell && pFormShell->GetImpl() )
237 pFormShell->GetImpl()->viewDeactivated_Lock(*this);
238 else
239 pImpl->Deactivate();
241 // --- 3. activate all controls, if we're switching to alive mode
242 if ( !bDesign )
243 ActivateControls( GetSdrPageView() );
245 // --- 4. load resp. unload the forms
246 FmFormPage* pCurPage = GetCurPage();
247 if ( pCurPage )
249 if ( pFormShell && pFormShell->GetImpl() )
250 pFormShell->GetImpl()->loadForms_Lock(pCurPage, (bDesign ? LoadFormsFlags::Unload : LoadFormsFlags::Load));
253 // --- 5. base class functionality
254 SetDesignMode( bDesign );
256 // --- 6. simulate an activation (the shell will handle some things there ...?)
257 OSL_PRECOND( pFormShell && pFormShell->GetImpl(), "FmFormView::ChangeDesignMode: is this really allowed? No shell?" );
258 if ( pFormShell && pFormShell->GetImpl() )
259 pFormShell->GetImpl()->viewActivated_Lock(*this);
260 else
261 pImpl->Activate();
263 if ( pCurPage )
265 if ( bDesign )
267 if ( GetActualOutDev() && GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW )
269 const vcl::Window* pWindow = static_cast< const vcl::Window* >( GetActualOutDev() );
270 const_cast< vcl::Window* >( pWindow )->GrabFocus();
273 // redraw UNO objects
274 if ( GetSdrPageView() )
276 SdrObjListIter aIter(pCurPage);
277 while( aIter.IsMore() )
279 SdrObject* pObj = aIter.Next();
280 if (pObj && pObj->IsUnoObj())
282 // For redraw just use ActionChanged()
283 // pObj->BroadcastObjectChange();
284 pObj->ActionChanged();
289 else
291 // set the auto focus to the first control (if indicated by the model to do so)
292 bool bForceControlFocus = pModel && pModel->GetAutoControlFocus();
293 if (bForceControlFocus)
294 pImpl->AutoFocus();
298 // Unlock Undo-Environment
299 if (pModel)
300 pModel->GetUndoEnv().UnLock();
304 void FmFormView::GrabFirstControlFocus()
306 if ( !IsDesignMode() )
307 pImpl->AutoFocus();
311 SdrPageView* FmFormView::ShowSdrPage(SdrPage* pPage)
313 SdrPageView* pPV = E3dView::ShowSdrPage(pPage);
315 if (pPage)
317 if (!IsDesignMode())
319 // creating the controllers
320 ActivateControls(pPV);
322 // Deselect all
323 UnmarkAll();
325 else if ( pFormShell && pFormShell->IsDesignMode() )
327 FmXFormShell* pFormShellImpl = pFormShell->GetImpl();
328 pFormShellImpl->UpdateForms_Lock(true);
330 // so that the form navigator can react to the pagechange
331 pFormShell->GetViewShell()->GetViewFrame()->GetBindings().Invalidate(SID_FM_FMEXPLORER_CONTROL, true);
333 pFormShellImpl->SetSelection_Lock(GetMarkedObjectList());
337 // notify our shell that we have been activated
338 if ( pFormShell && pFormShell->GetImpl() )
339 pFormShell->GetImpl()->viewActivated_Lock(*this);
340 else
341 pImpl->Activate();
343 return pPV;
347 void FmFormView::HideSdrPage()
349 // --- 1. deactivate controls
350 if ( !IsDesignMode() )
351 DeactivateControls(GetSdrPageView());
353 // --- 2. tell the shell the view is (going to be) deactivated
354 if ( pFormShell && pFormShell->GetImpl() )
355 pFormShell->GetImpl()->viewDeactivated_Lock(*this);
356 else
357 pImpl->Deactivate();
359 // --- 3. base class behavior
360 E3dView::HideSdrPage();
364 void FmFormView::ActivateControls(SdrPageView const * pPageView)
366 if (!pPageView)
367 return;
369 for (sal_uInt32 i = 0; i < pPageView->PageWindowCount(); ++i)
371 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
372 pImpl->addWindow(rPageWindow);
377 void FmFormView::DeactivateControls(SdrPageView const * pPageView)
379 if( !pPageView )
380 return;
382 for (sal_uInt32 i = 0; i < pPageView->PageWindowCount(); ++i)
384 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
385 pImpl->removeWindow(rPageWindow.GetControlContainer() );
390 SdrObjectUniquePtr FmFormView::CreateFieldControl( const ODataAccessDescriptor& _rColumnDescriptor )
392 return pImpl->implCreateFieldControl( _rColumnDescriptor );
396 SdrObjectUniquePtr FmFormView::CreateXFormsControl( const OXFormsDescriptor &_rDesc )
398 return pImpl->implCreateXFormsControl(_rDesc);
402 SdrObjectUniquePtr FmFormView::CreateFieldControl(const OUString& rFieldDesc) const
404 sal_Int32 nIdx{ 0 };
405 OUString sDataSource = rFieldDesc.getToken(0, u'\x000B', nIdx);
406 OUString sObjectName = rFieldDesc.getToken(0, u'\x000B', nIdx);
407 sal_uInt16 nObjectType = static_cast<sal_uInt16>(rFieldDesc.getToken(0, u'\x000B', nIdx).toInt32());
408 OUString sFieldName = rFieldDesc.getToken(0, u'\x000B', nIdx);
410 if (sFieldName.isEmpty() || sObjectName.isEmpty() || sDataSource.isEmpty())
411 return nullptr;
413 ODataAccessDescriptor aColumnDescriptor;
414 aColumnDescriptor.setDataSource(sDataSource);
415 aColumnDescriptor[ DataAccessDescriptorProperty::Command ] <<= sObjectName;
416 aColumnDescriptor[ DataAccessDescriptorProperty::CommandType ] <<= nObjectType;
417 aColumnDescriptor[ DataAccessDescriptorProperty::ColumnName ] <<= sFieldName;
419 return pImpl->implCreateFieldControl( aColumnDescriptor );
423 void FmFormView::InsertControlContainer(const Reference< css::awt::XControlContainer > & xCC)
425 if( !IsDesignMode() )
427 SdrPageView* pPageView = GetSdrPageView();
428 if( pPageView )
430 for( sal_uInt32 i = 0; i < pPageView->PageWindowCount(); i++ )
432 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
434 if( rPageWindow.GetControlContainer( false ) == xCC )
436 pImpl->addWindow(rPageWindow);
437 break;
445 void FmFormView::RemoveControlContainer(const Reference< css::awt::XControlContainer > & xCC)
447 if( !IsDesignMode() )
449 pImpl->removeWindow( xCC );
454 SdrPaintWindow* FmFormView::BeginCompleteRedraw(OutputDevice* pOut)
456 SdrPaintWindow* pPaintWindow = E3dView::BeginCompleteRedraw( pOut );
457 pImpl->suspendTabOrderUpdate();
458 return pPaintWindow;
462 void FmFormView::EndCompleteRedraw( SdrPaintWindow& rPaintWindow, bool bPaintFormLayer )
464 E3dView::EndCompleteRedraw( rPaintWindow, bPaintFormLayer );
465 pImpl->resumeTabOrderUpdate();
469 bool FmFormView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin)
471 bool bDone = false;
472 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
473 if ( IsDesignMode()
474 && rKeyCode.GetCode() == KEY_RETURN
477 // RETURN alone enters grid controls, for keyboard accessibility
478 if ( pWin
479 && !rKeyCode.IsShift()
480 && !rKeyCode.IsMod1()
481 && !rKeyCode.IsMod2()
484 FmFormObj* pObj = getMarkedGrid();
485 if ( pObj )
487 Reference< awt::XWindow > xWindow( pObj->GetUnoControl( *this, *pWin ), UNO_QUERY );
488 if ( xWindow.is() )
490 pImpl->m_pMarkedGrid = pObj;
491 pImpl->m_xWindow = xWindow;
492 // add as listener to get notified when ESC will be pressed inside the grid
493 pImpl->m_xWindow->addFocusListener(pImpl.get());
494 SetMoveOutside(true);
495 //OLMRefreshAllIAOManagers();
496 xWindow->setFocus();
497 bDone = true;
501 // Alt-RETURN alone shows the properties of the selection
502 if ( pFormShell
503 && pFormShell->GetImpl()
504 && !rKeyCode.IsShift()
505 && !rKeyCode.IsMod1()
506 && rKeyCode.IsMod2()
509 pFormShell->GetImpl()->handleShowPropertiesRequest_Lock();
514 if ( !bDone )
515 bDone = E3dView::KeyInput(rKEvt,pWin);
516 return bDone;
519 bool FmFormView::checkUnMarkAll(const Reference< XInterface >& _xSource)
521 Reference< css::awt::XControl> xControl(pImpl->m_xWindow,UNO_QUERY);
522 bool bRet = !xControl.is() || !_xSource.is() || _xSource != xControl->getModel();
523 if ( bRet )
524 UnmarkAll();
526 return bRet;
530 bool FmFormView::MouseButtonDown( const MouseEvent& _rMEvt, OutputDevice* _pWin )
532 bool bReturn = E3dView::MouseButtonDown( _rMEvt, _pWin );
534 if ( pFormShell && pFormShell->GetImpl() )
536 SdrViewEvent aViewEvent;
537 PickAnything( _rMEvt, SdrMouseEventKind::BUTTONDOWN, aViewEvent );
538 pFormShell->GetImpl()->handleMouseButtonDown_Lock(aViewEvent);
541 return bReturn;
545 FmFormObj* FmFormView::getMarkedGrid() const
547 FmFormObj* pFormObject = nullptr;
548 const SdrMarkList& rMarkList = GetMarkedObjectList();
549 if ( 1 == rMarkList.GetMarkCount() )
551 SdrMark* pMark = rMarkList.GetMark(0);
552 if ( pMark )
554 pFormObject = FmFormObj::GetFormObject( pMark->GetMarkedSdrObj() );
555 if ( pFormObject )
557 Reference< XServiceInfo > xServInfo( pFormObject->GetUnoControlModel(), UNO_QUERY );
558 if ( !xServInfo.is() || !xServInfo->supportsService( FM_SUN_COMPONENT_GRIDCONTROL ) )
559 pFormObject = nullptr;
563 return pFormObject;
567 void FmFormView::createControlLabelPair( OutputDevice const * _pOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM,
568 const Reference< XPropertySet >& _rxField, const Reference< XNumberFormats >& _rxNumberFormats,
569 sal_uInt16 _nControlObjectID, SdrInventor _nInventor, sal_uInt16 _nLabelObjectID,
570 SdrModel& _rModel,
571 std::unique_ptr<SdrUnoObj, SdrObjectFreeOp>& _rpLabel,
572 std::unique_ptr<SdrUnoObj, SdrObjectFreeOp>& _rpControl )
574 FmXFormView::createControlLabelPair(
575 *_pOutDev, _nXOffsetMM, _nYOffsetMM,
576 _rxField, _rxNumberFormats,
577 _nControlObjectID, "", _nInventor, _nLabelObjectID,
578 _rModel,
579 _rpLabel, _rpControl
583 Reference< runtime::XFormController > FmFormView::GetFormController( const Reference< XForm >& _rxForm, const OutputDevice& _rDevice ) const
585 return pImpl->getFormController( _rxForm, _rDevice );
588 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */