Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / form / fmview.cxx
blobe693f8e122b188a26c5e59b87baf08395d8f8f82
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 <com/sun/star/sdb/SQLContext.hpp>
25 #include <com/sun/star/sdbc/XConnection.hpp>
26 #include <com/sun/star/form/XLoadable.hpp>
27 #include <fmvwimp.hxx>
28 #include <sfx2/objsh.hxx>
29 #include <sfx2/viewsh.hxx>
30 #include <sfx2/viewfrm.hxx>
31 #include <sfx2/bindings.hxx>
32 #include <fmobj.hxx>
33 #include <svx/svditer.hxx>
34 #include <svx/svdpagv.hxx>
35 #include <svx/fmview.hxx>
36 #include <svx/fmmodel.hxx>
37 #include <svx/fmpage.hxx>
38 #include <svx/fmshell.hxx>
39 #include <fmshimp.hxx>
40 #include <fmservs.hxx>
41 #include <fmundo.hxx>
42 #include <svx/dataaccessdescriptor.hxx>
43 #include <comphelper/namedvaluecollection.hxx>
44 #include <o3tl/deleter.hxx>
45 #include <toolkit/helper/vclunohelper.hxx>
46 #include <com/sun/star/lang/XServiceInfo.hpp>
47 #include <com/sun/star/awt/XControl.hpp>
48 #include <tools/debug.hxx>
49 #include <svx/sdrpagewindow.hxx>
50 #include <svx/sdrpaintwindow.hxx>
51 #include <svx/svxids.hrc>
52 #include <vcl/i18nhelp.hxx>
53 #include <vcl/window.hxx>
54 #include <o3tl/string_view.hxx>
56 using namespace ::com::sun::star;
57 using namespace ::com::sun::star::uno;
58 using namespace ::com::sun::star::lang;
59 using namespace ::com::sun::star::sdbc;
60 using namespace ::com::sun::star::sdb;
61 using namespace ::com::sun::star::beans;
62 using namespace ::com::sun::star::container;
63 using namespace ::com::sun::star::form;
64 using namespace ::com::sun::star::util;
65 using namespace ::svxform;
66 using namespace ::svx;
68 FmFormView::FmFormView(
69 SdrModel& rSdrModel,
70 OutputDevice* pOut)
71 : E3dView(rSdrModel, pOut)
73 Init();
76 void FmFormView::Init()
78 pFormShell = nullptr;
79 pImpl = new FmXFormView(this);
81 // set model
82 SdrModel* pModel = &GetModel();
84 DBG_ASSERT( dynamic_cast<const FmFormModel*>( pModel) != nullptr, "Wrong model" );
85 FmFormModel* pFormModel = dynamic_cast<FmFormModel*>(pModel);
86 if( !pFormModel )
87 return;
89 // get DesignMode from model
90 bool bInitDesignMode = pFormModel->GetOpenInDesignMode();
91 if ( pFormModel->OpenInDesignModeIsDefaulted( ) )
92 { // this means that nobody ever explicitly set this on the model, and the model has never
93 // been loaded from a stream.
94 // This means this is a newly created document. This means, we want to have it in design
95 // mode by default (though a newly created model returns true for GetOpenInDesignMode).
96 // We _want_ to have this because it makes a lot of hacks following the original fix
97 DBG_ASSERT( !bInitDesignMode, "FmFormView::Init: doesn't the model default to FALSE anymore?" );
98 // if this asserts, either the on-construction default in the model has changed (then this here
99 // may not be necessary anymore), or we're not dealing with a new document...
100 bInitDesignMode = true;
103 SfxObjectShell* pObjShell = pFormModel->GetObjectShell();
104 if ( pObjShell && pObjShell->GetMedium() )
106 if ( const SfxUnoAnyItem *pItem = pObjShell->GetMedium()->GetItemSet()->GetItemIfSet( SID_COMPONENTDATA, false ) )
108 ::comphelper::NamedValueCollection aComponentData( pItem->GetValue() );
109 bInitDesignMode = aComponentData.getOrDefault( "ApplyFormDesignMode", bInitDesignMode );
113 // this will be done in the shell
114 // bDesignMode = !bInitDesignMode; // forces execution of SetDesignMode
115 SetDesignMode( bInitDesignMode );
118 FmFormView::~FmFormView()
120 if (pFormShell)
121 suppress_fun_call_w_exception(pFormShell->SetView(nullptr));
123 pImpl->notifyViewDying();
126 FmFormPage* FmFormView::GetCurPage()
128 SdrPageView* pPageView = GetSdrPageView();
129 FmFormPage* pCurPage = pPageView ? dynamic_cast<FmFormPage*>( pPageView->GetPage() ) : nullptr;
130 return pCurPage;
133 void FmFormView::MarkListHasChanged()
135 E3dView::MarkListHasChanged();
137 if ( !(pFormShell && IsDesignMode()) )
138 return;
140 FmFormObj* pObj = getMarkedGrid();
141 if ( pImpl->m_pMarkedGrid && pImpl->m_pMarkedGrid != pObj )
143 pImpl->m_pMarkedGrid = nullptr;
144 if ( pImpl->m_xWindow.is() )
146 pImpl->m_xWindow->removeFocusListener(pImpl);
147 pImpl->m_xWindow = nullptr;
149 SetMoveOutside(false);
150 //OLMRefreshAllIAOManagers();
153 pFormShell->GetImpl()->SetSelectionDelayed_Lock();
156 namespace
158 const SdrPageWindow* findPageWindow( const SdrPaintView* _pView, OutputDevice const * _pWindow )
160 SdrPageView* pPageView = _pView->GetSdrPageView();
161 if(pPageView)
163 for ( sal_uInt32 window = 0; window < pPageView->PageWindowCount(); ++window )
165 const SdrPageWindow* pPageWindow = pPageView->GetPageWindow( window );
166 if ( !pPageWindow || &pPageWindow->GetPaintWindow().GetOutputDevice() != _pWindow )
167 continue;
169 return pPageWindow;
172 return nullptr;
177 void FmFormView::AddDeviceToPaintView(OutputDevice& rNewDev, vcl::Window* pWindow)
179 E3dView::AddDeviceToPaintView(rNewDev, pWindow);
181 // look up the PageViewWindow for the newly inserted window, and care for it
182 // #i39269# / 2004-12-20 / frank.schoenheit@sun.com
183 const SdrPageWindow* pPageWindow = findPageWindow( this, &rNewDev );
184 if ( pPageWindow )
185 pImpl->addWindow( *pPageWindow );
189 void FmFormView::DeleteDeviceFromPaintView(OutputDevice& rNewDev)
191 const SdrPageWindow* pPageWindow = findPageWindow( this, &rNewDev );
192 if ( pPageWindow )
193 pImpl->removeWindow( pPageWindow->GetControlContainer() );
195 E3dView::DeleteDeviceFromPaintView(rNewDev);
199 void FmFormView::ChangeDesignMode(bool bDesign)
201 if (bDesign == IsDesignMode())
202 return;
204 FmFormModel* pModel = dynamic_cast<FmFormModel*>(&GetModel());
205 if (pModel)
206 { // For the duration of the transition the Undo-Environment is disabled. This ensures that non-transient Properties can
207 // also be changed (this should be done with care and also reversed before switching the mode back. An example is the
208 // setting of the maximal length of the text by FmXEditModel on its control.)
209 pModel->GetUndoEnv().Lock();
212 // --- 1. deactivate all controls if we are switching to design mode
213 if ( bDesign )
214 DeactivateControls( GetSdrPageView() );
216 // --- 2. simulate a deactivation (the shell will handle some things there ...?)
217 if ( pFormShell && pFormShell->GetImpl() )
218 pFormShell->GetImpl()->viewDeactivated_Lock(*this);
219 else
220 pImpl->Deactivate();
222 // --- 3. activate all controls, if we're switching to alive mode
223 if ( !bDesign )
224 ActivateControls( GetSdrPageView() );
226 // --- 4. load resp. unload the forms
227 FmFormPage* pCurPage = GetCurPage();
228 if ( pCurPage )
230 if ( pFormShell && pFormShell->GetImpl() )
231 pFormShell->GetImpl()->loadForms_Lock(pCurPage, (bDesign ? LoadFormsFlags::Unload : LoadFormsFlags::Load));
234 // --- 5. base class functionality
235 SetDesignMode( bDesign );
237 // --- 6. simulate an activation (the shell will handle some things there ...?)
238 OSL_PRECOND( pFormShell && pFormShell->GetImpl(), "FmFormView::ChangeDesignMode: is this really allowed? No shell?" );
239 if ( pFormShell && pFormShell->GetImpl() )
240 pFormShell->GetImpl()->viewActivated_Lock(*this);
241 else
242 pImpl->Activate();
244 if ( pCurPage )
246 if ( bDesign )
248 if ( GetActualOutDev() && GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW )
250 const vcl::Window* pWindow = GetActualOutDev()->GetOwnerWindow();
251 const_cast< vcl::Window* >( pWindow )->GrabFocus();
254 // redraw UNO objects
255 if ( GetSdrPageView() )
257 SdrObjListIter aIter(pCurPage);
258 while( aIter.IsMore() )
260 SdrObject* pObj = aIter.Next();
261 if (pObj && pObj->IsUnoObj())
263 // For redraw just use ActionChanged()
264 // pObj->BroadcastObjectChange();
265 pObj->ActionChanged();
270 else
272 // set the auto focus to the first control (if indicated by the model to do so)
273 bool bForceControlFocus = pModel && pModel->GetAutoControlFocus();
274 if (bForceControlFocus)
275 pImpl->AutoFocus();
279 // Unlock Undo-Environment
280 if (pModel)
281 pModel->GetUndoEnv().UnLock();
285 void FmFormView::GrabFirstControlFocus()
287 if ( !IsDesignMode() )
288 pImpl->AutoFocus();
292 SdrPageView* FmFormView::ShowSdrPage(SdrPage* pPage)
294 SdrPageView* pPV = E3dView::ShowSdrPage(pPage);
296 if (pPage)
298 if (!IsDesignMode())
300 // creating the controllers
301 ActivateControls(pPV);
303 // Deselect all
304 UnmarkAll();
306 else if ( pFormShell && pFormShell->IsDesignMode() )
308 FmXFormShell* pFormShellImpl = pFormShell->GetImpl();
309 pFormShellImpl->UpdateForms_Lock(true);
311 // so that the form navigator can react to the pagechange
312 pFormShell->GetViewShell()->GetViewFrame().GetBindings().Invalidate(SID_FM_FMEXPLORER_CONTROL, true);
314 pFormShellImpl->SetSelection_Lock(GetMarkedObjectList());
318 // notify our shell that we have been activated
319 if ( pFormShell && pFormShell->GetImpl() )
320 pFormShell->GetImpl()->viewActivated_Lock(*this);
321 else
322 pImpl->Activate();
324 return pPV;
328 void FmFormView::HideSdrPage()
330 // --- 1. deactivate controls
331 if ( !IsDesignMode() )
332 DeactivateControls(GetSdrPageView());
334 // --- 2. tell the shell the view is (going to be) deactivated
335 if ( pFormShell && pFormShell->GetImpl() )
336 pFormShell->GetImpl()->viewDeactivated_Lock(*this);
337 else
338 pImpl->Deactivate();
340 // --- 3. base class behavior
341 E3dView::HideSdrPage();
345 void FmFormView::ActivateControls(SdrPageView const * pPageView)
347 if (!pPageView)
348 return;
350 for (sal_uInt32 i = 0; i < pPageView->PageWindowCount(); ++i)
352 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
353 pImpl->addWindow(rPageWindow);
358 void FmFormView::DeactivateControls(SdrPageView const * pPageView)
360 if( !pPageView )
361 return;
363 for (sal_uInt32 i = 0; i < pPageView->PageWindowCount(); ++i)
365 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
366 pImpl->removeWindow(rPageWindow.GetControlContainer() );
371 rtl::Reference<SdrObject> FmFormView::CreateFieldControl( const ODataAccessDescriptor& _rColumnDescriptor )
373 return pImpl->implCreateFieldControl( _rColumnDescriptor );
377 rtl::Reference<SdrObject> FmFormView::CreateXFormsControl( const OXFormsDescriptor &_rDesc )
379 return pImpl->implCreateXFormsControl(_rDesc);
383 rtl::Reference<SdrObject> FmFormView::CreateFieldControl(std::u16string_view rFieldDesc) const
385 sal_Int32 nIdx{ 0 };
386 OUString sDataSource( o3tl::getToken(rFieldDesc, 0, u'\x000B', nIdx));
387 OUString sObjectName( o3tl::getToken(rFieldDesc, 0, u'\x000B', nIdx));
388 sal_uInt16 nObjectType = static_cast<sal_uInt16>(o3tl::toInt32(o3tl::getToken(rFieldDesc, 0, u'\x000B', nIdx)));
389 OUString sFieldName( o3tl::getToken(rFieldDesc, 0, u'\x000B', nIdx));
391 if (sFieldName.isEmpty() || sObjectName.isEmpty() || sDataSource.isEmpty())
392 return nullptr;
394 ODataAccessDescriptor aColumnDescriptor;
395 aColumnDescriptor.setDataSource(sDataSource);
396 aColumnDescriptor[ DataAccessDescriptorProperty::Command ] <<= sObjectName;
397 aColumnDescriptor[ DataAccessDescriptorProperty::CommandType ] <<= nObjectType;
398 aColumnDescriptor[ DataAccessDescriptorProperty::ColumnName ] <<= sFieldName;
400 return pImpl->implCreateFieldControl( aColumnDescriptor );
404 void FmFormView::InsertControlContainer(const Reference< css::awt::XControlContainer > & xCC)
406 if( IsDesignMode() )
407 return;
409 SdrPageView* pPageView = GetSdrPageView();
410 if( !pPageView )
411 return;
413 for( sal_uInt32 i = 0; i < pPageView->PageWindowCount(); i++ )
415 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
417 if( rPageWindow.GetControlContainer( false ) == xCC )
419 pImpl->addWindow(rPageWindow);
420 break;
426 void FmFormView::RemoveControlContainer(const Reference< css::awt::XControlContainer > & xCC)
428 if( !IsDesignMode() )
430 pImpl->removeWindow( xCC );
435 SdrPaintWindow* FmFormView::BeginCompleteRedraw(OutputDevice* pOut)
437 SdrPaintWindow* pPaintWindow = E3dView::BeginCompleteRedraw( pOut );
438 pImpl->suspendTabOrderUpdate();
439 return pPaintWindow;
443 void FmFormView::EndCompleteRedraw( SdrPaintWindow& rPaintWindow, bool bPaintFormLayer )
445 E3dView::EndCompleteRedraw( rPaintWindow, bPaintFormLayer );
446 pImpl->resumeTabOrderUpdate();
450 bool FmFormView::KeyInput(const KeyEvent& rKEvt, vcl::Window* pWin)
452 bool bDone = false;
453 const vcl::KeyCode& rKeyCode = rKEvt.GetKeyCode();
454 if ( IsDesignMode()
455 && rKeyCode.GetCode() == KEY_RETURN
458 // RETURN alone enters grid controls, for keyboard accessibility
459 if ( pWin
460 && !rKeyCode.IsShift()
461 && !rKeyCode.IsMod1()
462 && !rKeyCode.IsMod2()
465 FmFormObj* pObj = getMarkedGrid();
466 if ( pObj )
468 Reference< awt::XWindow > xWindow( pObj->GetUnoControl( *this, *pWin->GetOutDev() ), UNO_QUERY );
469 if ( xWindow.is() )
471 pImpl->m_pMarkedGrid = pObj;
472 pImpl->m_xWindow = xWindow;
473 // add as listener to get notified when ESC will be pressed inside the grid
474 pImpl->m_xWindow->addFocusListener(pImpl);
475 SetMoveOutside(true);
476 //OLMRefreshAllIAOManagers();
477 xWindow->setFocus();
478 bDone = true;
482 // Alt-RETURN alone shows the properties of the selection
483 if ( pFormShell
484 && pFormShell->GetImpl()
485 && !rKeyCode.IsShift()
486 && !rKeyCode.IsMod1()
487 && rKeyCode.IsMod2()
490 pFormShell->GetImpl()->handleShowPropertiesRequest_Lock();
495 // tdf#139804 Allow selecting form controls with Alt-<Mnemonic>
496 if (rKeyCode.IsMod2() && rKeyCode.GetCode())
498 if (FmFormPage* pCurPage = GetCurPage())
500 for (size_t a = 0; a < pCurPage->GetObjCount(); ++a)
502 SdrObject* pObj = pCurPage->GetObj(a);
503 FmFormObj* pFormObject = FmFormObj::GetFormObject(pObj);
504 if (!pFormObject)
505 continue;
507 Reference<awt::XControl> xControl = pFormObject->GetUnoControl(*this, *pWin->GetOutDev());
508 if (!xControl.is())
509 continue;
510 const vcl::I18nHelper& rI18nHelper = Application::GetSettings().GetUILocaleI18nHelper();
511 VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xControl->getPeer());
512 if (rI18nHelper.MatchMnemonic(pWindow->GetText(), rKEvt.GetCharCode()))
514 pWindow->GrabFocus();
515 pWindow->KeyInput(rKEvt);
516 bDone = true;
517 break;
523 if ( !bDone )
524 bDone = E3dView::KeyInput(rKEvt,pWin);
525 return bDone;
528 bool FmFormView::checkUnMarkAll(const Reference< XInterface >& _xSource)
530 Reference< css::awt::XControl> xControl(pImpl->m_xWindow,UNO_QUERY);
531 bool bRet = !xControl.is() || !_xSource.is() || _xSource != xControl->getModel();
532 if ( bRet )
533 UnmarkAll();
535 return bRet;
539 bool FmFormView::MouseButtonDown( const MouseEvent& _rMEvt, OutputDevice* _pWin )
541 bool bReturn = E3dView::MouseButtonDown( _rMEvt, _pWin );
543 if ( pFormShell && pFormShell->GetImpl() )
545 SdrViewEvent aViewEvent;
546 PickAnything( _rMEvt, SdrMouseEventKind::BUTTONDOWN, aViewEvent );
547 pFormShell->GetImpl()->handleMouseButtonDown_Lock(aViewEvent);
550 return bReturn;
554 FmFormObj* FmFormView::getMarkedGrid() const
556 FmFormObj* pFormObject = nullptr;
557 const SdrMarkList& rMarkList = GetMarkedObjectList();
558 if ( 1 == rMarkList.GetMarkCount() )
560 SdrMark* pMark = rMarkList.GetMark(0);
561 if ( pMark )
563 pFormObject = FmFormObj::GetFormObject( pMark->GetMarkedSdrObj() );
564 if ( pFormObject )
566 Reference< XServiceInfo > xServInfo( pFormObject->GetUnoControlModel(), UNO_QUERY );
567 if ( !xServInfo.is() || !xServInfo->supportsService( FM_SUN_COMPONENT_GRIDCONTROL ) )
568 pFormObject = nullptr;
572 return pFormObject;
575 void FmFormView::createControlLabelPair( OutputDevice const * _pOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM,
576 const Reference< XPropertySet >& _rxField, const Reference< XNumberFormats >& _rxNumberFormats,
577 SdrObjKind _nControlObjectID, SdrInventor _nInventor, SdrObjKind _nLabelObjectID,
578 SdrModel& _rModel,
579 rtl::Reference<SdrUnoObj>& _rpLabel,
580 rtl::Reference<SdrUnoObj>& _rpControl )
582 FmXFormView::createControlLabelPair(
583 *_pOutDev, _nXOffsetMM, _nYOffsetMM,
584 _rxField, _rxNumberFormats,
585 _nControlObjectID, u"", _nInventor, _nLabelObjectID,
586 _rModel,
587 _rpLabel, _rpControl
591 Reference< runtime::XFormController > FmFormView::GetFormController( const Reference< XForm >& _rxForm, const OutputDevice& _rDevice ) const
593 return pImpl->getFormController( _rxForm, _rDevice );
596 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */