bump product version to 4.1.6.2
[LibreOffice.git] / svx / source / form / fmundo.cxx
blob29ef91a77aa52bd7de6e35d9a71ff79e7c4752c3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <sal/macros.h>
22 #include "fmundo.hxx"
23 #include "fmpgeimp.hxx"
24 #include "svx/dbtoolsclient.hxx"
25 #include "svx/svditer.hxx"
26 #include "fmobj.hxx"
27 #include "fmprop.hrc"
28 #include "svx/fmresids.hrc"
29 #include "svx/fmglob.hxx"
30 #include "svx/dialmgr.hxx"
31 #include "svx/fmmodel.hxx"
32 #include "svx/fmpage.hxx"
34 #include <com/sun/star/util/XModifyBroadcaster.hpp>
35 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #include <com/sun/star/container/XContainer.hpp>
37 #include <com/sun/star/container/XContainerListener.hpp>
38 #include <com/sun/star/script/XEventAttacherManager.hpp>
39 #include <com/sun/star/form/binding/XBindableValue.hpp>
40 #include <com/sun/star/form/binding/XListEntrySink.hpp>
41 #include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
43 #include "svx/fmtools.hxx"
44 #include <rtl/logfile.hxx>
45 #include <svl/macitem.hxx>
46 #include <tools/shl.hxx>
47 #include <tools/diagnose_ex.h>
48 #include <sfx2/objsh.hxx>
49 #include <sfx2/docfile.hxx>
50 #include <sfx2/app.hxx>
51 #include <sfx2/sfx.hrc>
52 #include <sfx2/event.hxx>
53 #include <osl/mutex.hxx>
54 #include <comphelper/property.hxx>
55 #include <comphelper/uno3.hxx>
56 #include <comphelper/stl_types.hxx>
57 #include <comphelper/componentcontext.hxx>
59 using namespace ::com::sun::star::uno;
60 using namespace ::com::sun::star::awt;
61 using namespace ::com::sun::star::beans;
62 using namespace ::com::sun::star::container;
63 using namespace ::com::sun::star::script;
64 using namespace ::com::sun::star::lang;
65 using namespace ::com::sun::star::form;
66 using namespace ::com::sun::star::util;
67 using namespace ::com::sun::star::reflection;
68 using namespace ::com::sun::star::form::binding;
69 using namespace ::svxform;
72 #include <com/sun/star/script/XScriptListener.hpp>
73 #include <comphelper/processfactory.hxx>
74 #include <cppuhelper/implbase1.hxx>
76 typedef cppu::WeakImplHelper1< XScriptListener > ScriptEventListener_BASE;
77 class ScriptEventListenerWrapper : public ScriptEventListener_BASE
79 public:
80 ScriptEventListenerWrapper( FmFormModel& _rModel) throw ( RuntimeException )
81 :m_rModel( _rModel )
82 ,m_attemptedListenerCreation( false )
86 // XEventListener
87 virtual void SAL_CALL disposing(const EventObject& ) throw( RuntimeException ){}
89 // XScriptListener
90 virtual void SAL_CALL firing(const ScriptEvent& evt) throw(RuntimeException)
92 attemptListenerCreation();
93 if ( m_vbaListener.is() )
95 m_vbaListener->firing( evt );
99 virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) throw( com::sun::star::reflection::InvocationTargetException, RuntimeException)
101 attemptListenerCreation();
102 if ( m_vbaListener.is() )
104 return m_vbaListener->approveFiring( evt );
106 return Any();
109 private:
110 void attemptListenerCreation()
112 if ( m_attemptedListenerCreation )
113 return;
114 m_attemptedListenerCreation = true;
118 ::comphelper::ComponentContext const aContext( ::comphelper::getProcessComponentContext() );
119 Reference< XScriptListener > const xScriptListener( aContext.createComponent( "ooo.vba.EventListener" ), UNO_QUERY_THROW );
120 Reference< XPropertySet > const xListenerProps( xScriptListener, UNO_QUERY_THROW );
121 // SfxObjectShellRef is good here since the model controls the lifetime of the shell
122 SfxObjectShellRef const xObjectShell = m_rModel.GetObjectShell();
123 ENSURE_OR_THROW( xObjectShell.Is(), "no object shell!" );
124 xListenerProps->setPropertyValue( OUString( "Model" ), makeAny( xObjectShell->GetModel() ) );
126 m_vbaListener = xScriptListener;
128 catch( Exception const & )
130 DBG_UNHANDLED_EXCEPTION();
133 FmFormModel& m_rModel;
134 Reference< XScriptListener > m_vbaListener;
135 bool m_attemptedListenerCreation;
140 //------------------------------------------------------------------------------
141 // some helper structs for caching property infos
142 //------------------------------------------------------------------------------
143 struct PropertyInfo
145 sal_Bool bIsTransientOrReadOnly : 1; // the property is transient or read-only, thus we need no undo action for it
146 sal_Bool bIsValueProperty : 1; // the property is the special value property, thus it may be handled
147 // as if it's transient or persistent
150 struct PropertySetInfo
152 DECLARE_STL_USTRINGACCESS_MAP(PropertyInfo, AllProperties);
154 AllProperties aProps; // all properties of this set which we know so far
155 sal_Bool bHasEmptyControlSource; // sal_True -> the set has a DataField property, and the current value is an empty string
156 // sal_False -> the set has _no_ such property or it's value isn't empty
159 sal_Bool operator < (const Reference< XPropertySet >& lhs,
160 const Reference< XPropertySet >& rhs)
162 return lhs.get() < rhs.get();
165 DECLARE_STL_STDKEY_MAP(Reference< XPropertySet >, PropertySetInfo, PropertySetInfoCache);
167 //------------------------------------------------------------------------------
169 String static_STR_UNDO_PROPERTY;
170 //------------------------------------------------------------------------------
171 DBG_NAME(FmXUndoEnvironment)
172 //------------------------------------------------------------------------------
173 FmXUndoEnvironment::FmXUndoEnvironment(FmFormModel& _rModel)
174 :rModel( _rModel )
175 ,m_pPropertySetCache( NULL )
176 ,m_pScriptingEnv( ::svxform::createDefaultFormScriptingEnvironment( _rModel ) )
177 ,m_Locks( 0 )
178 ,bReadOnly( sal_False )
179 ,m_bDisposed( false )
181 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::FmXUndoEnvironment" );
182 DBG_CTOR(FmXUndoEnvironment,NULL);
185 m_vbaListener = new ScriptEventListenerWrapper( _rModel );
187 catch( Exception& )
192 //------------------------------------------------------------------------------
193 FmXUndoEnvironment::~FmXUndoEnvironment()
195 DBG_DTOR(FmXUndoEnvironment,NULL);
196 if (m_pPropertySetCache)
197 delete static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
200 //------------------------------------------------------------------------------
201 void FmXUndoEnvironment::dispose()
203 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::dispose" );
204 OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::dispose: disposed twice?" );
205 if ( !m_bDisposed )
206 return;
208 Lock();
210 sal_uInt16 nCount = rModel.GetPageCount();
211 sal_uInt16 i;
212 for (i = 0; i < nCount; i++)
214 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
215 if ( pPage )
217 Reference< css::form::XForms > xForms = pPage->GetForms( false ).get();
218 if ( xForms.is() )
219 RemoveElement( xForms );
223 nCount = rModel.GetMasterPageCount();
224 for (i = 0; i < nCount; i++)
226 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
227 if ( pPage )
229 Reference< css::form::XForms > xForms = pPage->GetForms( false ).get();
230 if ( xForms.is() )
231 RemoveElement( xForms );
235 UnLock();
237 OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::dispose: no object shell anymore!" );
238 if ( rModel.GetObjectShell() )
239 EndListening( *rModel.GetObjectShell() );
241 if ( IsListening( rModel ) )
242 EndListening( rModel );
244 m_pScriptingEnv->dispose();
246 m_bDisposed = true;
249 //------------------------------------------------------------------------------
250 void FmXUndoEnvironment::ModeChanged()
252 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::ModeChanged" );
253 OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::ModeChanged: no object shell anymore!" );
254 if ( !rModel.GetObjectShell() )
255 return;
257 if (bReadOnly != (rModel.GetObjectShell()->IsReadOnly() || rModel.GetObjectShell()->IsReadOnlyUI()))
259 bReadOnly = !bReadOnly;
261 sal_uInt16 nCount = rModel.GetPageCount();
262 sal_uInt16 i;
263 for (i = 0; i < nCount; i++)
265 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
266 if ( pPage )
268 Reference< css::form::XForms > xForms = pPage->GetForms( false ).get();
269 if ( xForms.is() )
270 TogglePropertyListening( xForms );
274 nCount = rModel.GetMasterPageCount();
275 for (i = 0; i < nCount; i++)
277 FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
278 if ( pPage )
280 Reference< css::form::XForms > xForms = pPage->GetForms( false ).get();
281 if ( xForms.is() )
282 TogglePropertyListening( xForms );
286 if (!bReadOnly)
287 StartListening(rModel);
288 else
289 EndListening(rModel);
293 //------------------------------------------------------------------------------
294 void FmXUndoEnvironment::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
296 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Notify" );
297 if (rHint.ISA(SdrHint))
299 SdrHint* pSdrHint = (SdrHint*)&rHint;
300 switch( pSdrHint->GetKind() )
302 case HINT_OBJINSERTED:
304 SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
305 Inserted( pSdrObj );
306 } break;
307 case HINT_OBJREMOVED:
309 SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
310 Removed( pSdrObj );
312 break;
313 default:
314 break;
317 else if (rHint.ISA(SfxSimpleHint))
319 switch ( ((SfxSimpleHint&)rHint).GetId() )
321 case SFX_HINT_DYING:
322 dispose();
323 rModel.SetObjectShell( NULL );
324 break;
325 case SFX_HINT_MODECHANGED:
326 ModeChanged();
327 break;
330 else if (rHint.ISA(SfxEventHint))
332 switch (((SfxEventHint&)rHint).GetEventId())
334 case SFX_EVENT_CREATEDOC:
335 case SFX_EVENT_OPENDOC:
336 ModeChanged();
337 break;
343 //------------------------------------------------------------------
344 void FmXUndoEnvironment::Inserted(SdrObject* pObj)
346 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
347 if (pObj->GetObjInventor() == FmFormInventor)
349 FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
350 Inserted( pFormObj );
352 else if (pObj->IsGroupObject())
354 SdrObjListIter aIter(*pObj->GetSubList());
355 while ( aIter.IsMore() )
356 Inserted( aIter.Next() );
360 //------------------------------------------------------------------------------
361 namespace
363 sal_Bool lcl_searchElement(const Reference< XIndexAccess>& xCont, const Reference< XInterface >& xElement)
365 if (!xCont.is() || !xElement.is())
366 return sal_False;
368 sal_Int32 nCount = xCont->getCount();
369 Reference< XInterface > xComp;
370 for (sal_Int32 i = 0; i < nCount; i++)
374 xCont->getByIndex(i) >>= xComp;
375 if (xComp.is())
377 if ( xElement == xComp )
378 return sal_True;
379 else
381 Reference< XIndexAccess> xCont2(xComp, UNO_QUERY);
382 if (xCont2.is() && lcl_searchElement(xCont2, xElement))
383 return sal_True;
387 catch(const Exception&)
389 DBG_UNHANDLED_EXCEPTION();
392 return sal_False;
396 //------------------------------------------------------------------------------
397 void FmXUndoEnvironment::Inserted(FmFormObj* pObj)
399 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
400 DBG_ASSERT( pObj, "FmXUndoEnvironment::Inserted: invalid object!" );
401 if ( !pObj )
402 return;
404 // ist das Control noch einer Form zugeordnet
405 Reference< XInterface > xModel(pObj->GetUnoControlModel(), UNO_QUERY);
406 Reference< XFormComponent > xContent(xModel, UNO_QUERY);
407 if (xContent.is() && pObj->GetPage())
409 // if the component doesn't belong to a form, yet, find one to insert into
410 if (!xContent->getParent().is())
414 Reference< XIndexContainer > xObjectParent = pObj->GetOriginalParent();
416 FmFormPage& rPage = dynamic_cast< FmFormPage& >( *pObj->GetPage() );
417 Reference< XIndexAccess > xForms( rPage.GetForms(), UNO_QUERY_THROW );
419 Reference< XIndexContainer > xNewParent;
420 Reference< XForm > xForm;
421 sal_Int32 nPos = -1;
422 if ( lcl_searchElement( xForms, xObjectParent ) )
424 // the form which was the parent of the object when it was removed is still
425 // part of the form component hierachy of the current page
426 xNewParent = xObjectParent;
427 xForm.set( xNewParent, UNO_QUERY_THROW );
428 nPos = ::std::min( pObj->GetOriginalIndex(), xNewParent->getCount() );
430 else
432 xForm.set( rPage.GetImpl().findPlaceInFormComponentHierarchy( xContent ), UNO_SET_THROW );
433 xNewParent.set( xForm, UNO_QUERY_THROW );
434 nPos = xNewParent->getCount();
437 rPage.GetImpl().setUniqueName( xContent, xForm );
438 xNewParent->insertByIndex( nPos, makeAny( xContent ) );
440 Reference< XEventAttacherManager > xManager( xNewParent, UNO_QUERY_THROW );
441 xManager->registerScriptEvents( nPos, pObj->GetOriginalEvents() );
443 catch( const Exception& )
445 DBG_UNHANDLED_EXCEPTION();
449 // FormObject zuruecksetzen
450 pObj->ClearObjEnv();
454 //------------------------------------------------------------------
455 void FmXUndoEnvironment::Removed(SdrObject* pObj)
457 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
458 if ( pObj->IsVirtualObj() )
459 // for virtual objects, we've already been notified of the removal of the master
460 // object, which is sufficient here
461 return;
463 if (pObj->GetObjInventor() == FmFormInventor)
465 FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
466 Removed(pFormObj);
468 else if (pObj->IsGroupObject())
470 SdrObjListIter aIter(*pObj->GetSubList());
471 while ( aIter.IsMore() )
472 Removed( aIter.Next() );
476 //------------------------------------------------------------------------------
477 void FmXUndoEnvironment::Removed(FmFormObj* pObj)
479 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
480 DBG_ASSERT( pObj, "FmXUndoEnvironment::Removed: invalid object!" );
481 if ( !pObj )
482 return;
484 // ist das Control noch einer Form zugeordnet
485 Reference< XFormComponent > xContent(pObj->GetUnoControlModel(), UNO_QUERY);
486 if (xContent.is())
488 // das Object wird aus einer Liste herausgenommen
489 // existiert ein Vater wird das Object beim beim Vater entfernt und
490 // am FormObject gemerkt!
492 // wird das Object wieder eingefuegt und ein Parent existiert, so wird dieser
493 // Parent wiederum gesetzt
494 Reference< XIndexContainer > xForm(xContent->getParent(), UNO_QUERY);
495 if (xForm.is())
497 Reference< XIndexAccess > xIndexAccess((XIndexContainer*)xForm.get());
498 // Feststellen an welcher Position sich das Kind befunden hat
499 const sal_Int32 nPos = getElementPos(xIndexAccess, xContent);
500 if (nPos >= 0)
502 Sequence< ScriptEventDescriptor > aEvts;
503 Reference< XEventAttacherManager > xManager(xForm, UNO_QUERY);
504 if (xManager.is())
505 aEvts = xManager->getScriptEvents(nPos);
509 pObj->SetObjEnv(xForm, nPos, aEvts);
510 xForm->removeByIndex(nPos);
512 catch(Exception&)
514 DBG_UNHANDLED_EXCEPTION();
522 // XEventListener
523 //------------------------------------------------------------------------------
524 void SAL_CALL FmXUndoEnvironment::disposing(const EventObject& e) throw( RuntimeException )
526 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::disposing" );
527 // check if it's an object we have cached information about
528 if (m_pPropertySetCache)
530 Reference< XPropertySet > xSourceSet(e.Source, UNO_QUERY);
531 if (xSourceSet.is())
533 PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
534 PropertySetInfoCacheIterator aSetPos = pCache->find(xSourceSet);
535 if (aSetPos != pCache->end())
536 pCache->erase(aSetPos);
541 // XPropertyChangeListener
542 //------------------------------------------------------------------------------
543 void SAL_CALL FmXUndoEnvironment::propertyChange(const PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException)
545 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::propertyChange" );
546 ::osl::ClearableMutexGuard aGuard( m_aMutex );
548 if (!IsLocked())
550 Reference< XPropertySet > xSet(evt.Source, UNO_QUERY);
551 if (!xSet.is())
552 return;
554 // if it's a "default value" property of a control model, set the according "value" property
555 static OUString pDefaultValueProperties[] = {
556 OUString(FM_PROP_DEFAULT_TEXT), OUString(FM_PROP_DEFAULTCHECKED), OUString(FM_PROP_DEFAULT_DATE), OUString(FM_PROP_DEFAULT_TIME),
557 OUString(FM_PROP_DEFAULT_VALUE), OUString(FM_PROP_DEFAULT_SELECT_SEQ), OUString(FM_PROP_EFFECTIVE_DEFAULT)
559 const OUString aValueProperties[] = {
560 OUString(FM_PROP_TEXT), OUString(FM_PROP_STATE), OUString(FM_PROP_DATE), OUString(FM_PROP_TIME),
561 OUString(FM_PROP_VALUE), OUString(FM_PROP_SELECT_SEQ), OUString(FM_PROP_EFFECTIVE_VALUE)
563 sal_Int32 nDefaultValueProps = sizeof(pDefaultValueProperties)/sizeof(pDefaultValueProperties[0]);
564 OSL_ENSURE(sizeof(aValueProperties)/sizeof(aValueProperties[0]) == nDefaultValueProps,
565 "FmXUndoEnvironment::propertyChange: inconsistence!");
566 for (sal_Int32 i=0; i<nDefaultValueProps; ++i)
568 if (evt.PropertyName == pDefaultValueProperties[i])
572 xSet->setPropertyValue(aValueProperties[i], evt.NewValue);
574 catch(const Exception&)
576 OSL_FAIL("FmXUndoEnvironment::propertyChange: could not adjust the value property!");
581 // no Undo for transient and readonly props. But unfortunately "transient" is not only that the
582 // "transient" flag is set for the property in question, instead is is somewhat more complex
583 // Transience criterions are:
584 // - the "transient" flag is set for the property
585 // - OR the control has a non-empty COntrolSource property, i.e. is intended to be bound
586 // to a database column. Note that it doesn't matter here whether the control actually
587 // *is* bound to a column
588 // - OR the control is bound to an external value via XBindableValue/XValueBinding
589 // which does not have a "ExternalData" property being <TRUE/>
591 if (!m_pPropertySetCache)
592 m_pPropertySetCache = new PropertySetInfoCache;
593 PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
595 // let's see if we know something about the set
596 PropertySetInfoCacheIterator aSetPos = pCache->find(xSet);
597 if (aSetPos == pCache->end())
599 PropertySetInfo aNewEntry;
600 if (!::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xSet))
602 aNewEntry.bHasEmptyControlSource = sal_False;
604 else
608 Any aCurrentControlSource = xSet->getPropertyValue(FM_PROP_CONTROLSOURCE);
609 aNewEntry.bHasEmptyControlSource = !aCurrentControlSource.hasValue() || ::comphelper::getString(aCurrentControlSource).isEmpty();
611 catch(const Exception&)
613 DBG_UNHANDLED_EXCEPTION();
616 aSetPos = pCache->insert(PropertySetInfoCache::value_type(xSet,aNewEntry)).first;
617 DBG_ASSERT(aSetPos != pCache->end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
619 else
620 { // is it the DataField property ?
621 if (evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
623 aSetPos->second.bHasEmptyControlSource = !evt.NewValue.hasValue() || ::comphelper::getString(evt.NewValue).isEmpty();
627 // now we have access to the cached info about the set
628 // let's see what we know about the property
629 PropertySetInfo::AllProperties& rPropInfos = aSetPos->second.aProps;
630 PropertySetInfo::AllPropertiesIterator aPropertyPos = rPropInfos.find(evt.PropertyName);
631 if (aPropertyPos == rPropInfos.end())
632 { // nothing 'til now ... have to change this ....
633 PropertyInfo aNewEntry;
635 // the attributes
636 sal_Int32 nAttributes = xSet->getPropertySetInfo()->getPropertyByName(evt.PropertyName).Attributes;
637 aNewEntry.bIsTransientOrReadOnly = ((nAttributes & PropertyAttribute::READONLY) != 0) || ((nAttributes & PropertyAttribute::TRANSIENT) != 0);
639 // check if it is the special "DataFieldProperty"
640 aNewEntry.bIsValueProperty = sal_False;
643 if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCEPROPERTY, xSet))
645 Any aControlSourceProperty = xSet->getPropertyValue(FM_PROP_CONTROLSOURCEPROPERTY);
646 OUString sControlSourceProperty;
647 aControlSourceProperty >>= sControlSourceProperty;
649 aNewEntry.bIsValueProperty = (sControlSourceProperty.equals(evt.PropertyName));
652 catch(const Exception&)
654 DBG_UNHANDLED_EXCEPTION();
657 // insert the new entry
658 aPropertyPos = rPropInfos.insert(PropertySetInfo::AllProperties::value_type(evt.PropertyName,aNewEntry)).first;
659 DBG_ASSERT(aPropertyPos != rPropInfos.end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
662 // now we have access to the cached info about the property affected
663 // and are able to decide whether or not we need an undo action
665 bool bAddUndoAction = rModel.IsUndoEnabled();
666 // no UNDO for transient/readonly properties
667 if ( bAddUndoAction && aPropertyPos->second.bIsTransientOrReadOnly )
668 bAddUndoAction = false;
670 if ( bAddUndoAction && aPropertyPos->second.bIsValueProperty )
672 // no UNDO when the "value" property changes, but the ControlSource is non-empty
673 // (in this case the control is intended to be bound to a database column)
674 if ( !aSetPos->second.bHasEmptyControlSource )
675 bAddUndoAction = false;
677 // no UNDO if the control is currently bound to an external value
678 if ( bAddUndoAction )
680 Reference< XBindableValue > xBindable( evt.Source, UNO_QUERY );
681 Reference< XValueBinding > xBinding;
682 if ( xBindable.is() )
683 xBinding = xBindable->getValueBinding();
685 Reference< XPropertySet > xBindingProps;
686 Reference< XPropertySetInfo > xBindingPropsPSI;
687 if ( xBindable.is() )
688 xBindingProps.set( xBinding, UNO_QUERY );
689 if ( xBindingProps.is() )
690 xBindingPropsPSI = xBindingProps->getPropertySetInfo();
691 // TODO: we should cache all those things, else this might be too expensive.
692 // However, this requires we're notified of changes in the value binding
694 static const OUString s_sExternalData( "ExternalData" );
695 if ( xBindingPropsPSI.is() && xBindingPropsPSI->hasPropertyByName( s_sExternalData ) )
697 sal_Bool bExternalData = sal_True;
698 OSL_VERIFY( xBindingProps->getPropertyValue( s_sExternalData ) >>= bExternalData );
699 bAddUndoAction = !bExternalData;
701 else
702 bAddUndoAction = !xBinding.is();
706 if ( bAddUndoAction && ( evt.PropertyName == FM_PROP_STRINGITEMLIST ) )
708 Reference< XListEntrySink > xSink( evt.Source, UNO_QUERY );
709 if ( xSink.is() && xSink->getListEntrySource().is() )
710 // #i41029# / 2005-01-31 / frank.schoenheit@sun.com
711 bAddUndoAction = false;
714 if ( bAddUndoAction )
716 aGuard.clear();
717 // TODO: this is a potential race condition: two threads here could in theory
718 // add their undo actions out-of-order
720 SolarMutexGuard aSolarGuard;
721 rModel.AddUndo(new FmUndoPropertyAction(rModel, evt));
724 else
726 // if it's the DataField property we may have to adjust our cache
727 if (m_pPropertySetCache && evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
729 Reference< XPropertySet > xSet(evt.Source, UNO_QUERY);
730 PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
731 PropertySetInfo& rSetInfo = (*pCache)[xSet];
732 rSetInfo.bHasEmptyControlSource = !evt.NewValue.hasValue() || ::comphelper::getString(evt.NewValue).isEmpty();
737 // XContainerListener
738 //------------------------------------------------------------------------------
739 void SAL_CALL FmXUndoEnvironment::elementInserted(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
741 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementInserted" );
742 SolarMutexGuard aSolarGuard;
743 ::osl::MutexGuard aGuard( m_aMutex );
745 // neues Object zum lauschen
746 Reference< XInterface > xIface;
747 evt.Element >>= xIface;
748 OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementInserted: invalid container notification!");
749 AddElement(xIface);
751 implSetModified();
754 //------------------------------------------------------------------------------
755 void FmXUndoEnvironment::implSetModified()
757 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::implSetModified" );
758 if ( !IsLocked() && rModel.GetObjectShell() )
760 rModel.GetObjectShell()->SetModified( sal_True );
764 //------------------------------------------------------------------------------
765 void SAL_CALL FmXUndoEnvironment::elementReplaced(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
767 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementReplaced" );
768 SolarMutexGuard aSolarGuard;
769 ::osl::MutexGuard aGuard( m_aMutex );
771 Reference< XInterface > xIface;
772 evt.ReplacedElement >>= xIface;
773 OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementReplaced: invalid container notification!");
774 RemoveElement(xIface);
776 evt.Element >>= xIface;
777 AddElement(xIface);
779 implSetModified();
782 //------------------------------------------------------------------------------
783 void SAL_CALL FmXUndoEnvironment::elementRemoved(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
785 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementRemoved" );
786 SolarMutexGuard aSolarGuard;
787 ::osl::MutexGuard aGuard( m_aMutex );
789 Reference< XInterface > xIface( evt.Element, UNO_QUERY );
790 OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementRemoved: invalid container notification!");
791 RemoveElement(xIface);
793 implSetModified();
796 //------------------------------------------------------------------------------
797 void SAL_CALL FmXUndoEnvironment::modified( const EventObject& /*aEvent*/ ) throw (RuntimeException)
799 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::modified" );
800 implSetModified();
803 //------------------------------------------------------------------------------
804 void FmXUndoEnvironment::AddForms(const Reference< XNameContainer > & rForms)
806 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddForms" );
807 Lock();
808 Reference< XInterface > xInt(rForms, UNO_QUERY);
809 AddElement(xInt);
810 UnLock();
813 //------------------------------------------------------------------------------
814 void FmXUndoEnvironment::RemoveForms(const Reference< XNameContainer > & rForms)
816 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveForms" );
817 Lock();
818 Reference< XInterface > xInt(rForms, UNO_QUERY);
819 RemoveElement(xInt);
820 UnLock();
823 //------------------------------------------------------------------------------
824 void FmXUndoEnvironment::TogglePropertyListening(const Reference< XInterface > & Element)
826 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::TogglePropertyListening" );
827 // am Container horchen
828 Reference< XIndexContainer > xContainer(Element, UNO_QUERY);
829 if (xContainer.is())
831 sal_uInt32 nCount = xContainer->getCount();
832 Reference< XInterface > xIface;
833 for (sal_uInt32 i = 0; i < nCount; i++)
835 xContainer->getByIndex(i) >>= xIface;
836 TogglePropertyListening(xIface);
840 Reference< XPropertySet > xSet(Element, UNO_QUERY);
841 if (xSet.is())
843 if (!bReadOnly)
844 xSet->addPropertyChangeListener( OUString(), this );
845 else
846 xSet->removePropertyChangeListener( OUString(), this );
851 //------------------------------------------------------------------------------
852 void FmXUndoEnvironment::switchListening( const Reference< XIndexContainer >& _rxContainer, bool _bStartListening ) SAL_THROW(())
854 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
855 OSL_PRECOND( _rxContainer.is(), "FmXUndoEnvironment::switchListening: invalid container!" );
856 if ( !_rxContainer.is() )
857 return;
861 // if it's an EventAttacherManager, then we need to listen for
862 // script events
863 Reference< XEventAttacherManager > xManager( _rxContainer, UNO_QUERY );
864 if ( xManager.is() )
866 if ( _bStartListening )
868 m_pScriptingEnv->registerEventAttacherManager( xManager );
869 if ( m_vbaListener.is() )
870 xManager->addScriptListener( m_vbaListener );
872 else
874 m_pScriptingEnv->revokeEventAttacherManager( xManager );
875 if ( m_vbaListener.is() )
876 xManager->removeScriptListener( m_vbaListener );
880 // also handle all children of this element
881 sal_uInt32 nCount = _rxContainer->getCount();
882 Reference< XInterface > xInterface;
883 for ( sal_uInt32 i = 0; i < nCount; ++i )
885 _rxContainer->getByIndex( i ) >>= xInterface;
886 if ( _bStartListening )
887 AddElement( xInterface );
888 else
889 RemoveElement( xInterface );
892 // be notified of any changes in the container elements
893 Reference< XContainer > xSimpleContainer( _rxContainer, UNO_QUERY );
894 OSL_ENSURE( xSimpleContainer.is(), "FmXUndoEnvironment::switchListening: how are we expected to be notified of changes in the container?" );
895 if ( xSimpleContainer.is() )
897 if ( _bStartListening )
898 xSimpleContainer->addContainerListener( this );
899 else
900 xSimpleContainer->removeContainerListener( this );
903 catch( const Exception& )
905 OSL_FAIL( "FmXUndoEnvironment::switchListening: caught an exception!" );
909 //------------------------------------------------------------------------------
910 void FmXUndoEnvironment::switchListening( const Reference< XInterface >& _rxObject, bool _bStartListening ) SAL_THROW(())
912 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
913 OSL_PRECOND( _rxObject.is(), "FmXUndoEnvironment::switchListening: how should I listen at a NULL object?" );
917 if ( !bReadOnly )
919 Reference< XPropertySet > xProps( _rxObject, UNO_QUERY );
920 if ( xProps.is() )
922 if ( _bStartListening )
923 xProps->addPropertyChangeListener( OUString(), this );
924 else
925 xProps->removePropertyChangeListener( OUString(), this );
929 Reference< XModifyBroadcaster > xBroadcaster( _rxObject, UNO_QUERY );
930 if ( xBroadcaster.is() )
932 if ( _bStartListening )
933 xBroadcaster->addModifyListener( this );
934 else
935 xBroadcaster->removeModifyListener( this );
938 catch( const Exception& )
940 OSL_FAIL( "FmXUndoEnvironment::switchListening: caught an exception!" );
944 //------------------------------------------------------------------------------
945 void FmXUndoEnvironment::AddElement(const Reference< XInterface >& _rxElement )
947 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddElement" );
948 OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::AddElement: not when I'm already disposed!" );
950 // am Container horchen
951 Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
952 if ( xContainer.is() )
953 switchListening( xContainer, true );
955 switchListening( _rxElement, true );
958 //------------------------------------------------------------------------------
959 void FmXUndoEnvironment::RemoveElement(const Reference< XInterface >& _rxElement)
961 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveElement" );
962 if ( m_bDisposed )
963 return;
965 switchListening( _rxElement, false );
967 if (!bReadOnly)
969 // reset the ActiveConnection if the form is to be removed. This will (should) free the resources
970 // associated with this connection
971 // 86299 - 05/02/2001 - frank.schoenheit@germany.sun.com
972 Reference< XForm > xForm( _rxElement, UNO_QUERY );
973 Reference< XPropertySet > xFormProperties( xForm, UNO_QUERY );
974 if ( xFormProperties.is() )
975 if ( !::svxform::OStaticDataAccessTools().isEmbeddedInDatabase( _rxElement ) )
976 // (if there is a connection in the context of the component, setting
977 // a new connection would be vetoed, anyway)
978 // #i34196#
979 xFormProperties->setPropertyValue( FM_PROP_ACTIVE_CONNECTION, Any() );
982 Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
983 if ( xContainer.is() )
984 switchListening( xContainer, false );
988 //------------------------------------------------------------------------------
989 FmUndoPropertyAction::FmUndoPropertyAction(FmFormModel& rNewMod, const PropertyChangeEvent& evt)
990 :SdrUndoAction(rNewMod)
991 ,xObj(evt.Source, UNO_QUERY)
992 ,aPropertyName(evt.PropertyName)
993 ,aNewValue(evt.NewValue)
994 ,aOldValue(evt.OldValue)
996 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::FmUndoPropertyAction" );
997 if (rNewMod.GetObjectShell())
998 rNewMod.GetObjectShell()->SetModified(sal_True);
999 if(static_STR_UNDO_PROPERTY.Len() == 0)
1000 static_STR_UNDO_PROPERTY = SVX_RESSTR(RID_STR_UNDO_PROPERTY);
1004 //------------------------------------------------------------------------------
1005 void FmUndoPropertyAction::Undo()
1007 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Undo" );
1008 FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
1010 if (xObj.is() && !rEnv.IsLocked())
1012 rEnv.Lock();
1015 xObj->setPropertyValue( aPropertyName, aOldValue );
1017 catch( const Exception& )
1019 OSL_FAIL( "FmUndoPropertyAction::Undo: caught an exception!" );
1021 rEnv.UnLock();
1025 //------------------------------------------------------------------------------
1026 void FmUndoPropertyAction::Redo()
1028 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Redo" );
1029 FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
1031 if (xObj.is() && !rEnv.IsLocked())
1033 rEnv.Lock();
1036 xObj->setPropertyValue( aPropertyName, aNewValue );
1038 catch( const Exception& )
1040 OSL_FAIL( "FmUndoPropertyAction::Redo: caught an exception!" );
1042 rEnv.UnLock();
1046 //------------------------------------------------------------------------------
1047 OUString FmUndoPropertyAction::GetComment() const
1049 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::GetComment" );
1050 String aStr(static_STR_UNDO_PROPERTY);
1052 aStr.SearchAndReplace( OUString('#'), aPropertyName );
1053 return aStr;
1057 DBG_NAME(FmUndoContainerAction);
1058 //------------------------------------------------------------------------------
1059 FmUndoContainerAction::FmUndoContainerAction(FmFormModel& _rMod,
1060 Action _eAction,
1061 const Reference< XIndexContainer > & xCont,
1062 const Reference< XInterface > & xElem,
1063 sal_Int32 nIdx)
1064 :SdrUndoAction( _rMod )
1065 ,m_xContainer( xCont )
1066 ,m_nIndex( nIdx )
1067 ,m_eAction( _eAction )
1069 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::FmUndoContainerAction" );
1070 OSL_ENSURE( nIdx >= 0, "FmUndoContainerAction::FmUndoContainerAction: invalid index!" );
1071 // some old code suggested this could be a valid argument. However, this code was
1072 // buggy, and it *seemed* that nobody used it - so it was removed.
1074 DBG_CTOR(FmUndoContainerAction,NULL);
1075 if ( xCont.is() && xElem.is() )
1077 // normalize
1078 m_xElement = m_xElement.query( xElem );
1079 if ( m_eAction == Removed )
1081 if (m_nIndex >= 0)
1083 Reference< XEventAttacherManager > xManager( xCont, UNO_QUERY );
1084 if ( xManager.is() )
1085 m_aEvents = xManager->getScriptEvents(m_nIndex);
1087 else
1088 m_xElement = NULL;
1090 // we now own the element
1091 m_xOwnElement = m_xElement;
1096 //------------------------------------------------------------------------------
1097 FmUndoContainerAction::~FmUndoContainerAction()
1099 // if we own the object ....
1100 DisposeElement( m_xOwnElement );
1101 DBG_DTOR(FmUndoContainerAction,NULL);
1104 //------------------------------------------------------------------------------
1106 void FmUndoContainerAction::DisposeElement( const Reference< XInterface > & xElem )
1108 Reference< XComponent > xComp( xElem, UNO_QUERY );
1109 if ( xComp.is() )
1111 // and the object does not have a parent
1112 Reference< XChild > xChild( xElem, UNO_QUERY );
1113 if ( xChild.is() && !xChild->getParent().is() )
1114 // -> dispose it
1115 xComp->dispose();
1119 //------------------------------------------------------------------------------
1120 void FmUndoContainerAction::implReInsert( ) SAL_THROW( ( Exception ) )
1122 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReInsert" );
1123 if ( m_xContainer->getCount() >= m_nIndex )
1125 // insert the element
1126 Any aVal;
1127 if ( m_xContainer->getElementType() == ::getCppuType( static_cast< const Reference< XFormComponent >* >( NULL ) ) )
1129 aVal <<= Reference< XFormComponent >( m_xElement, UNO_QUERY );
1131 else
1133 aVal <<= Reference< XForm >( m_xElement, UNO_QUERY );
1135 m_xContainer->insertByIndex( m_nIndex, aVal );
1137 OSL_ENSURE( getElementPos( m_xContainer.get(), m_xElement ) == m_nIndex, "FmUndoContainerAction::implReInsert: insertion did not work!" );
1139 // register the events
1140 Reference< XEventAttacherManager > xManager( m_xContainer, UNO_QUERY );
1141 if ( xManager.is() )
1142 xManager->registerScriptEvents( m_nIndex, m_aEvents );
1144 // we don't own the object anymore
1145 m_xOwnElement = NULL;
1149 //------------------------------------------------------------------------------
1150 void FmUndoContainerAction::implReRemove( ) SAL_THROW( ( Exception ) )
1152 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReRemove" );
1153 Reference< XInterface > xElement;
1154 if ( ( m_nIndex >= 0 ) && ( m_nIndex < m_xContainer->getCount() ) )
1155 m_xContainer->getByIndex( m_nIndex ) >>= xElement;
1157 if ( xElement != m_xElement )
1159 // the indexes in the container changed. Okay, so go the long way and
1160 // manually determine the index
1161 m_nIndex = getElementPos( m_xContainer.get(), m_xElement );
1162 if ( m_nIndex != -1 )
1163 xElement = m_xElement;
1166 OSL_ENSURE( xElement == m_xElement, "FmUndoContainerAction::implReRemove: cannot find the element which I'm responsible for!" );
1167 if ( xElement == m_xElement )
1169 Reference< XEventAttacherManager > xManager( m_xContainer, UNO_QUERY );
1170 if ( xManager.is() )
1171 m_aEvents = xManager->getScriptEvents( m_nIndex );
1172 m_xContainer->removeByIndex( m_nIndex );
1173 // from now on, we own this object
1174 m_xOwnElement = m_xElement;
1178 //------------------------------------------------------------------------------
1179 void FmUndoContainerAction::Undo()
1181 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Undo" );
1182 FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
1184 if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
1186 rEnv.Lock();
1189 switch ( m_eAction )
1191 case Inserted:
1192 implReRemove();
1193 break;
1195 case Removed:
1196 implReInsert();
1197 break;
1200 catch( const Exception& )
1202 OSL_FAIL( "FmUndoContainerAction::Undo: caught an exception!" );
1204 rEnv.UnLock();
1208 //------------------------------------------------------------------------------
1209 void FmUndoContainerAction::Redo()
1211 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Redo" );
1212 FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
1213 if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
1215 rEnv.Lock();
1218 switch ( m_eAction )
1220 case Inserted:
1221 implReInsert();
1222 break;
1224 case Removed:
1225 implReRemove();
1226 break;
1229 catch( const Exception& )
1231 OSL_FAIL( "FmUndoContainerAction::Redo: caught an exception!" );
1233 rEnv.UnLock();
1237 //------------------------------------------------------------------------------
1238 FmUndoModelReplaceAction::FmUndoModelReplaceAction(FmFormModel& _rMod, SdrUnoObj* _pObject, const Reference< XControlModel > & _xReplaced)
1239 :SdrUndoAction(_rMod)
1240 ,m_xReplaced(_xReplaced)
1241 ,m_pObject(_pObject)
1243 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::FmUndoModelReplaceAction" );
1246 //------------------------------------------------------------------------------
1247 FmUndoModelReplaceAction::~FmUndoModelReplaceAction()
1249 // dispose our element if nobody else is responsible for
1250 DisposeElement(m_xReplaced);
1253 //------------------------------------------------------------------------------
1255 void FmUndoModelReplaceAction::DisposeElement( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel>& xReplaced )
1257 Reference< XComponent > xComp(xReplaced, UNO_QUERY);
1258 if (xComp.is())
1260 Reference< XChild > xChild(xReplaced, UNO_QUERY);
1261 if (!xChild.is() || !xChild->getParent().is())
1262 xComp->dispose();
1266 //------------------------------------------------------------------------------
1267 void FmUndoModelReplaceAction::Undo()
1269 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::Undo" );
1272 Reference< XControlModel > xCurrentModel( m_pObject->GetUnoControlModel() );
1274 // replace the model within the parent
1275 Reference< XChild > xCurrentAsChild( xCurrentModel, UNO_QUERY );
1276 Reference< XNameContainer > xCurrentsParent;
1277 if ( xCurrentAsChild.is() )
1278 xCurrentsParent = xCurrentsParent.query( xCurrentAsChild->getParent() );
1279 DBG_ASSERT( xCurrentsParent.is(), "FmUndoModelReplaceAction::Undo: invalid current model!" );
1281 if ( xCurrentsParent.is() )
1283 // the form container works with FormComponents
1284 Reference< XFormComponent > xComponent( m_xReplaced, UNO_QUERY );
1285 DBG_ASSERT( xComponent.is(), "FmUndoModelReplaceAction::Undo: the new model is no form component !" );
1287 Reference< XPropertySet > xCurrentAsSet( xCurrentModel, UNO_QUERY );
1288 DBG_ASSERT( ::comphelper::hasProperty(FM_PROP_NAME, xCurrentAsSet ), "FmUndoModelReplaceAction::Undo : one of the models is invalid !");
1290 OUString sName;
1291 xCurrentAsSet->getPropertyValue( FM_PROP_NAME ) >>= sName;
1292 xCurrentsParent->replaceByName( sName, makeAny( xComponent ) );
1294 m_pObject->SetUnoControlModel(m_xReplaced);
1295 m_pObject->SetChanged();
1297 m_xReplaced = xCurrentModel;
1300 catch(Exception&)
1302 OSL_FAIL("FmUndoModelReplaceAction::Undo : could not replace the model !");
1306 //------------------------------------------------------------------------------
1307 OUString FmUndoModelReplaceAction::GetComment() const
1309 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::GetComment" );
1310 return SVX_RESSTR(RID_STR_UNDO_MODEL_REPLACE);
1313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */