merge the formfield patch from ooo-build
[ooovba.git] / svx / source / form / fmundo.cxx
blob1deff36ac9f559748c572a40f200c1b1a312c2bb
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fmundo.cxx,v $
10 * $Revision: 1.45 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include "fmundo.hxx"
35 /** === begin UNO includes === **/
36 #include <com/sun/star/util/XModifyBroadcaster.hpp>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <com/sun/star/form/XFormController.hpp>
39 #include <com/sun/star/container/XContainer.hpp>
40 #include <com/sun/star/container/XContainerListener.hpp>
41 #include <com/sun/star/script/XEventAttacherManager.hpp>
42 #include <com/sun/star/form/binding/XBindableValue.hpp>
43 #include <com/sun/star/form/binding/XListEntrySink.hpp>
44 #include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
45 /** === end UNO includes === **/
47 #ifndef _FM_FMMODEL_HXX
48 #include <svx/fmmodel.hxx>
49 #endif
50 #include "fmtools.hxx"
51 #include <svx/fmpage.hxx>
52 #ifndef _SVX_FMRESIDS_HRC
53 #include "fmresids.hrc"
54 #endif
55 #include <rtl/logfile.hxx>
56 #include <svx/dialmgr.hxx>
57 #include "fmpgeimp.hxx"
58 #include "svx/dbtoolsclient.hxx"
59 #include <svtools/macitem.hxx>
60 #include <tools/shl.hxx>
61 #include <tools/diagnose_ex.h>
62 #include <sfx2/objsh.hxx>
63 #include <sfx2/docfile.hxx>
64 #include <sfx2/app.hxx>
65 #include <sfx2/sfx.hrc>
66 #include <sfx2/event.hxx>
67 #include "svditer.hxx"
68 #include "fmobj.hxx"
69 #include <osl/mutex.hxx>
70 #include <svx/fmglob.hxx>
71 #ifndef _SVX_FMPROP_HRC
72 #include "fmprop.hrc"
73 #endif
74 #include <comphelper/property.hxx>
75 #include <comphelper/uno3.hxx>
76 #include <comphelper/stl_types.hxx>
78 using namespace ::com::sun::star::uno;
79 using namespace ::com::sun::star::awt;
80 using namespace ::com::sun::star::beans;
81 using namespace ::com::sun::star::container;
82 using namespace ::com::sun::star::script;
83 using namespace ::com::sun::star::lang;
84 using namespace ::com::sun::star::form;
85 using namespace ::com::sun::star::util;
86 using namespace ::com::sun::star::reflection;
87 using namespace ::com::sun::star::form::binding;
88 using namespace ::svxform;
91 #include <com/sun/star/script/XScriptListener.hdl>
92 #include <comphelper/processfactory.hxx>
93 #include <cppuhelper/implbase1.hxx>
95 typedef cppu::WeakImplHelper1< XScriptListener > ScriptEventListener_BASE;
96 class ScriptEventListenerWrapper : public ScriptEventListener_BASE
98 public:
99 ScriptEventListenerWrapper( FmFormModel& _rModel) throw ( RuntimeException ) : pModel(&_rModel)
101 Reference < XPropertySet > xProps(
102 ::comphelper::getProcessServiceFactory(), UNO_QUERY );
103 if ( xProps.is() )
105 Reference< XComponentContext > xCtx( xProps->getPropertyValue(
106 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), UNO_QUERY );
107 if ( xCtx.is() )
109 Reference< XMultiComponentFactory > xMFac(
110 xCtx->getServiceManager(), UNO_QUERY );
111 if ( xMFac.is() )
113 m_vbaListener.set( xMFac->createInstanceWithContext(
114 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
115 "ooo.vba.EventListener" ) ), xCtx ),
116 UNO_QUERY_THROW );
121 // XEventListener
122 virtual void SAL_CALL disposing(const EventObject& ) throw( RuntimeException ){}
124 // XScriptListener
125 virtual void SAL_CALL firing(const ScriptEvent& evt) throw(RuntimeException)
127 setModel();
128 if ( m_vbaListener.is() )
130 m_vbaListener->firing( evt );
134 virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) throw( com::sun::star::reflection::InvocationTargetException, RuntimeException)
136 setModel();
137 if ( m_vbaListener.is() )
139 return m_vbaListener->approveFiring( evt );
141 return Any();
144 private:
145 void setModel()
147 Reference< XPropertySet > xProps( m_vbaListener, UNO_QUERY );
148 if ( xProps.is() )
152 SfxObjectShellRef xObjSh = pModel->GetObjectShell();
153 if ( xObjSh.Is() && m_vbaListener.is() )
155 Any aVal;
156 aVal <<= xObjSh->GetModel();
157 xProps->setPropertyValue(
158 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) ),
159 aVal );
162 catch( Exception& e )
164 //swallow any errors
168 FmFormModel* pModel;
169 Reference< XScriptListener > m_vbaListener;
174 //------------------------------------------------------------------------------
175 // some helper structs for caching property infos
176 //------------------------------------------------------------------------------
177 struct PropertyInfo
179 BOOL bIsTransientOrReadOnly : 1; // the property is transient or read-only, thus we need no undo action for it
180 BOOL bIsValueProperty : 1; // the property is the special value property, thus it may be handled
181 // as if it's transient or persistent
184 struct PropertySetInfo
186 DECLARE_STL_USTRINGACCESS_MAP(PropertyInfo, AllProperties);
188 AllProperties aProps; // all properties of this set which we know so far
189 BOOL bHasEmptyControlSource; // sal_True -> the set has a DataField property, and the current value is an empty string
190 // sal_False -> the set has _no_ such property or it's value isn't empty
193 BOOL operator < (const Reference< XPropertySet >& lhs,
194 const Reference< XPropertySet >& rhs)
196 return lhs.get() < rhs.get();
199 DECLARE_STL_STDKEY_MAP(Reference< XPropertySet >, PropertySetInfo, PropertySetInfoCache);
201 //------------------------------------------------------------------------------
203 String static_STR_UNDO_PROPERTY;
204 //------------------------------------------------------------------------------
205 DBG_NAME(FmXUndoEnvironment)
206 //------------------------------------------------------------------------------
207 FmXUndoEnvironment::FmXUndoEnvironment(FmFormModel& _rModel)
208 :rModel( _rModel )
209 ,m_pPropertySetCache( NULL )
210 ,m_pScriptingEnv( ::svxform::createDefaultFormScriptingEnvironment( _rModel ) )
211 ,m_Locks( 0 )
212 ,bReadOnly( sal_False )
213 ,m_bDisposed( false )
215 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::FmXUndoEnvironment" );
216 DBG_CTOR(FmXUndoEnvironment,NULL);
219 m_vbaListener = new ScriptEventListenerWrapper( _rModel );
221 catch( Exception& )
226 //------------------------------------------------------------------------------
227 FmXUndoEnvironment::~FmXUndoEnvironment()
229 DBG_DTOR(FmXUndoEnvironment,NULL);
230 if (m_pPropertySetCache)
231 delete static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
234 //------------------------------------------------------------------------------
235 void FmXUndoEnvironment::dispose()
237 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::dispose" );
238 OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::dispose: disposed twice?" );
239 if ( !m_bDisposed )
240 return;
242 Lock();
244 sal_uInt16 nCount = rModel.GetPageCount();
245 sal_uInt16 i;
246 for (i = 0; i < nCount; i++)
248 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
249 if ( pPage )
251 Reference< XInterface > xForms = pPage->GetForms( false ).get();
252 if ( xForms.is() )
253 RemoveElement( xForms );
257 nCount = rModel.GetMasterPageCount();
258 for (i = 0; i < nCount; i++)
260 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
261 if ( pPage )
263 Reference< XInterface > xForms = pPage->GetForms( false ).get();
264 if ( xForms.is() )
265 RemoveElement( xForms );
269 UnLock();
271 OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::dispose: no object shell anymore!" );
272 if ( rModel.GetObjectShell() )
273 EndListening( *rModel.GetObjectShell() );
275 if ( IsListening( rModel ) )
276 EndListening( rModel );
278 m_pScriptingEnv->dispose();
280 m_bDisposed = true;
283 //------------------------------------------------------------------------------
284 void FmXUndoEnvironment::ModeChanged()
286 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::ModeChanged" );
287 OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::ModeChanged: no object shell anymore!" );
288 if ( !rModel.GetObjectShell() )
289 return;
291 if (bReadOnly != (rModel.GetObjectShell()->IsReadOnly() || rModel.GetObjectShell()->IsReadOnlyUI()))
293 bReadOnly = !bReadOnly;
295 sal_uInt16 nCount = rModel.GetPageCount();
296 sal_uInt16 i;
297 for (i = 0; i < nCount; i++)
299 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
300 if ( pPage )
302 Reference< XInterface > xForms = pPage->GetForms( false ).get();
303 if ( xForms.is() )
304 TogglePropertyListening( xForms );
308 nCount = rModel.GetMasterPageCount();
309 for (i = 0; i < nCount; i++)
311 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
312 if ( pPage )
314 Reference< XInterface > xForms = pPage->GetForms( false ).get();
315 if ( xForms.is() )
316 TogglePropertyListening( xForms );
320 if (!bReadOnly)
321 StartListening(rModel);
322 else
323 EndListening(rModel);
327 //------------------------------------------------------------------------------
328 void FmXUndoEnvironment::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
330 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Notify" );
331 if (rHint.ISA(SdrHint))
333 SdrHint* pSdrHint = (SdrHint*)&rHint;
334 switch( pSdrHint->GetKind() )
336 case HINT_OBJINSERTED:
338 SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
339 Inserted( pSdrObj );
340 } break;
341 case HINT_OBJREMOVED:
343 SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
344 Removed( pSdrObj );
346 break;
347 default:
348 break;
351 else if (rHint.ISA(SfxSimpleHint))
353 switch ( ((SfxSimpleHint&)rHint).GetId() )
355 case SFX_HINT_DYING:
356 dispose();
357 rModel.SetObjectShell( NULL );
358 break;
359 case SFX_HINT_MODECHANGED:
360 ModeChanged();
361 break;
364 else if (rHint.ISA(SfxEventHint))
366 switch (((SfxEventHint&)rHint).GetEventId())
368 case SFX_EVENT_CREATEDOC:
369 case SFX_EVENT_OPENDOC:
370 ModeChanged();
371 break;
377 //------------------------------------------------------------------
378 void FmXUndoEnvironment::Inserted(SdrObject* pObj)
380 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
381 if (pObj->GetObjInventor() == FmFormInventor)
383 FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
384 Inserted( pFormObj );
386 else if (pObj->IsGroupObject())
388 SdrObjListIter aIter(*pObj->GetSubList());
389 while ( aIter.IsMore() )
390 Inserted( aIter.Next() );
394 //------------------------------------------------------------------------------
395 void FmXUndoEnvironment::Inserted(FmFormObj* pObj)
397 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
398 DBG_ASSERT( pObj, "FmXUndoEnvironment::Inserted: invalid object!" );
399 if ( !pObj )
400 return;
402 // ist das Control noch einer Form zugeordnet
403 Reference< XInterface > xModel(pObj->GetUnoControlModel(), UNO_QUERY);
404 Reference< XFormComponent > xContent(xModel, UNO_QUERY);
405 if (xContent.is() && pObj->GetPage())
407 // if the component doesn't belong to a form, yet, find one to insert into
408 if (!xContent->getParent().is())
412 Reference< XIndexContainer > xObjectParent = pObj->GetOriginalParent();
414 FmFormPage& rPage = dynamic_cast< FmFormPage& >( *pObj->GetPage() );
415 Reference< XIndexAccess > xForms( rPage.GetForms(), UNO_QUERY_THROW );
417 Reference< XIndexContainer > xNewParent;
418 Reference< XForm > xForm;
419 sal_Int32 nPos = -1;
420 if ( searchElement( xForms, xObjectParent ) )
422 // the form which was the parent of the object when it was removed is still
423 // part of the form component hierachy of the current page
424 xNewParent = xObjectParent;
425 xForm.set( xNewParent, UNO_QUERY_THROW );
426 nPos = ::std::min( pObj->GetOriginalIndex(), xNewParent->getCount() );
428 else
430 xForm.set( rPage.GetImpl().findPlaceInFormComponentHierarchy( xContent ), UNO_SET_THROW );
431 xNewParent.set( xForm, UNO_QUERY_THROW );
432 nPos = xNewParent->getCount();
435 rPage.GetImpl().setUniqueName( xContent, xForm );
436 xNewParent->insertByIndex( nPos, makeAny( xContent ) );
438 Reference< XEventAttacherManager > xManager( xNewParent, UNO_QUERY_THROW );
439 xManager->registerScriptEvents( nPos, pObj->GetOriginalEvents() );
441 catch( const Exception& )
443 DBG_UNHANDLED_EXCEPTION();
447 // FormObject zuruecksetzen
448 pObj->ClearObjEnv();
452 //------------------------------------------------------------------
453 void FmXUndoEnvironment::Removed(SdrObject* pObj)
455 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
456 if ( pObj->IsVirtualObj() )
457 // for virtual objects, we've already been notified of the removal of the master
458 // object, which is sufficient here
459 return;
461 if (pObj->GetObjInventor() == FmFormInventor)
463 FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
464 Removed(pFormObj);
466 else if (pObj->IsGroupObject())
468 SdrObjListIter aIter(*pObj->GetSubList());
469 while ( aIter.IsMore() )
470 Removed( aIter.Next() );
474 //------------------------------------------------------------------------------
475 void FmXUndoEnvironment::Removed(FmFormObj* pObj)
477 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
478 DBG_ASSERT( pObj, "FmXUndoEnvironment::Removed: invalid object!" );
479 if ( !pObj )
480 return;
482 // ist das Control noch einer Form zugeordnet
483 Reference< XFormComponent > xContent(pObj->GetUnoControlModel(), UNO_QUERY);
484 if (xContent.is())
486 // das Object wird aus einer Liste herausgenommen
487 // existiert ein Vater wird das Object beim beim Vater entfernt und
488 // am FormObject gemerkt!
490 // wird das Object wieder eingefuegt und ein Parent existiert, so wird dieser
491 // Parent wiederum gesetzt
492 Reference< XIndexContainer > xForm(xContent->getParent(), UNO_QUERY);
493 if (xForm.is())
495 Reference< XIndexAccess > xIndexAccess((XIndexContainer*)xForm.get());
496 // Feststellen an welcher Position sich das Kind befunden hat
497 const sal_Int32 nPos = getElementPos(xIndexAccess, xContent);
498 if (nPos >= 0)
500 Sequence< ScriptEventDescriptor > aEvts;
501 Reference< XEventAttacherManager > xManager(xForm, UNO_QUERY);
502 if (xManager.is())
503 aEvts = xManager->getScriptEvents(nPos);
507 pObj->SetObjEnv(xForm, nPos, aEvts);
508 xForm->removeByIndex(nPos);
510 catch(Exception&)
512 DBG_UNHANDLED_EXCEPTION();
520 // XEventListener
521 //------------------------------------------------------------------------------
522 void SAL_CALL FmXUndoEnvironment::disposing(const EventObject& e) throw( RuntimeException )
524 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::disposing" );
525 // check if it's an object we have cached informations about
526 if (m_pPropertySetCache)
528 Reference< XPropertySet > xSourceSet(e.Source, UNO_QUERY);
529 if (xSourceSet.is())
531 PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
532 PropertySetInfoCacheIterator aSetPos = pCache->find(xSourceSet);
533 if (aSetPos != pCache->end())
534 pCache->erase(aSetPos);
539 // XPropertyChangeListener
540 //------------------------------------------------------------------------------
541 void SAL_CALL FmXUndoEnvironment::propertyChange(const PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException)
543 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::propertyChange" );
544 ::osl::ClearableMutexGuard aGuard( m_aMutex );
546 if (!IsLocked())
548 Reference< XPropertySet > xSet(evt.Source, UNO_QUERY);
549 if (!xSet.is())
550 return;
552 // if it's a "default value" property of a control model, set the according "value" property
553 static ::rtl::OUString pDefaultValueProperties[] = {
554 FM_PROP_DEFAULT_TEXT, FM_PROP_DEFAULTCHECKED, FM_PROP_DEFAULT_DATE, FM_PROP_DEFAULT_TIME,
555 FM_PROP_DEFAULT_VALUE, FM_PROP_DEFAULT_SELECT_SEQ, FM_PROP_EFFECTIVE_DEFAULT
557 const ::rtl::OUString aValueProperties[] = {
558 FM_PROP_TEXT, FM_PROP_STATE, FM_PROP_DATE, FM_PROP_TIME,
559 FM_PROP_VALUE, FM_PROP_SELECT_SEQ, FM_PROP_EFFECTIVE_VALUE
561 sal_Int32 nDefaultValueProps = sizeof(pDefaultValueProperties)/sizeof(pDefaultValueProperties[0]);
562 OSL_ENSURE(sizeof(aValueProperties)/sizeof(aValueProperties[0]) == nDefaultValueProps,
563 "FmXUndoEnvironment::propertyChange: inconsistence!");
564 for (sal_Int32 i=0; i<nDefaultValueProps; ++i)
566 if (0 == evt.PropertyName.compareTo(pDefaultValueProperties[i]))
570 xSet->setPropertyValue(aValueProperties[i], evt.NewValue);
572 catch(const Exception&)
574 OSL_ENSURE(sal_False, "FmXUndoEnvironment::propertyChange: could not adjust the value property!");
579 // no Undo for transient and readonly props. But unfortunately "transient" is not only that the
580 // "transient" flag is set for the property in question, instead is is somewhat more complex
581 // Transience criterions are:
582 // - the "transient" flag is set for the property
583 // - OR the control has a non-empty COntrolSource property, i.e. is intended to be bound
584 // to a database column. Note that it doesn't matter here whether the control actually
585 // *is* bound to a column
586 // - OR the control is bound to an external value via XBindableValue/XValueBinding
587 // which does not have a "ExternalData" property being <TRUE/>
589 if (!m_pPropertySetCache)
590 m_pPropertySetCache = new PropertySetInfoCache;
591 PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
593 // let's see if we know something about the set
594 PropertySetInfoCacheIterator aSetPos = pCache->find(xSet);
595 if (aSetPos == pCache->end())
597 PropertySetInfo aNewEntry;
598 if (!::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xSet))
600 aNewEntry.bHasEmptyControlSource = sal_False;
602 else
606 Any aCurrentControlSource = xSet->getPropertyValue(FM_PROP_CONTROLSOURCE);
607 aNewEntry.bHasEmptyControlSource = !aCurrentControlSource.hasValue() || (::comphelper::getString(aCurrentControlSource).getLength() == 0);
609 catch(const Exception&)
611 DBG_UNHANDLED_EXCEPTION();
614 aSetPos = pCache->insert(PropertySetInfoCache::value_type(xSet,aNewEntry)).first;
615 DBG_ASSERT(aSetPos != pCache->end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
617 else
618 { // is it the DataField property ?
619 if (evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
621 aSetPos->second.bHasEmptyControlSource = !evt.NewValue.hasValue() || (::comphelper::getString(evt.NewValue).getLength() == 0);
625 // now we have access to the cached info about the set
626 // let's see what we know about the property
627 PropertySetInfo::AllProperties& rPropInfos = aSetPos->second.aProps;
628 PropertySetInfo::AllPropertiesIterator aPropertyPos = rPropInfos.find(evt.PropertyName);
629 if (aPropertyPos == rPropInfos.end())
630 { // nothing 'til now ... have to change this ....
631 PropertyInfo aNewEntry;
633 // the attributes
634 INT32 nAttributes = xSet->getPropertySetInfo()->getPropertyByName(evt.PropertyName).Attributes;
635 aNewEntry.bIsTransientOrReadOnly = ((nAttributes & PropertyAttribute::READONLY) != 0) || ((nAttributes & PropertyAttribute::TRANSIENT) != 0);
637 // check if it is the special "DataFieldProperty"
638 aNewEntry.bIsValueProperty = sal_False;
641 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCEPROPERTY, xSet))
643 Any aControlSourceProperty = xSet->getPropertyValue(FM_PROP_CONTROLSOURCEPROPERTY);
644 ::rtl::OUString sControlSourceProperty;
645 aControlSourceProperty >>= sControlSourceProperty;
647 aNewEntry.bIsValueProperty = (sControlSourceProperty.equals(evt.PropertyName));
650 catch(const Exception&)
652 DBG_UNHANDLED_EXCEPTION();
655 // insert the new entry
656 aPropertyPos = rPropInfos.insert(PropertySetInfo::AllProperties::value_type(evt.PropertyName,aNewEntry)).first;
657 DBG_ASSERT(aPropertyPos != rPropInfos.end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
660 // now we have access to the cached info about the property affected
661 // and are able to decide wether or not we need an undo action
663 bool bAddUndoAction = rModel.IsUndoEnabled();
664 // no UNDO for transient/readonly properties
665 if ( bAddUndoAction && aPropertyPos->second.bIsTransientOrReadOnly )
666 bAddUndoAction = false;
668 if ( bAddUndoAction && aPropertyPos->second.bIsValueProperty )
670 // no UNDO when the "value" property changes, but the ControlSource is non-empty
671 // (in this case the control is intended to be bound to a database column)
672 if ( !aSetPos->second.bHasEmptyControlSource )
673 bAddUndoAction = false;
675 // no UNDO if the control is currently bound to an external value
676 if ( bAddUndoAction )
678 Reference< XBindableValue > xBindable( evt.Source, UNO_QUERY );
679 Reference< XValueBinding > xBinding;
680 if ( xBindable.is() )
681 xBinding = xBindable->getValueBinding();
683 Reference< XPropertySet > xBindingProps;
684 Reference< XPropertySetInfo > xBindingPropsPSI;
685 if ( xBindable.is() )
686 xBindingProps.set( xBinding, UNO_QUERY );
687 if ( xBindingProps.is() )
688 xBindingPropsPSI = xBindingProps->getPropertySetInfo();
689 // TODO: we should cache all those things, else this might be too expensive.
690 // However, this requires we're notified of changes in the value binding
692 static const ::rtl::OUString s_sExternalData( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) );
693 if ( xBindingPropsPSI.is() && xBindingPropsPSI->hasPropertyByName( s_sExternalData ) )
695 sal_Bool bExternalData = sal_True;
696 OSL_VERIFY( xBindingProps->getPropertyValue( s_sExternalData ) >>= bExternalData );
697 bAddUndoAction = !bExternalData;
699 else
700 bAddUndoAction = !xBinding.is();
704 if ( bAddUndoAction && ( evt.PropertyName == FM_PROP_STRINGITEMLIST ) )
706 Reference< XListEntrySink > xSink( evt.Source, UNO_QUERY );
707 if ( xSink.is() && xSink->getListEntrySource().is() )
708 // #i41029# / 2005-01-31 / frank.schoenheit@sun.com
709 bAddUndoAction = false;
712 if ( bAddUndoAction )
714 aGuard.clear();
715 // TODO: this is a potential race condition: two threads here could in theory
716 // add their undo actions out-of-order
718 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
719 rModel.AddUndo(new FmUndoPropertyAction(rModel, evt));
722 else
724 // if it's the DataField property we may have to adjust our cache
725 if (m_pPropertySetCache && evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
727 Reference< XPropertySet > xSet(evt.Source, UNO_QUERY);
728 PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
729 PropertySetInfo& rSetInfo = (*pCache)[xSet];
730 rSetInfo.bHasEmptyControlSource = !evt.NewValue.hasValue() || (::comphelper::getString(evt.NewValue).getLength() == 0);
735 // XContainerListener
736 //------------------------------------------------------------------------------
737 void SAL_CALL FmXUndoEnvironment::elementInserted(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
739 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementInserted" );
740 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
741 ::osl::MutexGuard aGuard( m_aMutex );
743 // neues Object zum lauschen
744 Reference< XInterface > xIface;
745 evt.Element >>= xIface;
746 OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementInserted: invalid container notification!");
747 AddElement(xIface);
749 implSetModified();
752 //------------------------------------------------------------------------------
753 void FmXUndoEnvironment::implSetModified()
755 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::implSetModified" );
756 if ( !IsLocked() && rModel.GetObjectShell() )
758 rModel.GetObjectShell()->SetModified( sal_True );
762 //------------------------------------------------------------------------------
763 void SAL_CALL FmXUndoEnvironment::elementReplaced(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
765 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementReplaced" );
766 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
767 ::osl::MutexGuard aGuard( m_aMutex );
769 Reference< XInterface > xIface;
770 evt.ReplacedElement >>= xIface;
771 OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementReplaced: invalid container notification!");
772 RemoveElement(xIface);
774 evt.Element >>= xIface;
775 AddElement(xIface);
777 implSetModified();
780 //------------------------------------------------------------------------------
781 void SAL_CALL FmXUndoEnvironment::elementRemoved(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
783 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementRemoved" );
784 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
785 ::osl::MutexGuard aGuard( m_aMutex );
787 Reference< XInterface > xIface( evt.Element, UNO_QUERY );
788 OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementRemoved: invalid container notification!");
789 RemoveElement(xIface);
791 implSetModified();
794 //------------------------------------------------------------------------------
795 void SAL_CALL FmXUndoEnvironment::modified( const EventObject& /*aEvent*/ ) throw (RuntimeException)
797 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::modified" );
798 implSetModified();
801 //------------------------------------------------------------------------------
802 void FmXUndoEnvironment::AddForms(const Reference< XNameContainer > & rForms)
804 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddForms" );
805 Lock();
806 Reference< XInterface > xInt(rForms, UNO_QUERY);
807 AddElement(xInt);
808 UnLock();
811 //------------------------------------------------------------------------------
812 void FmXUndoEnvironment::RemoveForms(const Reference< XNameContainer > & rForms)
814 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveForms" );
815 Lock();
816 Reference< XInterface > xInt(rForms, UNO_QUERY);
817 RemoveElement(xInt);
818 UnLock();
821 //------------------------------------------------------------------------------
822 void FmXUndoEnvironment::TogglePropertyListening(const Reference< XInterface > & Element)
824 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::TogglePropertyListening" );
825 // am Container horchen
826 Reference< XIndexContainer > xContainer(Element, UNO_QUERY);
827 if (xContainer.is())
829 sal_uInt32 nCount = xContainer->getCount();
830 Reference< XInterface > xIface;
831 for (sal_uInt32 i = 0; i < nCount; i++)
833 xContainer->getByIndex(i) >>= xIface;
834 TogglePropertyListening(xIface);
838 Reference< XPropertySet > xSet(Element, UNO_QUERY);
839 if (xSet.is())
841 if (!bReadOnly)
842 xSet->addPropertyChangeListener( ::rtl::OUString(), this );
843 else
844 xSet->removePropertyChangeListener( ::rtl::OUString(), this );
849 //------------------------------------------------------------------------------
850 void FmXUndoEnvironment::switchListening( const Reference< XIndexContainer >& _rxContainer, bool _bStartListening ) SAL_THROW(())
852 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
853 OSL_PRECOND( _rxContainer.is(), "FmXUndoEnvironment::switchListening: invalid container!" );
854 if ( !_rxContainer.is() )
855 return;
859 // if it's an EventAttacherManager, then we need to listen for
860 // script events
861 Reference< XEventAttacherManager > xManager( _rxContainer, UNO_QUERY );
862 if ( xManager.is() )
864 if ( _bStartListening )
866 m_pScriptingEnv->registerEventAttacherManager( xManager );
867 if ( m_vbaListener.is() )
868 xManager->addScriptListener( m_vbaListener );
870 else
872 m_pScriptingEnv->revokeEventAttacherManager( xManager );
873 if ( m_vbaListener.is() )
874 xManager->removeScriptListener( m_vbaListener );
878 // also handle all children of this element
879 sal_uInt32 nCount = _rxContainer->getCount();
880 Reference< XInterface > xInterface;
881 for ( sal_uInt32 i = 0; i < nCount; ++i )
883 _rxContainer->getByIndex( i ) >>= xInterface;
884 if ( _bStartListening )
885 AddElement( xInterface );
886 else
887 RemoveElement( xInterface );
890 // be notified of any changes in the container elements
891 Reference< XContainer > xSimpleContainer( _rxContainer, UNO_QUERY );
892 OSL_ENSURE( xSimpleContainer.is(), "FmXUndoEnvironment::switchListening: how are we expected to be notified of changes in the container?" );
893 if ( xSimpleContainer.is() )
895 if ( _bStartListening )
896 xSimpleContainer->addContainerListener( this );
897 else
898 xSimpleContainer->removeContainerListener( this );
901 catch( const Exception& )
903 OSL_ENSURE( sal_False, "FmXUndoEnvironment::switchListening: caught an exception!" );
907 //------------------------------------------------------------------------------
908 void FmXUndoEnvironment::switchListening( const Reference< XInterface >& _rxObject, bool _bStartListening ) SAL_THROW(())
910 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
911 OSL_PRECOND( _rxObject.is(), "FmXUndoEnvironment::switchListening: how should I listen at a NULL object?" );
915 if ( !bReadOnly )
917 Reference< XPropertySet > xProps( _rxObject, UNO_QUERY );
918 if ( xProps.is() )
920 if ( _bStartListening )
921 xProps->addPropertyChangeListener( ::rtl::OUString(), this );
922 else
923 xProps->removePropertyChangeListener( ::rtl::OUString(), this );
927 Reference< XModifyBroadcaster > xBroadcaster( _rxObject, UNO_QUERY );
928 if ( xBroadcaster.is() )
930 if ( _bStartListening )
931 xBroadcaster->addModifyListener( this );
932 else
933 xBroadcaster->removeModifyListener( this );
936 catch( const Exception& )
938 OSL_ENSURE( sal_False, "FmXUndoEnvironment::switchListening: caught an exception!" );
942 //------------------------------------------------------------------------------
943 void FmXUndoEnvironment::AddElement(const Reference< XInterface >& _rxElement )
945 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddElement" );
946 OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::AddElement: not when I'm already disposed!" );
948 // am Container horchen
949 Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
950 if ( xContainer.is() )
951 switchListening( xContainer, true );
953 switchListening( _rxElement, true );
956 //------------------------------------------------------------------------------
957 void FmXUndoEnvironment::RemoveElement(const Reference< XInterface >& _rxElement)
959 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveElement" );
960 if ( m_bDisposed )
961 return;
963 switchListening( _rxElement, false );
965 if (!bReadOnly)
967 // reset the ActiveConnection if the form is to be removed. This will (should) free the resources
968 // associated with this connection
969 // 86299 - 05/02/2001 - frank.schoenheit@germany.sun.com
970 Reference< XForm > xForm( _rxElement, UNO_QUERY );
971 Reference< XPropertySet > xFormProperties( xForm, UNO_QUERY );
972 if ( xFormProperties.is() )
973 if ( !::svxform::OStaticDataAccessTools().isEmbeddedInDatabase( _rxElement ) )
974 // (if there is a connection in the context of the component, setting
975 // a new connection would be vetoed, anyway)
976 // #i34196# - 2004-09-21 - fs@openoffice.org
977 xFormProperties->setPropertyValue( FM_PROP_ACTIVE_CONNECTION, Any() );
980 Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
981 if ( xContainer.is() )
982 switchListening( xContainer, false );
986 //------------------------------------------------------------------------------
987 FmUndoPropertyAction::FmUndoPropertyAction(FmFormModel& rNewMod, const PropertyChangeEvent& evt)
988 :SdrUndoAction(rNewMod)
989 ,xObj(evt.Source, UNO_QUERY)
990 ,aPropertyName(evt.PropertyName)
991 ,aNewValue(evt.NewValue)
992 ,aOldValue(evt.OldValue)
994 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::FmUndoPropertyAction" );
995 if (rNewMod.GetObjectShell())
996 rNewMod.GetObjectShell()->SetModified(sal_True);
997 if(static_STR_UNDO_PROPERTY.Len() == 0)
998 static_STR_UNDO_PROPERTY = SVX_RES(RID_STR_UNDO_PROPERTY);
1002 //------------------------------------------------------------------------------
1003 void FmUndoPropertyAction::Undo()
1005 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Undo" );
1006 FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
1008 if (xObj.is() && !rEnv.IsLocked())
1010 rEnv.Lock();
1013 xObj->setPropertyValue( aPropertyName, aOldValue );
1015 catch( const Exception& )
1017 OSL_ENSURE( sal_False, "FmUndoPropertyAction::Undo: caught an exception!" );
1019 rEnv.UnLock();
1023 //------------------------------------------------------------------------------
1024 void FmUndoPropertyAction::Redo()
1026 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Redo" );
1027 FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
1029 if (xObj.is() && !rEnv.IsLocked())
1031 rEnv.Lock();
1034 xObj->setPropertyValue( aPropertyName, aNewValue );
1036 catch( const Exception& )
1038 OSL_ENSURE( sal_False, "FmUndoPropertyAction::Redo: caught an exception!" );
1040 rEnv.UnLock();
1044 //------------------------------------------------------------------------------
1045 String FmUndoPropertyAction::GetComment() const
1047 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::GetComment" );
1048 String aStr(static_STR_UNDO_PROPERTY);
1050 aStr.SearchAndReplace( '#', aPropertyName );
1051 return aStr;
1055 DBG_NAME(FmUndoContainerAction);
1056 //------------------------------------------------------------------------------
1057 FmUndoContainerAction::FmUndoContainerAction(FmFormModel& _rMod,
1058 Action _eAction,
1059 const Reference< XIndexContainer > & xCont,
1060 const Reference< XInterface > & xElem,
1061 sal_Int32 nIdx)
1062 :SdrUndoAction( _rMod )
1063 ,m_xContainer( xCont )
1064 ,m_nIndex( nIdx )
1065 ,m_eAction( _eAction )
1067 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::FmUndoContainerAction" );
1068 OSL_ENSURE( nIdx >= 0, "FmUndoContainerAction::FmUndoContainerAction: invalid index!" );
1069 // some old code suggested this could be a valid argument. However, this code was
1070 // buggy, and it *seemed* that nobody used it - so it was removed.
1072 DBG_CTOR(FmUndoContainerAction,NULL);
1073 if ( xCont.is() && xElem.is() )
1075 // normalize
1076 m_xElement = m_xElement.query( xElem );
1077 if ( m_eAction == Removed )
1079 if (m_nIndex >= 0)
1081 Reference< XEventAttacherManager > xManager( xCont, UNO_QUERY );
1082 if ( xManager.is() )
1083 m_aEvents = xManager->getScriptEvents(m_nIndex);
1085 else
1086 m_xElement = NULL;
1088 // we now own the element
1089 m_xOwnElement = m_xElement;
1094 //------------------------------------------------------------------------------
1095 FmUndoContainerAction::~FmUndoContainerAction()
1097 // if we own the object ....
1098 DisposeElement( m_xOwnElement );
1099 DBG_DTOR(FmUndoContainerAction,NULL);
1102 //------------------------------------------------------------------------------
1104 void FmUndoContainerAction::DisposeElement( const Reference< XInterface > & xElem )
1106 Reference< XComponent > xComp( xElem, UNO_QUERY );
1107 if ( xComp.is() )
1109 // and the object does not have a parent
1110 Reference< XChild > xChild( xElem, UNO_QUERY );
1111 if ( xChild.is() && !xChild->getParent().is() )
1112 // -> dispose it
1113 xComp->dispose();
1117 //------------------------------------------------------------------------------
1118 void FmUndoContainerAction::implReInsert( ) SAL_THROW( ( Exception ) )
1120 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReInsert" );
1121 if ( m_xContainer->getCount() >= m_nIndex )
1123 // insert the element
1124 Any aVal;
1125 if ( m_xContainer->getElementType() == ::getCppuType( static_cast< const Reference< XFormComponent >* >( NULL ) ) )
1127 aVal <<= Reference< XFormComponent >( m_xElement, UNO_QUERY );
1129 else
1131 aVal <<= Reference< XForm >( m_xElement, UNO_QUERY );
1133 m_xContainer->insertByIndex( m_nIndex, aVal );
1135 OSL_ENSURE( getElementPos( m_xContainer.get(), m_xElement ) == m_nIndex, "FmUndoContainerAction::implReInsert: insertion did not work!" );
1137 // register the events
1138 Reference< XEventAttacherManager > xManager( m_xContainer, UNO_QUERY );
1139 if ( xManager.is() )
1140 xManager->registerScriptEvents( m_nIndex, m_aEvents );
1142 // we don't own the object anymore
1143 m_xOwnElement = NULL;
1147 //------------------------------------------------------------------------------
1148 void FmUndoContainerAction::implReRemove( ) SAL_THROW( ( Exception ) )
1150 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReRemove" );
1151 Reference< XInterface > xElement;
1152 if ( ( m_nIndex >= 0 ) && ( m_nIndex < m_xContainer->getCount() ) )
1153 m_xContainer->getByIndex( m_nIndex ) >>= xElement;
1155 if ( xElement != m_xElement )
1157 // the indexes in the container changed. Okay, so go the long way and
1158 // manually determine the index
1159 m_nIndex = getElementPos( m_xContainer.get(), m_xElement );
1160 if ( m_nIndex != -1 )
1161 xElement = m_xElement;
1164 OSL_ENSURE( xElement == m_xElement, "FmUndoContainerAction::implReRemove: cannot find the element which I'm responsible for!" );
1165 if ( xElement == m_xElement )
1167 Reference< XEventAttacherManager > xManager( m_xContainer, UNO_QUERY );
1168 if ( xManager.is() )
1169 m_aEvents = xManager->getScriptEvents( m_nIndex );
1170 m_xContainer->removeByIndex( m_nIndex );
1171 // from now on, we own this object
1172 m_xOwnElement = m_xElement;
1176 //------------------------------------------------------------------------------
1177 void FmUndoContainerAction::Undo()
1179 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Undo" );
1180 FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
1182 if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
1184 rEnv.Lock();
1187 switch ( m_eAction )
1189 case Inserted:
1190 implReRemove();
1191 break;
1193 case Removed:
1194 implReInsert();
1195 break;
1198 catch( const Exception& )
1200 OSL_ENSURE( sal_False, "FmUndoContainerAction::Undo: caught an exception!" );
1202 rEnv.UnLock();
1206 //------------------------------------------------------------------------------
1207 void FmUndoContainerAction::Redo()
1209 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Redo" );
1210 FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
1211 if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
1213 rEnv.Lock();
1216 switch ( m_eAction )
1218 case Inserted:
1219 implReInsert();
1220 break;
1222 case Removed:
1223 implReRemove();
1224 break;
1227 catch( const Exception& )
1229 OSL_ENSURE( sal_False, "FmUndoContainerAction::Redo: caught an exception!" );
1231 rEnv.UnLock();
1235 //------------------------------------------------------------------------------
1236 FmUndoModelReplaceAction::FmUndoModelReplaceAction(FmFormModel& _rMod, SdrUnoObj* _pObject, const Reference< XControlModel > & _xReplaced)
1237 :SdrUndoAction(_rMod)
1238 ,m_xReplaced(_xReplaced)
1239 ,m_pObject(_pObject)
1241 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::FmUndoModelReplaceAction" );
1244 //------------------------------------------------------------------------------
1245 FmUndoModelReplaceAction::~FmUndoModelReplaceAction()
1247 // dispose our element if nobody else is responsible for
1248 DisposeElement(m_xReplaced);
1251 //------------------------------------------------------------------------------
1253 void FmUndoModelReplaceAction::DisposeElement( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel>& xReplaced )
1255 Reference< XComponent > xComp(xReplaced, UNO_QUERY);
1256 if (xComp.is())
1258 Reference< XChild > xChild(xReplaced, UNO_QUERY);
1259 if (!xChild.is() || !xChild->getParent().is())
1260 xComp->dispose();
1264 //------------------------------------------------------------------------------
1265 void FmUndoModelReplaceAction::Undo()
1267 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::Undo" );
1270 Reference< XControlModel > xCurrentModel( m_pObject->GetUnoControlModel() );
1272 // replace the model within the parent
1273 Reference< XChild > xCurrentAsChild( xCurrentModel, UNO_QUERY );
1274 Reference< XNameContainer > xCurrentsParent;
1275 if ( xCurrentAsChild.is() )
1276 xCurrentsParent = xCurrentsParent.query( xCurrentAsChild->getParent() );
1277 DBG_ASSERT( xCurrentsParent.is(), "FmUndoModelReplaceAction::Undo: invalid current model!" );
1279 if ( xCurrentsParent.is() )
1281 // the form container works with FormComponents
1282 Reference< XFormComponent > xComponent( m_xReplaced, UNO_QUERY );
1283 DBG_ASSERT( xComponent.is(), "FmUndoModelReplaceAction::Undo: the new model is no form component !" );
1285 Reference< XPropertySet > xCurrentAsSet( xCurrentModel, UNO_QUERY );
1286 DBG_ASSERT( ::comphelper::hasProperty(FM_PROP_NAME, xCurrentAsSet ), "FmUndoModelReplaceAction::Undo : one of the models is invalid !");
1288 ::rtl::OUString sName;
1289 xCurrentAsSet->getPropertyValue( FM_PROP_NAME ) >>= sName;
1290 xCurrentsParent->replaceByName( sName, makeAny( xComponent ) );
1292 m_pObject->SetUnoControlModel(m_xReplaced);
1293 m_pObject->SetChanged();
1295 m_xReplaced = xCurrentModel;
1298 catch(Exception&)
1300 DBG_ERROR("FmUndoModelReplaceAction::Undo : could not replace the model !");
1304 //------------------------------------------------------------------------------
1305 String FmUndoModelReplaceAction::GetComment() const
1307 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::GetComment" );
1308 return SVX_RES(RID_STR_UNDO_MODEL_REPLACE);