/src/libreoffice/svx/source/form/fmvwimp.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | |
21 | | #include <memory> |
22 | | #include <fmdocumentclassification.hxx> |
23 | | #include <fmobj.hxx> |
24 | | #include <fmpgeimp.hxx> |
25 | | #include <fmprop.hxx> |
26 | | #include <svx/strings.hrc> |
27 | | #include <fmservs.hxx> |
28 | | #include <fmshimp.hxx> |
29 | | #include <svx/fmtools.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/svdobjkind.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> |
45 | | #include <toolkit/helper/vclunohelper.hxx> |
46 | | |
47 | | #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> |
48 | | #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> |
49 | | #include <com/sun/star/sdbc/XRowSet.hpp> |
50 | | #include <com/sun/star/util/XNumberFormatsSupplier.hpp> |
51 | | #include <com/sun/star/util/XNumberFormats.hpp> |
52 | | #include <com/sun/star/sdb/CommandType.hpp> |
53 | | #include <com/sun/star/sdbc/DataType.hpp> |
54 | | #include <com/sun/star/form/FormComponentType.hpp> |
55 | | #include <com/sun/star/form/FormButtonType.hpp> |
56 | | #include <com/sun/star/form/binding/XBindableValue.hpp> |
57 | | #include <com/sun/star/form/binding/XValueBinding.hpp> |
58 | | #include <com/sun/star/form/runtime/FormController.hpp> |
59 | | #include <com/sun/star/form/submission/XSubmissionSupplier.hpp> |
60 | | #include <com/sun/star/awt/XTabControllerModel.hpp> |
61 | | #include <com/sun/star/awt/XControlContainer.hpp> |
62 | | #include <com/sun/star/awt/XTabController.hpp> |
63 | | #include <com/sun/star/container/XIndexAccess.hpp> |
64 | | #include <com/sun/star/awt/XControl.hpp> |
65 | | #include <com/sun/star/sdbc/SQLException.hpp> |
66 | | #include <com/sun/star/container/XContainer.hpp> |
67 | | |
68 | | #include <comphelper/namedvaluecollection.hxx> |
69 | | #include <comphelper/property.hxx> |
70 | | #include <comphelper/processfactory.hxx> |
71 | | #include <comphelper/types.hxx> |
72 | | #include <cppuhelper/exc_hlp.hxx> |
73 | | #include <unotools/moduleoptions.hxx> |
74 | | #include <tools/debug.hxx> |
75 | | #include <comphelper/diagnose_ex.hxx> |
76 | | #include <sal/log.hxx> |
77 | | #include <utility> |
78 | | #include <vcl/svapp.hxx> |
79 | | #include <vcl/stdtext.hxx> |
80 | | #include <vcl/window.hxx> |
81 | | #include <connectivity/dbtools.hxx> |
82 | | |
83 | | #include <algorithm> |
84 | | |
85 | | using namespace ::comphelper; |
86 | | using namespace ::svx; |
87 | | using namespace ::svxform; |
88 | | using namespace ::dbtools; |
89 | | |
90 | | using namespace ::com::sun::star; |
91 | | using ::com::sun::star::uno::Exception; |
92 | | using ::com::sun::star::uno::XInterface; |
93 | | using ::com::sun::star::uno::Sequence; |
94 | | using ::com::sun::star::uno::UNO_QUERY; |
95 | | using ::com::sun::star::uno::UNO_QUERY_THROW; |
96 | | using ::com::sun::star::uno::UNO_SET_THROW; |
97 | | using ::com::sun::star::uno::Type; |
98 | | using ::com::sun::star::uno::Reference; |
99 | | using ::com::sun::star::uno::Any; |
100 | | using ::com::sun::star::uno::XComponentContext; |
101 | | using ::com::sun::star::form::FormButtonType_SUBMIT; |
102 | | using ::com::sun::star::form::binding::XValueBinding; |
103 | | using ::com::sun::star::form::binding::XBindableValue; |
104 | | using ::com::sun::star::lang::XComponent; |
105 | | using ::com::sun::star::container::XIndexAccess; |
106 | | using ::com::sun::star::form::runtime::FormController; |
107 | | using ::com::sun::star::form::runtime::XFormController; |
108 | | using ::com::sun::star::script::XEventAttacherManager; |
109 | | using ::com::sun::star::awt::XTabControllerModel; |
110 | | using ::com::sun::star::container::XChild; |
111 | | using ::com::sun::star::task::XInteractionHandler; |
112 | | using ::com::sun::star::awt::XTabController; |
113 | | using ::com::sun::star::awt::XControlContainer; |
114 | | using ::com::sun::star::awt::XControl; |
115 | | using ::com::sun::star::form::XFormComponent; |
116 | | using ::com::sun::star::form::XForm; |
117 | | using ::com::sun::star::lang::IndexOutOfBoundsException; |
118 | | using ::com::sun::star::container::XContainer; |
119 | | using ::com::sun::star::container::ContainerEvent; |
120 | | using ::com::sun::star::lang::EventObject; |
121 | | using ::com::sun::star::sdb::SQLErrorEvent; |
122 | | using ::com::sun::star::sdbc::XRowSet; |
123 | | using ::com::sun::star::beans::XPropertySet; |
124 | | using ::com::sun::star::container::XElementAccess; |
125 | | using ::com::sun::star::awt::XWindow; |
126 | | using ::com::sun::star::awt::FocusEvent; |
127 | | using ::com::sun::star::ui::dialogs::XExecutableDialog; |
128 | | using ::com::sun::star::sdbc::XDataSource; |
129 | | using ::com::sun::star::container::XIndexContainer; |
130 | | using ::com::sun::star::sdbc::XConnection; |
131 | | using ::com::sun::star::container::XNameAccess; |
132 | | using ::com::sun::star::sdbc::SQLException; |
133 | | using ::com::sun::star::util::XNumberFormatsSupplier; |
134 | | using ::com::sun::star::util::XNumberFormats; |
135 | | using ::com::sun::star::beans::XPropertySetInfo; |
136 | | |
137 | | namespace FormComponentType = ::com::sun::star::form::FormComponentType; |
138 | | namespace CommandType = ::com::sun::star::sdb::CommandType; |
139 | | namespace DataType = ::com::sun::star::sdbc::DataType; |
140 | | |
141 | | |
142 | | class FmXFormView::ObjectRemoveListener : public SfxListener |
143 | | { |
144 | | FmXFormView* m_pParent; |
145 | | public: |
146 | | explicit ObjectRemoveListener( FmXFormView* pParent ); |
147 | | virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; |
148 | | }; |
149 | | |
150 | | FormViewPageWindowAdapter::FormViewPageWindowAdapter( css::uno::Reference<css::uno::XComponentContext> _xContext, const SdrPageWindow& _rWindow, FmXFormView* _pViewImpl ) |
151 | 30 | : m_xControlContainer( _rWindow.GetControlContainer() ), |
152 | 30 | m_xContext(std::move( _xContext )), |
153 | 30 | m_pViewImpl( _pViewImpl ), |
154 | 30 | m_pWindow( _rWindow.GetPaintWindow().GetOutputDevice().GetOwnerWindow() ) |
155 | 30 | { |
156 | | |
157 | | // create an XFormController for every form |
158 | 30 | FmFormPage* pFormPage = dynamic_cast< FmFormPage* >( _rWindow.GetPageView().GetPage() ); |
159 | 30 | DBG_ASSERT( pFormPage, "FormViewPageWindowAdapter::FormViewPageWindowAdapter: no FmFormPage found!" ); |
160 | 30 | if ( !pFormPage ) |
161 | 0 | return; |
162 | | |
163 | 30 | try |
164 | 30 | { |
165 | 30 | Reference< XIndexAccess > xForms( pFormPage->GetForms(), UNO_QUERY_THROW ); |
166 | 30 | sal_uInt32 nLength = xForms->getCount(); |
167 | 30 | for (sal_uInt32 i = 0; i < nLength; i++) |
168 | 0 | { |
169 | 0 | Reference< XForm > xForm( xForms->getByIndex(i), UNO_QUERY ); |
170 | 0 | if ( xForm.is() ) |
171 | 0 | setController( xForm, nullptr ); |
172 | 0 | } |
173 | 30 | } |
174 | 30 | catch (const Exception&) |
175 | 30 | { |
176 | 30 | DBG_UNHANDLED_EXCEPTION("svx"); |
177 | 30 | } |
178 | 30 | } |
179 | | |
180 | | FormViewPageWindowAdapter::~FormViewPageWindowAdapter() |
181 | 30 | { |
182 | 30 | } |
183 | | |
184 | | void FormViewPageWindowAdapter::dispose() |
185 | 30 | { |
186 | 30 | for ( ::std::vector< Reference< XFormController > >::const_iterator i = m_aControllerList.begin(); |
187 | 30 | i != m_aControllerList.end(); |
188 | 30 | ++i |
189 | 30 | ) |
190 | 0 | { |
191 | 0 | try |
192 | 0 | { |
193 | 0 | Reference< XFormController > xController( *i, UNO_SET_THROW ); |
194 | | |
195 | | // detaching the events |
196 | 0 | Reference< XChild > xControllerModel( xController->getModel(), UNO_QUERY ); |
197 | 0 | if ( xControllerModel.is() ) |
198 | 0 | { |
199 | 0 | Reference< XEventAttacherManager > xEventManager( xControllerModel->getParent(), UNO_QUERY_THROW ); |
200 | 0 | Reference< XInterface > xControllerNormalized( xController, UNO_QUERY_THROW ); |
201 | 0 | xEventManager->detach( i - m_aControllerList.begin(), xControllerNormalized ); |
202 | 0 | } |
203 | | |
204 | | // dispose the formcontroller |
205 | 0 | xController->dispose(); |
206 | 0 | } |
207 | 0 | catch (const Exception&) |
208 | 0 | { |
209 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
210 | 0 | } |
211 | 0 | } |
212 | | |
213 | 30 | m_aControllerList.clear(); |
214 | 30 | } |
215 | | |
216 | | sal_Bool SAL_CALL FormViewPageWindowAdapter::hasElements() |
217 | 0 | { |
218 | 0 | return getCount() != 0; |
219 | 0 | } |
220 | | |
221 | | Type SAL_CALL FormViewPageWindowAdapter::getElementType() |
222 | 0 | { |
223 | 0 | return cppu::UnoType<XFormController>::get(); |
224 | 0 | } |
225 | | |
226 | | // XIndexAccess |
227 | | sal_Int32 SAL_CALL FormViewPageWindowAdapter::getCount() |
228 | 0 | { |
229 | 0 | return m_aControllerList.size(); |
230 | 0 | } |
231 | | |
232 | | Any SAL_CALL FormViewPageWindowAdapter::getByIndex(sal_Int32 nIndex) |
233 | 0 | { |
234 | 0 | if (nIndex < 0 || |
235 | 0 | nIndex >= getCount()) |
236 | 0 | throw IndexOutOfBoundsException(); |
237 | | |
238 | 0 | Any aElement; |
239 | 0 | aElement <<= m_aControllerList[nIndex]; |
240 | 0 | return aElement; |
241 | 0 | } |
242 | | |
243 | | void SAL_CALL FormViewPageWindowAdapter::makeVisible( const Reference< XControl >& Control ) |
244 | 0 | { |
245 | 0 | SolarMutexGuard aSolarGuard; |
246 | |
|
247 | 0 | Reference< XWindow > xWindow( Control, UNO_QUERY ); |
248 | 0 | if ( xWindow.is() && m_pViewImpl->getView() && m_pWindow ) |
249 | 0 | { |
250 | 0 | awt::Rectangle aRect = xWindow->getPosSize(); |
251 | 0 | ::tools::Rectangle aNewRect( aRect.X, aRect.Y, aRect.X + aRect.Width, aRect.Y + aRect.Height ); |
252 | 0 | aNewRect = m_pWindow->PixelToLogic( aNewRect ); |
253 | 0 | m_pViewImpl->getView()->MakeVisible( aNewRect, *m_pWindow ); |
254 | 0 | } |
255 | 0 | } |
256 | | |
257 | | static Reference< XFormController > getControllerSearchChildren( const Reference< XIndexAccess > & xIndex, const Reference< XTabControllerModel > & xModel) |
258 | 0 | { |
259 | 0 | if (xIndex.is() && xIndex->getCount()) |
260 | 0 | { |
261 | 0 | Reference< XFormController > xController; |
262 | |
|
263 | 0 | for (sal_Int32 n = xIndex->getCount(); n-- && !xController.is(); ) |
264 | 0 | { |
265 | 0 | xIndex->getByIndex(n) >>= xController; |
266 | 0 | if (xModel.get() == xController->getModel().get()) |
267 | 0 | return xController; |
268 | 0 | else |
269 | 0 | { |
270 | 0 | xController = getControllerSearchChildren(xController, xModel); |
271 | 0 | if ( xController.is() ) |
272 | 0 | return xController; |
273 | 0 | } |
274 | 0 | } |
275 | 0 | } |
276 | 0 | return Reference< XFormController > (); |
277 | 0 | } |
278 | | |
279 | | // Search the according controller |
280 | | Reference< XFormController > FormViewPageWindowAdapter::getController( const Reference< XForm > & xForm ) const |
281 | 0 | { |
282 | 0 | Reference< XTabControllerModel > xModel(xForm, UNO_QUERY); |
283 | 0 | for (const auto& rpController : m_aControllerList) |
284 | 0 | { |
285 | 0 | if (rpController->getModel().get() == xModel.get()) |
286 | 0 | return rpController; |
287 | | |
288 | | // the current-round controller isn't the right one. perhaps one of its children ? |
289 | 0 | Reference< XFormController > xChildSearch = getControllerSearchChildren(Reference< XIndexAccess > (rpController, UNO_QUERY), xModel); |
290 | 0 | if (xChildSearch.is()) |
291 | 0 | return xChildSearch; |
292 | 0 | } |
293 | 0 | return Reference< XFormController > (); |
294 | 0 | } |
295 | | |
296 | | |
297 | | void FormViewPageWindowAdapter::setController(const Reference< XForm > & xForm, const Reference< XFormController >& _rxParentController ) |
298 | 0 | { |
299 | 0 | DBG_ASSERT( xForm.is(), "FormViewPageWindowAdapter::setController: there should be a form!" ); |
300 | 0 | Reference< XIndexAccess > xFormCps(xForm, UNO_QUERY); |
301 | 0 | if (!xFormCps.is()) |
302 | 0 | return; |
303 | | |
304 | 0 | Reference< XTabControllerModel > xTabOrder(xForm, UNO_QUERY); |
305 | | |
306 | | // create a form controller |
307 | 0 | Reference< XFormController > xController( FormController::create(m_xContext) ); |
308 | |
|
309 | 0 | Reference< XInteractionHandler > xHandler; |
310 | 0 | if ( _rxParentController.is() ) |
311 | 0 | xHandler = _rxParentController->getInteractionHandler(); |
312 | 0 | else |
313 | 0 | { |
314 | | // TODO: should we create a default handler? Not really necessary, since the |
315 | | // FormController itself has a default fallback |
316 | 0 | } |
317 | 0 | if ( xHandler.is() ) |
318 | 0 | xController->setInteractionHandler( xHandler ); |
319 | |
|
320 | 0 | xController->setContext( this ); |
321 | |
|
322 | 0 | xController->setModel( xTabOrder ); |
323 | 0 | xController->setContainer( m_xControlContainer ); |
324 | 0 | xController->activateTabOrder(); |
325 | 0 | xController->addActivateListener( m_pViewImpl ); |
326 | |
|
327 | 0 | if ( _rxParentController.is() ) |
328 | 0 | _rxParentController->addChildController( xController ); |
329 | 0 | else |
330 | 0 | { |
331 | 0 | m_aControllerList.push_back(xController); |
332 | |
|
333 | 0 | xController->setParent( *this ); |
334 | | |
335 | | // attaching the events |
336 | 0 | Reference< XEventAttacherManager > xEventManager( xForm->getParent(), UNO_QUERY ); |
337 | 0 | xEventManager->attach(m_aControllerList.size() - 1, Reference<XInterface>( xController, UNO_QUERY ), Any(xController) ); |
338 | 0 | } |
339 | | |
340 | | // now go through the subforms |
341 | 0 | sal_uInt32 nLength = xFormCps->getCount(); |
342 | 0 | Reference< XForm > xSubForm; |
343 | 0 | for (sal_uInt32 i = 0; i < nLength; i++) |
344 | 0 | { |
345 | 0 | if ( xFormCps->getByIndex(i) >>= xSubForm ) |
346 | 0 | setController( xSubForm, xController ); |
347 | 0 | } |
348 | 0 | } |
349 | | |
350 | | |
351 | | void FormViewPageWindowAdapter::updateTabOrder( const Reference< XForm >& _rxForm ) |
352 | 0 | { |
353 | 0 | OSL_PRECOND( _rxForm.is(), "FormViewPageWindowAdapter::updateTabOrder: illegal argument!" ); |
354 | 0 | if ( !_rxForm.is() ) |
355 | 0 | return; |
356 | | |
357 | 0 | try |
358 | 0 | { |
359 | 0 | Reference< XTabController > xTabCtrl( getController( _rxForm ) ); |
360 | 0 | if ( xTabCtrl.is() ) |
361 | 0 | { // if there already is a TabController for this form, then delegate the "updateTabOrder" request |
362 | 0 | xTabCtrl->activateTabOrder(); |
363 | 0 | } |
364 | 0 | else |
365 | 0 | { // otherwise, create a TabController |
366 | | |
367 | | // if it's a sub form, then we must ensure there exist TabControllers |
368 | | // for all its ancestors, too |
369 | 0 | Reference< XForm > xParentForm( _rxForm->getParent(), UNO_QUERY ); |
370 | | // there is a parent form -> look for the respective controller |
371 | 0 | Reference< XFormController > xParentController; |
372 | 0 | if ( xParentForm.is() ) |
373 | 0 | xParentController = getController( xParentForm ); |
374 | |
|
375 | 0 | setController( _rxForm, xParentController ); |
376 | 0 | } |
377 | 0 | } |
378 | 0 | catch (const Exception&) |
379 | 0 | { |
380 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
381 | 0 | } |
382 | 0 | } |
383 | | |
384 | | |
385 | | FmXFormView::FmXFormView(FmFormView* _pView ) |
386 | 87.9k | :m_pMarkedGrid(nullptr) |
387 | 87.9k | ,m_pView(_pView) |
388 | 87.9k | ,m_nActivationEvent(nullptr) |
389 | 87.9k | ,m_nErrorMessageEvent( nullptr ) |
390 | 87.9k | ,m_nAutoFocusEvent( nullptr ) |
391 | 87.9k | ,m_nControlWizardEvent( nullptr ) |
392 | 87.9k | ,m_bFirstActivation( true ) |
393 | 87.9k | ,m_isTabOrderUpdateSuspended( false ) |
394 | 87.9k | { |
395 | 87.9k | } |
396 | | |
397 | | |
398 | | void FmXFormView::cancelEvents() |
399 | 175k | { |
400 | 175k | if ( m_nActivationEvent ) |
401 | 0 | { |
402 | 0 | Application::RemoveUserEvent( m_nActivationEvent ); |
403 | 0 | m_nActivationEvent = nullptr; |
404 | 0 | } |
405 | | |
406 | 175k | if ( m_nErrorMessageEvent ) |
407 | 0 | { |
408 | 0 | Application::RemoveUserEvent( m_nErrorMessageEvent ); |
409 | 0 | m_nErrorMessageEvent = nullptr; |
410 | 0 | } |
411 | | |
412 | 175k | if ( m_nAutoFocusEvent ) |
413 | 0 | { |
414 | 0 | Application::RemoveUserEvent( m_nAutoFocusEvent ); |
415 | 0 | m_nAutoFocusEvent = nullptr; |
416 | 0 | } |
417 | | |
418 | 175k | if ( m_nControlWizardEvent ) |
419 | 0 | { |
420 | 0 | Application::RemoveUserEvent( m_nControlWizardEvent ); |
421 | 0 | m_nControlWizardEvent = nullptr; |
422 | 0 | } |
423 | 175k | } |
424 | | |
425 | | |
426 | | void FmXFormView::notifyViewDying( ) |
427 | 87.9k | { |
428 | 87.9k | DBG_ASSERT( m_pView, "FmXFormView::notifyViewDying: my view already died!" ); |
429 | 87.9k | m_pView = nullptr; |
430 | 87.9k | cancelEvents(); |
431 | 87.9k | } |
432 | | |
433 | | |
434 | | FmXFormView::~FmXFormView() |
435 | 87.9k | { |
436 | 87.9k | DBG_ASSERT( m_aPageWindowAdapters.empty(), "FmXFormView::~FmXFormView: Window list not empty!" ); |
437 | 87.9k | for (const auto& rpAdapter : m_aPageWindowAdapters) |
438 | 0 | { |
439 | 0 | rpAdapter->dispose(); |
440 | 0 | } |
441 | | |
442 | 87.9k | cancelEvents(); |
443 | 87.9k | } |
444 | | |
445 | | // EventListener |
446 | | |
447 | | void SAL_CALL FmXFormView::disposing(const EventObject& Source) |
448 | 0 | { |
449 | 0 | if ( m_xWindow.is() && Source.Source == m_xWindow ) |
450 | 0 | { |
451 | 0 | m_xWindow->removeFocusListener(this); |
452 | 0 | if ( m_pView ) |
453 | 0 | { |
454 | 0 | m_pView->SetMoveOutside( false, FmFormView::ImplAccess() ); |
455 | 0 | } |
456 | 0 | m_xWindow = nullptr; |
457 | 0 | } |
458 | 0 | } |
459 | | |
460 | | // XFormControllerListener |
461 | | |
462 | | void SAL_CALL FmXFormView::formActivated(const EventObject& rEvent) |
463 | 0 | { |
464 | 0 | if ( m_pView && m_pView->GetFormShell() && m_pView->GetFormShell()->GetImpl() ) |
465 | 0 | m_pView->GetFormShell()->GetImpl()->formActivated( rEvent ); |
466 | 0 | } |
467 | | |
468 | | |
469 | | void SAL_CALL FmXFormView::formDeactivated(const EventObject& rEvent) |
470 | 0 | { |
471 | 0 | if ( m_pView && m_pView->GetFormShell() && m_pView->GetFormShell()->GetImpl() ) |
472 | 0 | m_pView->GetFormShell()->GetImpl()->formDeactivated( rEvent ); |
473 | 0 | } |
474 | | |
475 | | // XContainerListener |
476 | | |
477 | | void SAL_CALL FmXFormView::elementInserted(const ContainerEvent& evt) |
478 | 0 | { |
479 | 0 | try |
480 | 0 | { |
481 | 0 | Reference< XControlContainer > xControlContainer( evt.Source, UNO_QUERY_THROW ); |
482 | 0 | Reference< XControl > xControl( evt.Element, UNO_QUERY_THROW ); |
483 | 0 | Reference< XFormComponent > xControlModel( xControl->getModel(), UNO_QUERY_THROW ); |
484 | 0 | Reference< XForm > xForm( xControlModel->getParent(), UNO_QUERY_THROW ); |
485 | |
|
486 | 0 | if ( m_isTabOrderUpdateSuspended ) |
487 | 0 | { |
488 | | // remember the container and the control, so we can update the tab order on resumeTabOrderUpdate |
489 | 0 | m_aNeedTabOrderUpdate[ xControlContainer ].insert( xForm ); |
490 | 0 | } |
491 | 0 | else |
492 | 0 | { |
493 | 0 | rtl::Reference< FormViewPageWindowAdapter > pAdapter = findWindow( xControlContainer ); |
494 | 0 | if ( pAdapter.is() ) |
495 | 0 | pAdapter->updateTabOrder( xForm ); |
496 | 0 | } |
497 | 0 | } |
498 | 0 | catch (const Exception&) |
499 | 0 | { |
500 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
501 | 0 | } |
502 | 0 | } |
503 | | |
504 | | |
505 | | void SAL_CALL FmXFormView::elementReplaced(const ContainerEvent& evt) |
506 | 0 | { |
507 | 0 | elementInserted(evt); |
508 | 0 | } |
509 | | |
510 | | |
511 | | void SAL_CALL FmXFormView::elementRemoved(const ContainerEvent& /*evt*/) |
512 | 0 | { |
513 | 0 | } |
514 | | |
515 | | |
516 | | rtl::Reference< FormViewPageWindowAdapter > FmXFormView::findWindow( const Reference< XControlContainer >& _rxCC ) const |
517 | 60 | { |
518 | 60 | auto i = std::find_if(m_aPageWindowAdapters.begin(), m_aPageWindowAdapters.end(), |
519 | 60 | [&_rxCC](const rtl::Reference< FormViewPageWindowAdapter >& rpAdapter) { return _rxCC == rpAdapter->getControlContainer(); }); |
520 | 60 | if (i != m_aPageWindowAdapters.end()) |
521 | 30 | return *i; |
522 | 30 | return nullptr; |
523 | 60 | } |
524 | | |
525 | | |
526 | | void FmXFormView::addWindow(const SdrPageWindow& rWindow) |
527 | 60 | { |
528 | 60 | FmFormPage* pFormPage = dynamic_cast<FmFormPage*>( rWindow.GetPageView().GetPage() ); |
529 | 60 | if ( !pFormPage ) |
530 | 0 | return; |
531 | | |
532 | 60 | const rtl::Reference< UnoControlContainer > & xCC = rWindow.GetControlContainer(); |
533 | 60 | if ( xCC.is() |
534 | 60 | && ( !findWindow( xCC ).is() ) |
535 | 60 | ) |
536 | 30 | { |
537 | 30 | rtl::Reference< FormViewPageWindowAdapter > pAdapter = new FormViewPageWindowAdapter( comphelper::getProcessComponentContext(), rWindow, this ); |
538 | 30 | m_aPageWindowAdapters.push_back( pAdapter ); |
539 | | |
540 | | // listen at the ControlContainer to notice changes |
541 | 30 | xCC->addContainerListener( this ); |
542 | 30 | } |
543 | 60 | } |
544 | | |
545 | | |
546 | | void FmXFormView::removeWindow( const Reference< XControlContainer >& _rxCC ) |
547 | 60 | { |
548 | | // Is called if |
549 | | // - the design mode is being switched to |
550 | | // - a window is deleted while in the design mode |
551 | | // - the control container for a window is removed while the active mode is on |
552 | | |
553 | 60 | auto i = std::find_if(m_aPageWindowAdapters.begin(), m_aPageWindowAdapters.end(), |
554 | 60 | [&_rxCC](const rtl::Reference< FormViewPageWindowAdapter >& rpAdapter) { return _rxCC == rpAdapter->getControlContainer(); }); |
555 | 60 | if (i != m_aPageWindowAdapters.end()) |
556 | 30 | { |
557 | 30 | Reference< XContainer > xContainer( _rxCC, UNO_QUERY ); |
558 | 30 | if ( xContainer.is() ) |
559 | 30 | xContainer->removeContainerListener( this ); |
560 | | |
561 | 30 | (*i)->dispose(); |
562 | 30 | m_aPageWindowAdapters.erase( i ); |
563 | 30 | } |
564 | 60 | } |
565 | | |
566 | | void FmXFormView::displayAsyncErrorMessage( const SQLErrorEvent& _rEvent ) |
567 | 0 | { |
568 | 0 | DBG_ASSERT( nullptr == m_nErrorMessageEvent, "FmXFormView::displayAsyncErrorMessage: not too fast, please!" ); |
569 | | // This should not happen - usually, the PostUserEvent is faster than any possible user |
570 | | // interaction which could trigger a new error. If it happens, we need a queue for the events. |
571 | 0 | m_aAsyncError = _rEvent; |
572 | 0 | m_nErrorMessageEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnDelayedErrorMessage ) ); |
573 | 0 | } |
574 | | |
575 | | IMPL_LINK_NOARG(FmXFormView, OnDelayedErrorMessage, void*, void) |
576 | 0 | { |
577 | 0 | m_nErrorMessageEvent = nullptr; |
578 | 0 | displayException(m_aAsyncError, GetParentWindow()); |
579 | 0 | } |
580 | | |
581 | | void FmXFormView::onFirstViewActivation( const FmFormModel* _pDocModel ) |
582 | 13 | { |
583 | 13 | if ( _pDocModel && _pDocModel->GetAutoControlFocus() ) |
584 | 0 | m_nAutoFocusEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnAutoFocus ) ); |
585 | 13 | } |
586 | | |
587 | | void FmXFormView::suspendTabOrderUpdate() |
588 | 83.4k | { |
589 | 83.4k | OSL_ENSURE( !m_isTabOrderUpdateSuspended, "FmXFormView::suspendTabOrderUpdate: nesting not allowed!" ); |
590 | 83.4k | m_isTabOrderUpdateSuspended = true; |
591 | 83.4k | } |
592 | | |
593 | | void FmXFormView::resumeTabOrderUpdate() |
594 | 83.4k | { |
595 | 83.4k | OSL_ENSURE( m_isTabOrderUpdateSuspended, "FmXFormView::resumeTabOrderUpdate: not suspended!" ); |
596 | 83.4k | m_isTabOrderUpdateSuspended = false; |
597 | | |
598 | | // update the tab orders for all components which were collected since the suspendTabOrderUpdate call. |
599 | 83.4k | for (const auto& rContainer : m_aNeedTabOrderUpdate) |
600 | 0 | { |
601 | 0 | rtl::Reference< FormViewPageWindowAdapter > pAdapter = findWindow( rContainer.first ); |
602 | 0 | if ( !pAdapter.is() ) |
603 | 0 | continue; |
604 | | |
605 | 0 | for (const auto& rForm : rContainer.second) |
606 | 0 | { |
607 | 0 | pAdapter->updateTabOrder( rForm ); |
608 | 0 | } |
609 | 0 | } |
610 | 83.4k | m_aNeedTabOrderUpdate.clear(); |
611 | 83.4k | } |
612 | | |
613 | | namespace |
614 | | { |
615 | | bool isActivableDatabaseForm(const Reference< XFormController > &xController) |
616 | 0 | { |
617 | | // only database forms are to be activated |
618 | 0 | Reference< XRowSet > xForm(xController->getModel(), UNO_QUERY); |
619 | 0 | if ( !xForm.is() || !getConnection( xForm ).is() ) |
620 | 0 | return false; |
621 | | |
622 | 0 | Reference< XPropertySet > xFormSet( xForm, UNO_QUERY ); |
623 | 0 | if ( !xFormSet.is() ) |
624 | 0 | { |
625 | 0 | SAL_WARN( "svx.form", "FmXFormView::OnActivate: a form which does not have properties?" ); |
626 | 0 | return false; |
627 | 0 | } |
628 | | |
629 | 0 | const OUString aSource = ::comphelper::getString( xFormSet->getPropertyValue( FM_PROP_COMMAND ) ); |
630 | |
|
631 | 0 | return !aSource.isEmpty(); |
632 | 0 | } |
633 | | |
634 | | class find_active_databaseform |
635 | | { |
636 | | const Reference< XFormController > xActiveController; |
637 | | |
638 | | public: |
639 | | |
640 | | explicit find_active_databaseform( const Reference< XFormController >& _xActiveController ) |
641 | 0 | : xActiveController(_xActiveController ) |
642 | 0 | {} |
643 | | |
644 | | Reference < XFormController > operator() (const Reference< XFormController > &xController) |
645 | 0 | { |
646 | 0 | if(xController == xActiveController && isActivableDatabaseForm(xController)) |
647 | 0 | return xController; |
648 | | |
649 | 0 | if ( !xController.is() ) |
650 | 0 | { |
651 | 0 | SAL_WARN( "svx.form", "FmXFormView::OnActivate: a form controller which does not have children?" ); |
652 | 0 | return nullptr; |
653 | 0 | } |
654 | | |
655 | 0 | for(sal_Int32 i = 0; i < xController->getCount(); ++i) |
656 | 0 | { |
657 | 0 | const Any a(xController->getByIndex(i)); |
658 | 0 | Reference < XFormController > xI; |
659 | 0 | if ((a >>= xI) && xI.is()) |
660 | 0 | { |
661 | 0 | Reference < XFormController > xRes(operator()(xI)); |
662 | 0 | if (xRes.is()) |
663 | 0 | return xRes; |
664 | 0 | } |
665 | 0 | } |
666 | | |
667 | 0 | return nullptr; |
668 | 0 | } |
669 | | }; |
670 | | } |
671 | | |
672 | | |
673 | | IMPL_LINK_NOARG(FmXFormView, OnActivate, void*, void) |
674 | 0 | { |
675 | 0 | m_nActivationEvent = nullptr; |
676 | |
|
677 | 0 | if ( !m_pView ) |
678 | 0 | { |
679 | 0 | OSL_FAIL( "FmXFormView::OnActivate: well... seems we have a timing problem (the view already died)!" ); |
680 | 0 | return; |
681 | 0 | } |
682 | | |
683 | | // setting the controller to activate |
684 | 0 | if (!(m_pView->GetFormShell() && m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW)) |
685 | 0 | return; |
686 | | |
687 | 0 | FmXFormShell* const pShImpl = m_pView->GetFormShell()->GetImpl(); |
688 | |
|
689 | 0 | if(!pShImpl) |
690 | 0 | return; |
691 | | |
692 | 0 | find_active_databaseform fad(pShImpl->getActiveController_Lock()); |
693 | |
|
694 | 0 | vcl::Window* pWindow = m_pView->GetActualOutDev()->GetOwnerWindow(); |
695 | 0 | rtl::Reference< FormViewPageWindowAdapter > pAdapter = m_aPageWindowAdapters.empty() ? nullptr : m_aPageWindowAdapters[0]; |
696 | 0 | for (const auto& rpPageWindowAdapter : m_aPageWindowAdapters) |
697 | 0 | { |
698 | 0 | if ( pWindow == rpPageWindowAdapter->getWindow() ) |
699 | 0 | pAdapter = rpPageWindowAdapter; |
700 | 0 | } |
701 | |
|
702 | 0 | if ( !pAdapter.is() ) |
703 | 0 | return; |
704 | | |
705 | 0 | Reference< XFormController > xControllerToActivate; |
706 | 0 | for (const Reference< XFormController > & xController : pAdapter->GetList()) |
707 | 0 | { |
708 | 0 | if ( !xController.is() ) |
709 | 0 | continue; |
710 | | |
711 | 0 | { |
712 | 0 | Reference< XFormController > xActiveController(fad(xController)); |
713 | 0 | if (xActiveController.is()) |
714 | 0 | { |
715 | 0 | xControllerToActivate = std::move(xActiveController); |
716 | 0 | break; |
717 | 0 | } |
718 | 0 | } |
719 | | |
720 | 0 | if(xControllerToActivate.is() || !isActivableDatabaseForm(xController)) |
721 | 0 | continue; |
722 | | |
723 | 0 | xControllerToActivate = xController; |
724 | 0 | } |
725 | 0 | pShImpl->setActiveController_Lock(xControllerToActivate); |
726 | 0 | } |
727 | | |
728 | | |
729 | | void FmXFormView::Activate(bool bSync) |
730 | 88.0k | { |
731 | 88.0k | if (m_nActivationEvent) |
732 | 13 | { |
733 | 13 | Application::RemoveUserEvent(m_nActivationEvent); |
734 | 13 | m_nActivationEvent = nullptr; |
735 | 13 | } |
736 | | |
737 | 88.0k | if (bSync) |
738 | 0 | { |
739 | 0 | LINK(this,FmXFormView,OnActivate).Call(nullptr); |
740 | 0 | } |
741 | 88.0k | else |
742 | 88.0k | m_nActivationEvent = Application::PostUserEvent(LINK(this,FmXFormView,OnActivate)); |
743 | 88.0k | } |
744 | | |
745 | | |
746 | | void FmXFormView::Deactivate(bool bDeactivateController) |
747 | 88.0k | { |
748 | 88.0k | if (m_nActivationEvent) |
749 | 87.9k | { |
750 | 87.9k | Application::RemoveUserEvent(m_nActivationEvent); |
751 | 87.9k | m_nActivationEvent = nullptr; |
752 | 87.9k | } |
753 | | |
754 | 88.0k | FmXFormShell* pShImpl = m_pView->GetFormShell() ? m_pView->GetFormShell()->GetImpl() : nullptr; |
755 | 88.0k | if (pShImpl && bDeactivateController) |
756 | 0 | pShImpl->setActiveController_Lock(nullptr); |
757 | 88.0k | } |
758 | | |
759 | | |
760 | | FmFormShell* FmXFormView::GetFormShell() const |
761 | 9.15k | { |
762 | 9.15k | return m_pView ? m_pView->GetFormShell() : nullptr; |
763 | 9.15k | } |
764 | | |
765 | | void FmXFormView::AutoFocus() |
766 | 0 | { |
767 | 0 | if (m_nAutoFocusEvent) |
768 | 0 | Application::RemoveUserEvent(m_nAutoFocusEvent); |
769 | |
|
770 | 0 | m_nAutoFocusEvent = Application::PostUserEvent(LINK(this, FmXFormView, OnAutoFocus)); |
771 | 0 | } |
772 | | |
773 | | |
774 | | bool FmXFormView::isFocusable( const Reference< XControl >& i_rControl ) |
775 | 0 | { |
776 | 0 | if ( !i_rControl.is() ) |
777 | 0 | return false; |
778 | | |
779 | 0 | try |
780 | 0 | { |
781 | 0 | Reference< XPropertySet > xModelProps( i_rControl->getModel(), UNO_QUERY_THROW ); |
782 | | |
783 | | // only enabled controls are allowed to participate |
784 | 0 | bool bEnabled = false; |
785 | 0 | OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_ENABLED ) >>= bEnabled ); |
786 | 0 | if ( !bEnabled ) |
787 | 0 | return false; |
788 | | |
789 | | // check the class id of the control model |
790 | 0 | sal_Int16 nClassId = FormComponentType::CONTROL; |
791 | 0 | OSL_VERIFY( xModelProps->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId ); |
792 | | |
793 | | // controls which are not focussable |
794 | 0 | if ( ( FormComponentType::CONTROL != nClassId ) |
795 | 0 | && ( FormComponentType::IMAGEBUTTON != nClassId ) |
796 | 0 | && ( FormComponentType::GROUPBOX != nClassId ) |
797 | 0 | && ( FormComponentType::FIXEDTEXT != nClassId ) |
798 | 0 | && ( FormComponentType::HIDDENCONTROL != nClassId ) |
799 | 0 | && ( FormComponentType::IMAGECONTROL != nClassId ) |
800 | 0 | && ( FormComponentType::SCROLLBAR != nClassId ) |
801 | 0 | && ( FormComponentType::SPINBUTTON!= nClassId ) |
802 | 0 | ) |
803 | 0 | { |
804 | 0 | return true; |
805 | 0 | } |
806 | 0 | } |
807 | 0 | catch (const Exception&) |
808 | 0 | { |
809 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
810 | 0 | } |
811 | 0 | return false; |
812 | 0 | } |
813 | | |
814 | | |
815 | | static Reference< XControl > lcl_firstFocussableControl( const Sequence< Reference< XControl > >& _rControls ) |
816 | 0 | { |
817 | 0 | Reference< XControl > xReturn; |
818 | | |
819 | | // loop through all the controls |
820 | 0 | for ( auto const & control : _rControls ) |
821 | 0 | { |
822 | 0 | if ( !control.is() ) |
823 | 0 | continue; |
824 | | |
825 | 0 | if ( FmXFormView::isFocusable( control ) ) |
826 | 0 | { |
827 | 0 | xReturn = control; |
828 | 0 | break; |
829 | 0 | } |
830 | 0 | } |
831 | |
|
832 | 0 | if ( !xReturn.is() && _rControls.hasElements() ) |
833 | 0 | xReturn = _rControls[0]; |
834 | |
|
835 | 0 | return xReturn; |
836 | 0 | } |
837 | | |
838 | | |
839 | | namespace |
840 | | { |
841 | | |
842 | | void lcl_ensureControlsOfFormExist_nothrow( const SdrPage& _rPage, const SdrView& _rView, const vcl::Window& _rWindow, const Reference< XForm >& _rxForm ) |
843 | 0 | { |
844 | 0 | try |
845 | 0 | { |
846 | 0 | Reference< XInterface > xNormalizedForm( _rxForm, UNO_QUERY_THROW ); |
847 | |
|
848 | 0 | SdrObjListIter aSdrObjectLoop( &_rPage, SdrIterMode::DeepNoGroups ); |
849 | 0 | while ( aSdrObjectLoop.IsMore() ) |
850 | 0 | { |
851 | 0 | FmFormObj* pFormObject = FmFormObj::GetFormObject( aSdrObjectLoop.Next() ); |
852 | 0 | if ( !pFormObject ) |
853 | 0 | continue; |
854 | | |
855 | 0 | Reference< XChild > xModel( pFormObject->GetUnoControlModel(), UNO_QUERY_THROW ); |
856 | 0 | Reference< XInterface > xModelParent( xModel->getParent(), UNO_QUERY ); |
857 | |
|
858 | 0 | if ( xNormalizedForm.get() != xModelParent.get() ) |
859 | 0 | continue; |
860 | | |
861 | 0 | pFormObject->GetUnoControl( _rView, *_rWindow.GetOutDev() ); |
862 | 0 | } |
863 | 0 | } |
864 | 0 | catch (const Exception&) |
865 | 0 | { |
866 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
867 | 0 | } |
868 | 0 | } |
869 | | } |
870 | | |
871 | | |
872 | | Reference< XFormController > FmXFormView::getFormController( const Reference< XForm >& _rxForm, const OutputDevice& _rDevice ) const |
873 | 0 | { |
874 | 0 | Reference< XFormController > xController; |
875 | |
|
876 | 0 | for (const rtl::Reference< FormViewPageWindowAdapter >& pAdapter : m_aPageWindowAdapters) |
877 | 0 | { |
878 | 0 | if ( !pAdapter ) |
879 | 0 | { |
880 | 0 | SAL_WARN( "svx.form", "FmXFormView::getFormController: invalid page window adapter!" ); |
881 | 0 | continue; |
882 | 0 | } |
883 | | |
884 | 0 | if ( pAdapter->getWindow() != _rDevice.GetOwnerWindow() ) |
885 | | // wrong device |
886 | 0 | continue; |
887 | | |
888 | 0 | xController = pAdapter->getController( _rxForm ); |
889 | 0 | if ( xController.is() ) |
890 | 0 | break; |
891 | 0 | } |
892 | 0 | return xController; |
893 | 0 | } |
894 | | |
895 | | |
896 | | IMPL_LINK_NOARG(FmXFormView, OnAutoFocus, void*, void) |
897 | 0 | { |
898 | 0 | m_nAutoFocusEvent = nullptr; |
899 | | |
900 | | // go to the first form of our page, examine it's TabController, go to its first (in terms of the tab order) |
901 | | // control, give it the focus |
902 | |
|
903 | 0 | SdrPageView *pPageView = m_pView ? m_pView->GetSdrPageView() : nullptr; |
904 | 0 | SdrPage *pSdrPage = pPageView ? pPageView->GetPage() : nullptr; |
905 | | // get the forms collection of the page we belong to |
906 | 0 | FmFormPage* pPage = dynamic_cast<FmFormPage*>( pSdrPage ); |
907 | 0 | Reference< XIndexAccess > xForms( pPage ? Reference< XIndexAccess >( pPage->GetForms() ) : Reference< XIndexAccess >() ); |
908 | |
|
909 | 0 | const rtl::Reference< FormViewPageWindowAdapter > pAdapter = m_aPageWindowAdapters.empty() ? nullptr : m_aPageWindowAdapters[0]; |
910 | 0 | const vcl::Window* pWindow = pAdapter ? pAdapter->getWindow() : nullptr; |
911 | |
|
912 | 0 | ENSURE_OR_RETURN_VOID( xForms.is() && pWindow, "FmXFormView::OnAutoFocus: could not collect all essentials!" ); |
913 | |
|
914 | 0 | try |
915 | 0 | { |
916 | | // go for the tab controller of the first form |
917 | 0 | if ( !xForms->getCount() ) |
918 | 0 | return; |
919 | 0 | Reference< XForm > xForm( xForms->getByIndex( 0 ), UNO_QUERY_THROW ); |
920 | 0 | Reference< XTabController > xTabController( pAdapter->getController( xForm ), UNO_QUERY_THROW ); |
921 | | |
922 | | // go for the first control of the controller |
923 | 0 | Sequence< Reference< XControl > > aControls( xTabController->getControls() ); |
924 | 0 | if ( !aControls.hasElements() ) |
925 | 0 | { |
926 | 0 | Reference< XElementAccess > xFormElementAccess( xForm, UNO_QUERY_THROW ); |
927 | 0 | if (xFormElementAccess->hasElements() && pPage && m_pView) |
928 | 0 | { |
929 | | // there are control models in the form, but no controls, yet. |
930 | | // Well, since some time controls are created on demand only. In particular, |
931 | | // they're normally created when they're first painted. |
932 | | // Unfortunately, the FormController does not have any way to |
933 | | // trigger the creation itself, so we must hack this ... |
934 | 0 | lcl_ensureControlsOfFormExist_nothrow( *pPage, *m_pView, *pWindow, xForm ); |
935 | 0 | aControls = xTabController->getControls(); |
936 | 0 | OSL_ENSURE( aControls.hasElements(), "FmXFormView::OnAutoFocus: no controls at all!" ); |
937 | 0 | } |
938 | 0 | } |
939 | | |
940 | | // set the focus to this first control |
941 | 0 | Reference< XWindow > xControlWindow( lcl_firstFocussableControl( aControls ), UNO_QUERY ); |
942 | 0 | if ( !xControlWindow.is() ) |
943 | 0 | return; |
944 | | |
945 | 0 | xControlWindow->setFocus(); |
946 | | |
947 | | // ensure that the control is visible |
948 | | // 80210 - 12/07/00 - FS |
949 | 0 | const OutputDevice* pOut = m_pView ? m_pView->GetActualOutDev() : nullptr; |
950 | 0 | const vcl::Window* pCurrentWindow = pOut ? pOut->GetOwnerWindow() : nullptr; |
951 | 0 | if ( pCurrentWindow ) |
952 | 0 | { |
953 | 0 | awt::Rectangle aRect = xControlWindow->getPosSize(); |
954 | 0 | ::tools::Rectangle aNonUnoRect( aRect.X, aRect.Y, aRect.X + aRect.Width, aRect.Y + aRect.Height ); |
955 | 0 | m_pView->MakeVisible( pCurrentWindow->PixelToLogic( aNonUnoRect ), *const_cast< vcl::Window* >( pCurrentWindow ) ); |
956 | 0 | } |
957 | 0 | } |
958 | 0 | catch (const Exception&) |
959 | 0 | { |
960 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
961 | 0 | } |
962 | 0 | } |
963 | | |
964 | | |
965 | | void FmXFormView::onCreatedFormObject( FmFormObj const & _rFormObject ) |
966 | 0 | { |
967 | 0 | FmFormShell* pShell = m_pView ? m_pView->GetFormShell() : nullptr; |
968 | 0 | FmXFormShell* pShellImpl = pShell ? pShell->GetImpl() : nullptr; |
969 | 0 | OSL_ENSURE( pShellImpl, "FmXFormView::onCreatedFormObject: no form shell!" ); |
970 | 0 | if ( !pShellImpl ) |
971 | 0 | return; |
972 | | |
973 | | // it is valid that the form shell's forms collection is not initialized, yet |
974 | 0 | pShellImpl->UpdateForms_Lock(true); |
975 | |
|
976 | 0 | m_xLastCreatedControlModel.set( _rFormObject.GetUnoControlModel(), UNO_QUERY ); |
977 | 0 | if ( !m_xLastCreatedControlModel.is() ) |
978 | 0 | return; |
979 | | |
980 | | // some initial property defaults |
981 | 0 | FormControlFactory aControlFactory; |
982 | 0 | aControlFactory.initializeControlModel(pShellImpl->getDocumentType_Lock(), _rFormObject); |
983 | |
|
984 | 0 | if (!pShellImpl->GetWizardUsing_Lock()) |
985 | 0 | return; |
986 | | |
987 | | // #i31958# don't call wizards in XForms mode |
988 | 0 | if (pShellImpl->isEnhancedForm_Lock()) |
989 | 0 | return; |
990 | | |
991 | | // #i46898# no wizards if there is no Base installed - currently, all wizards are |
992 | | // database related |
993 | 0 | if (!SvtModuleOptions().IsDataBaseInstalled()) |
994 | 0 | return; |
995 | | |
996 | 0 | if ( m_nControlWizardEvent ) |
997 | 0 | Application::RemoveUserEvent( m_nControlWizardEvent ); |
998 | 0 | m_nControlWizardEvent = Application::PostUserEvent( LINK( this, FmXFormView, OnStartControlWizard ) ); |
999 | 0 | } |
1000 | | |
1001 | | void FmXFormView::breakCreateFormObject() |
1002 | 0 | { |
1003 | 0 | if (m_nControlWizardEvent != nullptr) |
1004 | 0 | { |
1005 | 0 | Application::RemoveUserEvent(m_nControlWizardEvent); |
1006 | 0 | m_nControlWizardEvent = nullptr; |
1007 | 0 | } |
1008 | 0 | m_xLastCreatedControlModel.clear(); |
1009 | 0 | } |
1010 | | |
1011 | | Reference<XWindow> FmXFormView::GetParentWindow() const |
1012 | 0 | { |
1013 | 0 | const OutputDevice* pOut = m_pView ? m_pView->GetActualOutDev() : nullptr; |
1014 | 0 | const vcl::Window* pCurrentWindow = pOut ? pOut->GetOwnerWindow() : nullptr; |
1015 | 0 | return VCLUnoHelper::GetInterface(const_cast<vcl::Window*>(pCurrentWindow)); |
1016 | 0 | } |
1017 | | |
1018 | | IMPL_LINK_NOARG( FmXFormView, OnStartControlWizard, void*, void ) |
1019 | 0 | { |
1020 | 0 | m_nControlWizardEvent = nullptr; |
1021 | 0 | OSL_PRECOND( m_xLastCreatedControlModel.is(), "FmXFormView::OnStartControlWizard: illegal call!" ); |
1022 | 0 | if ( !m_xLastCreatedControlModel.is() ) |
1023 | 0 | return; |
1024 | | |
1025 | 0 | sal_Int16 nClassId = FormComponentType::CONTROL; |
1026 | 0 | try |
1027 | 0 | { |
1028 | 0 | OSL_VERIFY( m_xLastCreatedControlModel->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId ); |
1029 | 0 | } |
1030 | 0 | catch (const Exception&) |
1031 | 0 | { |
1032 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
1033 | 0 | } |
1034 | |
|
1035 | 0 | const char* pWizardAsciiName = nullptr; |
1036 | 0 | switch ( nClassId ) |
1037 | 0 | { |
1038 | 0 | case FormComponentType::GRIDCONTROL: |
1039 | 0 | pWizardAsciiName = "com.sun.star.sdb.GridControlAutoPilot"; |
1040 | 0 | break; |
1041 | 0 | case FormComponentType::LISTBOX: |
1042 | 0 | case FormComponentType::COMBOBOX: |
1043 | 0 | pWizardAsciiName = "com.sun.star.sdb.ListComboBoxAutoPilot"; |
1044 | 0 | break; |
1045 | 0 | case FormComponentType::GROUPBOX: |
1046 | 0 | pWizardAsciiName = "com.sun.star.sdb.GroupBoxAutoPilot"; |
1047 | 0 | break; |
1048 | 0 | } |
1049 | | |
1050 | 0 | if ( pWizardAsciiName ) |
1051 | 0 | { |
1052 | | // build the argument list |
1053 | 0 | ::comphelper::NamedValueCollection aWizardArgs; |
1054 | 0 | aWizardArgs.put(u"ObjectModel"_ustr, m_xLastCreatedControlModel); |
1055 | 0 | aWizardArgs.put(u"ParentWindow"_ustr, GetParentWindow()); |
1056 | | |
1057 | | // create the wizard object |
1058 | 0 | Reference< XExecutableDialog > xWizard; |
1059 | 0 | try |
1060 | 0 | { |
1061 | 0 | const Reference<XComponentContext>& xContext = comphelper::getProcessComponentContext(); |
1062 | 0 | xWizard.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext( OUString::createFromAscii(pWizardAsciiName), aWizardArgs.getWrappedPropertyValues(), xContext ), UNO_QUERY); |
1063 | 0 | } |
1064 | 0 | catch (const Exception&) |
1065 | 0 | { |
1066 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
1067 | 0 | } |
1068 | |
|
1069 | 0 | if ( !xWizard.is() ) |
1070 | 0 | { |
1071 | 0 | ShowServiceNotAvailableError( nullptr, OUString::createFromAscii(pWizardAsciiName), true ); |
1072 | 0 | } |
1073 | 0 | else |
1074 | 0 | { |
1075 | | // execute the wizard |
1076 | 0 | try |
1077 | 0 | { |
1078 | 0 | xWizard->execute(); |
1079 | 0 | } |
1080 | 0 | catch (const Exception&) |
1081 | 0 | { |
1082 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
1083 | 0 | } |
1084 | 0 | } |
1085 | 0 | } |
1086 | |
|
1087 | 0 | m_xLastCreatedControlModel.clear(); |
1088 | 0 | } |
1089 | | |
1090 | | |
1091 | | namespace |
1092 | | { |
1093 | | void lcl_insertIntoFormComponentHierarchy_throw( const FmFormView& _rView, const SdrUnoObj& _rSdrObj, |
1094 | | const Reference< XDataSource >& _rxDataSource, const OUString& _rDataSourceName, |
1095 | | const OUString& _rCommand, const sal_Int32 _nCommandType ) |
1096 | 0 | { |
1097 | 0 | FmFormPage& rPage = static_cast< FmFormPage& >( *_rView.GetSdrPageView()->GetPage() ); |
1098 | |
|
1099 | 0 | Reference< XFormComponent > xFormComponent( _rSdrObj.GetUnoControlModel(), UNO_QUERY_THROW ); |
1100 | 0 | Reference< XForm > xTargetForm( |
1101 | 0 | rPage.GetImpl().findPlaceInFormComponentHierarchy( xFormComponent, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType ), |
1102 | 0 | UNO_SET_THROW ); |
1103 | |
|
1104 | 0 | FmFormPageImpl::setUniqueName( xFormComponent, xTargetForm ); |
1105 | |
|
1106 | 0 | Reference< XIndexContainer > xFormAsContainer( xTargetForm, UNO_QUERY_THROW ); |
1107 | 0 | xFormAsContainer->insertByIndex( xFormAsContainer->getCount(), Any( xFormComponent ) ); |
1108 | 0 | } |
1109 | | } |
1110 | | |
1111 | | |
1112 | | rtl::Reference<SdrObject> FmXFormView::implCreateFieldControl( const svx::ODataAccessDescriptor& _rColumnDescriptor ) |
1113 | 0 | { |
1114 | | // not if we're in design mode |
1115 | 0 | if ( !m_pView->IsDesignMode() ) |
1116 | 0 | return nullptr; |
1117 | | |
1118 | 0 | OUString sCommand, sFieldName; |
1119 | 0 | sal_Int32 nCommandType = CommandType::COMMAND; |
1120 | 0 | SharedConnection xConnection; |
1121 | |
|
1122 | 0 | OUString sDataSource = _rColumnDescriptor.getDataSource(); |
1123 | 0 | _rColumnDescriptor[ DataAccessDescriptorProperty::Command ] >>= sCommand; |
1124 | 0 | _rColumnDescriptor[ DataAccessDescriptorProperty::ColumnName ] >>= sFieldName; |
1125 | 0 | _rColumnDescriptor[ DataAccessDescriptorProperty::CommandType ] >>= nCommandType; |
1126 | 0 | { |
1127 | 0 | Reference< XConnection > xExternalConnection; |
1128 | 0 | _rColumnDescriptor[ DataAccessDescriptorProperty::Connection ] >>= xExternalConnection; |
1129 | 0 | xConnection.reset( xExternalConnection, SharedConnection::NoTakeOwnership ); |
1130 | 0 | } |
1131 | |
|
1132 | 0 | if ( sCommand.isEmpty() |
1133 | 0 | || sFieldName.isEmpty() |
1134 | 0 | || ( sDataSource.isEmpty() |
1135 | 0 | && !xConnection.is() |
1136 | 0 | ) |
1137 | 0 | ) |
1138 | 0 | { |
1139 | 0 | OSL_FAIL( "FmXFormView::implCreateFieldControl: nonsense!" ); |
1140 | 0 | } |
1141 | |
|
1142 | 0 | Reference< XDataSource > xDataSource; |
1143 | 0 | SQLErrorEvent aError; |
1144 | 0 | try |
1145 | 0 | { |
1146 | 0 | if ( xConnection.is() && !xDataSource.is() && sDataSource.isEmpty() ) |
1147 | 0 | { |
1148 | 0 | Reference< XChild > xChild( xConnection, UNO_QUERY ); |
1149 | 0 | if ( xChild.is() ) |
1150 | 0 | xDataSource.set(xChild->getParent(), css::uno::UNO_QUERY); |
1151 | 0 | } |
1152 | | |
1153 | | // obtain the data source |
1154 | 0 | if ( !xDataSource.is() ) |
1155 | 0 | xDataSource = getDataSource( sDataSource, comphelper::getProcessComponentContext() ); |
1156 | | |
1157 | | // and the connection, if necessary |
1158 | 0 | if ( !xConnection.is() ) |
1159 | 0 | xConnection.reset( getConnection_withFeedback( |
1160 | 0 | sDataSource, |
1161 | 0 | OUString(), |
1162 | 0 | OUString(), |
1163 | 0 | comphelper::getProcessComponentContext(), |
1164 | 0 | nullptr |
1165 | 0 | ) ); |
1166 | 0 | } |
1167 | 0 | catch (const SQLException&) |
1168 | 0 | { |
1169 | 0 | aError.Reason = ::cppu::getCaughtException(); |
1170 | 0 | } |
1171 | 0 | catch (const Exception& ) |
1172 | 0 | { |
1173 | | /* will be asserted below */ |
1174 | 0 | } |
1175 | 0 | if (aError.Reason.hasValue()) |
1176 | 0 | { |
1177 | 0 | displayAsyncErrorMessage( aError ); |
1178 | 0 | return nullptr; |
1179 | 0 | } |
1180 | | |
1181 | | // need a data source and a connection here |
1182 | 0 | if (!xDataSource.is() || !xConnection.is()) |
1183 | 0 | { |
1184 | 0 | OSL_FAIL("FmXFormView::implCreateFieldControl : could not retrieve the data source or the connection!"); |
1185 | 0 | return nullptr; |
1186 | 0 | } |
1187 | | |
1188 | 0 | Reference< XComponent > xKeepFieldsAlive; |
1189 | | // go |
1190 | 0 | try |
1191 | 0 | { |
1192 | | // determine the table/query field which we should create a control for |
1193 | 0 | Reference< XPropertySet > xField; |
1194 | |
|
1195 | 0 | Reference< XNameAccess > xFields = getFieldsByCommandDescriptor( |
1196 | 0 | xConnection, nCommandType, sCommand, xKeepFieldsAlive ); |
1197 | |
|
1198 | 0 | if (xFields.is() && xFields->hasByName(sFieldName)) |
1199 | 0 | xFields->getByName(sFieldName) >>= xField; |
1200 | 0 | if ( !xField.is() ) |
1201 | 0 | return nullptr; |
1202 | | |
1203 | 0 | Reference< XNumberFormatsSupplier > xSupplier( getNumberFormats( xConnection ), UNO_SET_THROW ); |
1204 | 0 | Reference< XNumberFormats > xNumberFormats( xSupplier->getNumberFormats(), UNO_SET_THROW ); |
1205 | |
|
1206 | 0 | OUString sLabelPostfix; |
1207 | | |
1208 | | |
1209 | | // only for text size |
1210 | 0 | OutputDevice* pOutDev = nullptr; |
1211 | 0 | if (m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW) |
1212 | 0 | pOutDev = const_cast<OutputDevice*>(m_pView->GetActualOutDev()); |
1213 | 0 | else |
1214 | 0 | {// find OutDev |
1215 | 0 | if (SdrPageView* pPageView = m_pView->GetSdrPageView()) |
1216 | 0 | { |
1217 | | // const SdrPageViewWinList& rWinList = pPageView->GetWinList(); |
1218 | | // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows(); |
1219 | |
|
1220 | 0 | for( sal_uInt32 i = 0; i < pPageView->PageWindowCount(); i++ ) |
1221 | 0 | { |
1222 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i); |
1223 | |
|
1224 | 0 | if( rPageWindow.GetPaintWindow().OutputToWindow()) |
1225 | 0 | { |
1226 | 0 | pOutDev = &rPageWindow.GetPaintWindow().GetOutputDevice(); |
1227 | 0 | break; |
1228 | 0 | } |
1229 | 0 | } |
1230 | 0 | } |
1231 | 0 | } |
1232 | |
|
1233 | 0 | if ( !pOutDev ) |
1234 | 0 | return nullptr; |
1235 | | |
1236 | 0 | sal_Int32 nDataType = ::comphelper::getINT32(xField->getPropertyValue(FM_PROP_FIELDTYPE)); |
1237 | 0 | if ((DataType::BINARY == nDataType) || (DataType::VARBINARY == nDataType)) |
1238 | 0 | return nullptr; |
1239 | | |
1240 | | |
1241 | | // determine the control type by examining the data type of the bound column |
1242 | 0 | SdrObjKind nOBJID = SdrObjKind::NONE; |
1243 | 0 | bool bDateNTimeField = false; |
1244 | |
|
1245 | 0 | bool bIsCurrency = false; |
1246 | 0 | if (::comphelper::hasProperty(FM_PROP_ISCURRENCY, xField)) |
1247 | 0 | bIsCurrency = ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_ISCURRENCY)); |
1248 | |
|
1249 | 0 | if (bIsCurrency) |
1250 | 0 | nOBJID = SdrObjKind::FormCurrencyField; |
1251 | 0 | else |
1252 | 0 | switch (nDataType) |
1253 | 0 | { |
1254 | 0 | case DataType::BLOB: |
1255 | 0 | case DataType::LONGVARBINARY: |
1256 | 0 | nOBJID = SdrObjKind::FormImageControl; |
1257 | 0 | break; |
1258 | 0 | case DataType::LONGVARCHAR: |
1259 | 0 | case DataType::CLOB: |
1260 | 0 | nOBJID = SdrObjKind::FormEdit; |
1261 | 0 | break; |
1262 | 0 | case DataType::BINARY: |
1263 | 0 | case DataType::VARBINARY: |
1264 | 0 | return nullptr; |
1265 | 0 | case DataType::BIT: |
1266 | 0 | case DataType::BOOLEAN: |
1267 | 0 | nOBJID = SdrObjKind::FormCheckbox; |
1268 | 0 | break; |
1269 | 0 | case DataType::TINYINT: |
1270 | 0 | case DataType::SMALLINT: |
1271 | 0 | case DataType::INTEGER: |
1272 | 0 | nOBJID = SdrObjKind::FormNumericField; |
1273 | 0 | break; |
1274 | 0 | case DataType::REAL: |
1275 | 0 | case DataType::DOUBLE: |
1276 | 0 | case DataType::NUMERIC: |
1277 | 0 | case DataType::DECIMAL: |
1278 | 0 | nOBJID = SdrObjKind::FormFormattedField; |
1279 | 0 | break; |
1280 | 0 | case DataType::TIMESTAMP: |
1281 | 0 | bDateNTimeField = true; |
1282 | 0 | sLabelPostfix = SvxResId(RID_STR_POSTFIX_DATE); |
1283 | 0 | [[fallthrough]]; |
1284 | 0 | case DataType::DATE: |
1285 | 0 | nOBJID = SdrObjKind::FormDateField; |
1286 | 0 | break; |
1287 | 0 | case DataType::TIME: |
1288 | 0 | nOBJID = SdrObjKind::FormTimeField; |
1289 | 0 | break; |
1290 | 0 | case DataType::CHAR: |
1291 | 0 | case DataType::VARCHAR: |
1292 | 0 | default: |
1293 | 0 | nOBJID = SdrObjKind::FormEdit; |
1294 | 0 | break; |
1295 | 0 | } |
1296 | 0 | if (nOBJID == SdrObjKind::NONE) |
1297 | 0 | return nullptr; |
1298 | | |
1299 | 0 | rtl::Reference<SdrUnoObj> pLabel; |
1300 | 0 | rtl::Reference<SdrUnoObj> pControl; |
1301 | 0 | if ( !createControlLabelPair( *pOutDev, 0, 0, xField, xNumberFormats, nOBJID, sLabelPostfix, |
1302 | 0 | pLabel, pControl, xDataSource, sDataSource, sCommand, nCommandType ) |
1303 | 0 | ) |
1304 | 0 | { |
1305 | 0 | return nullptr; |
1306 | 0 | } |
1307 | | |
1308 | | |
1309 | | // group objects |
1310 | 0 | bool bCheckbox = ( SdrObjKind::FormCheckbox == nOBJID ); |
1311 | 0 | OSL_ENSURE( !bCheckbox || !pLabel, "FmXFormView::implCreateFieldControl: why was there a label created for a check box?" ); |
1312 | 0 | if ( bCheckbox ) |
1313 | 0 | return pControl; |
1314 | | |
1315 | 0 | rtl::Reference<SdrObjGroup> pGroup = new SdrObjGroup(getView()->getSdrModelFromSdrView()); |
1316 | 0 | SdrObjList* pObjList = pGroup->GetSubList(); |
1317 | 0 | pObjList->InsertObject( pLabel.get() ); |
1318 | 0 | pObjList->InsertObject( pControl.get() ); |
1319 | |
|
1320 | 0 | if ( bDateNTimeField ) |
1321 | 0 | { // so far we created a date field only, but we also need a time field |
1322 | 0 | if ( createControlLabelPair( *pOutDev, 0, 1000, xField, xNumberFormats, SdrObjKind::FormTimeField, |
1323 | 0 | SvxResId(RID_STR_POSTFIX_TIME), pLabel, pControl, |
1324 | 0 | xDataSource, sDataSource, sCommand, nCommandType ) |
1325 | 0 | ) |
1326 | 0 | { |
1327 | 0 | pObjList->InsertObject( pLabel.get() ); |
1328 | 0 | pObjList->InsertObject( pControl.get() ); |
1329 | 0 | } |
1330 | 0 | } |
1331 | |
|
1332 | 0 | return pGroup; // and done |
1333 | 0 | } |
1334 | 0 | catch (const Exception&) |
1335 | 0 | { |
1336 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
1337 | 0 | } |
1338 | | |
1339 | | |
1340 | 0 | return nullptr; |
1341 | 0 | } |
1342 | | |
1343 | | |
1344 | | rtl::Reference<SdrObject> FmXFormView::implCreateXFormsControl( const svx::OXFormsDescriptor &_rDesc ) |
1345 | 0 | { |
1346 | | // not if we're in design mode |
1347 | 0 | if ( !m_pView->IsDesignMode() ) |
1348 | 0 | return nullptr; |
1349 | | |
1350 | | // go |
1351 | 0 | try |
1352 | 0 | { |
1353 | | // determine the table/query field which we should create a control for |
1354 | 0 | Reference< XNumberFormats > xNumberFormats; |
1355 | 0 | OUString sLabelPostfix = _rDesc.szName; |
1356 | | |
1357 | | |
1358 | | // only for text size |
1359 | 0 | OutputDevice* pOutDev = nullptr; |
1360 | 0 | if (m_pView->GetActualOutDev() && m_pView->GetActualOutDev()->GetOutDevType() == OUTDEV_WINDOW) |
1361 | 0 | pOutDev = const_cast<OutputDevice*>(m_pView->GetActualOutDev()); |
1362 | 0 | else |
1363 | 0 | {// find OutDev |
1364 | 0 | if (SdrPageView* pPageView = m_pView->GetSdrPageView()) |
1365 | 0 | { |
1366 | | // const SdrPageViewWinList& rWinList = pPageView->GetWinList(); |
1367 | | // const SdrPageViewWindows& rPageViewWindows = pPageView->GetPageViewWindows(); |
1368 | |
|
1369 | 0 | for( sal_uInt32 i = 0; i < pPageView->PageWindowCount(); i++ ) |
1370 | 0 | { |
1371 | 0 | const SdrPageWindow& rPageWindow = *pPageView->GetPageWindow(i); |
1372 | |
|
1373 | 0 | if( rPageWindow.GetPaintWindow().GetOutputDevice().GetOutDevType() == OUTDEV_WINDOW) |
1374 | 0 | { |
1375 | 0 | pOutDev = &rPageWindow.GetPaintWindow().GetOutputDevice(); |
1376 | 0 | break; |
1377 | 0 | } |
1378 | 0 | } |
1379 | 0 | } |
1380 | 0 | } |
1381 | |
|
1382 | 0 | if ( !pOutDev ) |
1383 | 0 | return nullptr; |
1384 | | |
1385 | | |
1386 | | // The service name decides which control should be created |
1387 | 0 | SdrObjKind nOBJID = SdrObjKind::FormEdit; |
1388 | 0 | if(_rDesc.szServiceName == FM_SUN_COMPONENT_NUMERICFIELD) |
1389 | 0 | nOBJID = SdrObjKind::FormNumericField; |
1390 | 0 | if(_rDesc.szServiceName == FM_SUN_COMPONENT_CHECKBOX) |
1391 | 0 | nOBJID = SdrObjKind::FormCheckbox; |
1392 | 0 | if(_rDesc.szServiceName == FM_COMPONENT_COMMANDBUTTON) |
1393 | 0 | nOBJID = SdrObjKind::FormButton; |
1394 | |
|
1395 | 0 | Reference< css::form::submission::XSubmission > xSubmission(_rDesc.xPropSet, UNO_QUERY); |
1396 | | |
1397 | | // xform control or submission button? |
1398 | 0 | if ( !xSubmission.is() ) |
1399 | 0 | { |
1400 | 0 | rtl::Reference<SdrUnoObj> pLabel; |
1401 | 0 | rtl::Reference<SdrUnoObj> pControl; |
1402 | 0 | if ( !createControlLabelPair( *pOutDev, 0, 0, nullptr, xNumberFormats, nOBJID, sLabelPostfix, |
1403 | 0 | pLabel, pControl, nullptr, u""_ustr, u""_ustr, -1 ) |
1404 | 0 | ) |
1405 | 0 | { |
1406 | 0 | return nullptr; |
1407 | 0 | } |
1408 | | |
1409 | | |
1410 | | // Now build the connection between the control and the data item. |
1411 | 0 | Reference< XValueBinding > xValueBinding(_rDesc.xPropSet,UNO_QUERY); |
1412 | 0 | Reference< XBindableValue > xBindableValue(pControl->GetUnoControlModel(),UNO_QUERY); |
1413 | |
|
1414 | 0 | DBG_ASSERT( xBindableValue.is(), "FmXFormView::implCreateXFormsControl: control's not bindable!" ); |
1415 | 0 | if ( xBindableValue.is() ) |
1416 | 0 | xBindableValue->setValueBinding(xValueBinding); |
1417 | |
|
1418 | 0 | bool bCheckbox = ( SdrObjKind::FormCheckbox == nOBJID ); |
1419 | 0 | OSL_ENSURE( !bCheckbox || !pLabel, "FmXFormView::implCreateXFormsControl: why was there a label created for a check box?" ); |
1420 | 0 | if ( bCheckbox ) |
1421 | 0 | return pControl; |
1422 | | |
1423 | | |
1424 | | // group objects |
1425 | 0 | rtl::Reference<SdrObjGroup> pGroup = new SdrObjGroup(getView()->getSdrModelFromSdrView()); |
1426 | 0 | SdrObjList* pObjList = pGroup->GetSubList(); |
1427 | 0 | pObjList->InsertObject(pLabel.get()); |
1428 | 0 | pObjList->InsertObject(pControl.get()); |
1429 | |
|
1430 | 0 | return pGroup; |
1431 | 0 | } |
1432 | 0 | else { |
1433 | | |
1434 | | // create a button control |
1435 | 0 | const MapMode& eTargetMode( pOutDev->GetMapMode() ); |
1436 | 0 | const MapMode eSourceMode(MapUnit::Map100thMM); |
1437 | 0 | const SdrObjKind nObjID = SdrObjKind::FormButton; |
1438 | 0 | ::Size controlSize(4000, 500); |
1439 | 0 | rtl::Reference<FmFormObj> pControl = static_cast<FmFormObj*>( |
1440 | 0 | SdrObjFactory::MakeNewObject( |
1441 | 0 | getView()->getSdrModelFromSdrView(), |
1442 | 0 | SdrInventor::FmForm, |
1443 | 0 | nObjID).get()); |
1444 | 0 | controlSize.setWidth( tools::Long(controlSize.Width() * eTargetMode.GetScaleX()) ); |
1445 | 0 | controlSize.setHeight( tools::Long(controlSize.Height() * eTargetMode.GetScaleY()) ); |
1446 | 0 | ::Point controlPos( OutputDevice::LogicToLogic( ::Point( controlSize.Width(), 0 ), eSourceMode, eTargetMode ) ); |
1447 | 0 | ::tools::Rectangle controlRect( controlPos, OutputDevice::LogicToLogic( controlSize, eSourceMode, eTargetMode ) ); |
1448 | 0 | pControl->SetLogicRect(controlRect); |
1449 | | |
1450 | | // set the button label |
1451 | 0 | Reference< XPropertySet > xControlSet(pControl->GetUnoControlModel(), UNO_QUERY); |
1452 | 0 | xControlSet->setPropertyValue(FM_PROP_LABEL, Any(_rDesc.szName)); |
1453 | | |
1454 | | // connect the submission with the submission supplier (aka the button) |
1455 | 0 | xControlSet->setPropertyValue( FM_PROP_BUTTON_TYPE, |
1456 | 0 | Any( FormButtonType_SUBMIT ) ); |
1457 | 0 | Reference< css::form::submission::XSubmissionSupplier > xSubmissionSupplier(pControl->GetUnoControlModel(), UNO_QUERY); |
1458 | 0 | xSubmissionSupplier->setSubmission(xSubmission); |
1459 | |
|
1460 | 0 | return rtl::Reference<SdrObject>(pControl); |
1461 | 0 | } |
1462 | 0 | } |
1463 | 0 | catch (const Exception&) |
1464 | 0 | { |
1465 | 0 | TOOLS_WARN_EXCEPTION("svx.form", "caught an exception while creating the control !"); |
1466 | 0 | } |
1467 | | |
1468 | | |
1469 | 0 | return nullptr; |
1470 | 0 | } |
1471 | | |
1472 | | bool FmXFormView::createControlLabelPair( OutputDevice const & _rOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM, |
1473 | | const Reference< XPropertySet >& _rxField, const Reference< XNumberFormats >& _rxNumberFormats, |
1474 | | SdrObjKind _nControlObjectID, std::u16string_view _rFieldPostfix, |
1475 | | rtl::Reference<SdrUnoObj>& _rpLabel, |
1476 | | rtl::Reference<SdrUnoObj>& _rpControl, |
1477 | | const Reference< XDataSource >& _rxDataSource, const OUString& _rDataSourceName, |
1478 | | const OUString& _rCommand, const sal_Int32 _nCommandType ) |
1479 | 0 | { |
1480 | 0 | if(!createControlLabelPair( |
1481 | 0 | _rOutDev, |
1482 | 0 | _nXOffsetMM, |
1483 | 0 | _nYOffsetMM, |
1484 | 0 | _rxField, |
1485 | 0 | _rxNumberFormats, |
1486 | 0 | _nControlObjectID, |
1487 | 0 | _rFieldPostfix, |
1488 | 0 | SdrInventor::FmForm, |
1489 | 0 | SdrObjKind::FormFixedText, |
1490 | | |
1491 | | // tdf#118963 Hand over a SdrModel to SdrObject-creation. It uses the local m_pView |
1492 | | // and already returning false when nullptr == getView() could be done, but m_pView |
1493 | | // is already dereferenced here in many places (see below), so just use it for now. |
1494 | 0 | getView()->getSdrModelFromSdrView(), |
1495 | |
|
1496 | 0 | _rpLabel, |
1497 | 0 | _rpControl)) |
1498 | 0 | { |
1499 | 0 | return false; |
1500 | 0 | } |
1501 | | |
1502 | | // insert the control model(s) into the form component hierarchy |
1503 | 0 | if ( _rpLabel ) |
1504 | 0 | lcl_insertIntoFormComponentHierarchy_throw( *m_pView, *_rpLabel, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType ); |
1505 | 0 | lcl_insertIntoFormComponentHierarchy_throw( *m_pView, *_rpControl, _rxDataSource, _rDataSourceName, _rCommand, _nCommandType ); |
1506 | | |
1507 | | // some context-dependent initializations |
1508 | 0 | FormControlFactory aControlFactory; |
1509 | 0 | if ( _rpLabel ) |
1510 | 0 | aControlFactory.initializeControlModel( impl_getDocumentType(), *_rpLabel ); |
1511 | 0 | aControlFactory.initializeControlModel( impl_getDocumentType(), *_rpControl ); |
1512 | |
|
1513 | 0 | return true; |
1514 | 0 | } |
1515 | | |
1516 | | |
1517 | | bool FmXFormView::createControlLabelPair( OutputDevice const & _rOutDev, sal_Int32 _nXOffsetMM, sal_Int32 _nYOffsetMM, |
1518 | | const Reference< XPropertySet >& _rxField, |
1519 | | const Reference< XNumberFormats >& _rxNumberFormats, SdrObjKind _nControlObjectID, |
1520 | | std::u16string_view _rFieldPostfix, SdrInventor _nInventor, SdrObjKind _nLabelObjectID, |
1521 | | SdrModel& _rModel, |
1522 | | rtl::Reference<SdrUnoObj>& _rpLabel, rtl::Reference<SdrUnoObj>& _rpControl) |
1523 | 0 | { |
1524 | 0 | sal_Int32 nDataType = 0; |
1525 | 0 | OUString sFieldName; |
1526 | 0 | Any aFieldName; |
1527 | 0 | if ( _rxField.is() ) |
1528 | 0 | { |
1529 | 0 | nDataType = ::comphelper::getINT32(_rxField->getPropertyValue(FM_PROP_FIELDTYPE)); |
1530 | 0 | aFieldName = _rxField->getPropertyValue(FM_PROP_NAME); |
1531 | 0 | aFieldName >>= sFieldName; |
1532 | 0 | } |
1533 | | |
1534 | | // calculate the positions, respecting the settings of the target device |
1535 | 0 | ::Size aTextSize( _rOutDev.GetTextWidth(sFieldName + _rFieldPostfix), _rOutDev.GetTextHeight() ); |
1536 | |
|
1537 | 0 | const MapMode & eTargetMode( _rOutDev.GetMapMode() ); |
1538 | 0 | MapMode eSourceMode( MapUnit::Map100thMM ); |
1539 | | |
1540 | | // text width is at least 4 centimeters |
1541 | | // text height is always half a centimeter |
1542 | 0 | ::Size aDefTxtSize(4000, 500); |
1543 | 0 | ::Size aDefSize(4000, 500); |
1544 | 0 | ::Size aDefImageSize(4000, 4000); |
1545 | |
|
1546 | 0 | ::Size aRealSize = OutputDevice::LogicToLogic(aTextSize, eTargetMode, eSourceMode); |
1547 | 0 | aRealSize.setWidth( std::max(aRealSize.Width(), aDefTxtSize.Width()) ); |
1548 | 0 | aRealSize.setHeight( aDefSize.Height() ); |
1549 | | |
1550 | | // adjust to scaling of the target device (#53523#) |
1551 | 0 | aRealSize.setWidth( tools::Long(Fraction(aRealSize.Width(), 1) * eTargetMode.GetScaleX()) ); |
1552 | 0 | aRealSize.setHeight( tools::Long(Fraction(aRealSize.Height(), 1) * eTargetMode.GetScaleY()) ); |
1553 | | |
1554 | | // for boolean fields, we do not create a label, but just a checkbox |
1555 | 0 | bool bNeedLabel = ( _nControlObjectID != SdrObjKind::FormCheckbox ); |
1556 | | |
1557 | | // the label |
1558 | 0 | rtl::Reference< SdrUnoObj > pLabel; |
1559 | 0 | Reference< XPropertySet > xLabelModel; |
1560 | |
|
1561 | 0 | if ( bNeedLabel ) |
1562 | 0 | { |
1563 | 0 | pLabel = dynamic_cast< SdrUnoObj* >( |
1564 | 0 | SdrObjFactory::MakeNewObject( |
1565 | 0 | _rModel, |
1566 | 0 | _nInventor, |
1567 | 0 | _nLabelObjectID).get() ); |
1568 | |
|
1569 | 0 | OSL_ENSURE(pLabel, "FmXFormView::createControlLabelPair: could not create the label!"); |
1570 | |
|
1571 | 0 | if (!pLabel) |
1572 | 0 | return false; |
1573 | | |
1574 | 0 | xLabelModel.set( pLabel->GetUnoControlModel(), UNO_QUERY ); |
1575 | 0 | if ( xLabelModel.is() ) |
1576 | 0 | { |
1577 | 0 | OUString sLabel; |
1578 | 0 | if ( _rxField.is() && _rxField->getPropertySetInfo()->hasPropertyByName(FM_PROP_LABEL) ) |
1579 | 0 | _rxField->getPropertyValue(FM_PROP_LABEL) >>= sLabel; |
1580 | 0 | if ( sLabel.isEmpty() ) |
1581 | 0 | sLabel = sFieldName; |
1582 | |
|
1583 | 0 | xLabelModel->setPropertyValue( FM_PROP_LABEL, Any( sLabel + _rFieldPostfix ) ); |
1584 | 0 | OUString sObjectLabel(SvxResId(RID_STR_OBJECT_LABEL).replaceAll("#object#", sFieldName)); |
1585 | 0 | xLabelModel->setPropertyValue(FM_PROP_NAME, Any(sObjectLabel)); |
1586 | 0 | } |
1587 | |
|
1588 | 0 | pLabel->SetLogicRect( ::tools::Rectangle( |
1589 | 0 | OutputDevice::LogicToLogic( ::Point( _nXOffsetMM, _nYOffsetMM ), eSourceMode, eTargetMode ), |
1590 | 0 | OutputDevice::LogicToLogic( aRealSize, eSourceMode, eTargetMode ) |
1591 | 0 | ) ); |
1592 | 0 | } |
1593 | | |
1594 | | // the control |
1595 | 0 | rtl::Reference< SdrUnoObj > pControl( dynamic_cast< SdrUnoObj* >( |
1596 | 0 | SdrObjFactory::MakeNewObject( |
1597 | 0 | _rModel, |
1598 | 0 | _nInventor, |
1599 | 0 | _nControlObjectID).get() )); |
1600 | |
|
1601 | 0 | OSL_ENSURE(pControl, "FmXFormView::createControlLabelPair: could not create the control!"); |
1602 | |
|
1603 | 0 | if (!pControl) |
1604 | 0 | return false; |
1605 | | |
1606 | 0 | Reference< XPropertySet > xControlSet( pControl->GetUnoControlModel(), UNO_QUERY ); |
1607 | 0 | if ( !xControlSet.is() ) |
1608 | 0 | return false; |
1609 | | |
1610 | | // size of the control |
1611 | 0 | ::Size aControlSize( aDefSize ); |
1612 | 0 | switch ( nDataType ) |
1613 | 0 | { |
1614 | 0 | case DataType::BIT: |
1615 | 0 | case DataType::BOOLEAN: |
1616 | 0 | aControlSize = aDefSize; |
1617 | 0 | break; |
1618 | 0 | case DataType::LONGVARCHAR: |
1619 | 0 | case DataType::CLOB: |
1620 | 0 | case DataType::LONGVARBINARY: |
1621 | 0 | case DataType::BLOB: |
1622 | 0 | aControlSize = aDefImageSize; |
1623 | 0 | break; |
1624 | 0 | } |
1625 | | |
1626 | 0 | if ( SdrObjKind::FormImageControl == _nControlObjectID ) |
1627 | 0 | aControlSize = aDefImageSize; |
1628 | |
|
1629 | 0 | aControlSize.setWidth( tools::Long(Fraction(aControlSize.Width(), 1) * eTargetMode.GetScaleX()) ); |
1630 | 0 | aControlSize.setHeight( tools::Long(Fraction(aControlSize.Height(), 1) * eTargetMode.GetScaleY()) ); |
1631 | |
|
1632 | 0 | pControl->SetLogicRect( ::tools::Rectangle( |
1633 | 0 | OutputDevice::LogicToLogic( ::Point( aRealSize.Width() + _nXOffsetMM, _nYOffsetMM ), eSourceMode, eTargetMode ), |
1634 | 0 | OutputDevice::LogicToLogic( aControlSize, eSourceMode, eTargetMode ) |
1635 | 0 | ) ); |
1636 | | |
1637 | | // some initializations |
1638 | 0 | Reference< XPropertySetInfo > xControlPropInfo = xControlSet->getPropertySetInfo(); |
1639 | |
|
1640 | 0 | if ( aFieldName.hasValue() ) |
1641 | 0 | { |
1642 | 0 | xControlSet->setPropertyValue( FM_PROP_CONTROLSOURCE, aFieldName ); |
1643 | 0 | xControlSet->setPropertyValue( FM_PROP_NAME, aFieldName ); |
1644 | 0 | if ( !bNeedLabel ) |
1645 | 0 | { |
1646 | | // no dedicated label control => use the label property |
1647 | 0 | if ( xControlPropInfo->hasPropertyByName( FM_PROP_LABEL ) ) |
1648 | 0 | xControlSet->setPropertyValue( FM_PROP_LABEL, Any( sFieldName + _rFieldPostfix ) ); |
1649 | 0 | else |
1650 | 0 | OSL_FAIL( "FmXFormView::createControlLabelPair: can't set a label for the control!" ); |
1651 | 0 | } |
1652 | 0 | } |
1653 | |
|
1654 | 0 | if ( (nDataType == DataType::LONGVARCHAR || nDataType == DataType::CLOB) && xControlPropInfo->hasPropertyByName( FM_PROP_MULTILINE ) ) |
1655 | 0 | { |
1656 | 0 | xControlSet->setPropertyValue( FM_PROP_MULTILINE, Any( true ) ); |
1657 | 0 | } |
1658 | | |
1659 | | // announce the label to the control |
1660 | 0 | if ( xControlPropInfo->hasPropertyByName( FM_PROP_CONTROLLABEL ) && xLabelModel.is() ) |
1661 | 0 | { |
1662 | 0 | try |
1663 | 0 | { |
1664 | 0 | xControlSet->setPropertyValue( FM_PROP_CONTROLLABEL, Any( xLabelModel ) ); |
1665 | 0 | } |
1666 | 0 | catch (const Exception&) |
1667 | 0 | { |
1668 | 0 | DBG_UNHANDLED_EXCEPTION("svx"); |
1669 | 0 | } |
1670 | 0 | } |
1671 | |
|
1672 | 0 | if ( _rxField.is() ) |
1673 | 0 | { |
1674 | 0 | FormControlFactory::initializeFieldDependentProperties( _rxField, xControlSet, _rxNumberFormats ); |
1675 | 0 | } |
1676 | |
|
1677 | 0 | _rpLabel = std::move(pLabel); |
1678 | 0 | _rpControl = std::move(pControl); |
1679 | 0 | return true; |
1680 | 0 | } |
1681 | | |
1682 | | |
1683 | | FmXFormView::ObjectRemoveListener::ObjectRemoveListener( FmXFormView* pParent ) |
1684 | 13 | :m_pParent( pParent ) |
1685 | 13 | { |
1686 | 13 | } |
1687 | | |
1688 | | |
1689 | | void FmXFormView::ObjectRemoveListener::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) |
1690 | 0 | { |
1691 | 0 | if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint) |
1692 | 0 | return; |
1693 | 0 | const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint); |
1694 | 0 | if (pSdrHint->GetKind() == SdrHintKind::ObjectRemoved) |
1695 | 0 | m_pParent->ObjectRemovedInAliveMode(pSdrHint->GetObject()); |
1696 | 0 | } |
1697 | | |
1698 | | |
1699 | | void FmXFormView::ObjectRemovedInAliveMode( const SdrObject* pObject ) |
1700 | 0 | { |
1701 | | // if the remote object in my MarkList, which I have memorized when switching to the |
1702 | | // Alive mode, I have to take it out now, because I otherwise try to set the mark |
1703 | | // again when switching back (interestingly, this fails only with grouped objects |
1704 | | // (when accessing their ObjList GPF), not with individual ones) |
1705 | |
|
1706 | 0 | const size_t nCount = m_aMark.GetMarkCount(); |
1707 | 0 | for (size_t i = 0; i < nCount; ++i) |
1708 | 0 | { |
1709 | 0 | SdrMark* pMark = m_aMark.GetMark(i); |
1710 | 0 | SdrObject* pCurrent = pMark->GetMarkedSdrObj(); |
1711 | 0 | if (pObject == pCurrent) |
1712 | 0 | { |
1713 | 0 | m_aMark.DeleteMark(i); |
1714 | 0 | return; |
1715 | 0 | } |
1716 | | // I do not need to descend into GroupObjects: if an object is deleted there, |
1717 | | // then the pointer, which I have, to the GroupObject still remains valid ... |
1718 | 0 | } |
1719 | 0 | } |
1720 | | |
1721 | | |
1722 | | void FmXFormView::stopMarkListWatching() |
1723 | 4.56k | { |
1724 | 4.56k | if ( m_pWatchStoredList ) |
1725 | 0 | { |
1726 | 0 | m_pWatchStoredList->EndListeningAll(); |
1727 | 0 | m_pWatchStoredList.reset(); |
1728 | 0 | } |
1729 | 4.56k | } |
1730 | | |
1731 | | |
1732 | | void FmXFormView::startMarkListWatching() |
1733 | 13 | { |
1734 | 13 | if ( !m_pWatchStoredList ) |
1735 | 13 | { |
1736 | 13 | FmFormModel* pModel = GetFormShell() ? GetFormShell()->GetFormModel() : nullptr; |
1737 | 13 | DBG_ASSERT( pModel != nullptr, "FmXFormView::startMarkListWatching: shell has no model!" ); |
1738 | 13 | if (pModel) |
1739 | 13 | { |
1740 | 13 | m_pWatchStoredList.reset(new ObjectRemoveListener( this )); |
1741 | 13 | m_pWatchStoredList->StartListening( *static_cast< SfxBroadcaster* >( pModel ) ); |
1742 | 13 | } |
1743 | 13 | } |
1744 | 0 | else |
1745 | 0 | { |
1746 | 0 | OSL_FAIL( "FmXFormView::startMarkListWatching: already listening!" ); |
1747 | 0 | } |
1748 | 13 | } |
1749 | | |
1750 | | void FmXFormView::saveMarkList() |
1751 | 13 | { |
1752 | 13 | if ( m_pView ) |
1753 | 13 | { |
1754 | 13 | m_aMark = m_pView->GetMarkedObjectList(); |
1755 | 13 | const size_t nCount = m_aMark.GetMarkCount( ); |
1756 | 13 | for ( size_t i = 0; i < nCount; ++i ) |
1757 | 0 | { |
1758 | 0 | SdrMark* pMark = m_aMark.GetMark(i); |
1759 | 0 | SdrObject* pObj = pMark->GetMarkedSdrObj(); |
1760 | |
|
1761 | 0 | if ( m_pView->IsObjMarked( pObj ) ) |
1762 | 0 | { |
1763 | 0 | if ( pObj->IsGroupObject() ) |
1764 | 0 | { |
1765 | 0 | SdrObjListIter aIter( pObj->GetSubList() ); |
1766 | 0 | bool bMixed = false; |
1767 | 0 | while ( aIter.IsMore() && !bMixed ) |
1768 | 0 | bMixed = ( aIter.Next()->GetObjInventor() != SdrInventor::FmForm ); |
1769 | |
|
1770 | 0 | if ( !bMixed ) |
1771 | 0 | { |
1772 | | // all objects in the group are form objects |
1773 | 0 | m_pView->MarkObj( pMark->GetMarkedSdrObj(), pMark->GetPageView(), true /* unmark! */ ); |
1774 | 0 | } |
1775 | 0 | } |
1776 | 0 | else |
1777 | 0 | { |
1778 | 0 | if ( pObj->GetObjInventor() == SdrInventor::FmForm ) |
1779 | 0 | { // this is a form layer object |
1780 | 0 | m_pView->MarkObj( pMark->GetMarkedSdrObj(), pMark->GetPageView(), true /* unmark! */ ); |
1781 | 0 | } |
1782 | 0 | } |
1783 | 0 | } |
1784 | 0 | } |
1785 | 13 | } |
1786 | 0 | else |
1787 | 0 | { |
1788 | 0 | OSL_FAIL( "FmXFormView::saveMarkList: invalid view!" ); |
1789 | 0 | m_aMark.Clear(); |
1790 | 0 | } |
1791 | 13 | } |
1792 | | |
1793 | | static bool lcl_hasObject( SdrObjListIter& rIter, SdrObject const * pObj ) |
1794 | 0 | { |
1795 | 0 | bool bFound = false; |
1796 | 0 | while (rIter.IsMore() && !bFound) |
1797 | 0 | bFound = pObj == rIter.Next(); |
1798 | |
|
1799 | 0 | rIter.Reset(); |
1800 | 0 | return bFound; |
1801 | 0 | } |
1802 | | |
1803 | | |
1804 | | void FmXFormView::restoreMarkList( SdrMarkList& _rRestoredMarkList ) |
1805 | 4.56k | { |
1806 | 4.56k | if ( !m_pView ) |
1807 | 0 | return; |
1808 | | |
1809 | 4.56k | _rRestoredMarkList.Clear(); |
1810 | | |
1811 | 4.56k | const SdrMarkList& rCurrentList = m_pView->GetMarkedObjectList(); |
1812 | 4.56k | FmFormPage* pPage = GetFormShell() ? GetFormShell()->GetCurPage() : nullptr; |
1813 | 4.56k | if (!pPage) |
1814 | 0 | return; |
1815 | | |
1816 | 4.56k | if (rCurrentList.GetMarkCount()) |
1817 | 0 | { // there is a current mark ... hmm. Is it a subset of the mark we remembered in saveMarkList? |
1818 | 0 | bool bMisMatch = false; |
1819 | | |
1820 | | // loop through all current marks |
1821 | 0 | const size_t nCurrentCount = rCurrentList.GetMarkCount(); |
1822 | 0 | for ( size_t i=0; i<nCurrentCount && !bMisMatch; ++i ) |
1823 | 0 | { |
1824 | 0 | const SdrObject* pCurrentMarked = rCurrentList.GetMark( i )->GetMarkedSdrObj(); |
1825 | | |
1826 | | // loop through all saved marks, check for equality |
1827 | 0 | bool bFound = false; |
1828 | 0 | const size_t nSavedCount = m_aMark.GetMarkCount(); |
1829 | 0 | for ( size_t j=0; j<nSavedCount && !bFound; ++j ) |
1830 | 0 | { |
1831 | 0 | if ( m_aMark.GetMark( j )->GetMarkedSdrObj() == pCurrentMarked ) |
1832 | 0 | bFound = true; |
1833 | 0 | } |
1834 | | |
1835 | | // did not find a current mark in the saved marks |
1836 | 0 | if ( !bFound ) |
1837 | 0 | bMisMatch = true; |
1838 | 0 | } |
1839 | |
|
1840 | 0 | if ( bMisMatch ) |
1841 | 0 | { |
1842 | 0 | m_aMark.Clear(); |
1843 | 0 | _rRestoredMarkList = rCurrentList; |
1844 | 0 | return; |
1845 | 0 | } |
1846 | 0 | } |
1847 | | // it is important that the objects of the mark list are not accessed, |
1848 | | // because they can be already destroyed |
1849 | 4.56k | SdrPageView* pCurPageView = m_pView->GetSdrPageView(); |
1850 | 4.56k | SdrObjListIter aPageIter( pPage ); |
1851 | 4.56k | bool bFound = true; |
1852 | | |
1853 | | // do all objects still exist |
1854 | 4.56k | const size_t nCount = m_aMark.GetMarkCount(); |
1855 | 4.56k | for (size_t i = 0; i < nCount && bFound; ++i) |
1856 | 0 | { |
1857 | 0 | SdrMark* pMark = m_aMark.GetMark(i); |
1858 | 0 | SdrObject* pObj = pMark->GetMarkedSdrObj(); |
1859 | 0 | if (pObj->IsGroupObject()) |
1860 | 0 | { |
1861 | 0 | SdrObjListIter aIter(pObj->GetSubList()); |
1862 | 0 | while (aIter.IsMore() && bFound) |
1863 | 0 | bFound = lcl_hasObject(aPageIter, aIter.Next()); |
1864 | 0 | } |
1865 | 0 | else |
1866 | 0 | bFound = lcl_hasObject(aPageIter, pObj); |
1867 | |
|
1868 | 0 | bFound = bFound && pCurPageView == pMark->GetPageView(); |
1869 | 0 | } |
1870 | | |
1871 | 4.56k | if (bFound) |
1872 | 4.56k | { |
1873 | | // evaluate the LastObject |
1874 | 4.56k | if (nCount) // now mark the objects |
1875 | 0 | { |
1876 | 0 | for (size_t i = 0; i < nCount; ++i) |
1877 | 0 | { |
1878 | 0 | SdrMark* pMark = m_aMark.GetMark(i); |
1879 | 0 | SdrObject* pObj = pMark->GetMarkedSdrObj(); |
1880 | 0 | if ( pObj->GetObjInventor() == SdrInventor::FmForm ) |
1881 | 0 | if ( !m_pView->IsObjMarked( pObj ) ) |
1882 | 0 | m_pView->MarkObj( pObj, pMark->GetPageView() ); |
1883 | 0 | } |
1884 | |
|
1885 | 0 | _rRestoredMarkList = m_aMark; |
1886 | 0 | } |
1887 | 4.56k | } |
1888 | 4.56k | m_aMark.Clear(); |
1889 | 4.56k | } |
1890 | | |
1891 | | void SAL_CALL FmXFormView::focusGained( const FocusEvent& /*e*/ ) |
1892 | 0 | { |
1893 | 0 | if ( m_xWindow.is() && m_pView ) |
1894 | 0 | { |
1895 | 0 | m_pView->SetMoveOutside( true, FmFormView::ImplAccess() ); |
1896 | 0 | } |
1897 | 0 | } |
1898 | | |
1899 | | void SAL_CALL FmXFormView::focusLost( const FocusEvent& /*e*/ ) |
1900 | 0 | { |
1901 | | // when switch the focus outside the office the mark didn't change |
1902 | | // so we can not remove us as focus listener |
1903 | 0 | if ( m_xWindow.is() && m_pView ) |
1904 | 0 | { |
1905 | 0 | m_pView->SetMoveOutside( false, FmFormView::ImplAccess() ); |
1906 | 0 | } |
1907 | 0 | } |
1908 | | |
1909 | | DocumentType FmXFormView::impl_getDocumentType() const |
1910 | 0 | { |
1911 | 0 | if ( GetFormShell() && GetFormShell()->GetImpl() ) |
1912 | 0 | return GetFormShell()->GetImpl()->getDocumentType_Lock(); |
1913 | 0 | return eUnknownDocumentType; |
1914 | 0 | } |
1915 | | |
1916 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |