lok: Don't attempt to select the exact text after a failed search.
[LibreOffice.git] / svx / source / form / fmvwimp.cxx
blob8044e8b6c6dc9d378cde5fa13269a1820e96a80d
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 .
21 #include "fmdocumentclassification.hxx"
22 #include "fmobj.hxx"
23 #include "fmpgeimp.hxx"
24 #include "fmprop.hrc"
25 #include "svx/fmresids.hrc"
26 #include "fmservs.hxx"
27 #include "fmshimp.hxx"
28 #include "svx/fmtools.hxx"
29 #include "fmundo.hxx"
30 #include "fmvwimp.hxx"
31 #include "formcontrolfactory.hxx"
32 #include "svx/sdrpaintwindow.hxx"
33 #include "svx/svditer.hxx"
34 #include "svx/dataaccessdescriptor.hxx"
35 #include "svx/dialmgr.hxx"
36 #include "svx/fmglob.hxx"
37 #include "svx/fmmodel.hxx"
38 #include "svx/fmpage.hxx"
39 #include "svx/fmshell.hxx"
40 #include "svx/fmview.hxx"
41 #include "svx/sdrpagewindow.hxx"
42 #include "svx/svdogrp.hxx"
43 #include "svx/svdpagv.hxx"
44 #include "svx/xmlexchg.hxx"
46 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
47 #include <com/sun/star/style/VerticalAlignment.hpp>
48 #include <com/sun/star/lang/XInitialization.hpp>
49 #include <com/sun/star/sdbc/XRowSet.hpp>
50 #include <com/sun/star/form/XLoadable.hpp>
51 #include <com/sun/star/awt/VisualEffect.hpp>
52 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
53 #include <com/sun/star/util/XNumberFormats.hpp>
54 #include <com/sun/star/sdb/CommandType.hpp>
55 #include <com/sun/star/sdbc/DataType.hpp>
56 #include <com/sun/star/sdbc/ColumnValue.hpp>
57 #include <com/sun/star/form/FormComponentType.hpp>
58 #include <com/sun/star/form/FormButtonType.hpp>
59 #include <com/sun/star/form/XReset.hpp>
60 #include <com/sun/star/form/binding/XBindableValue.hpp>
61 #include <com/sun/star/form/binding/XValueBinding.hpp>
62 #include <com/sun/star/form/runtime/FormController.hpp>
63 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
64 #include <com/sun/star/awt/XTabControllerModel.hpp>
65 #include <com/sun/star/awt/XControlContainer.hpp>
66 #include <com/sun/star/awt/XTabController.hpp>
67 #include <com/sun/star/container/XIndexAccess.hpp>
68 #include <com/sun/star/awt/XControl.hpp>
69 #include <com/sun/star/lang/XUnoTunnel.hpp>
70 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
71 #include <com/sun/star/sdbc/XPreparedStatement.hpp>
72 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
73 #include <com/sun/star/container/XContainer.hpp>
75 #include <comphelper/enumhelper.hxx>
76 #include <comphelper/extract.hxx>
77 #include <comphelper/namedvaluecollection.hxx>
78 #include <comphelper/numbers.hxx>
79 #include <comphelper/property.hxx>
80 #include <comphelper/processfactory.hxx>
81 #include <cppuhelper/exc_hlp.hxx>
82 #include <unotools/moduleoptions.hxx>
83 #include <tools/diagnose_ex.h>
84 #include <vcl/msgbox.hxx>
85 #include <vcl/stdtext.hxx>
86 #include <osl/mutex.hxx>
87 #include <connectivity/dbtools.hxx>
89 #include <algorithm>
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::style::VerticalAlignment_MIDDLE;
110 using ::com::sun::star::form::FormButtonType_SUBMIT;
111 using ::com::sun::star::form::binding::XValueBinding;
112 using ::com::sun::star::form::binding::XBindableValue;
113 using ::com::sun::star::lang::XComponent;
114 using ::com::sun::star::container::XIndexAccess;
115 using ::com::sun::star::form::runtime::FormController;
116 using ::com::sun::star::form::runtime::XFormController;
117 using ::com::sun::star::script::XEventAttacherManager;
118 using ::com::sun::star::awt::XTabControllerModel;
119 using ::com::sun::star::container::XChild;
120 using ::com::sun::star::container::XEnumeration;
121 using ::com::sun::star::task::XInteractionHandler;
122 using ::com::sun::star::lang::XInitialization;
123 using ::com::sun::star::awt::XTabController;
124 using ::com::sun::star::lang::XUnoTunnel;
125 using ::com::sun::star::awt::XControlContainer;
126 using ::com::sun::star::awt::XControl;
127 using ::com::sun::star::form::XFormComponent;
128 using ::com::sun::star::form::XForm;
129 using ::com::sun::star::lang::IndexOutOfBoundsException;
130 using ::com::sun::star::lang::WrappedTargetException;
131 using ::com::sun::star::container::XContainer;
132 using ::com::sun::star::container::ContainerEvent;
133 using ::com::sun::star::lang::EventObject;
134 using ::com::sun::star::beans::NamedValue;
135 using ::com::sun::star::sdb::SQLErrorEvent;
136 using ::com::sun::star::sdbc::XRowSet;
137 using ::com::sun::star::beans::XPropertySet;
138 using ::com::sun::star::container::XElementAccess;
139 using ::com::sun::star::awt::XWindow;
140 using ::com::sun::star::awt::FocusEvent;
141 using ::com::sun::star::ui::dialogs::XExecutableDialog;
142 using ::com::sun::star::sdbc::XDataSource;
143 using ::com::sun::star::container::XIndexContainer;
144 using ::com::sun::star::sdbc::XConnection;
145 using ::com::sun::star::container::XNameAccess;
146 using ::com::sun::star::sdb::SQLContext;
147 using ::com::sun::star::sdbc::SQLWarning;
148 using ::com::sun::star::sdbc::SQLException;
149 using ::com::sun::star::util::XNumberFormatsSupplier;
150 using ::com::sun::star::util::XNumberFormats;
151 using ::com::sun::star::beans::XPropertySetInfo;
153 namespace FormComponentType = ::com::sun::star::form::FormComponentType;
154 namespace CommandType = ::com::sun::star::sdb::CommandType;
155 namespace DataType = ::com::sun::star::sdbc::DataType;
158 class FmXFormView::ObjectRemoveListener : public SfxListener
160 FmXFormView* m_pParent;
161 public:
162 ObjectRemoveListener( FmXFormView* pParent );
163 virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) SAL_OVERRIDE;
168 FormViewPageWindowAdapter::FormViewPageWindowAdapter( const css::uno::Reference<css::uno::XComponentContext>& _rContext, const SdrPageWindow& _rWindow, FmXFormView* _pViewImpl )
169 : m_xControlContainer( _rWindow.GetControlContainer() ),
170 m_xContext( _rContext ),
171 m_pViewImpl( _pViewImpl ),
172 m_pWindow( dynamic_cast< vcl::Window* >( &_rWindow.GetPaintWindow().GetOutputDevice() ) )
175 // create an XFormController for every form
176 FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( _rWindow.GetPageView().GetPage() );
177 DBG_ASSERT( pFormPage, "FormViewPageWindowAdapter::FormViewPageWindowAdapter: no FmFormPage found!" );
178 if ( pFormPage )
182 Reference< XIndexAccess > xForms( pFormPage->GetForms(), UNO_QUERY_THROW );
183 sal_uInt32 nLength = xForms->getCount();
184 for (sal_uInt32 i = 0; i < nLength; i++)
186 Reference< XForm > xForm( xForms->getByIndex(i), UNO_QUERY );
187 if ( xForm.is() )
188 setController( xForm, NULL );
191 catch (const Exception&)
193 DBG_UNHANDLED_EXCEPTION();
198 FormViewPageWindowAdapter::~FormViewPageWindowAdapter()
202 void FormViewPageWindowAdapter::dispose()
204 for ( ::std::vector< Reference< XFormController > >::const_iterator i = m_aControllerList.begin();
205 i != m_aControllerList.end();
211 Reference< XFormController > xController( *i, UNO_QUERY_THROW );
213 // detaching the events
214 Reference< XChild > xControllerModel( xController->getModel(), UNO_QUERY );
215 if ( xControllerModel.is() )
217 Reference< XEventAttacherManager > xEventManager( xControllerModel->getParent(), UNO_QUERY_THROW );
218 Reference< XInterface > xControllerNormalized( xController, UNO_QUERY_THROW );
219 xEventManager->detach( i - m_aControllerList.begin(), xControllerNormalized );
222 // dispose the formcontroller
223 xController->dispose();
225 catch (const Exception&)
227 DBG_UNHANDLED_EXCEPTION();
231 m_aControllerList.clear();
234 sal_Bool SAL_CALL FormViewPageWindowAdapter::hasElements() throw( RuntimeException, std::exception )
236 return getCount() != 0;
239 Type SAL_CALL FormViewPageWindowAdapter::getElementType() throw( RuntimeException, std::exception )
241 return cppu::UnoType<XFormController>::get();
244 // XIndexAccess
245 sal_Int32 SAL_CALL FormViewPageWindowAdapter::getCount() throw( RuntimeException, std::exception )
247 return m_aControllerList.size();
250 Any SAL_CALL FormViewPageWindowAdapter::getByIndex(sal_Int32 nIndex) throw( IndexOutOfBoundsException, WrappedTargetException, RuntimeException, std::exception )
252 if (nIndex < 0 ||
253 nIndex >= getCount())
254 throw IndexOutOfBoundsException();
256 Any aElement;
257 aElement <<= m_aControllerList[nIndex];
258 return aElement;
261 void SAL_CALL FormViewPageWindowAdapter::makeVisible( const Reference< XControl >& _Control ) throw (RuntimeException, std::exception)
263 SolarMutexGuard aSolarGuard;
265 Reference< XWindow > xWindow( _Control, UNO_QUERY );
266 if ( xWindow.is() && m_pViewImpl->getView() && m_pWindow )
268 awt::Rectangle aRect = xWindow->getPosSize();
269 ::Rectangle aNewRect( aRect.X, aRect.Y, aRect.X + aRect.Width, aRect.Y + aRect.Height );
270 aNewRect = m_pWindow->PixelToLogic( aNewRect );
271 m_pViewImpl->getView()->MakeVisible( aNewRect, *m_pWindow );
275 Reference< XFormController > getControllerSearchChildren( const Reference< XIndexAccess > & xIndex, const Reference< XTabControllerModel > & xModel)
277 if (xIndex.is() && xIndex->getCount())
279 Reference< XFormController > xController;
281 for (sal_Int32 n = xIndex->getCount(); n-- && !xController.is(); )
283 xIndex->getByIndex(n) >>= xController;
284 if ((XTabControllerModel*)xModel.get() == (XTabControllerModel*)xController->getModel().get())
285 return xController;
286 else
288 xController = getControllerSearchChildren(xController, xModel);
289 if ( xController.is() )
290 return xController;
294 return Reference< XFormController > ();
297 // Search the according controller
298 Reference< XFormController > FormViewPageWindowAdapter::getController( const Reference< XForm > & xForm ) const
300 Reference< XTabControllerModel > xModel(xForm, UNO_QUERY);
301 for (::std::vector< Reference< XFormController > >::const_iterator i = m_aControllerList.begin();
302 i != m_aControllerList.end(); ++i)
304 if ((XTabControllerModel*)(*i)->getModel().get() == (XTabControllerModel*)xModel.get())
305 return *i;
307 // the current-round controller isn't the right one. perhaps one of its children ?
308 Reference< XFormController > xChildSearch = getControllerSearchChildren(Reference< XIndexAccess > (*i, UNO_QUERY), xModel);
309 if (xChildSearch.is())
310 return xChildSearch;
312 return Reference< XFormController > ();
316 void FormViewPageWindowAdapter::setController(const Reference< XForm > & xForm, const Reference< XFormController >& _rxParentController )
318 DBG_ASSERT( xForm.is(), "FormViewPageWindowAdapter::setController: there should be a form!" );
319 Reference< XIndexAccess > xFormCps(xForm, UNO_QUERY);
320 if (!xFormCps.is())
321 return;
323 Reference< XTabControllerModel > xTabOrder(xForm, UNO_QUERY);
325 // create a form controller
326 Reference< XFormController > xController( FormController::create(m_xContext) );
328 Reference< XInteractionHandler > xHandler;
329 if ( _rxParentController.is() )
330 xHandler = _rxParentController->getInteractionHandler();
331 else
333 // TODO: should we create a default handler? Not really necessary, since the
334 // FormController itself has a default fallback
336 if ( xHandler.is() )
337 xController->setInteractionHandler( xHandler );
339 xController->setContext( this );
341 xController->setModel( xTabOrder );
342 xController->setContainer( m_xControlContainer );
343 xController->activateTabOrder();
344 xController->addActivateListener( m_pViewImpl );
346 if ( _rxParentController.is() )
347 _rxParentController->addChildController( xController );
348 else
350 m_aControllerList.push_back(xController);
352 xController->setParent( *this );
354 // attaching the events
355 Reference< XEventAttacherManager > xEventManager( xForm->getParent(), UNO_QUERY );
356 xEventManager->attach(m_aControllerList.size() - 1, Reference<XInterface>( xController, UNO_QUERY ), makeAny(xController) );
359 // jetzt die Subforms durchgehen
360 sal_uInt32 nLength = xFormCps->getCount();
361 Reference< XForm > xSubForm;
362 for (sal_uInt32 i = 0; i < nLength; i++)
364 if ( xFormCps->getByIndex(i) >>= xSubForm )
365 setController( xSubForm, xController );
370 void FormViewPageWindowAdapter::updateTabOrder( const Reference< XForm >& _rxForm )
372 OSL_PRECOND( _rxForm.is(), "FormViewPageWindowAdapter::updateTabOrder: illegal argument!" );
373 if ( !_rxForm.is() )
374 return;
378 Reference< XTabController > xTabCtrl( getController( _rxForm ).get() );
379 if ( xTabCtrl.is() )
380 { // if there already is a TabController for this form, then delegate the "updateTabOrder" request
381 xTabCtrl->activateTabOrder();
383 else
384 { // otherwise, create a TabController
386 // if it's a sub form, then we must ensure there exist TabControllers
387 // for all its ancestors, too
388 Reference< XForm > xParentForm( _rxForm->getParent(), UNO_QUERY );
389 // there is a parent form -> look for the respective controller
390 Reference< XFormController > xParentController;
391 if ( xParentForm.is() )
392 xParentController.set( getController( xParentForm ), UNO_QUERY );
394 setController( _rxForm, xParentController );
397 catch (const Exception&)
399 DBG_UNHANDLED_EXCEPTION();
404 FmXFormView::FmXFormView(FmFormView* _pView )
405 :m_pMarkedGrid(NULL)
406 ,m_pView(_pView)
407 ,m_nActivationEvent(0)
408 ,m_nErrorMessageEvent( 0 )
409 ,m_nAutoFocusEvent( 0 )
410 ,m_nControlWizardEvent( 0 )
411 ,m_pWatchStoredList( NULL )
412 ,m_bFirstActivation( true )
413 ,m_isTabOrderUpdateSuspended( false )
418 void FmXFormView::cancelEvents()
420 if ( m_nActivationEvent )
422 Application::RemoveUserEvent( m_nActivationEvent );
423 m_nActivationEvent = 0;
426 if ( m_nErrorMessageEvent )
428 Application::RemoveUserEvent( m_nErrorMessageEvent );
429 m_nErrorMessageEvent = 0;
432 if ( m_nAutoFocusEvent )
434 Application::RemoveUserEvent( m_nAutoFocusEvent );
435 m_nAutoFocusEvent = 0;
438 if ( m_nControlWizardEvent )
440 Application::RemoveUserEvent( m_nControlWizardEvent );
441 m_nControlWizardEvent = 0;
446 void FmXFormView::notifyViewDying( )
448 DBG_ASSERT( m_pView, "FmXFormView::notifyViewDying: my view already died!" );
449 m_pView = NULL;
450 cancelEvents();
454 FmXFormView::~FmXFormView()
456 DBG_ASSERT( m_aPageWindowAdapters.empty(), "FmXFormView::~FmXFormView: Window list not empty!" );
457 if ( !m_aPageWindowAdapters.empty() )
459 for ( PageWindowAdapterList::const_iterator loop = m_aPageWindowAdapters.begin();
460 loop != m_aPageWindowAdapters.end();
461 ++loop
464 (*loop)->dispose();
468 cancelEvents();
470 delete m_pWatchStoredList;
471 m_pWatchStoredList = NULL;
474 // EventListener
476 void SAL_CALL FmXFormView::disposing(const EventObject& Source) throw( RuntimeException, std::exception )
478 if ( m_xWindow.is() && Source.Source == m_xWindow )
479 removeGridWindowListening();
482 // XFormControllerListener
484 void SAL_CALL FmXFormView::formActivated(const EventObject& rEvent) throw( RuntimeException, std::exception )
486 if ( m_pView && m_pView->GetFormShell() && m_pView->GetFormShell()->GetImpl() )
487 m_pView->GetFormShell()->GetImpl()->formActivated( rEvent );
491 void SAL_CALL FmXFormView::formDeactivated(const EventObject& rEvent) throw( RuntimeException, std::exception )
493 if ( m_pView && m_pView->GetFormShell() && m_pView->GetFormShell()->GetImpl() )
494 m_pView->GetFormShell()->GetImpl()->formDeactivated( rEvent );
497 // XContainerListener
499 void SAL_CALL FmXFormView::elementInserted(const ContainerEvent& evt) throw( RuntimeException, std::exception )
503 Reference< XControlContainer > xControlContainer( evt.Source, UNO_QUERY_THROW );
504 Reference< XControl > xControl( evt.Element, UNO_QUERY_THROW );
505 Reference< XFormComponent > xControlModel( xControl->getModel(), UNO_QUERY_THROW );
506 Reference< XForm > xForm( xControlModel->getParent(), UNO_QUERY_THROW );
508 if ( m_isTabOrderUpdateSuspended )
510 // remember the container and the control, so we can update the tab order on resumeTabOrderUpdate
511 m_aNeedTabOrderUpdate[ xControlContainer ].insert( xForm );
513 else
515 PFormViewPageWindowAdapter pAdapter = findWindow( xControlContainer );
516 if ( pAdapter.is() )
517 pAdapter->updateTabOrder( xForm );
520 catch (const Exception&)
522 DBG_UNHANDLED_EXCEPTION();
527 void SAL_CALL FmXFormView::elementReplaced(const ContainerEvent& evt) throw( RuntimeException, std::exception )
529 elementInserted(evt);
533 void SAL_CALL FmXFormView::elementRemoved(const ContainerEvent& /*evt*/) throw( RuntimeException, std::exception )
538 PFormViewPageWindowAdapter FmXFormView::findWindow( const Reference< XControlContainer >& _rxCC ) const
540 for ( PageWindowAdapterList::const_iterator i = m_aPageWindowAdapters.begin();
541 i != m_aPageWindowAdapters.end();
545 if ( _rxCC == (*i)->getControlContainer() )
546 return *i;
548 return NULL;
552 void FmXFormView::addWindow(const SdrPageWindow& rWindow)
554 FmFormPage* pFormPage = PTR_CAST( FmFormPage, rWindow.GetPageView().GetPage() );
555 if ( !pFormPage )
556 return;
558 Reference< XControlContainer > xCC = rWindow.GetControlContainer();
559 if ( xCC.is()
560 && ( !findWindow( xCC ).is() )
563 PFormViewPageWindowAdapter pAdapter = new FormViewPageWindowAdapter( comphelper::getProcessComponentContext(), rWindow, this );
564 m_aPageWindowAdapters.push_back( pAdapter );
566 // Am ControlContainer horchen um Aenderungen mitzbekommen
567 Reference< XContainer > xContainer( xCC, UNO_QUERY );
568 if ( xContainer.is() )
569 xContainer->addContainerListener( this );
574 void FmXFormView::removeWindow( const Reference< XControlContainer >& _rxCC )
576 // Wird gerufen, wenn
577 // - in den Design-Modus geschaltet wird
578 // - ein Window geloescht wird, waehrend man im Design-Modus ist
579 // - der Control-Container fuer ein Window entfernt wird, waehrend
580 // der aktive Modus eingeschaltet ist.
582 for ( PageWindowAdapterList::iterator i = m_aPageWindowAdapters.begin();
583 i != m_aPageWindowAdapters.end();
587 if ( _rxCC != (*i)->getControlContainer() )
588 continue;
590 Reference< XContainer > xContainer( _rxCC, UNO_QUERY );
591 if ( xContainer.is() )
592 xContainer->removeContainerListener( this );
594 (*i)->dispose();
595 m_aPageWindowAdapters.erase( i );
596 break;
601 void FmXFormView::displayAsyncErrorMessage( const SQLErrorEvent& _rEvent )
603 DBG_ASSERT( 0 == m_nErrorMessageEvent, "FmXFormView::displayAsyncErrorMessage: not too fast, please!" );
604 // This should not happen - usually, the PostUserEvent is faster than any possible user
605 // interaction which could trigger a new error. If it happens, we need a queue for the events.
606 m_aAsyncError = _rEvent;
607 m_nErrorMessageEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnDelayedErrorMessage ) );
611 IMPL_LINK_NOARG(FmXFormView, OnDelayedErrorMessage)
613 m_nErrorMessageEvent = 0;
614 displayException( m_aAsyncError );
615 return 0L;
619 void FmXFormView::onFirstViewActivation( const FmFormModel* _pDocModel )
621 if ( _pDocModel && _pDocModel->GetAutoControlFocus() )
622 m_nAutoFocusEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnAutoFocus ) );
626 void FmXFormView::suspendTabOrderUpdate()
628 OSL_ENSURE( !m_isTabOrderUpdateSuspended, "FmXFormView::suspendTabOrderUpdate: nesting not allowed!" );
629 m_isTabOrderUpdateSuspended = true;
633 void FmXFormView::resumeTabOrderUpdate()
635 OSL_ENSURE( m_isTabOrderUpdateSuspended, "FmXFormView::resumeTabOrderUpdate: not suspended!" );
636 m_isTabOrderUpdateSuspended = false;
638 // update the tab orders for all components which were collected since the suspendTabOrderUpdate call.
639 for ( MapControlContainerToSetOfForms::const_iterator container = m_aNeedTabOrderUpdate.begin();
640 container != m_aNeedTabOrderUpdate.end();
641 ++container
644 PFormViewPageWindowAdapter pAdapter = findWindow( container->first );
645 if ( !pAdapter.is() )
646 continue;
648 for ( SetOfForms::const_iterator form = container->second.begin();
649 form != container->second.end();
650 ++form
653 pAdapter->updateTabOrder( *form );
656 m_aNeedTabOrderUpdate.clear();
660 IMPL_LINK_NOARG(FmXFormView, OnActivate)
662 m_nActivationEvent = 0;
664 if ( !m_pView )
666 OSL_FAIL( "FmXFormView::OnActivate: well .... seems we have a timing problem (the view already died)!" );
667 return 0;
670 // setting the controller to activate
671 if (m_pView->GetFormShell() && m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
673 vcl::Window* pWindow = const_cast<vcl::Window*>(static_cast<const vcl::Window*>(m_pView->GetActualOutDev()));
674 PFormViewPageWindowAdapter pAdapter = m_aPageWindowAdapters.empty() ? NULL : m_aPageWindowAdapters[0];
675 for ( PageWindowAdapterList::const_iterator i = m_aPageWindowAdapters.begin();
676 i != m_aPageWindowAdapters.end();
680 if ( pWindow == (*i)->getWindow() )
681 pAdapter =*i;
684 if ( pAdapter.get() )
686 for ( ::std::vector< Reference< XFormController > >::const_iterator i = pAdapter->GetList().begin();
687 i != pAdapter->GetList().end();
691 const Reference< XFormController > & xController = *i;
692 if ( !xController.is() )
693 continue;
695 // only database forms are to be activated
696 Reference< XRowSet > xForm(xController->getModel(), UNO_QUERY);
697 if ( !xForm.is() || !getConnection( xForm ).is() )
698 continue;
700 Reference< XPropertySet > xFormSet( xForm, UNO_QUERY );
701 if ( !xFormSet.is() )
703 SAL_WARN( "svx.form", "FmXFormView::OnActivate: a form which does not have properties?" );
704 continue;
707 const OUString aSource = ::comphelper::getString( xFormSet->getPropertyValue( FM_PROP_COMMAND ) );
708 if ( !aSource.isEmpty() )
710 FmXFormShell* pShImpl = m_pView->GetFormShell()->GetImpl();
711 if ( pShImpl )
712 pShImpl->setActiveController( xController );
713 break;
718 return 0;
722 void FmXFormView::Activate(bool bSync)
724 if (m_nActivationEvent)
726 Application::RemoveUserEvent(m_nActivationEvent);
727 m_nActivationEvent = 0;
730 if (bSync)
732 LINK(this,FmXFormView,OnActivate).Call(NULL);
734 else
735 m_nActivationEvent = Application::PostUserEvent(LINK(this,FmXFormView,OnActivate));
739 void FmXFormView::Deactivate(bool bDeactivateController)
741 if (m_nActivationEvent)
743 Application::RemoveUserEvent(m_nActivationEvent);
744 m_nActivationEvent = 0;
747 FmXFormShell* pShImpl = m_pView->GetFormShell() ? m_pView->GetFormShell()->GetImpl() : NULL;
748 if (pShImpl && bDeactivateController)
749 pShImpl->setActiveController( NULL );
753 FmFormShell* FmXFormView::GetFormShell() const
755 return m_pView ? m_pView->GetFormShell() : NULL;
758 void FmXFormView::AutoFocus( bool _bSync )
760 if (m_nAutoFocusEvent)
761 Application::RemoveUserEvent(m_nAutoFocusEvent);
763 if ( _bSync )
764 OnAutoFocus( NULL );
765 else
766 m_nAutoFocusEvent = Application::PostUserEvent(LINK(this, FmXFormView, OnAutoFocus));
770 bool FmXFormView::isFocusable( const Reference< XControl >& i_rControl )
772 if ( !i_rControl.is() )
773 return false;
777 Reference< XPropertySet > xModelProps( i_rControl->getModel(), UNO_QUERY_THROW );
779 // only enabled controls are allowed to participate
780 bool bEnabled = false;
781 OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_ENABLED ) >>= bEnabled );
782 if ( !bEnabled )
783 return false;
785 // check the class id of the control model
786 sal_Int16 nClassId = FormComponentType::CONTROL;
787 OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
789 // controls which are not focussable
790 if ( ( FormComponentType::CONTROL != nClassId )
791 && ( FormComponentType::IMAGEBUTTON != nClassId )
792 && ( FormComponentType::GROUPBOX != nClassId )
793 && ( FormComponentType::FIXEDTEXT != nClassId )
794 && ( FormComponentType::HIDDENCONTROL != nClassId )
795 && ( FormComponentType::IMAGECONTROL != nClassId )
796 && ( FormComponentType::SCROLLBAR != nClassId )
797 && ( FormComponentType::SPINBUTTON!= nClassId )
800 return true;
803 catch (const Exception&)
805 DBG_UNHANDLED_EXCEPTION();
807 return false;
811 static Reference< XControl > lcl_firstFocussableControl( const Sequence< Reference< XControl > >& _rControls )
813 Reference< XControl > xReturn;
815 // loop through all the controls
816 const Reference< XControl >* pControls = _rControls.getConstArray();
817 const Reference< XControl >* pControlsEnd = _rControls.getConstArray() + _rControls.getLength();
818 for ( ; pControls != pControlsEnd; ++pControls )
820 if ( !pControls->is() )
821 continue;
823 if ( FmXFormView::isFocusable( *pControls ) )
825 xReturn = *pControls;
826 break;
830 if ( !xReturn.is() && _rControls.getLength() )
831 xReturn = _rControls[0];
833 return xReturn;
837 namespace
840 void lcl_ensureControlsOfFormExist_nothrow( const SdrPage& _rPage, const SdrView& _rView, const vcl::Window& _rWindow, const Reference< XForm >& _rxForm )
844 Reference< XInterface > xNormalizedForm( _rxForm, UNO_QUERY_THROW );
846 SdrObjListIter aSdrObjectLoop( _rPage, IM_DEEPNOGROUPS );
847 while ( aSdrObjectLoop.IsMore() )
849 FmFormObj* pFormObject = FmFormObj::GetFormObject( aSdrObjectLoop.Next() );
850 if ( !pFormObject )
851 continue;
853 Reference< XChild > xModel( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW );
854 Reference< XInterface > xModelParent( xModel->getParent(), UNO_QUERY_THROW );
856 if ( xNormalizedForm.get() != xModelParent.get() )
857 continue;
859 pFormObject->GetUnoControl( _rView, _rWindow );
862 catch (const Exception&)
864 DBG_UNHANDLED_EXCEPTION();
870 Reference< XFormController > FmXFormView::getFormController( const Reference< XForm >& _rxForm, const OutputDevice& _rDevice ) const
872 Reference< XFormController > xController;
874 for ( PageWindowAdapterList::const_iterator pos = m_aPageWindowAdapters.begin();
875 pos != m_aPageWindowAdapters.end();
876 ++pos
879 const PFormViewPageWindowAdapter pAdapter( *pos );
880 if ( !pAdapter.get() )
882 SAL_WARN( "svx.form", "FmXFormView::getFormController: invalid page window adapter!" );
883 continue;
886 if ( pAdapter->getWindow() != &_rDevice )
887 // wrong device
888 continue;
890 xController = pAdapter->getController( _rxForm );
891 if ( xController.is() )
892 break;
894 return xController;
898 IMPL_LINK_NOARG(FmXFormView, OnAutoFocus)
900 m_nAutoFocusEvent = 0;
902 // go to the first form of our page, examine it's TabController, go to it's first (in terms of the tab order)
903 // control, give it the focus
908 SdrPageView *pPageView = m_pView ? m_pView->GetSdrPageView() : NULL;
909 SdrPage *pSdrPage = pPageView ? pPageView->GetPage() : NULL;
910 // get the forms collection of the page we belong to
911 FmFormPage* pPage = PTR_CAST( FmFormPage, pSdrPage );
912 Reference< XIndexAccess > xForms( pPage ? Reference< XIndexAccess >( pPage->GetForms(), UNO_QUERY ) : Reference< XIndexAccess >() );
914 const PFormViewPageWindowAdapter pAdapter = m_aPageWindowAdapters.empty() ? NULL : m_aPageWindowAdapters[0];
915 const vcl::Window* pWindow = pAdapter.get() ? pAdapter->getWindow() : NULL;
917 ENSURE_OR_RETURN( xForms.is() && pWindow, "FmXFormView::OnAutoFocus: could not collect all essentials!", 0L );
921 // go for the tab controller of the first form
922 if ( !xForms->getCount() )
923 break;
924 Reference< XForm > xForm( xForms->getByIndex( 0 ), UNO_QUERY_THROW );
925 Reference< XTabController > xTabController( pAdapter->getController( xForm ), UNO_QUERY_THROW );
927 // go for the first control of the controller
928 Sequence< Reference< XControl > > aControls( xTabController->getControls() );
929 if ( aControls.getLength() == 0 )
931 Reference< XElementAccess > xFormElementAccess( xForm, UNO_QUERY_THROW );
932 if (xFormElementAccess->hasElements() && pPage && m_pView)
934 // there are control models in the form, but no controls, yet.
935 // Well, since some time controls are created on demand only. In particular,
936 // they're normally created when they're first painted.
937 // Unfortunately, the FormController does not have any way to
938 // trigger the creation itself, so we must hack this ...
939 lcl_ensureControlsOfFormExist_nothrow( *pPage, *m_pView, *pWindow, xForm );
940 aControls = xTabController->getControls();
941 OSL_ENSURE( aControls.getLength(), "FmXFormView::OnAutoFocus: no controls at all!" );
945 // set the focus to this first control
946 Reference< XWindow > xControlWindow( lcl_firstFocussableControl( aControls ), UNO_QUERY );
947 if ( !xControlWindow.is() )
948 break;
950 xControlWindow->setFocus();
952 // ensure that the control is visible
953 // 80210 - 12/07/00 - FS
954 const vcl::Window* pCurrentWindow = m_pView ? dynamic_cast<const vcl::Window*>(m_pView->GetActualOutDev()) : NULL;
955 if ( pCurrentWindow )
957 awt::Rectangle aRect = xControlWindow->getPosSize();
958 ::Rectangle aNonUnoRect( aRect.X, aRect.Y, aRect.X + aRect.Width, aRect.Y + aRect.Height );
959 m_pView->MakeVisible( pCurrentWindow->PixelToLogic( aNonUnoRect ), *const_cast< vcl::Window* >( pCurrentWindow ) );
962 catch (const Exception&)
964 DBG_UNHANDLED_EXCEPTION();
967 } // do
968 while ( false );
970 return 1L;
974 void FmXFormView::onCreatedFormObject( FmFormObj& _rFormObject )
976 FmFormShell* pShell = m_pView ? m_pView->GetFormShell() : NULL;
977 FmXFormShell* pShellImpl = pShell ? pShell->GetImpl() : NULL;
978 OSL_ENSURE( pShellImpl, "FmXFormView::onCreatedFormObject: no form shell!" );
979 if ( !pShellImpl )
980 return;
982 // it is valid that the form shell's forms collection is not initialized, yet
983 pShellImpl->UpdateForms( true );
985 m_xLastCreatedControlModel.set( _rFormObject.GetUnoControlModel(), UNO_QUERY );
986 if ( !m_xLastCreatedControlModel.is() )
987 return;
989 // some initial property defaults
990 FormControlFactory aControlFactory;
991 aControlFactory.initializeControlModel( pShellImpl->getDocumentType(), _rFormObject );
993 if ( !pShellImpl->GetWizardUsing() )
994 return;
996 // #i31958# don't call wizards in XForms mode
997 if ( pShellImpl->isEnhancedForm() )
998 return;
1000 // #i46898# no wizards if there is no Base installed - currently, all wizards are
1001 // database related
1002 if ( !SvtModuleOptions().IsModuleInstalled( SvtModuleOptions::EModule::DATABASE ) )
1003 return;
1005 if ( m_nControlWizardEvent )
1006 Application::RemoveUserEvent( m_nControlWizardEvent );
1007 m_nControlWizardEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnStartControlWizard ) );
1010 void FmXFormView::breakCreateFormObject()
1012 if (m_nControlWizardEvent != 0)
1014 Application::RemoveUserEvent(m_nControlWizardEvent);
1015 m_nControlWizardEvent = 0;
1017 m_xLastCreatedControlModel.clear();
1020 IMPL_LINK_NOARG( FmXFormView, OnStartControlWizard )
1022 m_nControlWizardEvent = 0;
1023 OSL_PRECOND( m_xLastCreatedControlModel.is(), "FmXFormView::OnStartControlWizard: illegal call!" );
1024 if ( !m_xLastCreatedControlModel.is() )
1025 return 0L;
1027 sal_Int16 nClassId = FormComponentType::CONTROL;
1030 OSL_VERIFY( m_xLastCreatedControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId );
1032 catch (const Exception&)
1034 DBG_UNHANDLED_EXCEPTION();
1037 const sal_Char* pWizardAsciiName = NULL;
1038 switch ( nClassId )
1040 case FormComponentType::GRIDCONTROL:
1041 pWizardAsciiName = "com.sun.star.sdb.GridControlAutoPilot";
1042 break;
1043 case FormComponentType::LISTBOX:
1044 case FormComponentType::COMBOBOX:
1045 pWizardAsciiName = "com.sun.star.sdb.ListComboBoxAutoPilot";
1046 break;
1047 case FormComponentType::GROUPBOX:
1048 pWizardAsciiName = "com.sun.star.sdb.GroupBoxAutoPilot";
1049 break;
1052 if ( pWizardAsciiName )
1054 // build the argument list
1055 ::comphelper::NamedValueCollection aWizardArgs;
1056 aWizardArgs.put( "ObjectModel", m_xLastCreatedControlModel );
1058 // create the wizard object
1059 Reference< XExecutableDialog > xWizard;
1062 Reference<XComponentContext> xContext = comphelper::getProcessComponentContext();
1063 xWizard.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext( OUString::createFromAscii(pWizardAsciiName), aWizardArgs.getWrappedPropertyValues(), xContext ), UNO_QUERY);;
1065 catch (const Exception&)
1067 DBG_UNHANDLED_EXCEPTION();
1070 if ( !xWizard.is() )
1072 ShowServiceNotAvailableError( NULL, OUString::createFromAscii(pWizardAsciiName), true );
1074 else
1076 // execute the wizard
1079 xWizard->execute();
1081 catch (const Exception&)
1083 DBG_UNHANDLED_EXCEPTION();
1088 m_xLastCreatedControlModel.clear();
1089 return 1L;
1093 namespace
1095 void lcl_insertIntoFormComponentHierarchy_throw( const FmFormView& _rView, const SdrUnoObj& _rSdrObj,
1096 const Reference< XDataSource >& _rxDataSource = NULL, const OUString& _rDataSourceName = OUString(),
1097 const OUString& _rCommand = OUString(), const sal_Int32 _nCommandType = -1 )
1099 FmFormPage& rPage = static_cast< FmFormPage& >( *_rView.GetSdrPageView()->GetPage() );
1101 Reference< XFormComponent > xFormComponent( _rSdrObj.GetUnoControlModel(), UNO_QUERY_THROW );
1102 Reference< XForm > xTargetForm(
1103 rPage.GetImpl().findPlaceInFormComponentHierarchy( xFormComponent, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType ),
1104 UNO_SET_THROW );
1106 FmFormPageImpl::setUniqueName( xFormComponent, xTargetForm );
1108 Reference< XIndexContainer > xFormAsContainer( xTargetForm, UNO_QUERY_THROW );
1109 xFormAsContainer->insertByIndex( xFormAsContainer->getCount(), makeAny( xFormComponent ) );
1114 SdrObject* FmXFormView::implCreateFieldControl( const svx::ODataAccessDescriptor& _rColumnDescriptor )
1116 // not if we're in design mode
1117 if ( !m_pView->IsDesignMode() )
1118 return NULL;
1120 OUString sCommand, sFieldName;
1121 sal_Int32 nCommandType = CommandType::COMMAND;
1122 SharedConnection xConnection;
1124 OUString sDataSource = _rColumnDescriptor.getDataSource();
1125 _rColumnDescriptor[ daCommand ] >>= sCommand;
1126 _rColumnDescriptor[ daColumnName ] >>= sFieldName;
1127 _rColumnDescriptor[ daCommandType ] >>= nCommandType;
1129 Reference< XConnection > xExternalConnection;
1130 _rColumnDescriptor[ daConnection ] >>= xExternalConnection;
1131 xConnection.reset( xExternalConnection, SharedConnection::NoTakeOwnership );
1134 if ( sCommand.isEmpty()
1135 || sFieldName.isEmpty()
1136 || ( sDataSource.isEmpty()
1137 && !xConnection.is()
1141 OSL_FAIL( "FmXFormView::implCreateFieldControl: nonsense!" );
1144 Reference< XDataSource > xDataSource;
1145 SQLErrorEvent aError;
1148 if ( xConnection.is() && !xDataSource.is() && sDataSource.isEmpty() )
1150 Reference< XChild > xChild( xConnection, UNO_QUERY );
1151 if ( xChild.is() )
1152 xDataSource.set(xChild->getParent(), css::uno::UNO_QUERY);
1155 // obtain the data source
1156 if ( !xDataSource.is() )
1157 xDataSource = getDataSource( sDataSource, comphelper::getProcessComponentContext() );
1159 // and the connection, if necessary
1160 if ( !xConnection.is() )
1161 xConnection.reset( getConnection_withFeedback(
1162 sDataSource,
1163 OUString(),
1164 OUString(),
1165 comphelper::getProcessComponentContext()
1166 ) );
1168 catch (const SQLException&)
1170 aError.Reason = ::cppu::getCaughtException();
1172 catch (const Exception& )
1174 /* will be asserted below */
1176 if (aError.Reason.hasValue())
1178 displayAsyncErrorMessage( aError );
1179 return NULL;
1182 // need a data source and a connection here
1183 if (!xDataSource.is() || !xConnection.is())
1185 OSL_FAIL("FmXFormView::implCreateFieldControl : could not retrieve the data source or the connection!");
1186 return NULL;
1189 Reference< XComponent > xKeepFieldsAlive;
1190 // go
1193 // determine the table/query field which we should create a control for
1194 Reference< XPropertySet > xField;
1196 Reference< XNameAccess > xFields = getFieldsByCommandDescriptor(
1197 xConnection, nCommandType, sCommand, xKeepFieldsAlive );
1199 if (xFields.is() && xFields->hasByName(sFieldName))
1200 xFields->getByName(sFieldName) >>= xField;
1201 if ( !xField.is() )
1202 return NULL;
1204 Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( xConnection, false ), UNO_SET_THROW );
1205 Reference< XNumberFormats > xNumberFormats( xSupplier->getNumberFormats(), UNO_SET_THROW );
1207 OUString sLabelPostfix;
1210 // nur fuer Textgroesse
1211 OutputDevice* pOutDev = NULL;
1212 if (m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
1213 pOutDev = const_cast<OutputDevice*>(m_pView->GetActualOutDev());
1214 else
1215 {// OutDev suchen
1216 SdrPageView* pPageView = m_pView->GetSdrPageView();
1217 if( pPageView && !pOutDev )
1219 // const SdrPageViewWinList& rWinList = pPageView->GetWinList();
1220 // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows();
1222 for( sal_uInt32 i = 0L; i < pPageView->PageWindowCount(); i++ )
1224 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
1226 if( rPageWindow.GetPaintWindow().OutputToWindow())
1228 pOutDev = &rPageWindow.GetPaintWindow().GetOutputDevice();
1229 break;
1235 if ( !pOutDev )
1236 return NULL;
1238 sal_Int32 nDataType = ::comphelper::getINT32(xField->getPropertyValue(FM_PROP_FIELDTYPE));
1239 if ((DataType::BINARY == nDataType) || (DataType::VARBINARY == nDataType))
1240 return NULL;
1243 // determine the control type by examining the data type of the bound column
1244 sal_uInt16 nOBJID = 0;
1245 bool bDateNTimeField = false;
1247 bool bIsCurrency = false;
1248 if (::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField))
1249 bIsCurrency = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY));
1251 if (bIsCurrency)
1252 nOBJID = OBJ_FM_CURRENCYFIELD;
1253 else
1254 switch (nDataType)
1256 case DataType::BLOB:
1257 case DataType::LONGVARBINARY:
1258 nOBJID = OBJ_FM_IMAGECONTROL;
1259 break;
1260 case DataType::LONGVARCHAR:
1261 case DataType::CLOB:
1262 nOBJID = OBJ_FM_EDIT;
1263 break;
1264 case DataType::BINARY:
1265 case DataType::VARBINARY:
1266 return NULL;
1267 case DataType::BIT:
1268 case DataType::BOOLEAN:
1269 nOBJID = OBJ_FM_CHECKBOX;
1270 break;
1271 case DataType::TINYINT:
1272 case DataType::SMALLINT:
1273 case DataType::INTEGER:
1274 nOBJID = OBJ_FM_NUMERICFIELD;
1275 break;
1276 case DataType::REAL:
1277 case DataType::DOUBLE:
1278 case DataType::NUMERIC:
1279 case DataType::DECIMAL:
1280 nOBJID = OBJ_FM_FORMATTEDFIELD;
1281 break;
1282 case DataType::TIMESTAMP:
1283 bDateNTimeField = true;
1284 sLabelPostfix = SVX_RESSTR(RID_STR_POSTFIX_DATE);
1285 // DON'T break !
1286 case DataType::DATE:
1287 nOBJID = OBJ_FM_DATEFIELD;
1288 break;
1289 case DataType::TIME:
1290 nOBJID = OBJ_FM_TIMEFIELD;
1291 break;
1292 case DataType::CHAR:
1293 case DataType::VARCHAR:
1294 default:
1295 nOBJID = OBJ_FM_EDIT;
1296 break;
1298 if (!nOBJID)
1299 return NULL;
1301 SdrUnoObj* pLabel( NULL );
1302 SdrUnoObj* pControl( NULL );
1303 if ( !createControlLabelPair( *pOutDev, 0, 0, xField, xNumberFormats, nOBJID, sLabelPostfix,
1304 pLabel, pControl, xDataSource, sDataSource, sCommand, nCommandType )
1307 return NULL;
1311 // group objects
1312 bool bCheckbox = ( OBJ_FM_CHECKBOX == nOBJID );
1313 OSL_ENSURE( !bCheckbox || !pLabel, "FmXFormView::implCreateFieldControl: why was there a label created for a check box?" );
1314 if ( bCheckbox )
1315 return pControl;
1317 SdrObjGroup* pGroup = new SdrObjGroup();
1318 SdrObjList* pObjList = pGroup->GetSubList();
1319 pObjList->InsertObject( pLabel );
1320 pObjList->InsertObject( pControl );
1322 if ( bDateNTimeField )
1323 { // so far we created a date field only, but we also need a time field
1324 pLabel = pControl = NULL;
1325 if ( createControlLabelPair( *pOutDev, 0, 1000, xField, xNumberFormats, OBJ_FM_TIMEFIELD,
1326 SVX_RESSTR(RID_STR_POSTFIX_TIME), pLabel, pControl,
1327 xDataSource, sDataSource, sCommand, nCommandType )
1330 pObjList->InsertObject( pLabel );
1331 pObjList->InsertObject( pControl );
1335 return pGroup; // und fertig
1337 catch (const Exception&)
1339 DBG_UNHANDLED_EXCEPTION();
1343 return NULL;
1347 SdrObject* FmXFormView::implCreateXFormsControl( const svx::OXFormsDescriptor &_rDesc )
1349 // not if we're in design mode
1350 if ( !m_pView->IsDesignMode() )
1351 return NULL;
1353 Reference< XComponent > xKeepFieldsAlive;
1355 // go
1358 // determine the table/query field which we should create a control for
1359 Reference< XNumberFormats > xNumberFormats;
1360 OUString sLabelPostfix = _rDesc.szName;
1363 // nur fuer Textgroesse
1364 OutputDevice* pOutDev = NULL;
1365 if (m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)
1366 pOutDev = const_cast<OutputDevice*>(m_pView->GetActualOutDev());
1367 else
1368 {// OutDev suchen
1369 SdrPageView* pPageView = m_pView->GetSdrPageView();
1370 if( pPageView && !pOutDev )
1372 // const SdrPageViewWinList& rWinList = pPageView->GetWinList();
1373 // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows();
1375 for( sal_uInt32 i = 0L; i < pPageView->PageWindowCount(); i++ )
1377 const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i);
1379 if( rPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType() == OUTDEV_WINDOW)
1381 pOutDev = &rPageWindow.GetPaintWindow().GetOutputDevice();
1382 break;
1388 if ( !pOutDev )
1389 return NULL;
1392 // The service name decides which control should be created
1393 sal_uInt16 nOBJID = OBJ_FM_EDIT;
1394 if(OUString(_rDesc.szServiceName) == FM_SUN_COMPONENT_NUMERICFIELD)
1395 nOBJID = OBJ_FM_NUMERICFIELD;
1396 if(OUString(_rDesc.szServiceName) == FM_SUN_COMPONENT_CHECKBOX)
1397 nOBJID = OBJ_FM_CHECKBOX;
1398 if(OUString(_rDesc.szServiceName) == FM_COMPONENT_COMMANDBUTTON)
1399 nOBJID = OBJ_FM_BUTTON;
1401 typedef ::com::sun::star::form::submission::XSubmission XSubmission_t;
1402 Reference< XSubmission_t > xSubmission(_rDesc.xPropSet, UNO_QUERY);
1404 // xform control or submission button?
1405 if ( !xSubmission.is() )
1407 SdrUnoObj* pLabel( NULL );
1408 SdrUnoObj* pControl( NULL );
1409 if ( !createControlLabelPair( *pOutDev, 0, 0, NULL, xNumberFormats, nOBJID, sLabelPostfix,
1410 pLabel, pControl )
1413 return NULL;
1417 // Now build the connection between the control and the data item.
1418 Reference< XValueBinding > xValueBinding(_rDesc.xPropSet,UNO_QUERY);
1419 Reference< XBindableValue > xBindableValue(pControl->GetUnoControlModel(),UNO_QUERY);
1421 DBG_ASSERT( xBindableValue.is(), "FmXFormView::implCreateXFormsControl: control's not bindable!" );
1422 if ( xBindableValue.is() )
1423 xBindableValue->setValueBinding(xValueBinding);
1425 bool bCheckbox = ( OBJ_FM_CHECKBOX == nOBJID );
1426 OSL_ENSURE( !bCheckbox || !pLabel, "FmXFormView::implCreateXFormsControl: why was there a label created for a check box?" );
1427 if ( bCheckbox )
1428 return pControl;
1431 // group objects
1432 SdrObjGroup* pGroup = new SdrObjGroup();
1433 SdrObjList* pObjList = pGroup->GetSubList();
1434 pObjList->InsertObject(pLabel);
1435 pObjList->InsertObject(pControl);
1437 return pGroup;
1439 else {
1441 // create a button control
1442 const MapMode eTargetMode( pOutDev->GetMapMode() );
1443 const MapMode eSourceMode(MAP_100TH_MM);
1444 const sal_uInt16 nObjID = OBJ_FM_BUTTON;
1445 ::Size controlSize(4000, 500);
1446 FmFormObj *pControl = static_cast<FmFormObj*>(SdrObjFactory::MakeNewObject( FmFormInventor, nObjID, NULL, NULL ));
1447 controlSize.Width() = Fraction(controlSize.Width(), 1) * eTargetMode.GetScaleX();
1448 controlSize.Height() = Fraction(controlSize.Height(), 1) * eTargetMode.GetScaleY();
1449 ::Point controlPos( OutputDevice::LogicToLogic( ::Point( controlSize.Width(), 0 ), eSourceMode, eTargetMode ) );
1450 ::Rectangle controlRect( controlPos, OutputDevice::LogicToLogic( controlSize, eSourceMode, eTargetMode ) );
1451 pControl->SetLogicRect(controlRect);
1453 // set the button label
1454 Reference< XPropertySet > xControlSet(pControl->GetUnoControlModel(), UNO_QUERY);
1455 xControlSet->setPropertyValue(FM_PROP_LABEL, makeAny(OUString(_rDesc.szName)));
1457 // connect the submission with the submission supplier (aka the button)
1458 xControlSet->setPropertyValue( FM_PROP_BUTTON_TYPE,
1459 makeAny( FormButtonType_SUBMIT ) );
1460 typedef ::com::sun::star::form::submission::XSubmissionSupplier XSubmissionSupplier_t;
1461 Reference< XSubmissionSupplier_t > xSubmissionSupplier(pControl->GetUnoControlModel(), UNO_QUERY);
1462 xSubmissionSupplier->setSubmission(xSubmission);
1464 return pControl;
1467 catch (const Exception&)
1469 OSL_FAIL("FmXFormView::implCreateXFormsControl: caught an exception while creating the control !");
1473 return NULL;
1477 bool FmXFormView::createControlLabelPair( OutputDevice& _rOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM,
1478 const Reference< XPropertySet >& _rxField, const Reference< XNumberFormats >& _rxNumberFormats,
1479 sal_uInt16 _nControlObjectID, const OUString& _rFieldPostfix,
1480 SdrUnoObj*& _rpLabel, SdrUnoObj*& _rpControl,
1481 const Reference< XDataSource >& _rxDataSource, const OUString& _rDataSourceName,
1482 const OUString& _rCommand, const sal_Int32 _nCommandType )
1484 if ( !createControlLabelPair( _rOutDev, _nXOffsetMM, _nYOffsetMM,
1485 _rxField, _rxNumberFormats, _nControlObjectID, _rFieldPostfix, FmFormInventor, OBJ_FM_FIXEDTEXT,
1486 NULL, NULL, NULL, _rpLabel, _rpControl )
1488 return false;
1490 // insert the control model(s) into the form component hierarchy
1491 if ( _rpLabel )
1492 lcl_insertIntoFormComponentHierarchy_throw( *m_pView, *_rpLabel, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType );
1493 lcl_insertIntoFormComponentHierarchy_throw( *m_pView, *_rpControl, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType );
1495 // some context-dependent initializations
1496 FormControlFactory aControlFactory;
1497 if ( _rpLabel )
1498 aControlFactory.initializeControlModel( impl_getDocumentType(), *_rpLabel );
1499 aControlFactory.initializeControlModel( impl_getDocumentType(), *_rpControl );
1501 return true;
1505 bool FmXFormView::createControlLabelPair( OutputDevice& _rOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM,
1506 const Reference< XPropertySet >& _rxField,
1507 const Reference< XNumberFormats >& _rxNumberFormats, sal_uInt16 _nControlObjectID,
1508 const OUString& _rFieldPostfix, sal_uInt32 _nInventor, sal_uInt16 _nLabelObjectID,
1509 SdrPage* _pLabelPage, SdrPage* _pControlPage, SdrModel* _pModel, SdrUnoObj*& _rpLabel, SdrUnoObj*& _rpControl)
1511 sal_Int32 nDataType = 0;
1512 OUString sFieldName;
1513 Any aFieldName;
1514 if ( _rxField.is() )
1516 nDataType = ::comphelper::getINT32(_rxField->getPropertyValue(FM_PROP_FIELDTYPE));
1517 aFieldName = Any(_rxField->getPropertyValue(FM_PROP_NAME));
1518 aFieldName >>= sFieldName;
1521 // calculate the positions, respecting the settings of the target device
1522 ::Size aTextSize( _rOutDev.GetTextWidth(sFieldName + _rFieldPostfix), _rOutDev.GetTextHeight() );
1524 MapMode eTargetMode( _rOutDev.GetMapMode() ),
1525 eSourceMode( MAP_100TH_MM );
1527 // Textbreite ist mindestens 4cm
1528 // Texthoehe immer halber cm
1529 ::Size aDefTxtSize(4000, 500);
1530 ::Size aDefSize(4000, 500);
1531 ::Size aDefImageSize(4000, 4000);
1533 ::Size aRealSize = OutputDevice::LogicToLogic(aTextSize, eTargetMode, eSourceMode);
1534 aRealSize.Width() = std::max(aRealSize.Width(), aDefTxtSize.Width());
1535 aRealSize.Height()= aDefSize.Height();
1537 // adjust to scaling of the target device (#53523#)
1538 aRealSize.Width() = long(Fraction(aRealSize.Width(), 1) * eTargetMode.GetScaleX());
1539 aRealSize.Height() = long(Fraction(aRealSize.Height(), 1) * eTargetMode.GetScaleY());
1541 // for boolean fields, we do not create a label, but just a checkbox
1542 bool bNeedLabel = ( _nControlObjectID != OBJ_FM_CHECKBOX );
1544 // the label
1545 ::std::unique_ptr< SdrUnoObj > pLabel;
1546 Reference< XPropertySet > xLabelModel;
1547 if ( bNeedLabel )
1549 pLabel.reset( dynamic_cast< SdrUnoObj* >(
1550 SdrObjFactory::MakeNewObject( _nInventor, _nLabelObjectID, _pLabelPage, _pModel ) ) );
1551 OSL_ENSURE( pLabel.get(), "FmXFormView::createControlLabelPair: could not create the label!" );
1552 if ( !pLabel.get() )
1553 return false;
1555 xLabelModel.set( pLabel->GetUnoControlModel(), UNO_QUERY );
1556 if ( xLabelModel.is() )
1558 OUString sLabel;
1559 if ( _rxField.is() && _rxField->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) )
1560 _rxField->getPropertyValue(FM_PROP_LABEL) >>= sLabel;
1561 if ( sLabel.isEmpty() )
1562 sLabel = sFieldName;
1564 xLabelModel->setPropertyValue( FM_PROP_LABEL, makeAny( sLabel + _rFieldPostfix ) );
1565 OUString sObjectLabel(SVX_RESSTR(RID_STR_OBJECT_LABEL).replaceAll("#object#", sFieldName));
1566 xLabelModel->setPropertyValue(FM_PROP_NAME, makeAny(sObjectLabel));
1569 pLabel->SetLogicRect( ::Rectangle(
1570 OutputDevice::LogicToLogic( ::Point( _nXOffsetMM, _nYOffsetMM ), eSourceMode, eTargetMode ),
1571 OutputDevice::LogicToLogic( aRealSize, eSourceMode, eTargetMode )
1572 ) );
1575 // the control
1576 ::std::unique_ptr< SdrUnoObj > pControl( dynamic_cast< SdrUnoObj* >(
1577 SdrObjFactory::MakeNewObject( _nInventor, _nControlObjectID, _pControlPage, _pModel ) ) );
1578 OSL_ENSURE( pControl.get(), "FmXFormView::createControlLabelPair: could not create the control!" );
1579 if ( !pControl.get() )
1580 return false;
1582 Reference< XPropertySet > xControlSet( pControl->GetUnoControlModel(), UNO_QUERY );
1583 if ( !xControlSet.is() )
1584 return false;
1586 // size of the control
1587 ::Size aControlSize( aDefSize );
1588 switch ( nDataType )
1590 case DataType::BIT:
1591 case DataType::BOOLEAN:
1592 aControlSize = aDefSize;
1593 break;
1594 case DataType::LONGVARCHAR:
1595 case DataType::CLOB:
1596 case DataType::LONGVARBINARY:
1597 case DataType::BLOB:
1598 aControlSize = aDefImageSize;
1599 break;
1602 if ( OBJ_FM_IMAGECONTROL == _nControlObjectID )
1603 aControlSize = aDefImageSize;
1605 aControlSize.Width() = long(Fraction(aControlSize.Width(), 1) * eTargetMode.GetScaleX());
1606 aControlSize.Height() = long(Fraction(aControlSize.Height(), 1) * eTargetMode.GetScaleY());
1608 pControl->SetLogicRect( ::Rectangle(
1609 OutputDevice::LogicToLogic( ::Point( aRealSize.Width() + _nXOffsetMM, _nYOffsetMM ), eSourceMode, eTargetMode ),
1610 OutputDevice::LogicToLogic( aControlSize, eSourceMode, eTargetMode )
1611 ) );
1613 // some initializations
1614 Reference< XPropertySetInfo > xControlPropInfo = xControlSet->getPropertySetInfo();
1616 if ( aFieldName.hasValue() )
1618 xControlSet->setPropertyValue( FM_PROP_CONTROLSOURCE, aFieldName );
1619 xControlSet->setPropertyValue( FM_PROP_NAME, aFieldName );
1620 if ( !bNeedLabel )
1622 // no dedicated label control => use the label property
1623 if ( xControlPropInfo->hasPropertyByName( FM_PROP_LABEL ) )
1624 xControlSet->setPropertyValue( FM_PROP_LABEL, makeAny( sFieldName + _rFieldPostfix ) );
1625 else
1626 OSL_FAIL( "FmXFormView::createControlLabelPair: can't set a label for the control!" );
1630 if ( (nDataType == DataType::LONGVARCHAR || nDataType == DataType::CLOB) && xControlPropInfo->hasPropertyByName( FM_PROP_MULTILINE ) )
1632 xControlSet->setPropertyValue( FM_PROP_MULTILINE, makeAny( true ) );
1635 // announce the label to the control
1636 if ( xControlPropInfo->hasPropertyByName( FM_PROP_CONTROLLABEL ) && xLabelModel.is() )
1640 xControlSet->setPropertyValue( FM_PROP_CONTROLLABEL, makeAny( xLabelModel ) );
1642 catch (const Exception&)
1644 DBG_UNHANDLED_EXCEPTION();
1648 if ( _rxField.is() )
1650 FormControlFactory::initializeFieldDependentProperties( _rxField, xControlSet, _rxNumberFormats );
1653 _rpLabel = pLabel.release();
1654 _rpControl = pControl.release();
1655 return true;
1659 FmXFormView::ObjectRemoveListener::ObjectRemoveListener( FmXFormView* pParent )
1660 :m_pParent( pParent )
1665 void FmXFormView::ObjectRemoveListener::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
1667 const SdrHint* pSdrHint = dynamic_cast<const SdrHint*>(&rHint);
1668 if (pSdrHint && pSdrHint->GetKind() == HINT_OBJREMOVED)
1669 m_pParent->ObjectRemovedInAliveMode(pSdrHint->GetObject());
1673 void FmXFormView::ObjectRemovedInAliveMode( const SdrObject* pObject )
1675 // wenn das entfernte Objekt in meiner MarkList, die ich mir beim Umschalten in den Alive-Mode gemerkt habe, steht,
1676 // muss ich es jetzt da rausnehmen, da ich sonst beim Zurueckschalten versuche, die Markierung wieder zu setzen
1677 // (interesanterweise geht das nur bei gruppierten Objekten schief (beim Zugriff auf deren ObjList GPF), nicht bei einzelnen)
1679 const size_t nCount = m_aMark.GetMarkCount();
1680 for (size_t i = 0; i < nCount; ++i)
1682 SdrMark* pMark = m_aMark.GetMark(i);
1683 SdrObject* pCurrent = pMark->GetMarkedSdrObj();
1684 if (pObject == pCurrent)
1686 m_aMark.DeleteMark(i);
1687 return;
1689 // ich brauche nicht in GroupObjects absteigen : wenn dort unten ein Objekt geloescht wird, dann bleibt der
1690 // Zeiger auf das GroupObject, den ich habe, trotzdem weiter gueltig bleibt ...
1695 void FmXFormView::stopMarkListWatching()
1697 if ( m_pWatchStoredList )
1699 m_pWatchStoredList->EndListeningAll();
1700 delete m_pWatchStoredList;
1701 m_pWatchStoredList = NULL;
1706 void FmXFormView::startMarkListWatching()
1708 if ( !m_pWatchStoredList )
1710 FmFormModel* pModel = GetFormShell() ? GetFormShell()->GetFormModel() : NULL;
1711 DBG_ASSERT( pModel != NULL, "FmXFormView::startMarkListWatching: shell has no model!" );
1712 if (pModel)
1714 m_pWatchStoredList = new ObjectRemoveListener( this );
1715 m_pWatchStoredList->StartListening( *static_cast< SfxBroadcaster* >( pModel ) );
1718 else
1720 OSL_FAIL( "FmXFormView::startMarkListWatching: already listening!" );
1725 void FmXFormView::saveMarkList( bool _bSmartUnmark )
1727 if ( m_pView )
1729 m_aMark = m_pView->GetMarkedObjectList();
1730 if ( _bSmartUnmark )
1732 const size_t nCount = m_aMark.GetMarkCount( );
1733 for ( size_t i = 0; i < nCount; ++i )
1735 SdrMark* pMark = m_aMark.GetMark(i);
1736 SdrObject* pObj = pMark->GetMarkedSdrObj();
1738 if ( m_pView->IsObjMarked( pObj ) )
1740 if ( pObj->IsGroupObject() )
1742 SdrObjListIter aIter( *pObj->GetSubList() );
1743 bool bMixed = false;
1744 while ( aIter.IsMore() && !bMixed )
1745 bMixed = ( aIter.Next()->GetObjInventor() != FmFormInventor );
1747 if ( !bMixed )
1749 // all objects in the group are form objects
1750 m_pView->MarkObj( pMark->GetMarkedSdrObj(), pMark->GetPageView(), true /* unmark! */ );
1753 else
1755 if ( pObj->GetObjInventor() == FmFormInventor )
1756 { // this is a form layer object
1757 m_pView->MarkObj( pMark->GetMarkedSdrObj(), pMark->GetPageView(), true /* unmark! */ );
1764 else
1766 OSL_FAIL( "FmXFormView::saveMarkList: invalid view!" );
1767 m_aMark = SdrMarkList();
1772 static bool lcl_hasObject( SdrObjListIter& rIter, SdrObject* pObj )
1774 bool bFound = false;
1775 while (rIter.IsMore() && !bFound)
1776 bFound = pObj == rIter.Next();
1778 rIter.Reset();
1779 return bFound;
1783 void FmXFormView::restoreMarkList( SdrMarkList& _rRestoredMarkList )
1785 if ( !m_pView )
1786 return;
1788 _rRestoredMarkList.Clear();
1790 const SdrMarkList& rCurrentList = m_pView->GetMarkedObjectList();
1791 FmFormPage* pPage = GetFormShell() ? GetFormShell()->GetCurPage() : NULL;
1792 if (pPage)
1794 if (rCurrentList.GetMarkCount())
1795 { // there is a current mark ... hmm. Is it a subset of the mark we remembered in saveMarkList?
1796 bool bMisMatch = false;
1798 // loop through all current marks
1799 const size_t nCurrentCount = rCurrentList.GetMarkCount();
1800 for ( size_t i=0; i<nCurrentCount && !bMisMatch; ++i )
1802 const SdrObject* pCurrentMarked = rCurrentList.GetMark( i )->GetMarkedSdrObj();
1804 // loop through all saved marks, check for equality
1805 bool bFound = false;
1806 const size_t nSavedCount = m_aMark.GetMarkCount();
1807 for ( size_t j=0; j<nSavedCount && !bFound; ++j )
1809 if ( m_aMark.GetMark( j )->GetMarkedSdrObj() == pCurrentMarked )
1810 bFound = true;
1813 // did not find a current mark in the saved marks
1814 if ( !bFound )
1815 bMisMatch = true;
1818 if ( bMisMatch )
1820 m_aMark.Clear();
1821 _rRestoredMarkList = rCurrentList;
1822 return;
1825 // wichtig ist das auf die Objecte der markliste nicht zugegriffen wird
1826 // da diese bereits zerstoert sein koennen
1827 SdrPageView* pCurPageView = m_pView->GetSdrPageView();
1828 SdrObjListIter aPageIter( *pPage );
1829 bool bFound = true;
1831 // gibt es noch alle Objecte
1832 const size_t nCount = m_aMark.GetMarkCount();
1833 for (size_t i = 0; i < nCount && bFound; ++i)
1835 SdrMark* pMark = m_aMark.GetMark(i);
1836 SdrObject* pObj = pMark->GetMarkedSdrObj();
1837 if (pObj->IsGroupObject())
1839 SdrObjListIter aIter(*pObj->GetSubList());
1840 while (aIter.IsMore() && bFound)
1841 bFound = lcl_hasObject(aPageIter, aIter.Next());
1843 else
1844 bFound = lcl_hasObject(aPageIter, pObj);
1846 bFound = bFound && pCurPageView == pMark->GetPageView();
1849 if (bFound)
1851 // Das LastObject auswerten
1852 if (nCount) // Objecte jetzt Markieren
1854 for (size_t i = 0; i < nCount; ++i)
1856 SdrMark* pMark = m_aMark.GetMark(i);
1857 SdrObject* pObj = pMark->GetMarkedSdrObj();
1858 if ( pObj->GetObjInventor() == FmFormInventor )
1859 if ( !m_pView->IsObjMarked( pObj ) )
1860 m_pView->MarkObj( pObj, pMark->GetPageView() );
1863 _rRestoredMarkList = m_aMark;
1866 m_aMark.Clear();
1870 void SAL_CALL FmXFormView::focusGained( const FocusEvent& /*e*/ ) throw (RuntimeException, std::exception)
1872 if ( m_xWindow.is() && m_pView )
1874 m_pView->SetMoveOutside( true, FmFormView::ImplAccess() );
1878 void SAL_CALL FmXFormView::focusLost( const FocusEvent& /*e*/ ) throw (RuntimeException, std::exception)
1880 // when switch the focus outside the office the mark didn't change
1881 // so we can not remove us as focus listener
1882 if ( m_xWindow.is() && m_pView )
1884 m_pView->SetMoveOutside( false, FmFormView::ImplAccess() );
1888 void FmXFormView::removeGridWindowListening()
1890 if ( m_xWindow.is() )
1892 m_xWindow->removeFocusListener(this);
1893 if ( m_pView )
1895 m_pView->SetMoveOutside( false, FmFormView::ImplAccess() );
1897 m_xWindow = NULL;
1902 DocumentType FmXFormView::impl_getDocumentType() const
1904 if ( GetFormShell() && GetFormShell()->GetImpl() )
1905 return GetFormShell()->GetImpl()->getDocumentType();
1906 return eUnknownDocumentType;
1909 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */