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