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