1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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>
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>
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(
71 : E3dView(rSdrModel
, pOut
)
76 void FmFormView::Init()
79 pImpl
= new FmXFormView(this);
82 SdrModel
* pModel
= &GetModel();
84 DBG_ASSERT( dynamic_cast<const FmFormModel
*>( pModel
) != nullptr, "Wrong model" );
85 FmFormModel
* pFormModel
= dynamic_cast<FmFormModel
*>(pModel
);
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()
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;
133 void FmFormView::MarkListHasChanged()
135 E3dView::MarkListHasChanged();
137 if ( !(pFormShell
&& IsDesignMode()) )
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();
158 const SdrPageWindow
* findPageWindow( const SdrPaintView
* _pView
, OutputDevice
const * _pWindow
)
160 SdrPageView
* pPageView
= _pView
->GetSdrPageView();
163 for ( sal_uInt32 window
= 0; window
< pPageView
->PageWindowCount(); ++window
)
165 const SdrPageWindow
* pPageWindow
= pPageView
->GetPageWindow( window
);
166 if ( !pPageWindow
|| &pPageWindow
->GetPaintWindow().GetOutputDevice() != _pWindow
)
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
);
185 pImpl
->addWindow( *pPageWindow
);
189 void FmFormView::DeleteDeviceFromPaintView(OutputDevice
& rNewDev
)
191 const SdrPageWindow
* pPageWindow
= findPageWindow( this, &rNewDev
);
193 pImpl
->removeWindow( pPageWindow
->GetControlContainer() );
195 E3dView::DeleteDeviceFromPaintView(rNewDev
);
199 void FmFormView::ChangeDesignMode(bool bDesign
)
201 if (bDesign
== IsDesignMode())
204 FmFormModel
* pModel
= dynamic_cast<FmFormModel
*>(&GetModel());
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
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);
222 // --- 3. activate all controls, if we're switching to alive mode
224 ActivateControls( GetSdrPageView() );
226 // --- 4. load resp. unload the forms
227 FmFormPage
* pCurPage
= GetCurPage();
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);
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();
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
)
279 // Unlock Undo-Environment
281 pModel
->GetUndoEnv().UnLock();
285 void FmFormView::GrabFirstControlFocus()
287 if ( !IsDesignMode() )
292 SdrPageView
* FmFormView::ShowSdrPage(SdrPage
* pPage
)
294 SdrPageView
* pPV
= E3dView::ShowSdrPage(pPage
);
300 // creating the controllers
301 ActivateControls(pPV
);
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);
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);
340 // --- 3. base class behavior
341 E3dView::HideSdrPage();
345 void FmFormView::ActivateControls(SdrPageView
const * pPageView
)
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
)
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
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())
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
)
409 SdrPageView
* pPageView
= GetSdrPageView();
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
);
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();
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
)
453 const vcl::KeyCode
& rKeyCode
= rKEvt
.GetKeyCode();
455 && rKeyCode
.GetCode() == KEY_RETURN
458 // RETURN alone enters grid controls, for keyboard accessibility
460 && !rKeyCode
.IsShift()
461 && !rKeyCode
.IsMod1()
462 && !rKeyCode
.IsMod2()
465 FmFormObj
* pObj
= getMarkedGrid();
468 Reference
< awt::XWindow
> xWindow( pObj
->GetUnoControl( *this, *pWin
->GetOutDev() ), UNO_QUERY
);
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();
482 // Alt-RETURN alone shows the properties of the selection
484 && pFormShell
->GetImpl()
485 && !rKeyCode
.IsShift()
486 && !rKeyCode
.IsMod1()
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
);
507 Reference
<awt::XControl
> xControl
= pFormObject
->GetUnoControl(*this, *pWin
->GetOutDev());
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
);
524 bDone
= E3dView::KeyInput(rKEvt
,pWin
);
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();
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
);
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);
563 pFormObject
= FmFormObj::GetFormObject( pMark
->GetMarkedSdrObj() );
566 Reference
< XServiceInfo
> xServInfo( pFormObject
->GetUnoControlModel(), UNO_QUERY
);
567 if ( !xServInfo
.is() || !xServInfo
->supportsService( FM_SUN_COMPONENT_GRIDCONTROL
) )
568 pFormObject
= nullptr;
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
,
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
,
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: */