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 .
22 #include <fmdocumentclassification.hxx>
24 #include <fmpgeimp.hxx>
26 #include <svx/strings.hrc>
27 #include <fmservs.hxx>
28 #include <fmshimp.hxx>
29 #include <svx/fmtools.hxx>
31 #include <fmvwimp.hxx>
32 #include <formcontrolfactory.hxx>
33 #include <svx/sdrpaintwindow.hxx>
34 #include <svx/svditer.hxx>
35 #include <svx/dataaccessdescriptor.hxx>
36 #include <svx/dialmgr.hxx>
37 #include <svx/fmglob.hxx>
38 #include <svx/fmmodel.hxx>
39 #include <svx/fmpage.hxx>
40 #include <svx/fmshell.hxx>
41 #include <svx/fmview.hxx>
42 #include <svx/sdrpagewindow.hxx>
43 #include <svx/svdogrp.hxx>
44 #include <svx/svdpagv.hxx>
45 #include <svx/xmlexchg.hxx>
46 #include <toolkit/helper/vclunohelper.hxx>
48 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
49 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
50 #include <com/sun/star/sdbc/XRowSet.hpp>
51 #include <com/sun/star/form/XLoadable.hpp>
52 #include <com/sun/star/awt/VisualEffect.hpp>
53 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
54 #include <com/sun/star/util/XNumberFormats.hpp>
55 #include <com/sun/star/sdb/CommandType.hpp>
56 #include <com/sun/star/sdbc/DataType.hpp>
57 #include <com/sun/star/sdbc/ColumnValue.hpp>
58 #include <com/sun/star/form/FormComponentType.hpp>
59 #include <com/sun/star/form/FormButtonType.hpp>
60 #include <com/sun/star/form/XReset.hpp>
61 #include <com/sun/star/form/binding/XBindableValue.hpp>
62 #include <com/sun/star/form/binding/XValueBinding.hpp>
63 #include <com/sun/star/form/runtime/FormController.hpp>
64 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
65 #include <com/sun/star/awt/XTabControllerModel.hpp>
66 #include <com/sun/star/awt/XControlContainer.hpp>
67 #include <com/sun/star/awt/XTabController.hpp>
68 #include <com/sun/star/container/XIndexAccess.hpp>
69 #include <com/sun/star/awt/XControl.hpp>
70 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
71 #include <com/sun/star/sdbc/SQLException.hpp>
72 #include <com/sun/star/sdbc/XPreparedStatement.hpp>
73 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
74 #include <com/sun/star/container/XContainer.hpp>
76 #include <comphelper/namedvaluecollection.hxx>
77 #include <comphelper/property.hxx>
78 #include <comphelper/processfactory.hxx>
79 #include <comphelper/types.hxx>
80 #include <cppuhelper/exc_hlp.hxx>
81 #include <unotools/moduleoptions.hxx>
82 #include <tools/debug.hxx>
83 #include <tools/diagnose_ex.h>
84 #include <sal/log.hxx>
85 #include <vcl/svapp.hxx>
86 #include <vcl/stdtext.hxx>
87 #include <connectivity/dbtools.hxx>
91 using namespace ::comphelper
;
92 using namespace ::svx
;
93 using namespace ::svxform
;
94 using namespace ::dbtools
;
96 using namespace ::com::sun::star
;
97 using ::com::sun::star::uno::Exception
;
98 using ::com::sun::star::uno::RuntimeException
;
99 using ::com::sun::star::uno::XInterface
;
100 using ::com::sun::star::uno::Sequence
;
101 using ::com::sun::star::uno::UNO_QUERY
;
102 using ::com::sun::star::uno::UNO_QUERY_THROW
;
103 using ::com::sun::star::uno::UNO_SET_THROW
;
104 using ::com::sun::star::uno::Type
;
105 using ::com::sun::star::uno::Reference
;
106 using ::com::sun::star::uno::Any
;
107 using ::com::sun::star::uno::makeAny
;
108 using ::com::sun::star::uno::XComponentContext
;
109 using ::com::sun::star::form::FormButtonType_SUBMIT
;
110 using ::com::sun::star::form::binding::XValueBinding
;
111 using ::com::sun::star::form::binding::XBindableValue
;
112 using ::com::sun::star::lang::XComponent
;
113 using ::com::sun::star::container::XIndexAccess
;
114 using ::com::sun::star::form::runtime::FormController
;
115 using ::com::sun::star::form::runtime::XFormController
;
116 using ::com::sun::star::script::XEventAttacherManager
;
117 using ::com::sun::star::awt::XTabControllerModel
;
118 using ::com::sun::star::container::XChild
;
119 using ::com::sun::star::task::XInteractionHandler
;
120 using ::com::sun::star::awt::XTabController
;
121 using ::com::sun::star::awt::XControlContainer
;
122 using ::com::sun::star::awt::XControl
;
123 using ::com::sun::star::form::XFormComponent
;
124 using ::com::sun::star::form::XForm
;
125 using ::com::sun::star::lang::IndexOutOfBoundsException
;
126 using ::com::sun::star::lang::WrappedTargetException
;
127 using ::com::sun::star::container::XContainer
;
128 using ::com::sun::star::container::ContainerEvent
;
129 using ::com::sun::star::lang::EventObject
;
130 using ::com::sun::star::sdb::SQLErrorEvent
;
131 using ::com::sun::star::sdbc::XRowSet
;
132 using ::com::sun::star::beans::XPropertySet
;
133 using ::com::sun::star::container::XElementAccess
;
134 using ::com::sun::star::awt::XWindow
;
135 using ::com::sun::star::awt::FocusEvent
;
136 using ::com::sun::star::ui::dialogs::XExecutableDialog
;
137 using ::com::sun::star::sdbc::XDataSource
;
138 using ::com::sun::star::container::XIndexContainer
;
139 using ::com::sun::star::sdbc::XConnection
;
140 using ::com::sun::star::container::XNameAccess
;
141 using ::com::sun::star::sdbc::SQLException
;
142 using ::com::sun::star::util::XNumberFormatsSupplier
;
143 using ::com::sun::star::util::XNumberFormats
;
144 using ::com::sun::star::beans::XPropertySetInfo
;
146 namespace FormComponentType
= ::com::sun::star::form::FormComponentType
;
147 namespace CommandType
= ::com::sun::star::sdb::CommandType
;
148 namespace DataType
= ::com::sun::star::sdbc::DataType
;
151 class FmXFormView::ObjectRemoveListener
: public SfxListener
153 FmXFormView
* m_pParent
;
155 explicit ObjectRemoveListener( FmXFormView
* pParent
);
156 virtual void Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
) override
;
159 FormViewPageWindowAdapter::FormViewPageWindowAdapter( const css::uno::Reference
<css::uno::XComponentContext
>& _rContext
, const SdrPageWindow
& _rWindow
, FmXFormView
* _pViewImpl
)
160 : m_xControlContainer( _rWindow
.GetControlContainer() ),
161 m_xContext( _rContext
),
162 m_pViewImpl( _pViewImpl
),
163 m_pWindow( dynamic_cast< vcl::Window
* >( &_rWindow
.GetPaintWindow().GetOutputDevice() ) )
166 // create an XFormController for every form
167 FmFormPage
* pFormPage
= dynamic_cast< FmFormPage
* >( _rWindow
.GetPageView().GetPage() );
168 DBG_ASSERT( pFormPage
, "FormViewPageWindowAdapter::FormViewPageWindowAdapter: no FmFormPage found!" );
173 Reference
< XIndexAccess
> xForms( pFormPage
->GetForms(), UNO_QUERY_THROW
);
174 sal_uInt32 nLength
= xForms
->getCount();
175 for (sal_uInt32 i
= 0; i
< nLength
; i
++)
177 Reference
< XForm
> xForm( xForms
->getByIndex(i
), UNO_QUERY
);
179 setController( xForm
, nullptr );
182 catch (const Exception
&)
184 DBG_UNHANDLED_EXCEPTION("svx");
189 FormViewPageWindowAdapter::~FormViewPageWindowAdapter()
193 void FormViewPageWindowAdapter::dispose()
195 for ( ::std::vector
< Reference
< XFormController
> >::const_iterator i
= m_aControllerList
.begin();
196 i
!= m_aControllerList
.end();
202 Reference
< XFormController
> xController( *i
, UNO_SET_THROW
);
204 // detaching the events
205 Reference
< XChild
> xControllerModel( xController
->getModel(), UNO_QUERY
);
206 if ( xControllerModel
.is() )
208 Reference
< XEventAttacherManager
> xEventManager( xControllerModel
->getParent(), UNO_QUERY_THROW
);
209 Reference
< XInterface
> xControllerNormalized( xController
, UNO_QUERY_THROW
);
210 xEventManager
->detach( i
- m_aControllerList
.begin(), xControllerNormalized
);
213 // dispose the formcontroller
214 xController
->dispose();
216 catch (const Exception
&)
218 DBG_UNHANDLED_EXCEPTION("svx");
222 m_aControllerList
.clear();
225 sal_Bool SAL_CALL
FormViewPageWindowAdapter::hasElements()
227 return getCount() != 0;
230 Type SAL_CALL
FormViewPageWindowAdapter::getElementType()
232 return cppu::UnoType
<XFormController
>::get();
236 sal_Int32 SAL_CALL
FormViewPageWindowAdapter::getCount()
238 return m_aControllerList
.size();
241 Any SAL_CALL
FormViewPageWindowAdapter::getByIndex(sal_Int32 nIndex
)
244 nIndex
>= getCount())
245 throw IndexOutOfBoundsException();
248 aElement
<<= m_aControllerList
[nIndex
];
252 void SAL_CALL
FormViewPageWindowAdapter::makeVisible( const Reference
< XControl
>& Control
)
254 SolarMutexGuard aSolarGuard
;
256 Reference
< XWindow
> xWindow( Control
, UNO_QUERY
);
257 if ( xWindow
.is() && m_pViewImpl
->getView() && m_pWindow
)
259 awt::Rectangle aRect
= xWindow
->getPosSize();
260 ::tools::Rectangle
aNewRect( aRect
.X
, aRect
.Y
, aRect
.X
+ aRect
.Width
, aRect
.Y
+ aRect
.Height
);
261 aNewRect
= m_pWindow
->PixelToLogic( aNewRect
);
262 m_pViewImpl
->getView()->MakeVisible( aNewRect
, *m_pWindow
);
266 static Reference
< XFormController
> getControllerSearchChildren( const Reference
< XIndexAccess
> & xIndex
, const Reference
< XTabControllerModel
> & xModel
)
268 if (xIndex
.is() && xIndex
->getCount())
270 Reference
< XFormController
> xController
;
272 for (sal_Int32 n
= xIndex
->getCount(); n
-- && !xController
.is(); )
274 xIndex
->getByIndex(n
) >>= xController
;
275 if (xModel
.get() == xController
->getModel().get())
279 xController
= getControllerSearchChildren(xController
, xModel
);
280 if ( xController
.is() )
285 return Reference
< XFormController
> ();
288 // Search the according controller
289 Reference
< XFormController
> FormViewPageWindowAdapter::getController( const Reference
< XForm
> & xForm
) const
291 Reference
< XTabControllerModel
> xModel(xForm
, UNO_QUERY
);
292 for (const auto& rpController
: m_aControllerList
)
294 if (rpController
->getModel().get() == xModel
.get())
297 // the current-round controller isn't the right one. perhaps one of its children ?
298 Reference
< XFormController
> xChildSearch
= getControllerSearchChildren(Reference
< XIndexAccess
> (rpController
, UNO_QUERY
), xModel
);
299 if (xChildSearch
.is())
302 return Reference
< XFormController
> ();
306 void FormViewPageWindowAdapter::setController(const Reference
< XForm
> & xForm
, const Reference
< XFormController
>& _rxParentController
)
308 DBG_ASSERT( xForm
.is(), "FormViewPageWindowAdapter::setController: there should be a form!" );
309 Reference
< XIndexAccess
> xFormCps(xForm
, UNO_QUERY
);
313 Reference
< XTabControllerModel
> xTabOrder(xForm
, UNO_QUERY
);
315 // create a form controller
316 Reference
< XFormController
> xController( FormController::create(m_xContext
) );
318 Reference
< XInteractionHandler
> xHandler
;
319 if ( _rxParentController
.is() )
320 xHandler
= _rxParentController
->getInteractionHandler();
323 // TODO: should we create a default handler? Not really necessary, since the
324 // FormController itself has a default fallback
327 xController
->setInteractionHandler( xHandler
);
329 xController
->setContext( this );
331 xController
->setModel( xTabOrder
);
332 xController
->setContainer( m_xControlContainer
);
333 xController
->activateTabOrder();
334 xController
->addActivateListener( m_pViewImpl
);
336 if ( _rxParentController
.is() )
337 _rxParentController
->addChildController( xController
);
340 m_aControllerList
.push_back(xController
);
342 xController
->setParent( *this );
344 // attaching the events
345 Reference
< XEventAttacherManager
> xEventManager( xForm
->getParent(), UNO_QUERY
);
346 xEventManager
->attach(m_aControllerList
.size() - 1, Reference
<XInterface
>( xController
, UNO_QUERY
), makeAny(xController
) );
349 // now go through the subforms
350 sal_uInt32 nLength
= xFormCps
->getCount();
351 Reference
< XForm
> xSubForm
;
352 for (sal_uInt32 i
= 0; i
< nLength
; i
++)
354 if ( xFormCps
->getByIndex(i
) >>= xSubForm
)
355 setController( xSubForm
, xController
);
360 void FormViewPageWindowAdapter::updateTabOrder( const Reference
< XForm
>& _rxForm
)
362 OSL_PRECOND( _rxForm
.is(), "FormViewPageWindowAdapter::updateTabOrder: illegal argument!" );
368 Reference
< XTabController
> xTabCtrl( getController( _rxForm
).get() );
370 { // if there already is a TabController for this form, then delegate the "updateTabOrder" request
371 xTabCtrl
->activateTabOrder();
374 { // otherwise, create a TabController
376 // if it's a sub form, then we must ensure there exist TabControllers
377 // for all its ancestors, too
378 Reference
< XForm
> xParentForm( _rxForm
->getParent(), UNO_QUERY
);
379 // there is a parent form -> look for the respective controller
380 Reference
< XFormController
> xParentController
;
381 if ( xParentForm
.is() )
382 xParentController
= getController( xParentForm
);
384 setController( _rxForm
, xParentController
);
387 catch (const Exception
&)
389 DBG_UNHANDLED_EXCEPTION("svx");
394 FmXFormView::FmXFormView(FmFormView
* _pView
)
395 :m_pMarkedGrid(nullptr)
397 ,m_nActivationEvent(nullptr)
398 ,m_nErrorMessageEvent( nullptr )
399 ,m_nAutoFocusEvent( nullptr )
400 ,m_nControlWizardEvent( nullptr )
401 ,m_bFirstActivation( true )
402 ,m_isTabOrderUpdateSuspended( false )
407 void FmXFormView::cancelEvents()
409 if ( m_nActivationEvent
)
411 Application::RemoveUserEvent( m_nActivationEvent
);
412 m_nActivationEvent
= nullptr;
415 if ( m_nErrorMessageEvent
)
417 Application::RemoveUserEvent( m_nErrorMessageEvent
);
418 m_nErrorMessageEvent
= nullptr;
421 if ( m_nAutoFocusEvent
)
423 Application::RemoveUserEvent( m_nAutoFocusEvent
);
424 m_nAutoFocusEvent
= nullptr;
427 if ( m_nControlWizardEvent
)
429 Application::RemoveUserEvent( m_nControlWizardEvent
);
430 m_nControlWizardEvent
= nullptr;
435 void FmXFormView::notifyViewDying( )
437 DBG_ASSERT( m_pView
, "FmXFormView::notifyViewDying: my view already died!" );
443 FmXFormView::~FmXFormView()
445 DBG_ASSERT( m_aPageWindowAdapters
.empty(), "FmXFormView::~FmXFormView: Window list not empty!" );
446 for (const auto& rpAdapter
: m_aPageWindowAdapters
)
448 rpAdapter
->dispose();
456 void SAL_CALL
FmXFormView::disposing(const EventObject
& Source
)
458 if ( m_xWindow
.is() && Source
.Source
== m_xWindow
)
460 m_xWindow
->removeFocusListener(this);
463 m_pView
->SetMoveOutside( false, FmFormView::ImplAccess() );
469 // XFormControllerListener
471 void SAL_CALL
FmXFormView::formActivated(const EventObject
& rEvent
)
473 if ( m_pView
&& m_pView
->GetFormShell() && m_pView
->GetFormShell()->GetImpl() )
474 m_pView
->GetFormShell()->GetImpl()->formActivated( rEvent
);
478 void SAL_CALL
FmXFormView::formDeactivated(const EventObject
& rEvent
)
480 if ( m_pView
&& m_pView
->GetFormShell() && m_pView
->GetFormShell()->GetImpl() )
481 m_pView
->GetFormShell()->GetImpl()->formDeactivated( rEvent
);
484 // XContainerListener
486 void SAL_CALL
FmXFormView::elementInserted(const ContainerEvent
& evt
)
490 Reference
< XControlContainer
> xControlContainer( evt
.Source
, UNO_QUERY_THROW
);
491 Reference
< XControl
> xControl( evt
.Element
, UNO_QUERY_THROW
);
492 Reference
< XFormComponent
> xControlModel( xControl
->getModel(), UNO_QUERY_THROW
);
493 Reference
< XForm
> xForm( xControlModel
->getParent(), UNO_QUERY_THROW
);
495 if ( m_isTabOrderUpdateSuspended
)
497 // remember the container and the control, so we can update the tab order on resumeTabOrderUpdate
498 m_aNeedTabOrderUpdate
[ xControlContainer
].insert( xForm
);
502 PFormViewPageWindowAdapter pAdapter
= findWindow( xControlContainer
);
504 pAdapter
->updateTabOrder( xForm
);
507 catch (const Exception
&)
509 DBG_UNHANDLED_EXCEPTION("svx");
514 void SAL_CALL
FmXFormView::elementReplaced(const ContainerEvent
& evt
)
516 elementInserted(evt
);
520 void SAL_CALL
FmXFormView::elementRemoved(const ContainerEvent
& /*evt*/)
525 PFormViewPageWindowAdapter
FmXFormView::findWindow( const Reference
< XControlContainer
>& _rxCC
) const
527 auto i
= std::find_if(m_aPageWindowAdapters
.begin(), m_aPageWindowAdapters
.end(),
528 [&_rxCC
](const PFormViewPageWindowAdapter
& rpAdapter
) { return _rxCC
== rpAdapter
->getControlContainer(); });
529 if (i
!= m_aPageWindowAdapters
.end())
535 void FmXFormView::addWindow(const SdrPageWindow
& rWindow
)
537 FmFormPage
* pFormPage
= dynamic_cast<FmFormPage
*>( rWindow
.GetPageView().GetPage() );
541 const Reference
< XControlContainer
>& xCC
= rWindow
.GetControlContainer();
543 && ( !findWindow( xCC
).is() )
546 PFormViewPageWindowAdapter pAdapter
= new FormViewPageWindowAdapter( comphelper::getProcessComponentContext(), rWindow
, this );
547 m_aPageWindowAdapters
.push_back( pAdapter
);
549 // listen at the ControlContainer to notice changes
550 Reference
< XContainer
> xContainer( xCC
, UNO_QUERY
);
551 if ( xContainer
.is() )
552 xContainer
->addContainerListener( this );
557 void FmXFormView::removeWindow( const Reference
< XControlContainer
>& _rxCC
)
560 // - the design mode is being switched to
561 // - a window is deleted while in the design mode
562 // - the control container for a window is removed while the active mode is on
564 auto i
= std::find_if(m_aPageWindowAdapters
.begin(), m_aPageWindowAdapters
.end(),
565 [&_rxCC
](const PFormViewPageWindowAdapter
& rpAdapter
) { return _rxCC
== rpAdapter
->getControlContainer(); });
566 if (i
!= m_aPageWindowAdapters
.end())
568 Reference
< XContainer
> xContainer( _rxCC
, UNO_QUERY
);
569 if ( xContainer
.is() )
570 xContainer
->removeContainerListener( this );
573 m_aPageWindowAdapters
.erase( i
);
578 void FmXFormView::displayAsyncErrorMessage( const SQLErrorEvent
& _rEvent
)
580 DBG_ASSERT( nullptr == m_nErrorMessageEvent
, "FmXFormView::displayAsyncErrorMessage: not too fast, please!" );
581 // This should not happen - usually, the PostUserEvent is faster than any possible user
582 // interaction which could trigger a new error. If it happens, we need a queue for the events.
583 m_aAsyncError
= _rEvent
;
584 m_nErrorMessageEvent
= Application::PostUserEvent( LINK( this, FmXFormView
, OnDelayedErrorMessage
) );
588 IMPL_LINK_NOARG(FmXFormView
, OnDelayedErrorMessage
, void*, void)
590 m_nErrorMessageEvent
= nullptr;
591 displayException( m_aAsyncError
);
595 void FmXFormView::onFirstViewActivation( const FmFormModel
* _pDocModel
)
597 if ( _pDocModel
&& _pDocModel
->GetAutoControlFocus() )
598 m_nAutoFocusEvent
= Application::PostUserEvent( LINK( this, FmXFormView
, OnAutoFocus
) );
602 void FmXFormView::suspendTabOrderUpdate()
604 OSL_ENSURE( !m_isTabOrderUpdateSuspended
, "FmXFormView::suspendTabOrderUpdate: nesting not allowed!" );
605 m_isTabOrderUpdateSuspended
= true;
609 void FmXFormView::resumeTabOrderUpdate()
611 OSL_ENSURE( m_isTabOrderUpdateSuspended
, "FmXFormView::resumeTabOrderUpdate: not suspended!" );
612 m_isTabOrderUpdateSuspended
= false;
614 // update the tab orders for all components which were collected since the suspendTabOrderUpdate call.
615 for (const auto& rContainer
: m_aNeedTabOrderUpdate
)
617 PFormViewPageWindowAdapter pAdapter
= findWindow( rContainer
.first
);
618 if ( !pAdapter
.is() )
621 for (const auto& rForm
: rContainer
.second
)
623 pAdapter
->updateTabOrder( rForm
);
626 m_aNeedTabOrderUpdate
.clear();
631 bool isActivableDatabaseForm(const Reference
< XFormController
> &xController
)
633 // only database forms are to be activated
634 Reference
< XRowSet
> xForm(xController
->getModel(), UNO_QUERY
);
635 if ( !xForm
.is() || !getConnection( xForm
).is() )
638 Reference
< XPropertySet
> xFormSet( xForm
, UNO_QUERY
);
639 if ( !xFormSet
.is() )
641 SAL_WARN( "svx.form", "FmXFormView::OnActivate: a form which does not have properties?" );
645 const OUString aSource
= ::comphelper::getString( xFormSet
->getPropertyValue( FM_PROP_COMMAND
) );
647 return !aSource
.isEmpty();
650 class find_active_databaseform
652 const Reference
< XFormController
> xActiveController
;
656 explicit find_active_databaseform( const Reference
< XFormController
>& _xActiveController
)
657 : xActiveController(_xActiveController
)
660 Reference
< XFormController
> operator() (const Reference
< XFormController
> &xController
)
662 if(xController
== xActiveController
&& isActivableDatabaseForm(xController
))
665 if ( !xController
.is() )
667 SAL_WARN( "svx.form", "FmXFormView::OnActivate: a form controller which does not have children?" );
671 for(sal_Int32 i
= 0; i
< xController
->getCount(); ++i
)
673 const Any
a(xController
->getByIndex(i
));
674 Reference
< XFormController
> xI
;
675 if ((a
>>= xI
) && xI
.is())
677 Reference
< XFormController
> xRes(operator()(xI
));
689 IMPL_LINK_NOARG(FmXFormView
, OnActivate
, void*, void)
691 m_nActivationEvent
= nullptr;
695 OSL_FAIL( "FmXFormView::OnActivate: well... seems we have a timing problem (the view already died)!" );
699 // setting the controller to activate
700 if (m_pView
->GetFormShell() && m_pView
->GetActualOutDev() && m_pView
->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW
)
702 FmXFormShell
* const pShImpl
= m_pView
->GetFormShell()->GetImpl();
707 find_active_databaseform
fad(pShImpl
->getActiveController_Lock());
709 vcl::Window
* pWindow
= const_cast<vcl::Window
*>(static_cast<const vcl::Window
*>(m_pView
->GetActualOutDev()));
710 PFormViewPageWindowAdapter pAdapter
= m_aPageWindowAdapters
.empty() ? nullptr : m_aPageWindowAdapters
[0];
711 for (const auto& rpPageWindowAdapter
: m_aPageWindowAdapters
)
713 if ( pWindow
== rpPageWindowAdapter
->getWindow() )
714 pAdapter
= rpPageWindowAdapter
;
719 Reference
< XFormController
> xControllerToActivate
;
720 for (const Reference
< XFormController
> & xController
: pAdapter
->GetList())
722 if ( !xController
.is() )
726 Reference
< XFormController
> xActiveController(fad(xController
));
727 if (xActiveController
.is())
729 xControllerToActivate
= xActiveController
;
734 if(xControllerToActivate
.is() || !isActivableDatabaseForm(xController
))
737 xControllerToActivate
= xController
;
739 pShImpl
->setActiveController_Lock(xControllerToActivate
);
745 void FmXFormView::Activate(bool bSync
)
747 if (m_nActivationEvent
)
749 Application::RemoveUserEvent(m_nActivationEvent
);
750 m_nActivationEvent
= nullptr;
755 LINK(this,FmXFormView
,OnActivate
).Call(nullptr);
758 m_nActivationEvent
= Application::PostUserEvent(LINK(this,FmXFormView
,OnActivate
));
762 void FmXFormView::Deactivate(bool bDeactivateController
)
764 if (m_nActivationEvent
)
766 Application::RemoveUserEvent(m_nActivationEvent
);
767 m_nActivationEvent
= nullptr;
770 FmXFormShell
* pShImpl
= m_pView
->GetFormShell() ? m_pView
->GetFormShell()->GetImpl() : nullptr;
771 if (pShImpl
&& bDeactivateController
)
772 pShImpl
->setActiveController_Lock(nullptr);
776 FmFormShell
* FmXFormView::GetFormShell() const
778 return m_pView
? m_pView
->GetFormShell() : nullptr;
781 void FmXFormView::AutoFocus()
783 if (m_nAutoFocusEvent
)
784 Application::RemoveUserEvent(m_nAutoFocusEvent
);
786 m_nAutoFocusEvent
= Application::PostUserEvent(LINK(this, FmXFormView
, OnAutoFocus
));
790 bool FmXFormView::isFocusable( const Reference
< XControl
>& i_rControl
)
792 if ( !i_rControl
.is() )
797 Reference
< XPropertySet
> xModelProps( i_rControl
->getModel(), UNO_QUERY_THROW
);
799 // only enabled controls are allowed to participate
800 bool bEnabled
= false;
801 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_ENABLED
) >>= bEnabled
);
805 // check the class id of the control model
806 sal_Int16 nClassId
= FormComponentType::CONTROL
;
807 OSL_VERIFY( xModelProps
->getPropertyValue( FM_PROP_CLASSID
) >>= nClassId
);
809 // controls which are not focussable
810 if ( ( FormComponentType::CONTROL
!= nClassId
)
811 && ( FormComponentType::IMAGEBUTTON
!= nClassId
)
812 && ( FormComponentType::GROUPBOX
!= nClassId
)
813 && ( FormComponentType::FIXEDTEXT
!= nClassId
)
814 && ( FormComponentType::HIDDENCONTROL
!= nClassId
)
815 && ( FormComponentType::IMAGECONTROL
!= nClassId
)
816 && ( FormComponentType::SCROLLBAR
!= nClassId
)
817 && ( FormComponentType::SPINBUTTON
!= nClassId
)
823 catch (const Exception
&)
825 DBG_UNHANDLED_EXCEPTION("svx");
831 static Reference
< XControl
> lcl_firstFocussableControl( const Sequence
< Reference
< XControl
> >& _rControls
)
833 Reference
< XControl
> xReturn
;
835 // loop through all the controls
836 for ( auto const & control
: _rControls
)
841 if ( FmXFormView::isFocusable( control
) )
848 if ( !xReturn
.is() && _rControls
.hasElements() )
849 xReturn
= _rControls
[0];
858 void lcl_ensureControlsOfFormExist_nothrow( const SdrPage
& _rPage
, const SdrView
& _rView
, const vcl::Window
& _rWindow
, const Reference
< XForm
>& _rxForm
)
862 Reference
< XInterface
> xNormalizedForm( _rxForm
, UNO_QUERY_THROW
);
864 SdrObjListIter
aSdrObjectLoop( &_rPage
, SdrIterMode::DeepNoGroups
);
865 while ( aSdrObjectLoop
.IsMore() )
867 FmFormObj
* pFormObject
= FmFormObj::GetFormObject( aSdrObjectLoop
.Next() );
871 Reference
< XChild
> xModel( pFormObject
->GetUnoControlModel(), UNO_QUERY_THROW
);
872 Reference
< XInterface
> xModelParent( xModel
->getParent(), UNO_QUERY
);
874 if ( xNormalizedForm
.get() != xModelParent
.get() )
877 pFormObject
->GetUnoControl( _rView
, _rWindow
);
880 catch (const Exception
&)
882 DBG_UNHANDLED_EXCEPTION("svx");
888 Reference
< XFormController
> FmXFormView::getFormController( const Reference
< XForm
>& _rxForm
, const OutputDevice
& _rDevice
) const
890 Reference
< XFormController
> xController
;
892 for (const PFormViewPageWindowAdapter
& pAdapter
: m_aPageWindowAdapters
)
894 if ( !pAdapter
.get() )
896 SAL_WARN( "svx.form", "FmXFormView::getFormController: invalid page window adapter!" );
900 if ( pAdapter
->getWindow() != &_rDevice
)
904 xController
= pAdapter
->getController( _rxForm
);
905 if ( xController
.is() )
912 IMPL_LINK_NOARG(FmXFormView
, OnAutoFocus
, void*, void)
914 m_nAutoFocusEvent
= nullptr;
916 // go to the first form of our page, examine it's TabController, go to its first (in terms of the tab order)
917 // control, give it the focus
919 SdrPageView
*pPageView
= m_pView
? m_pView
->GetSdrPageView() : nullptr;
920 SdrPage
*pSdrPage
= pPageView
? pPageView
->GetPage() : nullptr;
921 // get the forms collection of the page we belong to
922 FmFormPage
* pPage
= dynamic_cast<FmFormPage
*>( pSdrPage
);
923 Reference
< XIndexAccess
> xForms( pPage
? Reference
< XIndexAccess
>( pPage
->GetForms() ) : Reference
< XIndexAccess
>() );
925 const PFormViewPageWindowAdapter pAdapter
= m_aPageWindowAdapters
.empty() ? nullptr : m_aPageWindowAdapters
[0];
926 const vcl::Window
* pWindow
= pAdapter
.get() ? pAdapter
->getWindow() : nullptr;
928 ENSURE_OR_RETURN_VOID( xForms
.is() && pWindow
, "FmXFormView::OnAutoFocus: could not collect all essentials!" );
932 // go for the tab controller of the first form
933 if ( !xForms
->getCount() )
935 Reference
< XForm
> xForm( xForms
->getByIndex( 0 ), UNO_QUERY_THROW
);
936 Reference
< XTabController
> xTabController( pAdapter
->getController( xForm
), UNO_QUERY_THROW
);
938 // go for the first control of the controller
939 Sequence
< Reference
< XControl
> > aControls( xTabController
->getControls() );
940 if ( !aControls
.hasElements() )
942 Reference
< XElementAccess
> xFormElementAccess( xForm
, UNO_QUERY_THROW
);
943 if (xFormElementAccess
->hasElements() && pPage
&& m_pView
)
945 // there are control models in the form, but no controls, yet.
946 // Well, since some time controls are created on demand only. In particular,
947 // they're normally created when they're first painted.
948 // Unfortunately, the FormController does not have any way to
949 // trigger the creation itself, so we must hack this ...
950 lcl_ensureControlsOfFormExist_nothrow( *pPage
, *m_pView
, *pWindow
, xForm
);
951 aControls
= xTabController
->getControls();
952 OSL_ENSURE( aControls
.hasElements(), "FmXFormView::OnAutoFocus: no controls at all!" );
956 // set the focus to this first control
957 Reference
< XWindow
> xControlWindow( lcl_firstFocussableControl( aControls
), UNO_QUERY
);
958 if ( !xControlWindow
.is() )
961 xControlWindow
->setFocus();
963 // ensure that the control is visible
964 // 80210 - 12/07/00 - FS
965 const vcl::Window
* pCurrentWindow
= m_pView
? dynamic_cast<const vcl::Window
*>(m_pView
->GetActualOutDev()) : nullptr;
966 if ( pCurrentWindow
)
968 awt::Rectangle aRect
= xControlWindow
->getPosSize();
969 ::tools::Rectangle
aNonUnoRect( aRect
.X
, aRect
.Y
, aRect
.X
+ aRect
.Width
, aRect
.Y
+ aRect
.Height
);
970 m_pView
->MakeVisible( pCurrentWindow
->PixelToLogic( aNonUnoRect
), *const_cast< vcl::Window
* >( pCurrentWindow
) );
973 catch (const Exception
&)
975 DBG_UNHANDLED_EXCEPTION("svx");
980 void FmXFormView::onCreatedFormObject( FmFormObj
const & _rFormObject
)
982 FmFormShell
* pShell
= m_pView
? m_pView
->GetFormShell() : nullptr;
983 FmXFormShell
* pShellImpl
= pShell
? pShell
->GetImpl() : nullptr;
984 OSL_ENSURE( pShellImpl
, "FmXFormView::onCreatedFormObject: no form shell!" );
988 // it is valid that the form shell's forms collection is not initialized, yet
989 pShellImpl
->UpdateForms_Lock(true);
991 m_xLastCreatedControlModel
.set( _rFormObject
.GetUnoControlModel(), UNO_QUERY
);
992 if ( !m_xLastCreatedControlModel
.is() )
995 // some initial property defaults
996 FormControlFactory aControlFactory
;
997 aControlFactory
.initializeControlModel(pShellImpl
->getDocumentType_Lock(), _rFormObject
);
999 if (!pShellImpl
->GetWizardUsing_Lock())
1002 // #i31958# don't call wizards in XForms mode
1003 if (pShellImpl
->isEnhancedForm_Lock())
1006 // #i46898# no wizards if there is no Base installed - currently, all wizards are
1008 if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE
) )
1011 if ( m_nControlWizardEvent
)
1012 Application::RemoveUserEvent( m_nControlWizardEvent
);
1013 m_nControlWizardEvent
= Application::PostUserEvent( LINK( this, FmXFormView
, OnStartControlWizard
) );
1016 void FmXFormView::breakCreateFormObject()
1018 if (m_nControlWizardEvent
!= nullptr)
1020 Application::RemoveUserEvent(m_nControlWizardEvent
);
1021 m_nControlWizardEvent
= nullptr;
1023 m_xLastCreatedControlModel
.clear();
1026 IMPL_LINK_NOARG( FmXFormView
, OnStartControlWizard
, void*, void )
1028 m_nControlWizardEvent
= nullptr;
1029 OSL_PRECOND( m_xLastCreatedControlModel
.is(), "FmXFormView::OnStartControlWizard: illegal call!" );
1030 if ( !m_xLastCreatedControlModel
.is() )
1033 sal_Int16 nClassId
= FormComponentType::CONTROL
;
1036 OSL_VERIFY( m_xLastCreatedControlModel
->getPropertyValue( FM_PROP_CLASSID
) >>= nClassId
);
1038 catch (const Exception
&)
1040 DBG_UNHANDLED_EXCEPTION("svx");
1043 const sal_Char
* pWizardAsciiName
= nullptr;
1046 case FormComponentType::GRIDCONTROL
:
1047 pWizardAsciiName
= "com.sun.star.sdb.GridControlAutoPilot";
1049 case FormComponentType::LISTBOX
:
1050 case FormComponentType::COMBOBOX
:
1051 pWizardAsciiName
= "com.sun.star.sdb.ListComboBoxAutoPilot";
1053 case FormComponentType::GROUPBOX
:
1054 pWizardAsciiName
= "com.sun.star.sdb.GroupBoxAutoPilot";
1058 if ( pWizardAsciiName
)
1060 // build the argument list
1061 ::comphelper::NamedValueCollection aWizardArgs
;
1062 aWizardArgs
.put("ObjectModel", m_xLastCreatedControlModel
);
1063 const vcl::Window
* pCurrentWindow
= m_pView
? dynamic_cast<const vcl::Window
*>(m_pView
->GetActualOutDev()) : nullptr;
1064 aWizardArgs
.put("ParentWindow", VCLUnoHelper::GetInterface(const_cast<vcl::Window
*>(pCurrentWindow
)));
1066 // create the wizard object
1067 Reference
< XExecutableDialog
> xWizard
;
1070 Reference
<XComponentContext
> xContext
= comphelper::getProcessComponentContext();
1071 xWizard
.set( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( OUString::createFromAscii(pWizardAsciiName
), aWizardArgs
.getWrappedPropertyValues(), xContext
), UNO_QUERY
);
1073 catch (const Exception
&)
1075 DBG_UNHANDLED_EXCEPTION("svx");
1078 if ( !xWizard
.is() )
1080 ShowServiceNotAvailableError( nullptr, OUString::createFromAscii(pWizardAsciiName
), true );
1084 // execute the wizard
1089 catch (const Exception
&)
1091 DBG_UNHANDLED_EXCEPTION("svx");
1096 m_xLastCreatedControlModel
.clear();
1102 void lcl_insertIntoFormComponentHierarchy_throw( const FmFormView
& _rView
, const SdrUnoObj
& _rSdrObj
,
1103 const Reference
< XDataSource
>& _rxDataSource
, const OUString
& _rDataSourceName
,
1104 const OUString
& _rCommand
, const sal_Int32 _nCommandType
)
1106 FmFormPage
& rPage
= static_cast< FmFormPage
& >( *_rView
.GetSdrPageView()->GetPage() );
1108 Reference
< XFormComponent
> xFormComponent( _rSdrObj
.GetUnoControlModel(), UNO_QUERY_THROW
);
1109 Reference
< XForm
> xTargetForm(
1110 rPage
.GetImpl().findPlaceInFormComponentHierarchy( xFormComponent
, _rxDataSource
, _rDataSourceName
, _rCommand
, _nCommandType
),
1113 FmFormPageImpl::setUniqueName( xFormComponent
, xTargetForm
);
1115 Reference
< XIndexContainer
> xFormAsContainer( xTargetForm
, UNO_QUERY_THROW
);
1116 xFormAsContainer
->insertByIndex( xFormAsContainer
->getCount(), makeAny( xFormComponent
) );
1121 SdrObjectUniquePtr
FmXFormView::implCreateFieldControl( const svx::ODataAccessDescriptor
& _rColumnDescriptor
)
1123 // not if we're in design mode
1124 if ( !m_pView
->IsDesignMode() )
1127 OUString sCommand
, sFieldName
;
1128 sal_Int32 nCommandType
= CommandType::COMMAND
;
1129 SharedConnection xConnection
;
1131 OUString sDataSource
= _rColumnDescriptor
.getDataSource();
1132 _rColumnDescriptor
[ DataAccessDescriptorProperty::Command
] >>= sCommand
;
1133 _rColumnDescriptor
[ DataAccessDescriptorProperty::ColumnName
] >>= sFieldName
;
1134 _rColumnDescriptor
[ DataAccessDescriptorProperty::CommandType
] >>= nCommandType
;
1136 Reference
< XConnection
> xExternalConnection
;
1137 _rColumnDescriptor
[ DataAccessDescriptorProperty::Connection
] >>= xExternalConnection
;
1138 xConnection
.reset( xExternalConnection
, SharedConnection::NoTakeOwnership
);
1141 if ( sCommand
.isEmpty()
1142 || sFieldName
.isEmpty()
1143 || ( sDataSource
.isEmpty()
1144 && !xConnection
.is()
1148 OSL_FAIL( "FmXFormView::implCreateFieldControl: nonsense!" );
1151 Reference
< XDataSource
> xDataSource
;
1152 SQLErrorEvent aError
;
1155 if ( xConnection
.is() && !xDataSource
.is() && sDataSource
.isEmpty() )
1157 Reference
< XChild
> xChild( xConnection
, UNO_QUERY
);
1159 xDataSource
.set(xChild
->getParent(), css::uno::UNO_QUERY
);
1162 // obtain the data source
1163 if ( !xDataSource
.is() )
1164 xDataSource
= getDataSource( sDataSource
, comphelper::getProcessComponentContext() );
1166 // and the connection, if necessary
1167 if ( !xConnection
.is() )
1168 xConnection
.reset( getConnection_withFeedback(
1172 comphelper::getProcessComponentContext(),
1176 catch (const SQLException
&)
1178 aError
.Reason
= ::cppu::getCaughtException();
1180 catch (const Exception
& )
1182 /* will be asserted below */
1184 if (aError
.Reason
.hasValue())
1186 displayAsyncErrorMessage( aError
);
1190 // need a data source and a connection here
1191 if (!xDataSource
.is() || !xConnection
.is())
1193 OSL_FAIL("FmXFormView::implCreateFieldControl : could not retrieve the data source or the connection!");
1197 Reference
< XComponent
> xKeepFieldsAlive
;
1201 // determine the table/query field which we should create a control for
1202 Reference
< XPropertySet
> xField
;
1204 Reference
< XNameAccess
> xFields
= getFieldsByCommandDescriptor(
1205 xConnection
, nCommandType
, sCommand
, xKeepFieldsAlive
);
1207 if (xFields
.is() && xFields
->hasByName(sFieldName
))
1208 xFields
->getByName(sFieldName
) >>= xField
;
1212 Reference
< XNumberFormatsSupplier
> xSupplier( getNumberFormats( xConnection
), UNO_SET_THROW
);
1213 Reference
< XNumberFormats
> xNumberFormats( xSupplier
->getNumberFormats(), UNO_SET_THROW
);
1215 OUString sLabelPostfix
;
1218 // only for text size
1219 OutputDevice
* pOutDev
= nullptr;
1220 if (m_pView
->GetActualOutDev() && m_pView
->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW
)
1221 pOutDev
= const_cast<OutputDevice
*>(m_pView
->GetActualOutDev());
1224 if (SdrPageView
* pPageView
= m_pView
->GetSdrPageView())
1226 // const SdrPageViewWinList& rWinList = pPageView->GetWinList();
1227 // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows();
1229 for( sal_uInt32 i
= 0; i
< pPageView
->PageWindowCount(); i
++ )
1231 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(i
);
1233 if( rPageWindow
.GetPaintWindow().OutputToWindow())
1235 pOutDev
= &rPageWindow
.GetPaintWindow().GetOutputDevice();
1245 sal_Int32 nDataType
= ::comphelper::getINT32(xField
->getPropertyValue(FM_PROP_FIELDTYPE
));
1246 if ((DataType::BINARY
== nDataType
) || (DataType::VARBINARY
== nDataType
))
1250 // determine the control type by examining the data type of the bound column
1251 sal_uInt16 nOBJID
= 0;
1252 bool bDateNTimeField
= false;
1254 bool bIsCurrency
= false;
1255 if (::comphelper::hasProperty(FM_PROP_ISCURRENCY
, xField
))
1256 bIsCurrency
= ::comphelper::getBOOL(xField
->getPropertyValue(FM_PROP_ISCURRENCY
));
1259 nOBJID
= OBJ_FM_CURRENCYFIELD
;
1263 case DataType::BLOB
:
1264 case DataType::LONGVARBINARY
:
1265 nOBJID
= OBJ_FM_IMAGECONTROL
;
1267 case DataType::LONGVARCHAR
:
1268 case DataType::CLOB
:
1269 nOBJID
= OBJ_FM_EDIT
;
1271 case DataType::BINARY
:
1272 case DataType::VARBINARY
:
1275 case DataType::BOOLEAN
:
1276 nOBJID
= OBJ_FM_CHECKBOX
;
1278 case DataType::TINYINT
:
1279 case DataType::SMALLINT
:
1280 case DataType::INTEGER
:
1281 nOBJID
= OBJ_FM_NUMERICFIELD
;
1283 case DataType::REAL
:
1284 case DataType::DOUBLE
:
1285 case DataType::NUMERIC
:
1286 case DataType::DECIMAL
:
1287 nOBJID
= OBJ_FM_FORMATTEDFIELD
;
1289 case DataType::TIMESTAMP
:
1290 bDateNTimeField
= true;
1291 sLabelPostfix
= SvxResId(RID_STR_POSTFIX_DATE
);
1293 case DataType::DATE
:
1294 nOBJID
= OBJ_FM_DATEFIELD
;
1296 case DataType::TIME
:
1297 nOBJID
= OBJ_FM_TIMEFIELD
;
1299 case DataType::CHAR
:
1300 case DataType::VARCHAR
:
1302 nOBJID
= OBJ_FM_EDIT
;
1308 std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
> pLabel
;
1309 std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
> pControl
;
1310 if ( !createControlLabelPair( *pOutDev
, 0, 0, xField
, xNumberFormats
, nOBJID
, sLabelPostfix
,
1311 pLabel
, pControl
, xDataSource
, sDataSource
, sCommand
, nCommandType
)
1319 bool bCheckbox
= ( OBJ_FM_CHECKBOX
== nOBJID
);
1320 OSL_ENSURE( !bCheckbox
|| !pLabel
, "FmXFormView::implCreateFieldControl: why was there a label created for a check box?" );
1322 return SdrObjectUniquePtr(pControl
.release());
1324 SdrObjGroup
* pGroup
= new SdrObjGroup(getView()->getSdrModelFromSdrView());
1325 SdrObjList
* pObjList
= pGroup
->GetSubList();
1326 pObjList
->InsertObject( pLabel
.release() );
1327 pObjList
->InsertObject( pControl
.release() );
1329 if ( bDateNTimeField
)
1330 { // so far we created a date field only, but we also need a time field
1331 if ( createControlLabelPair( *pOutDev
, 0, 1000, xField
, xNumberFormats
, OBJ_FM_TIMEFIELD
,
1332 SvxResId(RID_STR_POSTFIX_TIME
), pLabel
, pControl
,
1333 xDataSource
, sDataSource
, sCommand
, nCommandType
)
1336 pObjList
->InsertObject( pLabel
.release() );
1337 pObjList
->InsertObject( pControl
.release() );
1341 return SdrObjectUniquePtr(pGroup
); // and done
1343 catch (const Exception
&)
1345 DBG_UNHANDLED_EXCEPTION("svx");
1353 SdrObjectUniquePtr
FmXFormView::implCreateXFormsControl( const svx::OXFormsDescriptor
&_rDesc
)
1355 // not if we're in design mode
1356 if ( !m_pView
->IsDesignMode() )
1362 // determine the table/query field which we should create a control for
1363 Reference
< XNumberFormats
> xNumberFormats
;
1364 OUString sLabelPostfix
= _rDesc
.szName
;
1367 // only for text size
1368 OutputDevice
* pOutDev
= nullptr;
1369 if (m_pView
->GetActualOutDev() && m_pView
->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW
)
1370 pOutDev
= const_cast<OutputDevice
*>(m_pView
->GetActualOutDev());
1373 if (SdrPageView
* pPageView
= m_pView
->GetSdrPageView())
1375 // const SdrPageViewWinList& rWinList = pPageView->GetWinList();
1376 // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows();
1378 for( sal_uInt32 i
= 0; i
< pPageView
->PageWindowCount(); i
++ )
1380 const SdrPageWindow
& rPageWindow
= *pPageView
->GetPageWindow(i
);
1382 if( rPageWindow
.GetPaintWindow().GetOutputDevice().GetOutDevType() == OUTDEV_WINDOW
)
1384 pOutDev
= &rPageWindow
.GetPaintWindow().GetOutputDevice();
1395 // The service name decides which control should be created
1396 sal_uInt16 nOBJID
= OBJ_FM_EDIT
;
1397 if(_rDesc
.szServiceName
== FM_SUN_COMPONENT_NUMERICFIELD
)
1398 nOBJID
= OBJ_FM_NUMERICFIELD
;
1399 if(_rDesc
.szServiceName
== FM_SUN_COMPONENT_CHECKBOX
)
1400 nOBJID
= OBJ_FM_CHECKBOX
;
1401 if(_rDesc
.szServiceName
== FM_COMPONENT_COMMANDBUTTON
)
1402 nOBJID
= OBJ_FM_BUTTON
;
1404 Reference
< css::form::submission::XSubmission
> xSubmission(_rDesc
.xPropSet
, UNO_QUERY
);
1406 // xform control or submission button?
1407 if ( !xSubmission
.is() )
1409 std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
> pLabel
;
1410 std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
> pControl
;
1411 if ( !createControlLabelPair( *pOutDev
, 0, 0, nullptr, xNumberFormats
, nOBJID
, sLabelPostfix
,
1412 pLabel
, pControl
, nullptr, "", "", -1 )
1419 // Now build the connection between the control and the data item.
1420 Reference
< XValueBinding
> xValueBinding(_rDesc
.xPropSet
,UNO_QUERY
);
1421 Reference
< XBindableValue
> xBindableValue(pControl
->GetUnoControlModel(),UNO_QUERY
);
1423 DBG_ASSERT( xBindableValue
.is(), "FmXFormView::implCreateXFormsControl: control's not bindable!" );
1424 if ( xBindableValue
.is() )
1425 xBindableValue
->setValueBinding(xValueBinding
);
1427 bool bCheckbox
= ( OBJ_FM_CHECKBOX
== nOBJID
);
1428 OSL_ENSURE( !bCheckbox
|| !pLabel
, "FmXFormView::implCreateXFormsControl: why was there a label created for a check box?" );
1430 return SdrObjectUniquePtr(pControl
.release());
1434 SdrObjGroup
* pGroup
= new SdrObjGroup(getView()->getSdrModelFromSdrView());
1435 SdrObjList
* pObjList
= pGroup
->GetSubList();
1436 pObjList
->InsertObject(pLabel
.release());
1437 pObjList
->InsertObject(pControl
.release());
1439 return SdrObjectUniquePtr(pGroup
);
1443 // create a button control
1444 const MapMode
& eTargetMode( pOutDev
->GetMapMode() );
1445 const MapMode
eSourceMode(MapUnit::Map100thMM
);
1446 const sal_uInt16 nObjID
= OBJ_FM_BUTTON
;
1447 ::Size
controlSize(4000, 500);
1448 FmFormObj
*pControl
= static_cast<FmFormObj
*>(
1449 SdrObjFactory::MakeNewObject(
1450 getView()->getSdrModelFromSdrView(),
1451 SdrInventor::FmForm
,
1453 controlSize
.setWidth( long(controlSize
.Width() * eTargetMode
.GetScaleX()) );
1454 controlSize
.setHeight( long(controlSize
.Height() * eTargetMode
.GetScaleY()) );
1455 ::Point
controlPos( OutputDevice::LogicToLogic( ::Point( controlSize
.Width(), 0 ), eSourceMode
, eTargetMode
) );
1456 ::tools::Rectangle
controlRect( controlPos
, OutputDevice::LogicToLogic( controlSize
, eSourceMode
, eTargetMode
) );
1457 pControl
->SetLogicRect(controlRect
);
1459 // set the button label
1460 Reference
< XPropertySet
> xControlSet(pControl
->GetUnoControlModel(), UNO_QUERY
);
1461 xControlSet
->setPropertyValue(FM_PROP_LABEL
, makeAny(_rDesc
.szName
));
1463 // connect the submission with the submission supplier (aka the button)
1464 xControlSet
->setPropertyValue( FM_PROP_BUTTON_TYPE
,
1465 makeAny( FormButtonType_SUBMIT
) );
1466 Reference
< css::form::submission::XSubmissionSupplier
> xSubmissionSupplier(pControl
->GetUnoControlModel(), UNO_QUERY
);
1467 xSubmissionSupplier
->setSubmission(xSubmission
);
1469 return SdrObjectUniquePtr(pControl
);
1472 catch (const Exception
&)
1474 OSL_FAIL("FmXFormView::implCreateXFormsControl: caught an exception while creating the control !");
1482 bool FmXFormView::createControlLabelPair( OutputDevice
const & _rOutDev
, sal_Int32 _nXOffsetMM
, sal_Int32 _nYOffsetMM
,
1483 const Reference
< XPropertySet
>& _rxField
, const Reference
< XNumberFormats
>& _rxNumberFormats
,
1484 sal_uInt16 _nControlObjectID
, const OUString
& _rFieldPostfix
,
1485 std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
>& _rpLabel
,
1486 std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
>& _rpControl
,
1487 const Reference
< XDataSource
>& _rxDataSource
, const OUString
& _rDataSourceName
,
1488 const OUString
& _rCommand
, const sal_Int32 _nCommandType
)
1490 if(!createControlLabelPair(
1498 SdrInventor::FmForm
,
1501 // tdf#118963 Hand over a SdrModel to SdrObject-creation. It uses the local m_pView
1502 // and already returning false when nullptr == getView() could be done, but m_pView
1503 // is already dereferenced here in many places (see below), so just use it for now.
1504 getView()->getSdrModelFromSdrView(),
1512 // insert the control model(s) into the form component hierarchy
1514 lcl_insertIntoFormComponentHierarchy_throw( *m_pView
, *_rpLabel
, _rxDataSource
, _rDataSourceName
, _rCommand
, _nCommandType
);
1515 lcl_insertIntoFormComponentHierarchy_throw( *m_pView
, *_rpControl
, _rxDataSource
, _rDataSourceName
, _rCommand
, _nCommandType
);
1517 // some context-dependent initializations
1518 FormControlFactory aControlFactory
;
1520 aControlFactory
.initializeControlModel( impl_getDocumentType(), *_rpLabel
);
1521 aControlFactory
.initializeControlModel( impl_getDocumentType(), *_rpControl
);
1527 bool FmXFormView::createControlLabelPair( OutputDevice
const & _rOutDev
, sal_Int32 _nXOffsetMM
, sal_Int32 _nYOffsetMM
,
1528 const Reference
< XPropertySet
>& _rxField
,
1529 const Reference
< XNumberFormats
>& _rxNumberFormats
, sal_uInt16 _nControlObjectID
,
1530 const OUString
& _rFieldPostfix
, SdrInventor _nInventor
, sal_uInt16 _nLabelObjectID
,
1532 std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
>& _rpLabel
, std::unique_ptr
<SdrUnoObj
, SdrObjectFreeOp
>& _rpControl
)
1534 sal_Int32 nDataType
= 0;
1535 OUString sFieldName
;
1537 if ( _rxField
.is() )
1539 nDataType
= ::comphelper::getINT32(_rxField
->getPropertyValue(FM_PROP_FIELDTYPE
));
1540 aFieldName
= _rxField
->getPropertyValue(FM_PROP_NAME
);
1541 aFieldName
>>= sFieldName
;
1544 // calculate the positions, respecting the settings of the target device
1545 ::Size
aTextSize( _rOutDev
.GetTextWidth(sFieldName
+ _rFieldPostfix
), _rOutDev
.GetTextHeight() );
1547 MapMode
eTargetMode( _rOutDev
.GetMapMode() ),
1548 eSourceMode( MapUnit::Map100thMM
);
1550 // text width is at least 4 centimeters
1551 // text height is always half a centimeter
1552 ::Size
aDefTxtSize(4000, 500);
1553 ::Size
aDefSize(4000, 500);
1554 ::Size
aDefImageSize(4000, 4000);
1556 ::Size aRealSize
= OutputDevice::LogicToLogic(aTextSize
, eTargetMode
, eSourceMode
);
1557 aRealSize
.setWidth( std::max(aRealSize
.Width(), aDefTxtSize
.Width()) );
1558 aRealSize
.setHeight( aDefSize
.Height() );
1560 // adjust to scaling of the target device (#53523#)
1561 aRealSize
.setWidth( long(Fraction(aRealSize
.Width(), 1) * eTargetMode
.GetScaleX()) );
1562 aRealSize
.setHeight( long(Fraction(aRealSize
.Height(), 1) * eTargetMode
.GetScaleY()) );
1564 // for boolean fields, we do not create a label, but just a checkbox
1565 bool bNeedLabel
= ( _nControlObjectID
!= OBJ_FM_CHECKBOX
);
1568 ::std::unique_ptr
< SdrUnoObj
, SdrObjectFreeOp
> pLabel
;
1569 Reference
< XPropertySet
> xLabelModel
;
1573 pLabel
.reset( dynamic_cast< SdrUnoObj
* >(
1574 SdrObjFactory::MakeNewObject(
1579 OSL_ENSURE(pLabel
, "FmXFormView::createControlLabelPair: could not create the label!");
1584 xLabelModel
.set( pLabel
->GetUnoControlModel(), UNO_QUERY
);
1585 if ( xLabelModel
.is() )
1588 if ( _rxField
.is() && _rxField
->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL
) )
1589 _rxField
->getPropertyValue(FM_PROP_LABEL
) >>= sLabel
;
1590 if ( sLabel
.isEmpty() )
1591 sLabel
= sFieldName
;
1593 xLabelModel
->setPropertyValue( FM_PROP_LABEL
, makeAny( sLabel
+ _rFieldPostfix
) );
1594 OUString
sObjectLabel(SvxResId(RID_STR_OBJECT_LABEL
).replaceAll("#object#", sFieldName
));
1595 xLabelModel
->setPropertyValue(FM_PROP_NAME
, makeAny(sObjectLabel
));
1598 pLabel
->SetLogicRect( ::tools::Rectangle(
1599 OutputDevice::LogicToLogic( ::Point( _nXOffsetMM
, _nYOffsetMM
), eSourceMode
, eTargetMode
),
1600 OutputDevice::LogicToLogic( aRealSize
, eSourceMode
, eTargetMode
)
1605 ::std::unique_ptr
< SdrUnoObj
, SdrObjectFreeOp
> pControl( dynamic_cast< SdrUnoObj
* >(
1606 SdrObjFactory::MakeNewObject(
1609 _nControlObjectID
)));
1611 OSL_ENSURE(pControl
, "FmXFormView::createControlLabelPair: could not create the control!");
1616 Reference
< XPropertySet
> xControlSet( pControl
->GetUnoControlModel(), UNO_QUERY
);
1617 if ( !xControlSet
.is() )
1620 // size of the control
1621 ::Size
aControlSize( aDefSize
);
1622 switch ( nDataType
)
1625 case DataType::BOOLEAN
:
1626 aControlSize
= aDefSize
;
1628 case DataType::LONGVARCHAR
:
1629 case DataType::CLOB
:
1630 case DataType::LONGVARBINARY
:
1631 case DataType::BLOB
:
1632 aControlSize
= aDefImageSize
;
1636 if ( OBJ_FM_IMAGECONTROL
== _nControlObjectID
)
1637 aControlSize
= aDefImageSize
;
1639 aControlSize
.setWidth( long(Fraction(aControlSize
.Width(), 1) * eTargetMode
.GetScaleX()) );
1640 aControlSize
.setHeight( long(Fraction(aControlSize
.Height(), 1) * eTargetMode
.GetScaleY()) );
1642 pControl
->SetLogicRect( ::tools::Rectangle(
1643 OutputDevice::LogicToLogic( ::Point( aRealSize
.Width() + _nXOffsetMM
, _nYOffsetMM
), eSourceMode
, eTargetMode
),
1644 OutputDevice::LogicToLogic( aControlSize
, eSourceMode
, eTargetMode
)
1647 // some initializations
1648 Reference
< XPropertySetInfo
> xControlPropInfo
= xControlSet
->getPropertySetInfo();
1650 if ( aFieldName
.hasValue() )
1652 xControlSet
->setPropertyValue( FM_PROP_CONTROLSOURCE
, aFieldName
);
1653 xControlSet
->setPropertyValue( FM_PROP_NAME
, aFieldName
);
1656 // no dedicated label control => use the label property
1657 if ( xControlPropInfo
->hasPropertyByName( FM_PROP_LABEL
) )
1658 xControlSet
->setPropertyValue( FM_PROP_LABEL
, makeAny( sFieldName
+ _rFieldPostfix
) );
1660 OSL_FAIL( "FmXFormView::createControlLabelPair: can't set a label for the control!" );
1664 if ( (nDataType
== DataType::LONGVARCHAR
|| nDataType
== DataType::CLOB
) && xControlPropInfo
->hasPropertyByName( FM_PROP_MULTILINE
) )
1666 xControlSet
->setPropertyValue( FM_PROP_MULTILINE
, makeAny( true ) );
1669 // announce the label to the control
1670 if ( xControlPropInfo
->hasPropertyByName( FM_PROP_CONTROLLABEL
) && xLabelModel
.is() )
1674 xControlSet
->setPropertyValue( FM_PROP_CONTROLLABEL
, makeAny( xLabelModel
) );
1676 catch (const Exception
&)
1678 DBG_UNHANDLED_EXCEPTION("svx");
1682 if ( _rxField
.is() )
1684 FormControlFactory::initializeFieldDependentProperties( _rxField
, xControlSet
, _rxNumberFormats
);
1687 _rpLabel
= std::move(pLabel
);
1688 _rpControl
= std::move(pControl
);
1693 FmXFormView::ObjectRemoveListener::ObjectRemoveListener( FmXFormView
* pParent
)
1694 :m_pParent( pParent
)
1699 void FmXFormView::ObjectRemoveListener::Notify( SfxBroadcaster
& /*rBC*/, const SfxHint
& rHint
)
1701 if (rHint
.GetId() != SfxHintId::ThisIsAnSdrHint
)
1703 const SdrHint
* pSdrHint
= static_cast<const SdrHint
*>(&rHint
);
1704 if (pSdrHint
->GetKind() == SdrHintKind::ObjectRemoved
)
1705 m_pParent
->ObjectRemovedInAliveMode(pSdrHint
->GetObject());
1709 void FmXFormView::ObjectRemovedInAliveMode( const SdrObject
* pObject
)
1711 // if the remote object in my MarkList, which I have memorized when switching to the
1712 // Alive mode, I have to take it out now, because I otherwise try to set the mark
1713 // again when switching back (interestingly, this fails only with grouped objects
1714 // (when accessing their ObjList GPF), not with individual ones)
1716 const size_t nCount
= m_aMark
.GetMarkCount();
1717 for (size_t i
= 0; i
< nCount
; ++i
)
1719 SdrMark
* pMark
= m_aMark
.GetMark(i
);
1720 SdrObject
* pCurrent
= pMark
->GetMarkedSdrObj();
1721 if (pObject
== pCurrent
)
1723 m_aMark
.DeleteMark(i
);
1726 // I do not need to descend into GroupObjects: if an object is deleted there,
1727 // then the pointer, which I have, to the GroupObject still remains valid ...
1732 void FmXFormView::stopMarkListWatching()
1734 if ( m_pWatchStoredList
)
1736 m_pWatchStoredList
->EndListeningAll();
1737 m_pWatchStoredList
.reset();
1742 void FmXFormView::startMarkListWatching()
1744 if ( !m_pWatchStoredList
)
1746 FmFormModel
* pModel
= GetFormShell() ? GetFormShell()->GetFormModel() : nullptr;
1747 DBG_ASSERT( pModel
!= nullptr, "FmXFormView::startMarkListWatching: shell has no model!" );
1750 m_pWatchStoredList
.reset(new ObjectRemoveListener( this ));
1751 m_pWatchStoredList
->StartListening( *static_cast< SfxBroadcaster
* >( pModel
) );
1756 OSL_FAIL( "FmXFormView::startMarkListWatching: already listening!" );
1760 void FmXFormView::saveMarkList()
1764 m_aMark
= m_pView
->GetMarkedObjectList();
1765 const size_t nCount
= m_aMark
.GetMarkCount( );
1766 for ( size_t i
= 0; i
< nCount
; ++i
)
1768 SdrMark
* pMark
= m_aMark
.GetMark(i
);
1769 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
1771 if ( m_pView
->IsObjMarked( pObj
) )
1773 if ( pObj
->IsGroupObject() )
1775 SdrObjListIter
aIter( pObj
->GetSubList() );
1776 bool bMixed
= false;
1777 while ( aIter
.IsMore() && !bMixed
)
1778 bMixed
= ( aIter
.Next()->GetObjInventor() != SdrInventor::FmForm
);
1782 // all objects in the group are form objects
1783 m_pView
->MarkObj( pMark
->GetMarkedSdrObj(), pMark
->GetPageView(), true /* unmark! */ );
1788 if ( pObj
->GetObjInventor() == SdrInventor::FmForm
)
1789 { // this is a form layer object
1790 m_pView
->MarkObj( pMark
->GetMarkedSdrObj(), pMark
->GetPageView(), true /* unmark! */ );
1798 OSL_FAIL( "FmXFormView::saveMarkList: invalid view!" );
1803 static bool lcl_hasObject( SdrObjListIter
& rIter
, SdrObject
const * pObj
)
1805 bool bFound
= false;
1806 while (rIter
.IsMore() && !bFound
)
1807 bFound
= pObj
== rIter
.Next();
1814 void FmXFormView::restoreMarkList( SdrMarkList
& _rRestoredMarkList
)
1819 _rRestoredMarkList
.Clear();
1821 const SdrMarkList
& rCurrentList
= m_pView
->GetMarkedObjectList();
1822 FmFormPage
* pPage
= GetFormShell() ? GetFormShell()->GetCurPage() : nullptr;
1825 if (rCurrentList
.GetMarkCount())
1826 { // there is a current mark ... hmm. Is it a subset of the mark we remembered in saveMarkList?
1827 bool bMisMatch
= false;
1829 // loop through all current marks
1830 const size_t nCurrentCount
= rCurrentList
.GetMarkCount();
1831 for ( size_t i
=0; i
<nCurrentCount
&& !bMisMatch
; ++i
)
1833 const SdrObject
* pCurrentMarked
= rCurrentList
.GetMark( i
)->GetMarkedSdrObj();
1835 // loop through all saved marks, check for equality
1836 bool bFound
= false;
1837 const size_t nSavedCount
= m_aMark
.GetMarkCount();
1838 for ( size_t j
=0; j
<nSavedCount
&& !bFound
; ++j
)
1840 if ( m_aMark
.GetMark( j
)->GetMarkedSdrObj() == pCurrentMarked
)
1844 // did not find a current mark in the saved marks
1852 _rRestoredMarkList
= rCurrentList
;
1856 // it is important that the objects of the mark list are not accessed,
1857 // because they can be already destroyed
1858 SdrPageView
* pCurPageView
= m_pView
->GetSdrPageView();
1859 SdrObjListIter
aPageIter( pPage
);
1862 // do all objects still exist
1863 const size_t nCount
= m_aMark
.GetMarkCount();
1864 for (size_t i
= 0; i
< nCount
&& bFound
; ++i
)
1866 SdrMark
* pMark
= m_aMark
.GetMark(i
);
1867 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
1868 if (pObj
->IsGroupObject())
1870 SdrObjListIter
aIter(pObj
->GetSubList());
1871 while (aIter
.IsMore() && bFound
)
1872 bFound
= lcl_hasObject(aPageIter
, aIter
.Next());
1875 bFound
= lcl_hasObject(aPageIter
, pObj
);
1877 bFound
= bFound
&& pCurPageView
== pMark
->GetPageView();
1882 // evaluate the LastObject
1883 if (nCount
) // now mark the objects
1885 for (size_t i
= 0; i
< nCount
; ++i
)
1887 SdrMark
* pMark
= m_aMark
.GetMark(i
);
1888 SdrObject
* pObj
= pMark
->GetMarkedSdrObj();
1889 if ( pObj
->GetObjInventor() == SdrInventor::FmForm
)
1890 if ( !m_pView
->IsObjMarked( pObj
) )
1891 m_pView
->MarkObj( pObj
, pMark
->GetPageView() );
1894 _rRestoredMarkList
= m_aMark
;
1901 void SAL_CALL
FmXFormView::focusGained( const FocusEvent
& /*e*/ )
1903 if ( m_xWindow
.is() && m_pView
)
1905 m_pView
->SetMoveOutside( true, FmFormView::ImplAccess() );
1909 void SAL_CALL
FmXFormView::focusLost( const FocusEvent
& /*e*/ )
1911 // when switch the focus outside the office the mark didn't change
1912 // so we can not remove us as focus listener
1913 if ( m_xWindow
.is() && m_pView
)
1915 m_pView
->SetMoveOutside( false, FmFormView::ImplAccess() );
1919 DocumentType
FmXFormView::impl_getDocumentType() const
1921 if ( GetFormShell() && GetFormShell()->GetImpl() )
1922 return GetFormShell()->GetImpl()->getDocumentType_Lock();
1923 return eUnknownDocumentType
;
1926 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */