Line data Source code
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 : #include "fmobj.hxx"
21 : #include "fmprop.hrc"
22 : #include "fmvwimp.hxx"
23 : #include "fmpgeimp.hxx"
24 : #include "svx/fmresids.hrc"
25 : #include "svx/fmview.hxx"
26 : #include "svx/fmglob.hxx"
27 : #include "svx/fmpage.hxx"
28 : #include "editeng/editeng.hxx"
29 : #include "svx/svdovirt.hxx"
30 : #include "svx/fmmodel.hxx"
31 : #include "svx/dialmgr.hxx"
32 :
33 : #include <com/sun/star/awt/XDevice.hpp>
34 : #include <com/sun/star/script/XEventAttacherManager.hpp>
35 : #include <com/sun/star/io/XPersistObject.hpp>
36 : #include <com/sun/star/awt/XControlContainer.hpp>
37 : #include <com/sun/star/util/XCloneable.hpp>
38 : #include "svx/fmtools.hxx"
39 :
40 : #include <tools/shl.hxx>
41 : #include <comphelper/property.hxx>
42 : #include <comphelper/processfactory.hxx>
43 : #include <toolkit/awt/vclxdevice.hxx>
44 : #include <vcl/svapp.hxx>
45 : #include <tools/diagnose_ex.h>
46 :
47 : using namespace ::com::sun::star::io;
48 : using namespace ::com::sun::star::uno;
49 : using namespace ::com::sun::star::awt;
50 : using namespace ::com::sun::star::lang;
51 : using namespace ::com::sun::star::util;
52 : using namespace ::com::sun::star::form;
53 : using namespace ::com::sun::star::beans;
54 : using namespace ::com::sun::star::script;
55 : using namespace ::com::sun::star::container;
56 : using namespace ::svxform;
57 :
58 221 : TYPEINIT1(FmFormObj, SdrUnoObj);
59 : DBG_NAME(FmFormObj);
60 : //------------------------------------------------------------------
61 0 : FmFormObj::FmFormObj(const ::rtl::OUString& rModelName)
62 : :SdrUnoObj ( rModelName )
63 : ,m_nPos ( -1 )
64 0 : ,m_pLastKnownRefDevice ( NULL )
65 : {
66 : DBG_CTOR(FmFormObj, NULL);
67 :
68 : // normally, this is done in SetUnoControlModel, but if the call happened in the base class ctor,
69 : // then our incarnation of it was not called (since we were not constructed at this time).
70 0 : impl_checkRefDevice_nothrow( true );
71 0 : }
72 :
73 : //------------------------------------------------------------------
74 9 : FmFormObj::FmFormObj()
75 : :SdrUnoObj ( String() )
76 : ,m_nPos ( -1 )
77 9 : ,m_pLastKnownRefDevice ( NULL )
78 : {
79 : DBG_CTOR(FmFormObj, NULL);
80 9 : }
81 :
82 : //------------------------------------------------------------------
83 27 : FmFormObj::~FmFormObj()
84 : {
85 : DBG_DTOR(FmFormObj, NULL);
86 :
87 9 : Reference< XComponent> xHistory(m_xEnvironmentHistory, UNO_QUERY);
88 9 : if (xHistory.is())
89 0 : xHistory->dispose();
90 :
91 9 : m_xEnvironmentHistory = NULL;
92 9 : m_aEventsHistory.realloc(0);
93 18 : }
94 :
95 : //------------------------------------------------------------------
96 0 : void FmFormObj::SetObjEnv(const Reference< XIndexContainer > & xForm, const sal_Int32 nIdx,
97 : const Sequence< ScriptEventDescriptor >& rEvts)
98 : {
99 0 : m_xParent = xForm;
100 0 : aEvts = rEvts;
101 0 : m_nPos = nIdx;
102 0 : }
103 :
104 : //------------------------------------------------------------------
105 0 : void FmFormObj::ClearObjEnv()
106 : {
107 0 : m_xParent.clear();
108 0 : aEvts.realloc( 0 );
109 0 : m_nPos = -1;
110 0 : }
111 :
112 : //------------------------------------------------------------------
113 18 : void FmFormObj::impl_checkRefDevice_nothrow( bool _force )
114 : {
115 18 : const FmFormModel* pFormModel = PTR_CAST( FmFormModel, GetModel() );
116 18 : if ( !pFormModel || !pFormModel->ControlsUseRefDevice() )
117 : return;
118 :
119 0 : OutputDevice* pCurrentRefDevice = pFormModel ? pFormModel->GetRefDevice() : NULL;
120 0 : if ( ( m_pLastKnownRefDevice == pCurrentRefDevice ) && !_force )
121 : return;
122 :
123 0 : Reference< XControlModel > xControlModel( GetUnoControlModel() );
124 0 : if ( !xControlModel.is() )
125 : return;
126 :
127 0 : m_pLastKnownRefDevice = pCurrentRefDevice;
128 0 : if ( m_pLastKnownRefDevice == NULL )
129 : return;
130 :
131 : try
132 : {
133 0 : Reference< XPropertySet > xModelProps( GetUnoControlModel(), UNO_QUERY_THROW );
134 0 : Reference< XPropertySetInfo > xPropertyInfo( xModelProps->getPropertySetInfo(), UNO_SET_THROW );
135 :
136 0 : static const ::rtl::OUString sRefDevicePropName( RTL_CONSTASCII_USTRINGPARAM( "ReferenceDevice" ) );
137 0 : if ( xPropertyInfo->hasPropertyByName( sRefDevicePropName ) )
138 : {
139 0 : VCLXDevice* pUnoRefDevice = new VCLXDevice;
140 0 : pUnoRefDevice->SetOutputDevice( m_pLastKnownRefDevice );
141 0 : Reference< XDevice > xRefDevice( pUnoRefDevice );
142 0 : xModelProps->setPropertyValue( sRefDevicePropName, makeAny( xRefDevice ) );
143 0 : }
144 : }
145 0 : catch( const Exception& )
146 : {
147 : DBG_UNHANDLED_EXCEPTION();
148 0 : }
149 : }
150 :
151 : //------------------------------------------------------------------
152 0 : void FmFormObj::impl_isolateControlModel_nothrow()
153 : {
154 : try
155 : {
156 0 : Reference< XChild > xControlModel( GetUnoControlModel(), UNO_QUERY );
157 0 : if ( xControlModel.is() )
158 : {
159 0 : Reference< XIndexContainer> xParent( xControlModel->getParent(), UNO_QUERY );
160 0 : if ( xParent.is() )
161 : {
162 0 : sal_Int32 nPos = getElementPos( xParent.get(), xControlModel );
163 0 : xParent->removeByIndex( nPos );
164 0 : }
165 0 : }
166 : }
167 0 : catch( const Exception& )
168 : {
169 : DBG_UNHANDLED_EXCEPTION();
170 : }
171 0 : }
172 :
173 : //------------------------------------------------------------------
174 9 : void FmFormObj::SetPage(SdrPage* _pNewPage)
175 : {
176 9 : if ( GetPage() == _pNewPage )
177 : {
178 0 : SdrUnoObj::SetPage(_pNewPage);
179 : return;
180 : }
181 :
182 9 : FmFormPage* pOldFormPage = PTR_CAST( FmFormPage, GetPage() );
183 9 : if ( pOldFormPage )
184 0 : pOldFormPage->GetImpl().formObjectRemoved( *this );
185 :
186 9 : FmFormPage* pNewFormPage = PTR_CAST( FmFormPage, _pNewPage );
187 9 : if ( !pNewFormPage )
188 : { // Maybe it makes sense to create an environment history here : if somebody set's our page to NULL, and we have a valid page before,
189 : // me may want to remember our place within the old page. For this we could create a new m_xEnvironmentHistory to store it.
190 : // So the next SetPage with a valid new page would restore that environment within the new page.
191 : // But for the original Bug (#57300#) we don't need that, so I omit it here. Maybe this will be implemented later.
192 0 : impl_isolateControlModel_nothrow();
193 0 : SdrUnoObj::SetPage(_pNewPage);
194 : return;
195 : }
196 :
197 9 : Reference< XIndexContainer > xNewPageForms( pNewFormPage->GetForms( true ), UNO_QUERY );
198 9 : Reference< XIndexContainer > xNewParent;
199 9 : Sequence< ScriptEventDescriptor> aNewEvents;
200 :
201 : // calc the new parent for my model (within the new page's forms hierarchy)
202 : // do we have a history ? (from :Clone)
203 9 : if ( m_xEnvironmentHistory.is() )
204 : {
205 : // the element in m_xEnvironmentHistory which is equivalent to my new parent (which (perhaps) has to be created within _pNewPage->GetForms)
206 : // is the right-most element in the tree.
207 0 : Reference< XIndexContainer > xRightMostLeaf = m_xEnvironmentHistory;
208 : try
209 : {
210 0 : while ( xRightMostLeaf->getCount() )
211 : {
212 : xRightMostLeaf.set(
213 0 : xRightMostLeaf->getByIndex( xRightMostLeaf->getCount() - 1 ),
214 : UNO_QUERY_THROW
215 0 : );
216 : }
217 :
218 0 : xNewParent.set( ensureModelEnv( xRightMostLeaf, xNewPageForms ), UNO_QUERY_THROW );
219 :
220 : // we successfully cloned the environment in m_xEnvironmentHistory, so we can use m_aEventsHistory
221 : // (which describes the events of our model at the moment m_xEnvironmentHistory was created)
222 0 : aNewEvents = m_aEventsHistory;
223 : }
224 0 : catch( const Exception& )
225 : {
226 : DBG_UNHANDLED_EXCEPTION();
227 0 : }
228 : }
229 :
230 9 : if ( !xNewParent.is() )
231 : {
232 : // are we a valid part of our current page forms ?
233 9 : Reference< XIndexContainer > xOldForms;
234 9 : if ( pOldFormPage )
235 0 : xOldForms.set( pOldFormPage->GetForms(), UNO_QUERY_THROW );
236 :
237 9 : if ( xOldForms.is() )
238 : {
239 : // search (upward from our model) for xOldForms
240 0 : Reference< XChild > xSearch( GetUnoControlModel(), UNO_QUERY );
241 0 : while (xSearch.is())
242 : {
243 0 : if ( xSearch == xOldForms )
244 0 : break;
245 0 : xSearch = Reference< XChild >( xSearch->getParent(), UNO_QUERY );
246 : }
247 0 : if ( xSearch.is() ) // implies xSearch == xOldForms, which means we're a valid part of our current page forms hierarchy
248 : {
249 0 : Reference< XChild > xMeAsChild( GetUnoControlModel(), UNO_QUERY );
250 0 : xNewParent.set( ensureModelEnv( xMeAsChild->getParent(), xNewPageForms ), UNO_QUERY );
251 :
252 0 : if ( xNewParent.is() )
253 : {
254 : try
255 : {
256 : // transfer the events from our (model's) parent to the new (model's) parent, too
257 0 : Reference< XEventAttacherManager > xEventManager(xMeAsChild->getParent(), UNO_QUERY);
258 0 : Reference< XIndexAccess > xManagerAsIndex(xEventManager, UNO_QUERY);
259 0 : if (xManagerAsIndex.is())
260 : {
261 0 : sal_Int32 nPos = getElementPos(xManagerAsIndex, xMeAsChild);
262 0 : if (nPos >= 0)
263 0 : aNewEvents = xEventManager->getScriptEvents(nPos);
264 : }
265 : else
266 0 : aNewEvents = aEvts;
267 : }
268 0 : catch( const Exception& )
269 : {
270 : DBG_UNHANDLED_EXCEPTION();
271 : }
272 0 : }
273 0 : }
274 9 : }
275 : }
276 :
277 : // now set the page
278 9 : SdrUnoObj::SetPage(_pNewPage);
279 :
280 : // place my model within the new parent container
281 9 : if (xNewParent.is())
282 : {
283 0 : Reference< XFormComponent > xMeAsFormComp(GetUnoControlModel(), UNO_QUERY);
284 0 : if (xMeAsFormComp.is())
285 : {
286 : // check if I have another parent (and remove me, if neccessary)
287 0 : Reference< XIndexContainer > xOldParent(xMeAsFormComp->getParent(), UNO_QUERY);
288 0 : if (xOldParent.is())
289 : {
290 0 : sal_Int32 nPos = getElementPos(Reference< XIndexAccess > (xOldParent, UNO_QUERY), xMeAsFormComp);
291 0 : if (nPos > -1)
292 0 : xOldParent->removeByIndex(nPos);
293 : }
294 : // and insert into the new container
295 0 : xNewParent->insertByIndex(xNewParent->getCount(), makeAny(xMeAsFormComp));
296 :
297 : // transfer the events
298 0 : if (aNewEvents.getLength())
299 : {
300 : try
301 : {
302 0 : Reference< XEventAttacherManager > xEventManager(xNewParent, UNO_QUERY);
303 0 : Reference< XIndexAccess > xManagerAsIndex(xEventManager, UNO_QUERY);
304 0 : if (xManagerAsIndex.is())
305 : {
306 0 : sal_Int32 nPos = getElementPos(xManagerAsIndex, xMeAsFormComp);
307 : DBG_ASSERT(nPos >= 0, "FmFormObj::SetPage : inserted but not present ?");
308 0 : xEventManager->registerScriptEvents(nPos, aNewEvents);
309 0 : }
310 : }
311 0 : catch( const Exception& )
312 : {
313 : DBG_UNHANDLED_EXCEPTION();
314 : }
315 :
316 0 : }
317 0 : }
318 : }
319 :
320 : // delete my history
321 9 : Reference< XComponent> xHistory(m_xEnvironmentHistory, UNO_QUERY);
322 9 : if (xHistory.is())
323 0 : xHistory->dispose();
324 :
325 9 : m_xEnvironmentHistory = NULL;
326 9 : m_aEventsHistory.realloc(0);
327 :
328 9 : if ( pNewFormPage )
329 9 : pNewFormPage->GetImpl().formObjectInserted( *this );
330 : }
331 :
332 : //------------------------------------------------------------------
333 31 : sal_uInt32 FmFormObj::GetObjInventor() const
334 : {
335 31 : return FmFormInventor;
336 : }
337 :
338 : //------------------------------------------------------------------
339 17 : sal_uInt16 FmFormObj::GetObjIdentifier() const
340 : {
341 17 : return OBJ_UNO;
342 : }
343 :
344 : //------------------------------------------------------------------
345 0 : void FmFormObj::clonedFrom(const FmFormObj* _pSource)
346 : {
347 : DBG_ASSERT(_pSource != NULL, "FmFormObj::clonedFrom : invalid source !");
348 0 : Reference< XComponent> xHistory(m_xEnvironmentHistory, UNO_QUERY);
349 0 : if (xHistory.is())
350 0 : xHistory->dispose();
351 :
352 0 : m_xEnvironmentHistory = NULL;
353 0 : m_aEventsHistory.realloc(0);
354 :
355 0 : Reference< XChild > xSourceAsChild(_pSource->GetUnoControlModel(), UNO_QUERY);
356 0 : if (!xSourceAsChild.is())
357 0 : return;
358 :
359 0 : Reference< XInterface > xSourceContainer = xSourceAsChild->getParent();
360 :
361 : m_xEnvironmentHistory = Reference< XIndexContainer >(
362 0 : ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.Forms")) ),
363 0 : UNO_QUERY);
364 : DBG_ASSERT(m_xEnvironmentHistory.is(), "FmFormObj::clonedFrom : could not create a forms collection !");
365 :
366 0 : if (m_xEnvironmentHistory.is())
367 : {
368 0 : ensureModelEnv(xSourceContainer, m_xEnvironmentHistory);
369 0 : m_aEventsHistory = aEvts;
370 : // if we we're clone there was a call to operator=, so aEvts are excatly the events we need here ...
371 0 : }
372 : }
373 :
374 : //------------------------------------------------------------------
375 0 : FmFormObj* FmFormObj::Clone() const
376 : {
377 0 : FmFormObj* pFormObject = CloneHelper< FmFormObj >();
378 : DBG_ASSERT(pFormObject != NULL, "FmFormObj::Clone : invalid clone !");
379 0 : if (pFormObject)
380 0 : pFormObject->clonedFrom(this);
381 :
382 0 : return pFormObject;
383 : }
384 :
385 : //------------------------------------------------------------------
386 0 : void FmFormObj::NbcReformatText()
387 : {
388 0 : impl_checkRefDevice_nothrow( false );
389 0 : SdrUnoObj::NbcReformatText();
390 0 : }
391 :
392 : //------------------------------------------------------------------
393 0 : FmFormObj& FmFormObj::operator= (const FmFormObj& rObj)
394 : {
395 0 : if( this == &rObj )
396 0 : return *this;
397 0 : SdrUnoObj::operator= (rObj);
398 :
399 : // liegt das UnoControlModel in einer Eventumgebung,
400 : // dann koennen noch Events zugeordnet sein
401 0 : Reference< XFormComponent > xContent(rObj.xUnoControlModel, UNO_QUERY);
402 0 : if (xContent.is())
403 : {
404 0 : Reference< XEventAttacherManager > xManager(xContent->getParent(), UNO_QUERY);
405 0 : Reference< XIndexAccess > xManagerAsIndex(xManager, UNO_QUERY);
406 0 : if (xManagerAsIndex.is())
407 : {
408 0 : sal_Int32 nPos = getElementPos( xManagerAsIndex, xContent );
409 0 : if ( nPos >= 0 )
410 0 : aEvts = xManager->getScriptEvents( nPos );
411 0 : }
412 : }
413 : else
414 0 : aEvts = rObj.aEvts;
415 0 : return *this;
416 : }
417 :
418 : //------------------------------------------------------------------
419 : namespace
420 : {
421 0 : rtl::OUString lcl_getFormComponentAccessPath(const Reference< XInterface >& _xElement, Reference< XInterface >& _rTopLevelElement)
422 : {
423 0 : Reference< ::com::sun::star::form::XFormComponent> xChild(_xElement, UNO_QUERY);
424 0 : Reference< ::com::sun::star::container::XIndexAccess> xParent;
425 0 : if (xChild.is())
426 0 : xParent = Reference< ::com::sun::star::container::XIndexAccess>(xChild->getParent(), UNO_QUERY);
427 :
428 : // while the current content is a form
429 0 : String sReturn;
430 0 : String sCurrentIndex;
431 0 : while (xChild.is())
432 : {
433 : // get the content's relative pos within it's parent container
434 0 : sal_Int32 nPos = getElementPos(xParent, xChild);
435 :
436 : // prepend this current relaive pos
437 0 : sCurrentIndex = String::CreateFromInt32(nPos);
438 0 : if (sReturn.Len() != 0)
439 : {
440 0 : sCurrentIndex += '\\';
441 0 : sCurrentIndex += sReturn;
442 : }
443 :
444 0 : sReturn = sCurrentIndex;
445 :
446 : // travel up
447 0 : if (::comphelper::query_interface((Reference< XInterface >)xParent,xChild))
448 0 : xParent = Reference< ::com::sun::star::container::XIndexAccess>(xChild->getParent(), UNO_QUERY);
449 : }
450 :
451 0 : _rTopLevelElement = xParent;
452 0 : return sReturn;
453 : }
454 : }
455 :
456 : //------------------------------------------------------------------
457 0 : Reference< XInterface > FmFormObj::ensureModelEnv(const Reference< XInterface > & _rSourceContainer, const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexContainer > _rTopLevelDestContainer)
458 : {
459 0 : Reference< XInterface > xTopLevelSouce;
460 0 : rtl::OUString sAccessPath = lcl_getFormComponentAccessPath(_rSourceContainer, xTopLevelSouce);
461 0 : if (!xTopLevelSouce.is())
462 : // somthing went wrong, maybe _rSourceContainer isn't part of a valid forms hierarchy
463 0 : return Reference< XInterface > ();
464 :
465 0 : Reference< XIndexContainer > xDestContainer(_rTopLevelDestContainer);
466 0 : Reference< XIndexContainer > xSourceContainer(xTopLevelSouce, UNO_QUERY);
467 : DBG_ASSERT(xSourceContainer.is(), "FmFormObj::ensureModelEnv : the top level source is invalid !");
468 :
469 0 : sal_Int32 nTokIndex = 0;
470 0 : do
471 : {
472 0 : rtl::OUString aToken = sAccessPath.getToken( 0, '\\', nTokIndex );
473 0 : sal_uInt16 nIndex = (sal_uInt16)aToken.toInt32();
474 :
475 : // get the DSS of the source form (we have to find an aquivalent for)
476 : DBG_ASSERT(nIndex<xSourceContainer->getCount(), "FmFormObj::ensureModelEnv : invalid access path !");
477 0 : Reference< XPropertySet > xSourceForm;
478 0 : xSourceContainer->getByIndex(nIndex) >>= xSourceForm;
479 : DBG_ASSERT(xSourceForm.is(), "FmFormObj::ensureModelEnv : invalid source form !");
480 :
481 0 : Any aSrcCursorSource, aSrcCursorSourceType, aSrcDataSource;
482 : DBG_ASSERT(::comphelper::hasProperty(FM_PROP_COMMAND, xSourceForm) && ::comphelper::hasProperty(FM_PROP_COMMANDTYPE, xSourceForm)
483 : && ::comphelper::hasProperty(FM_PROP_DATASOURCE, xSourceForm), "FmFormObj::ensureModelEnv : invalid access path or invalid form (missing props) !");
484 : // the parent access path should refer to a row set
485 : try
486 : {
487 0 : aSrcCursorSource = xSourceForm->getPropertyValue(FM_PROP_COMMAND);
488 0 : aSrcCursorSourceType = xSourceForm->getPropertyValue(FM_PROP_COMMANDTYPE);
489 0 : aSrcDataSource = xSourceForm->getPropertyValue(FM_PROP_DATASOURCE);
490 : }
491 0 : catch(Exception&)
492 : {
493 : OSL_FAIL("FmFormObj::ensureModelEnv : could not retrieve a source DSS !");
494 : }
495 :
496 :
497 : // calc the number of (source) form siblings with the same DSS
498 0 : Reference< XPropertySet > xCurrentSourceForm, xCurrentDestForm;
499 0 : sal_Int16 nCurrentSourceIndex = 0, nCurrentDestIndex = 0;
500 0 : while (nCurrentSourceIndex <= nIndex)
501 : {
502 0 : sal_Bool bEqualDSS = sal_False;
503 0 : while (!bEqualDSS) // (we don't have to check nCurrentSourceIndex here : it's bound by nIndex)
504 : {
505 0 : xSourceContainer->getByIndex(nCurrentSourceIndex) >>= xCurrentSourceForm;
506 : DBG_ASSERT(xCurrentSourceForm.is(), "FmFormObj::ensureModelEnv : invalid form ancestor (2) !");
507 0 : bEqualDSS = sal_False;
508 0 : if (::comphelper::hasProperty(FM_PROP_DATASOURCE, xCurrentSourceForm))
509 : { // it is a form
510 : try
511 : {
512 0 : if ( ::comphelper::compare(xCurrentSourceForm->getPropertyValue(FM_PROP_COMMAND), aSrcCursorSource)
513 0 : && ::comphelper::compare(xCurrentSourceForm->getPropertyValue(FM_PROP_COMMANDTYPE), aSrcCursorSourceType)
514 0 : && ::comphelper::compare(xCurrentSourceForm->getPropertyValue(FM_PROP_DATASOURCE), aSrcDataSource)
515 : )
516 : {
517 0 : bEqualDSS = sal_True;
518 : }
519 : }
520 0 : catch(Exception&)
521 : {
522 : OSL_FAIL("FmFormObj::ensureModelEnv : exception while getting a sibling's DSS !");
523 : }
524 :
525 : }
526 0 : ++nCurrentSourceIndex;
527 : }
528 :
529 : DBG_ASSERT(bEqualDSS, "FmFormObj::ensureModelEnv : found no source form !");
530 : // ??? at least the nIndex-th one should have been found ???
531 :
532 : // now search the next one with the given DSS (within the destination container)
533 0 : bEqualDSS = sal_False;
534 0 : while (!bEqualDSS && (nCurrentDestIndex < xDestContainer->getCount()))
535 : {
536 0 : xDestContainer->getByIndex(nCurrentDestIndex) >>= xCurrentDestForm;
537 : DBG_ASSERT(xCurrentDestForm.is(), "FmFormObj::ensureModelEnv : invalid destination form !");
538 0 : bEqualDSS = sal_False;
539 0 : if (::comphelper::hasProperty(FM_PROP_DATASOURCE, xCurrentDestForm))
540 : { // it is a form
541 : try
542 : {
543 0 : if ( ::comphelper::compare(xCurrentDestForm->getPropertyValue(FM_PROP_COMMAND), aSrcCursorSource)
544 0 : && ::comphelper::compare(xCurrentDestForm->getPropertyValue(FM_PROP_COMMANDTYPE), aSrcCursorSourceType)
545 0 : && ::comphelper::compare(xCurrentDestForm->getPropertyValue(FM_PROP_DATASOURCE), aSrcDataSource)
546 : )
547 : {
548 0 : bEqualDSS = sal_True;
549 : }
550 : }
551 0 : catch(Exception&)
552 : {
553 : OSL_FAIL("FmFormObj::ensureModelEnv : exception while getting a destination DSS !");
554 : }
555 :
556 : }
557 0 : ++nCurrentDestIndex;
558 : }
559 :
560 0 : if (!bEqualDSS)
561 : { // There is at least one more source form with the given DSS than destination forms are.
562 : // correct this ...
563 : try
564 : {
565 : // create and insert (into the destination) a copy of the form
566 : xCurrentDestForm.set(
567 0 : ::comphelper::getProcessServiceFactory()->createInstance(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.component.DataForm" )) ),
568 0 : UNO_QUERY_THROW );
569 0 : ::comphelper::copyProperties( xCurrentSourceForm, xCurrentDestForm );
570 :
571 : DBG_ASSERT(nCurrentDestIndex == xDestContainer->getCount(), "FmFormObj::ensureModelEnv : something went wrong with the numbers !");
572 0 : xDestContainer->insertByIndex(nCurrentDestIndex, makeAny(xCurrentDestForm));
573 :
574 0 : ++nCurrentDestIndex;
575 : // like nCurrentSourceIndex, nCurrentDestIndex now points 'behind' the form it actally means
576 : }
577 0 : catch(Exception&)
578 : {
579 : OSL_FAIL("FmFormObj::ensureModelEnv : something went seriously wrong while creating a new form !");
580 : // no more options anymore ...
581 0 : return Reference< XInterface > ();
582 : }
583 :
584 : }
585 : }
586 :
587 : // now xCurrentDestForm is a form equivalent to xSourceForm (which means they have the same DSS and the same number
588 : // of left siblings with the same DSS, which counts for all their ancestors, too)
589 :
590 : // go down
591 0 : xDestContainer = Reference< XIndexContainer > (xCurrentDestForm, UNO_QUERY);
592 0 : xSourceContainer = Reference< XIndexContainer > (xSourceForm, UNO_QUERY);
593 0 : DBG_ASSERT(xDestContainer.is() && xSourceContainer.is(), "FmFormObj::ensureModelEnv : invalid container !");
594 : }
595 : while ( nTokIndex >= 0 );
596 :
597 0 : return Reference< XInterface > (xDestContainer, UNO_QUERY);
598 : }
599 :
600 : //------------------------------------------------------------------
601 9 : void FmFormObj::SetModel( SdrModel* _pNewModel )
602 : {
603 9 : SdrUnoObj::SetModel( _pNewModel );
604 9 : impl_checkRefDevice_nothrow();
605 9 : }
606 :
607 : //------------------------------------------------------------------
608 0 : FmFormObj* FmFormObj::GetFormObject( SdrObject* _pSdrObject )
609 : {
610 0 : FmFormObj* pFormObject = dynamic_cast< FmFormObj* >( _pSdrObject );
611 0 : if ( !pFormObject )
612 : {
613 0 : SdrVirtObj* pVirtualObject = dynamic_cast< SdrVirtObj* >( _pSdrObject );
614 0 : if ( pVirtualObject )
615 0 : pFormObject = dynamic_cast< FmFormObj* >( &pVirtualObject->ReferencedObj() );
616 : }
617 0 : return pFormObject;
618 : }
619 :
620 : //------------------------------------------------------------------
621 0 : const FmFormObj* FmFormObj::GetFormObject( const SdrObject* _pSdrObject )
622 : {
623 0 : const FmFormObj* pFormObject = dynamic_cast< const FmFormObj* >( _pSdrObject );
624 0 : if ( !pFormObject )
625 : {
626 0 : const SdrVirtObj* pVirtualObject = dynamic_cast< const SdrVirtObj* >( _pSdrObject );
627 0 : if ( pVirtualObject )
628 0 : pFormObject = dynamic_cast< const FmFormObj* >( &pVirtualObject->GetReferencedObj() );
629 : }
630 0 : return pFormObject;
631 : }
632 :
633 : //------------------------------------------------------------------
634 9 : void FmFormObj::SetUnoControlModel( const Reference< com::sun::star::awt::XControlModel >& _rxModel )
635 : {
636 9 : SdrUnoObj::SetUnoControlModel( _rxModel );
637 :
638 9 : FmFormPage* pFormPage = PTR_CAST( FmFormPage, GetPage() );
639 9 : if ( pFormPage )
640 1 : pFormPage->GetImpl().formModelAssigned( *this );
641 :
642 9 : impl_checkRefDevice_nothrow( true );
643 9 : }
644 :
645 : //------------------------------------------------------------------
646 0 : bool FmFormObj::EndCreate( SdrDragStat& rStat, SdrCreateCmd eCmd )
647 : {
648 0 : bool bResult = SdrUnoObj::EndCreate(rStat, eCmd);
649 0 : if ( bResult && SDRCREATE_FORCEEND == eCmd && rStat.GetView() )
650 : {
651 0 : if ( pPage )
652 : {
653 0 : FmFormPage& rPage = dynamic_cast< FmFormPage& >( *pPage );
654 :
655 : try
656 : {
657 0 : Reference< XFormComponent > xContent( xUnoControlModel, UNO_QUERY_THROW );
658 0 : Reference< XForm > xParentForm( xContent->getParent(), UNO_QUERY );
659 :
660 0 : Reference< XIndexContainer > xFormToInsertInto;
661 :
662 0 : if ( !xParentForm.is() )
663 : { // model is not yet part of a form component hierachy
664 0 : xParentForm.set( rPage.GetImpl().findPlaceInFormComponentHierarchy( xContent ), UNO_SET_THROW );
665 0 : xFormToInsertInto.set( xParentForm, UNO_QUERY_THROW );
666 : }
667 :
668 0 : rPage.GetImpl().setUniqueName( xContent, xParentForm );
669 :
670 0 : if ( xFormToInsertInto.is() )
671 0 : xFormToInsertInto->insertByIndex( xFormToInsertInto->getCount(), makeAny( xContent ) );
672 : }
673 0 : catch( const Exception& )
674 : {
675 : DBG_UNHANDLED_EXCEPTION();
676 : }
677 : }
678 :
679 0 : FmFormView* pView( dynamic_cast< FmFormView* >( rStat.GetView() ) );
680 0 : FmXFormView* pViewImpl = pView ? pView->GetImpl() : NULL;
681 : OSL_ENSURE( pViewImpl, "FmFormObj::EndCreate: no view!?" );
682 0 : if ( pViewImpl )
683 0 : pViewImpl->onCreatedFormObject( *this );
684 : }
685 0 : return bResult;
686 : }
687 :
688 : //------------------------------------------------------------------------------
689 0 : void FmFormObj::BrkCreate( SdrDragStat& rStat )
690 : {
691 0 : SdrUnoObj::BrkCreate( rStat );
692 0 : impl_isolateControlModel_nothrow();
693 0 : }
694 :
695 : // -----------------------------------------------------------------------------
696 : // #i70852# overload Layer interface to force to FormColtrol layer
697 :
698 32 : SdrLayerID FmFormObj::GetLayer() const
699 : {
700 : // #i72535#
701 : // i70852 was too radical, in SW obects (and thus, FormControls, too)
702 : // get moved to invisible layers to hide them (e.g. in hidden sections).
703 : // This means that form controls ARE allowed to be on other layers than
704 : // the form control layer ATM and that being member of form control layer
705 : // is no criteria to find all FormControls of a document.
706 : // To fix, use parent functionality
707 32 : return SdrUnoObj::GetLayer();
708 : }
709 :
710 16 : void FmFormObj::NbcSetLayer(SdrLayerID nLayer)
711 : {
712 : // #i72535#
713 : // See above. To fix, use parent functionality
714 16 : return SdrUnoObj::NbcSetLayer(nLayer);
715 : }
716 :
717 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|