xref: /aoo41x/main/svx/source/form/fmundo.cxx (revision acde0be0)
1f6e50924SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3f6e50924SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4f6e50924SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5f6e50924SAndrew Rist  * distributed with this work for additional information
6f6e50924SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7f6e50924SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8f6e50924SAndrew Rist  * "License"); you may not use this file except in compliance
9f6e50924SAndrew Rist  * with the License.  You may obtain a copy of the License at
10f6e50924SAndrew Rist  *
11f6e50924SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12f6e50924SAndrew Rist  *
13f6e50924SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14f6e50924SAndrew Rist  * software distributed under the License is distributed on an
15f6e50924SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16f6e50924SAndrew Rist  * KIND, either express or implied.  See the License for the
17f6e50924SAndrew Rist  * specific language governing permissions and limitations
18f6e50924SAndrew Rist  * under the License.
19f6e50924SAndrew Rist  *
20f6e50924SAndrew Rist  *************************************************************/
21f6e50924SAndrew Rist 
22f6e50924SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svx.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "fmundo.hxx"
28cdf0e10cSrcweir #include "fmpgeimp.hxx"
29cdf0e10cSrcweir #include "svx/dbtoolsclient.hxx"
30cdf0e10cSrcweir #include "svx/svditer.hxx"
31cdf0e10cSrcweir #include "fmobj.hxx"
32cdf0e10cSrcweir #include "fmprop.hrc"
33cdf0e10cSrcweir #include "svx/fmresids.hrc"
34cdf0e10cSrcweir #include "svx/fmglob.hxx"
35cdf0e10cSrcweir #include "svx/dialmgr.hxx"
36cdf0e10cSrcweir #include "svx/fmmodel.hxx"
37cdf0e10cSrcweir #include "svx/fmpage.hxx"
38cdf0e10cSrcweir 
39cdf0e10cSrcweir /** === begin UNO includes === **/
40cdf0e10cSrcweir #include <com/sun/star/util/XModifyBroadcaster.hpp>
41cdf0e10cSrcweir #include <com/sun/star/beans/PropertyAttribute.hpp>
42cdf0e10cSrcweir #include <com/sun/star/container/XContainer.hpp>
43cdf0e10cSrcweir #include <com/sun/star/container/XContainerListener.hpp>
44cdf0e10cSrcweir #include <com/sun/star/script/XEventAttacherManager.hpp>
45cdf0e10cSrcweir #include <com/sun/star/form/binding/XBindableValue.hpp>
46cdf0e10cSrcweir #include <com/sun/star/form/binding/XListEntrySink.hpp>
47cdf0e10cSrcweir #include <com/sun/star/reflection/XInterfaceMethodTypeDescription.hpp>
48cdf0e10cSrcweir /** === end UNO includes === **/
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #include "svx/fmtools.hxx"
51cdf0e10cSrcweir #include <rtl/logfile.hxx>
52cdf0e10cSrcweir #include <svl/macitem.hxx>
53cdf0e10cSrcweir #include <tools/shl.hxx>
54cdf0e10cSrcweir #include <tools/diagnose_ex.h>
55cdf0e10cSrcweir #include <sfx2/objsh.hxx>
56cdf0e10cSrcweir #include <sfx2/docfile.hxx>
57cdf0e10cSrcweir #include <sfx2/app.hxx>
58cdf0e10cSrcweir #include <sfx2/sfx.hrc>
59cdf0e10cSrcweir #include <sfx2/event.hxx>
60cdf0e10cSrcweir #include <osl/mutex.hxx>
61cdf0e10cSrcweir #include <vos/mutex.hxx>
62cdf0e10cSrcweir #include <comphelper/property.hxx>
63cdf0e10cSrcweir #include <comphelper/uno3.hxx>
64cdf0e10cSrcweir #include <comphelper/stl_types.hxx>
65cdf0e10cSrcweir #include <comphelper/componentcontext.hxx>
66cdf0e10cSrcweir 
67cdf0e10cSrcweir using namespace ::com::sun::star::uno;
68cdf0e10cSrcweir using namespace ::com::sun::star::awt;
69cdf0e10cSrcweir using namespace ::com::sun::star::beans;
70cdf0e10cSrcweir using namespace ::com::sun::star::container;
71cdf0e10cSrcweir using namespace ::com::sun::star::script;
72cdf0e10cSrcweir using namespace ::com::sun::star::lang;
73cdf0e10cSrcweir using namespace ::com::sun::star::form;
74cdf0e10cSrcweir using namespace ::com::sun::star::util;
75cdf0e10cSrcweir using namespace ::com::sun::star::reflection;
76cdf0e10cSrcweir using namespace ::com::sun::star::form::binding;
77cdf0e10cSrcweir using namespace ::svxform;
78cdf0e10cSrcweir 
79cdf0e10cSrcweir 
80cdf0e10cSrcweir #include <com/sun/star/script/XScriptListener.hdl>
81cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
82cdf0e10cSrcweir #include <cppuhelper/implbase1.hxx>
83cdf0e10cSrcweir 
84cdf0e10cSrcweir typedef cppu::WeakImplHelper1< XScriptListener > ScriptEventListener_BASE;
85cdf0e10cSrcweir class ScriptEventListenerWrapper : public ScriptEventListener_BASE
86cdf0e10cSrcweir {
87cdf0e10cSrcweir public:
ScriptEventListenerWrapper(FmFormModel & _rModel)88cdf0e10cSrcweir 	ScriptEventListenerWrapper( FmFormModel& _rModel) throw ( RuntimeException )
89cdf0e10cSrcweir 		:m_rModel( _rModel )
90cdf0e10cSrcweir 		,m_attemptedListenerCreation( false )
91cdf0e10cSrcweir 	{
92cdf0e10cSrcweir 
93cdf0e10cSrcweir 	}
94cdf0e10cSrcweir     // XEventListener
disposing(const EventObject &)95cdf0e10cSrcweir     virtual void SAL_CALL disposing(const EventObject& ) throw( RuntimeException ){}
96cdf0e10cSrcweir 
97cdf0e10cSrcweir     // XScriptListener
firing(const ScriptEvent & evt)98cdf0e10cSrcweir     virtual void SAL_CALL firing(const  ScriptEvent& evt) throw(RuntimeException)
99cdf0e10cSrcweir 	{
100cdf0e10cSrcweir 		attemptListenerCreation();
101cdf0e10cSrcweir 		if ( m_vbaListener.is() )
102cdf0e10cSrcweir 		{
103cdf0e10cSrcweir 			m_vbaListener->firing( evt );
104cdf0e10cSrcweir 		}
105cdf0e10cSrcweir 	}
106cdf0e10cSrcweir 
approveFiring(const ScriptEvent & evt)107cdf0e10cSrcweir     virtual Any SAL_CALL approveFiring(const ScriptEvent& evt) throw( com::sun::star::reflection::InvocationTargetException, RuntimeException)
108cdf0e10cSrcweir 	{
109cdf0e10cSrcweir 		attemptListenerCreation();
110cdf0e10cSrcweir 		if ( m_vbaListener.is() )
111cdf0e10cSrcweir 		{
112cdf0e10cSrcweir 			return m_vbaListener->approveFiring( evt );
113cdf0e10cSrcweir 		}
114cdf0e10cSrcweir 		return Any();
115cdf0e10cSrcweir 	}
116cdf0e10cSrcweir 
117cdf0e10cSrcweir private:
attemptListenerCreation()118cdf0e10cSrcweir 	void attemptListenerCreation()
119cdf0e10cSrcweir 	{
120cdf0e10cSrcweir 		if ( m_attemptedListenerCreation )
121cdf0e10cSrcweir 			return;
122cdf0e10cSrcweir 		m_attemptedListenerCreation = true;
123cdf0e10cSrcweir 
124cdf0e10cSrcweir 		try
125cdf0e10cSrcweir 		{
126cdf0e10cSrcweir 			::comphelper::ComponentContext const aContext( ::comphelper::getProcessServiceFactory() );
127cdf0e10cSrcweir 			Reference< XScriptListener > const xScriptListener( aContext.createComponent( "ooo.vba.EventListener" ), UNO_QUERY_THROW );
128cdf0e10cSrcweir 			Reference< XPropertySet > const xListenerProps( xScriptListener, UNO_QUERY_THROW );
129cdf0e10cSrcweir             // SfxObjectShellRef is good here since the model controls the lifetime of the shell
130cdf0e10cSrcweir 			SfxObjectShellRef const xObjectShell = m_rModel.GetObjectShell();
131cdf0e10cSrcweir 			ENSURE_OR_THROW( xObjectShell.Is(), "no object shell!" );
132cdf0e10cSrcweir 			xListenerProps->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Model" ) ), makeAny( xObjectShell->GetModel() ) );
133cdf0e10cSrcweir 
134cdf0e10cSrcweir 			m_vbaListener = xScriptListener;
135cdf0e10cSrcweir 		}
136cdf0e10cSrcweir 		catch( Exception const & )
137cdf0e10cSrcweir 		{
138cdf0e10cSrcweir 			DBG_UNHANDLED_EXCEPTION();
139cdf0e10cSrcweir 		}
140cdf0e10cSrcweir 	}
141cdf0e10cSrcweir     FmFormModel&					m_rModel;
142cdf0e10cSrcweir 	Reference< XScriptListener >	m_vbaListener;
143cdf0e10cSrcweir 	bool							m_attemptedListenerCreation;
144cdf0e10cSrcweir 
145cdf0e10cSrcweir 
146cdf0e10cSrcweir };
147cdf0e10cSrcweir 
148cdf0e10cSrcweir //------------------------------------------------------------------------------
149cdf0e10cSrcweir // some helper structs for caching property infos
150cdf0e10cSrcweir //------------------------------------------------------------------------------
151cdf0e10cSrcweir struct PropertyInfo
152cdf0e10cSrcweir {
153cdf0e10cSrcweir 	sal_Bool	bIsTransientOrReadOnly	: 1;	// the property is transient or read-only, thus we need no undo action for it
154cdf0e10cSrcweir 	sal_Bool	bIsValueProperty	    : 1;	// the property is the special value property, thus it may be handled
155cdf0e10cSrcweir 										    // as if it's transient or persistent
156cdf0e10cSrcweir };
157cdf0e10cSrcweir 
158cdf0e10cSrcweir struct PropertySetInfo
159cdf0e10cSrcweir {
160cdf0e10cSrcweir 	DECLARE_STL_USTRINGACCESS_MAP(PropertyInfo, AllProperties);
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 	AllProperties	aProps; 				// all properties of this set which we know so far
163cdf0e10cSrcweir 	sal_Bool			bHasEmptyControlSource; // sal_True -> the set has a DataField property, and the current value is an empty string
164cdf0e10cSrcweir 											// sal_False -> the set has _no_ such property or it's value isn't empty
165cdf0e10cSrcweir };
166cdf0e10cSrcweir 
operator <(const Reference<XPropertySet> & lhs,const Reference<XPropertySet> & rhs)167cdf0e10cSrcweir sal_Bool operator < (const Reference< XPropertySet >& lhs,
168cdf0e10cSrcweir 				 const Reference< XPropertySet >& rhs)
169cdf0e10cSrcweir {
170cdf0e10cSrcweir 	return lhs.get() < rhs.get();
171cdf0e10cSrcweir }
172cdf0e10cSrcweir 
173cdf0e10cSrcweir DECLARE_STL_STDKEY_MAP(Reference< XPropertySet >, PropertySetInfo, PropertySetInfoCache);
174cdf0e10cSrcweir 
175cdf0e10cSrcweir //------------------------------------------------------------------------------
176cdf0e10cSrcweir 
177cdf0e10cSrcweir String static_STR_UNDO_PROPERTY;
178cdf0e10cSrcweir //------------------------------------------------------------------------------
DBG_NAME(FmXUndoEnvironment)179cdf0e10cSrcweir DBG_NAME(FmXUndoEnvironment)
180cdf0e10cSrcweir //------------------------------------------------------------------------------
181cdf0e10cSrcweir FmXUndoEnvironment::FmXUndoEnvironment(FmFormModel& _rModel)
182cdf0e10cSrcweir 				   :rModel( _rModel )
183cdf0e10cSrcweir                    ,m_pPropertySetCache( NULL )
184cdf0e10cSrcweir                    ,m_pScriptingEnv( ::svxform::createDefaultFormScriptingEnvironment( _rModel ) )
185cdf0e10cSrcweir 				   ,m_Locks( 0 )
186cdf0e10cSrcweir 				   ,bReadOnly( sal_False )
187cdf0e10cSrcweir                    ,m_bDisposed( false )
188cdf0e10cSrcweir {
189cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::FmXUndoEnvironment" );
190cdf0e10cSrcweir 	DBG_CTOR(FmXUndoEnvironment,NULL);
191cdf0e10cSrcweir 	try
192cdf0e10cSrcweir 	{
193cdf0e10cSrcweir 		m_vbaListener =  new ScriptEventListenerWrapper( _rModel );
194cdf0e10cSrcweir 	}
195cdf0e10cSrcweir 	catch( Exception& )
196cdf0e10cSrcweir 	{
197cdf0e10cSrcweir 	}
198cdf0e10cSrcweir }
199cdf0e10cSrcweir 
200cdf0e10cSrcweir //------------------------------------------------------------------------------
~FmXUndoEnvironment()201cdf0e10cSrcweir FmXUndoEnvironment::~FmXUndoEnvironment()
202cdf0e10cSrcweir {
203cdf0e10cSrcweir 	DBG_DTOR(FmXUndoEnvironment,NULL);
204*acde0be0SJian Fang Zhang 	if ( !m_bDisposed )   // i120746, call FormScriptingEnvironment::dispose to avoid memory leak
205*acde0be0SJian Fang Zhang 		m_pScriptingEnv->dispose();
206*acde0be0SJian Fang Zhang 
207cdf0e10cSrcweir 	if (m_pPropertySetCache)
208cdf0e10cSrcweir 		delete static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
209cdf0e10cSrcweir }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir //------------------------------------------------------------------------------
dispose()212cdf0e10cSrcweir void FmXUndoEnvironment::dispose()
213cdf0e10cSrcweir {
214cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::dispose" );
215cdf0e10cSrcweir     OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::dispose: disposed twice?" );
216cdf0e10cSrcweir     if ( !m_bDisposed )
217cdf0e10cSrcweir         return;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir 	Lock();
220cdf0e10cSrcweir 
221cdf0e10cSrcweir     sal_uInt16 nCount = rModel.GetPageCount();
222cdf0e10cSrcweir 	sal_uInt16 i;
223cdf0e10cSrcweir 	for (i = 0; i < nCount; i++)
224cdf0e10cSrcweir 	{
225cdf0e10cSrcweir         FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
226cdf0e10cSrcweir         if ( pPage )
227cdf0e10cSrcweir         {
228cdf0e10cSrcweir             Reference< XInterface > xForms = pPage->GetForms( false ).get();
229cdf0e10cSrcweir             if ( xForms.is() )
230cdf0e10cSrcweir 		        RemoveElement( xForms );
231cdf0e10cSrcweir         }
232cdf0e10cSrcweir 	}
233cdf0e10cSrcweir 
234cdf0e10cSrcweir 	nCount = rModel.GetMasterPageCount();
235cdf0e10cSrcweir 	for (i = 0; i < nCount; i++)
236cdf0e10cSrcweir 	{
237cdf0e10cSrcweir         FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
238cdf0e10cSrcweir         if ( pPage )
239cdf0e10cSrcweir         {
240cdf0e10cSrcweir             Reference< XInterface > xForms = pPage->GetForms( false ).get();
241cdf0e10cSrcweir             if ( xForms.is() )
242cdf0e10cSrcweir 		        RemoveElement( xForms );
243cdf0e10cSrcweir         }
244cdf0e10cSrcweir 	}
245cdf0e10cSrcweir 
246cdf0e10cSrcweir     UnLock();
247cdf0e10cSrcweir 
248cdf0e10cSrcweir     OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::dispose: no object shell anymore!" );
249cdf0e10cSrcweir     if ( rModel.GetObjectShell() )
250cdf0e10cSrcweir 	    EndListening( *rModel.GetObjectShell() );
251cdf0e10cSrcweir 
252cdf0e10cSrcweir 	if ( IsListening( rModel ) )
253cdf0e10cSrcweir 		EndListening( rModel );
254cdf0e10cSrcweir 
255cdf0e10cSrcweir     m_pScriptingEnv->dispose();
256cdf0e10cSrcweir 
257cdf0e10cSrcweir     m_bDisposed = true;
258cdf0e10cSrcweir }
259cdf0e10cSrcweir 
260cdf0e10cSrcweir //------------------------------------------------------------------------------
ModeChanged()261cdf0e10cSrcweir void FmXUndoEnvironment::ModeChanged()
262cdf0e10cSrcweir {
263cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::ModeChanged" );
264cdf0e10cSrcweir     OSL_PRECOND( rModel.GetObjectShell(), "FmXUndoEnvironment::ModeChanged: no object shell anymore!" );
265cdf0e10cSrcweir     if ( !rModel.GetObjectShell() )
266cdf0e10cSrcweir         return;
267cdf0e10cSrcweir 
268cdf0e10cSrcweir 	if (bReadOnly != (rModel.GetObjectShell()->IsReadOnly() || rModel.GetObjectShell()->IsReadOnlyUI()))
269cdf0e10cSrcweir 	{
270cdf0e10cSrcweir 		bReadOnly = !bReadOnly;
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 		sal_uInt16 nCount = rModel.GetPageCount();
273cdf0e10cSrcweir 		sal_uInt16 i;
274cdf0e10cSrcweir 		for (i = 0; i < nCount; i++)
275cdf0e10cSrcweir 		{
276cdf0e10cSrcweir             FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetPage(i) );
277cdf0e10cSrcweir             if ( pPage )
278cdf0e10cSrcweir             {
279cdf0e10cSrcweir                 Reference< XInterface > xForms = pPage->GetForms( false ).get();
280cdf0e10cSrcweir                 if ( xForms.is() )
281cdf0e10cSrcweir                     TogglePropertyListening( xForms );
282cdf0e10cSrcweir             }
283cdf0e10cSrcweir 		}
284cdf0e10cSrcweir 
285cdf0e10cSrcweir 		nCount = rModel.GetMasterPageCount();
286cdf0e10cSrcweir 		for (i = 0; i < nCount; i++)
287cdf0e10cSrcweir 		{
288cdf0e10cSrcweir             FmFormPage* pPage = PTR_CAST( FmFormPage, rModel.GetMasterPage(i) );
289cdf0e10cSrcweir             if ( pPage )
290cdf0e10cSrcweir             {
291cdf0e10cSrcweir                 Reference< XInterface > xForms = pPage->GetForms( false ).get();
292cdf0e10cSrcweir                 if ( xForms.is() )
293cdf0e10cSrcweir 		            TogglePropertyListening( xForms );
294cdf0e10cSrcweir             }
295cdf0e10cSrcweir 		}
296cdf0e10cSrcweir 
297cdf0e10cSrcweir 		if (!bReadOnly)
298cdf0e10cSrcweir 			StartListening(rModel);
299cdf0e10cSrcweir 		else
300cdf0e10cSrcweir 			EndListening(rModel);
301cdf0e10cSrcweir 	}
302cdf0e10cSrcweir }
303cdf0e10cSrcweir 
304cdf0e10cSrcweir //------------------------------------------------------------------------------
Notify(SfxBroadcaster &,const SfxHint & rHint)305cdf0e10cSrcweir void FmXUndoEnvironment::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
306cdf0e10cSrcweir {
307cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Notify" );
308cdf0e10cSrcweir 	if (rHint.ISA(SdrHint))
309cdf0e10cSrcweir 	{
310cdf0e10cSrcweir 		SdrHint* pSdrHint = (SdrHint*)&rHint;
311cdf0e10cSrcweir 		switch( pSdrHint->GetKind() )
312cdf0e10cSrcweir 		{
313cdf0e10cSrcweir 			case HINT_OBJINSERTED:
314cdf0e10cSrcweir 			{
315cdf0e10cSrcweir 				SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
316cdf0e10cSrcweir 				Inserted( pSdrObj );
317cdf0e10cSrcweir 			}	break;
318cdf0e10cSrcweir 			case HINT_OBJREMOVED:
319cdf0e10cSrcweir 			{
320cdf0e10cSrcweir 				SdrObject* pSdrObj = (SdrObject*)pSdrHint->GetObject();
321cdf0e10cSrcweir 				Removed( pSdrObj );
322cdf0e10cSrcweir 			}
323cdf0e10cSrcweir 			break;
324cdf0e10cSrcweir             default:
325cdf0e10cSrcweir                 break;
326cdf0e10cSrcweir 		}
327cdf0e10cSrcweir 	}
328cdf0e10cSrcweir 	else if (rHint.ISA(SfxSimpleHint))
329cdf0e10cSrcweir 	{
330cdf0e10cSrcweir 		switch ( ((SfxSimpleHint&)rHint).GetId() )
331cdf0e10cSrcweir 		{
332cdf0e10cSrcweir 			case SFX_HINT_DYING:
333cdf0e10cSrcweir 				dispose();
334cdf0e10cSrcweir                 rModel.SetObjectShell( NULL );
335cdf0e10cSrcweir 				break;
336cdf0e10cSrcweir 			case SFX_HINT_MODECHANGED:
337cdf0e10cSrcweir 				ModeChanged();
338cdf0e10cSrcweir 				break;
339cdf0e10cSrcweir 		}
340cdf0e10cSrcweir 	}
341cdf0e10cSrcweir 	else if (rHint.ISA(SfxEventHint))
342cdf0e10cSrcweir 	{
343cdf0e10cSrcweir 		switch (((SfxEventHint&)rHint).GetEventId())
344cdf0e10cSrcweir 		{
345cdf0e10cSrcweir 		case SFX_EVENT_CREATEDOC:
346cdf0e10cSrcweir 			case SFX_EVENT_OPENDOC:
347cdf0e10cSrcweir 				ModeChanged();
348cdf0e10cSrcweir 				break;
349cdf0e10cSrcweir 		}
350cdf0e10cSrcweir 	}
351cdf0e10cSrcweir 
352cdf0e10cSrcweir }
353cdf0e10cSrcweir 
354cdf0e10cSrcweir //------------------------------------------------------------------
Inserted(SdrObject * pObj)355cdf0e10cSrcweir void FmXUndoEnvironment::Inserted(SdrObject* pObj)
356cdf0e10cSrcweir {
357cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
358cdf0e10cSrcweir 	if (pObj->GetObjInventor() == FmFormInventor)
359cdf0e10cSrcweir 	{
360cdf0e10cSrcweir 		FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
361cdf0e10cSrcweir 		Inserted( pFormObj );
362cdf0e10cSrcweir 	}
363cdf0e10cSrcweir 	else if (pObj->IsGroupObject())
364cdf0e10cSrcweir 	{
365cdf0e10cSrcweir 		SdrObjListIter aIter(*pObj->GetSubList());
366cdf0e10cSrcweir 		while ( aIter.IsMore() )
367cdf0e10cSrcweir 			Inserted( aIter.Next() );
368cdf0e10cSrcweir 	}
369cdf0e10cSrcweir }
370cdf0e10cSrcweir 
371cdf0e10cSrcweir //------------------------------------------------------------------------------
372cdf0e10cSrcweir namespace
373cdf0e10cSrcweir {
lcl_searchElement(const Reference<XIndexAccess> & xCont,const Reference<XInterface> & xElement)374cdf0e10cSrcweir     sal_Bool lcl_searchElement(const Reference< XIndexAccess>& xCont, const Reference< XInterface >& xElement)
375cdf0e10cSrcweir     {
376cdf0e10cSrcweir 	    if (!xCont.is() || !xElement.is())
377cdf0e10cSrcweir 		    return sal_False;
378cdf0e10cSrcweir 
379cdf0e10cSrcweir 	    sal_Int32 nCount = xCont->getCount();
380cdf0e10cSrcweir 	    Reference< XInterface > xComp;
381cdf0e10cSrcweir 	    for (sal_Int32 i = 0; i < nCount; i++)
382cdf0e10cSrcweir 	    {
383cdf0e10cSrcweir 		    try
384cdf0e10cSrcweir 		    {
385cdf0e10cSrcweir 			    xCont->getByIndex(i) >>= xComp;
386cdf0e10cSrcweir 			    if (xComp.is())
387cdf0e10cSrcweir 			    {
388cdf0e10cSrcweir 				    if ( xElement == xComp )
389cdf0e10cSrcweir 					    return sal_True;
390cdf0e10cSrcweir 				    else
391cdf0e10cSrcweir 				    {
392cdf0e10cSrcweir 					    Reference< XIndexAccess> xCont2(xComp, UNO_QUERY);
393cdf0e10cSrcweir 					    if (xCont2.is() && lcl_searchElement(xCont2, xElement))
394cdf0e10cSrcweir 						    return sal_True;
395cdf0e10cSrcweir 				    }
396cdf0e10cSrcweir 			    }
397cdf0e10cSrcweir 		    }
398cdf0e10cSrcweir 		    catch(const Exception&)
399cdf0e10cSrcweir 		    {
400cdf0e10cSrcweir                 DBG_UNHANDLED_EXCEPTION();
401cdf0e10cSrcweir 		    }
402cdf0e10cSrcweir 	    }
403cdf0e10cSrcweir 	    return sal_False;
404cdf0e10cSrcweir     }
405cdf0e10cSrcweir }
406cdf0e10cSrcweir 
407cdf0e10cSrcweir //------------------------------------------------------------------------------
Inserted(FmFormObj * pObj)408cdf0e10cSrcweir void FmXUndoEnvironment::Inserted(FmFormObj* pObj)
409cdf0e10cSrcweir {
410cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Inserted" );
411cdf0e10cSrcweir 	DBG_ASSERT( pObj, "FmXUndoEnvironment::Inserted: invalid object!" );
412cdf0e10cSrcweir 	if ( !pObj )
413cdf0e10cSrcweir 		return;
414cdf0e10cSrcweir 
415cdf0e10cSrcweir 	// ist das Control noch einer Form zugeordnet
416cdf0e10cSrcweir 	Reference< XInterface >  xModel(pObj->GetUnoControlModel(), UNO_QUERY);
417cdf0e10cSrcweir 	Reference< XFormComponent >  xContent(xModel, UNO_QUERY);
418cdf0e10cSrcweir 	if (xContent.is() && pObj->GetPage())
419cdf0e10cSrcweir 	{
420cdf0e10cSrcweir 		// if the component doesn't belong to a form, yet, find one to insert into
421cdf0e10cSrcweir 		if (!xContent->getParent().is())
422cdf0e10cSrcweir 		{
423cdf0e10cSrcweir             try
424cdf0e10cSrcweir             {
425cdf0e10cSrcweir 			    Reference< XIndexContainer > xObjectParent = pObj->GetOriginalParent();
426cdf0e10cSrcweir 
427cdf0e10cSrcweir                 FmFormPage& rPage = dynamic_cast< FmFormPage& >( *pObj->GetPage() );
428cdf0e10cSrcweir 			    Reference< XIndexAccess >  xForms( rPage.GetForms(), UNO_QUERY_THROW );
429cdf0e10cSrcweir 
430cdf0e10cSrcweir 			    Reference< XIndexContainer > xNewParent;
431cdf0e10cSrcweir                 Reference< XForm >           xForm;
432cdf0e10cSrcweir 			    sal_Int32 nPos = -1;
433cdf0e10cSrcweir 			    if ( lcl_searchElement( xForms, xObjectParent ) )
434cdf0e10cSrcweir                 {
435cdf0e10cSrcweir                     // the form which was the parent of the object when it was removed is still
436cdf0e10cSrcweir                     // part of the form component hierachy of the current page
437cdf0e10cSrcweir 				    xNewParent = xObjectParent;
438cdf0e10cSrcweir                     xForm.set( xNewParent, UNO_QUERY_THROW );
439cdf0e10cSrcweir                     nPos = ::std::min( pObj->GetOriginalIndex(), xNewParent->getCount() );
440cdf0e10cSrcweir                 }
441cdf0e10cSrcweir 			    else
442cdf0e10cSrcweir 			    {
443cdf0e10cSrcweir 				    xForm.set( rPage.GetImpl().findPlaceInFormComponentHierarchy( xContent ), UNO_SET_THROW );
444cdf0e10cSrcweir 				    xNewParent.set( xForm, UNO_QUERY_THROW );
445cdf0e10cSrcweir                     nPos = xNewParent->getCount();
446cdf0e10cSrcweir 			    }
447cdf0e10cSrcweir 
448cdf0e10cSrcweir                 rPage.GetImpl().setUniqueName( xContent, xForm );
449cdf0e10cSrcweir 			    xNewParent->insertByIndex( nPos, makeAny( xContent ) );
450cdf0e10cSrcweir 
451cdf0e10cSrcweir                 Reference< XEventAttacherManager >	xManager( xNewParent, UNO_QUERY_THROW );
452cdf0e10cSrcweir 			    xManager->registerScriptEvents( nPos, pObj->GetOriginalEvents() );
453cdf0e10cSrcweir             }
454cdf0e10cSrcweir             catch( const Exception& )
455cdf0e10cSrcweir             {
456cdf0e10cSrcweir             	DBG_UNHANDLED_EXCEPTION();
457cdf0e10cSrcweir             }
458cdf0e10cSrcweir 		}
459cdf0e10cSrcweir 
460cdf0e10cSrcweir 		// FormObject zuruecksetzen
461cdf0e10cSrcweir 		pObj->ClearObjEnv();
462cdf0e10cSrcweir 	}
463cdf0e10cSrcweir }
464cdf0e10cSrcweir 
465cdf0e10cSrcweir //------------------------------------------------------------------
Removed(SdrObject * pObj)466cdf0e10cSrcweir void FmXUndoEnvironment::Removed(SdrObject* pObj)
467cdf0e10cSrcweir {
468cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
469cdf0e10cSrcweir     if ( pObj->IsVirtualObj() )
470cdf0e10cSrcweir         // for virtual objects, we've already been notified of the removal of the master
471cdf0e10cSrcweir         // object, which is sufficient here
472cdf0e10cSrcweir         return;
473cdf0e10cSrcweir 
474cdf0e10cSrcweir 	if (pObj->GetObjInventor() == FmFormInventor)
475cdf0e10cSrcweir 	{
476cdf0e10cSrcweir 		FmFormObj* pFormObj = PTR_CAST(FmFormObj, pObj);
477cdf0e10cSrcweir 		Removed(pFormObj);
478cdf0e10cSrcweir 	}
479cdf0e10cSrcweir 	else if (pObj->IsGroupObject())
480cdf0e10cSrcweir 	{
481cdf0e10cSrcweir 		SdrObjListIter aIter(*pObj->GetSubList());
482cdf0e10cSrcweir 		while ( aIter.IsMore() )
483cdf0e10cSrcweir 			Removed( aIter.Next() );
484cdf0e10cSrcweir 	}
485cdf0e10cSrcweir }
486cdf0e10cSrcweir 
487cdf0e10cSrcweir //------------------------------------------------------------------------------
Removed(FmFormObj * pObj)488cdf0e10cSrcweir void FmXUndoEnvironment::Removed(FmFormObj* pObj)
489cdf0e10cSrcweir {
490cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::Removed" );
491cdf0e10cSrcweir 	DBG_ASSERT( pObj, "FmXUndoEnvironment::Removed: invalid object!" );
492cdf0e10cSrcweir 	if ( !pObj )
493cdf0e10cSrcweir 		return;
494cdf0e10cSrcweir 
495cdf0e10cSrcweir 	// ist das Control noch einer Form zugeordnet
496cdf0e10cSrcweir 	Reference< XFormComponent >  xContent(pObj->GetUnoControlModel(), UNO_QUERY);
497cdf0e10cSrcweir 	if (xContent.is())
498cdf0e10cSrcweir 	{
499cdf0e10cSrcweir 		// das Object wird aus einer Liste herausgenommen
500cdf0e10cSrcweir 		// existiert ein Vater wird das Object beim beim Vater entfernt und
501cdf0e10cSrcweir 		// am FormObject gemerkt!
502cdf0e10cSrcweir 
503cdf0e10cSrcweir 		// wird das Object wieder eingefuegt und ein Parent existiert, so wird dieser
504cdf0e10cSrcweir 		// Parent wiederum gesetzt
505cdf0e10cSrcweir 		Reference< XIndexContainer >  xForm(xContent->getParent(), UNO_QUERY);
506cdf0e10cSrcweir 		if (xForm.is())
507cdf0e10cSrcweir 		{
508cdf0e10cSrcweir 			Reference< XIndexAccess >  xIndexAccess((XIndexContainer*)xForm.get());
509cdf0e10cSrcweir 			// Feststellen an welcher Position sich das Kind befunden hat
510cdf0e10cSrcweir 			const sal_Int32 nPos = getElementPos(xIndexAccess, xContent);
511cdf0e10cSrcweir 			if (nPos >= 0)
512cdf0e10cSrcweir 			{
513cdf0e10cSrcweir 				Sequence< ScriptEventDescriptor > aEvts;
514cdf0e10cSrcweir 				Reference< XEventAttacherManager >	xManager(xForm, UNO_QUERY);
515cdf0e10cSrcweir 				if (xManager.is())
516cdf0e10cSrcweir 					aEvts = xManager->getScriptEvents(nPos);
517cdf0e10cSrcweir 
518cdf0e10cSrcweir 				try
519cdf0e10cSrcweir 				{
520cdf0e10cSrcweir 					pObj->SetObjEnv(xForm, nPos, aEvts);
521cdf0e10cSrcweir 					xForm->removeByIndex(nPos);
522cdf0e10cSrcweir 				}
523cdf0e10cSrcweir 				catch(Exception&)
524cdf0e10cSrcweir 				{
525cdf0e10cSrcweir                     DBG_UNHANDLED_EXCEPTION();
526cdf0e10cSrcweir 				}
527cdf0e10cSrcweir 
528cdf0e10cSrcweir 			}
529cdf0e10cSrcweir 		}
530cdf0e10cSrcweir 	}
531cdf0e10cSrcweir }
532cdf0e10cSrcweir 
533cdf0e10cSrcweir //	XEventListener
534cdf0e10cSrcweir //------------------------------------------------------------------------------
disposing(const EventObject & e)535cdf0e10cSrcweir void SAL_CALL FmXUndoEnvironment::disposing(const EventObject& e) throw( RuntimeException )
536cdf0e10cSrcweir {
537cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::disposing" );
538cdf0e10cSrcweir 	// check if it's an object we have cached informations about
539cdf0e10cSrcweir 	if (m_pPropertySetCache)
540cdf0e10cSrcweir 	{
541cdf0e10cSrcweir 		Reference< XPropertySet > xSourceSet(e.Source, UNO_QUERY);
542cdf0e10cSrcweir 		if (xSourceSet.is())
543cdf0e10cSrcweir 		{
544cdf0e10cSrcweir 			PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
545cdf0e10cSrcweir 			PropertySetInfoCacheIterator aSetPos = pCache->find(xSourceSet);
546cdf0e10cSrcweir 			if (aSetPos != pCache->end())
547cdf0e10cSrcweir 				pCache->erase(aSetPos);
548cdf0e10cSrcweir 		}
549cdf0e10cSrcweir 	}
550cdf0e10cSrcweir }
551cdf0e10cSrcweir 
552cdf0e10cSrcweir // XPropertyChangeListener
553cdf0e10cSrcweir //------------------------------------------------------------------------------
propertyChange(const PropertyChangeEvent & evt)554cdf0e10cSrcweir void SAL_CALL FmXUndoEnvironment::propertyChange(const PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException)
555cdf0e10cSrcweir {
556cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::propertyChange" );
557cdf0e10cSrcweir     ::osl::ClearableMutexGuard aGuard( m_aMutex );
558cdf0e10cSrcweir 
559cdf0e10cSrcweir 	if (!IsLocked())
560cdf0e10cSrcweir 	{
561cdf0e10cSrcweir 		Reference< XPropertySet >  xSet(evt.Source, UNO_QUERY);
562cdf0e10cSrcweir 		if (!xSet.is())
563cdf0e10cSrcweir 			return;
564cdf0e10cSrcweir 
565cdf0e10cSrcweir 		// if it's a "default value" property of a control model, set the according "value" property
566cdf0e10cSrcweir 		static ::rtl::OUString pDefaultValueProperties[] = {
567cdf0e10cSrcweir 			FM_PROP_DEFAULT_TEXT, FM_PROP_DEFAULTCHECKED, FM_PROP_DEFAULT_DATE, FM_PROP_DEFAULT_TIME,
568cdf0e10cSrcweir 			FM_PROP_DEFAULT_VALUE, FM_PROP_DEFAULT_SELECT_SEQ, FM_PROP_EFFECTIVE_DEFAULT
569cdf0e10cSrcweir 		};
570cdf0e10cSrcweir 		const ::rtl::OUString aValueProperties[] = {
571cdf0e10cSrcweir 			FM_PROP_TEXT, FM_PROP_STATE, FM_PROP_DATE, FM_PROP_TIME,
572cdf0e10cSrcweir 			FM_PROP_VALUE, FM_PROP_SELECT_SEQ, FM_PROP_EFFECTIVE_VALUE
573cdf0e10cSrcweir 		};
574cdf0e10cSrcweir 		sal_Int32 nDefaultValueProps = sizeof(pDefaultValueProperties)/sizeof(pDefaultValueProperties[0]);
575cdf0e10cSrcweir 		OSL_ENSURE(sizeof(aValueProperties)/sizeof(aValueProperties[0]) == nDefaultValueProps,
576cdf0e10cSrcweir 			"FmXUndoEnvironment::propertyChange: inconsistence!");
577cdf0e10cSrcweir 		for (sal_Int32 i=0; i<nDefaultValueProps; ++i)
578cdf0e10cSrcweir 		{
579cdf0e10cSrcweir 			if (0 == evt.PropertyName.compareTo(pDefaultValueProperties[i]))
580cdf0e10cSrcweir 			{
581cdf0e10cSrcweir 				try
582cdf0e10cSrcweir 				{
583cdf0e10cSrcweir 					xSet->setPropertyValue(aValueProperties[i], evt.NewValue);
584cdf0e10cSrcweir 				}
585cdf0e10cSrcweir 				catch(const Exception&)
586cdf0e10cSrcweir 				{
587cdf0e10cSrcweir 					OSL_ENSURE(sal_False, "FmXUndoEnvironment::propertyChange: could not adjust the value property!");
588cdf0e10cSrcweir 				}
589cdf0e10cSrcweir 			}
590cdf0e10cSrcweir 		}
591cdf0e10cSrcweir 
592cdf0e10cSrcweir 		// no Undo for transient and readonly props. But unfortunately "transient" is not only that the
593cdf0e10cSrcweir 		// "transient" flag is set for the property in question, instead is is somewhat more complex
594cdf0e10cSrcweir         // Transience criterions are:
595cdf0e10cSrcweir         // - the "transient" flag is set for the property
596cdf0e10cSrcweir         // - OR the control has a non-empty COntrolSource property, i.e. is intended to be bound
597cdf0e10cSrcweir         //   to a database column. Note that it doesn't matter here whether the control actually
598cdf0e10cSrcweir         //   *is* bound to a column
599cdf0e10cSrcweir         // - OR the control is bound to an external value via XBindableValue/XValueBinding
600cdf0e10cSrcweir         //   which does not have a "ExternalData" property being <TRUE/>
601cdf0e10cSrcweir 
602cdf0e10cSrcweir 		if (!m_pPropertySetCache)
603cdf0e10cSrcweir 			m_pPropertySetCache = new PropertySetInfoCache;
604cdf0e10cSrcweir 		PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
605cdf0e10cSrcweir 
606cdf0e10cSrcweir 		// let's see if we know something about the set
607cdf0e10cSrcweir 		PropertySetInfoCacheIterator aSetPos = pCache->find(xSet);
608cdf0e10cSrcweir 		if (aSetPos == pCache->end())
609cdf0e10cSrcweir 		{
610cdf0e10cSrcweir 			PropertySetInfo aNewEntry;
611cdf0e10cSrcweir 			if (!::comphelper::hasProperty(FM_PROP_CONTROLSOURCE, xSet))
612cdf0e10cSrcweir 			{
613cdf0e10cSrcweir 				aNewEntry.bHasEmptyControlSource = sal_False;
614cdf0e10cSrcweir 			}
615cdf0e10cSrcweir 			else
616cdf0e10cSrcweir 			{
617cdf0e10cSrcweir 				try
618cdf0e10cSrcweir 				{
619cdf0e10cSrcweir 					Any aCurrentControlSource = xSet->getPropertyValue(FM_PROP_CONTROLSOURCE);
620cdf0e10cSrcweir 					aNewEntry.bHasEmptyControlSource = !aCurrentControlSource.hasValue() || (::comphelper::getString(aCurrentControlSource).getLength() == 0);
621cdf0e10cSrcweir 				}
622cdf0e10cSrcweir 				catch(const Exception&)
623cdf0e10cSrcweir 				{
624cdf0e10cSrcweir                     DBG_UNHANDLED_EXCEPTION();
625cdf0e10cSrcweir 				}
626cdf0e10cSrcweir 			}
627cdf0e10cSrcweir 			aSetPos = pCache->insert(PropertySetInfoCache::value_type(xSet,aNewEntry)).first;
628cdf0e10cSrcweir 			DBG_ASSERT(aSetPos != pCache->end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
629cdf0e10cSrcweir 		}
630cdf0e10cSrcweir 		else
631cdf0e10cSrcweir 		{	// is it the DataField property ?
632cdf0e10cSrcweir 			if (evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
633cdf0e10cSrcweir 			{
634cdf0e10cSrcweir 				aSetPos->second.bHasEmptyControlSource = !evt.NewValue.hasValue() || (::comphelper::getString(evt.NewValue).getLength() == 0);
635cdf0e10cSrcweir 			}
636cdf0e10cSrcweir 		}
637cdf0e10cSrcweir 
638cdf0e10cSrcweir 		// now we have access to the cached info about the set
639cdf0e10cSrcweir 		// let's see what we know about the property
640cdf0e10cSrcweir 		PropertySetInfo::AllProperties& rPropInfos = aSetPos->second.aProps;
641cdf0e10cSrcweir 		PropertySetInfo::AllPropertiesIterator aPropertyPos = rPropInfos.find(evt.PropertyName);
642cdf0e10cSrcweir 		if (aPropertyPos == rPropInfos.end())
643cdf0e10cSrcweir 		{	// nothing 'til now ... have to change this ....
644cdf0e10cSrcweir 			PropertyInfo aNewEntry;
645cdf0e10cSrcweir 
646cdf0e10cSrcweir 			// the attributes
647cdf0e10cSrcweir 			sal_Int32 nAttributes = xSet->getPropertySetInfo()->getPropertyByName(evt.PropertyName).Attributes;
648cdf0e10cSrcweir 			aNewEntry.bIsTransientOrReadOnly = ((nAttributes & PropertyAttribute::READONLY) != 0) || ((nAttributes & PropertyAttribute::TRANSIENT) != 0);
649cdf0e10cSrcweir 
650cdf0e10cSrcweir 			// check if it is the special "DataFieldProperty"
651cdf0e10cSrcweir 			aNewEntry.bIsValueProperty = sal_False;
652cdf0e10cSrcweir 			try
653cdf0e10cSrcweir 			{
654cdf0e10cSrcweir 				if (::comphelper::hasProperty(FM_PROP_CONTROLSOURCEPROPERTY, xSet))
655cdf0e10cSrcweir 				{
656cdf0e10cSrcweir 					Any aControlSourceProperty = xSet->getPropertyValue(FM_PROP_CONTROLSOURCEPROPERTY);
657cdf0e10cSrcweir 					::rtl::OUString sControlSourceProperty;
658cdf0e10cSrcweir 					aControlSourceProperty >>= sControlSourceProperty;
659cdf0e10cSrcweir 
660cdf0e10cSrcweir 					aNewEntry.bIsValueProperty = (sControlSourceProperty.equals(evt.PropertyName));
661cdf0e10cSrcweir 				}
662cdf0e10cSrcweir 			}
663cdf0e10cSrcweir 			catch(const Exception&)
664cdf0e10cSrcweir 			{
665cdf0e10cSrcweir                 DBG_UNHANDLED_EXCEPTION();
666cdf0e10cSrcweir 			}
667cdf0e10cSrcweir 
668cdf0e10cSrcweir 			// insert the new entry
669cdf0e10cSrcweir 			aPropertyPos = rPropInfos.insert(PropertySetInfo::AllProperties::value_type(evt.PropertyName,aNewEntry)).first;
670cdf0e10cSrcweir 			DBG_ASSERT(aPropertyPos != rPropInfos.end(), "FmXUndoEnvironment::propertyChange : just inserted it ... why it's not there ?");
671cdf0e10cSrcweir 		}
672cdf0e10cSrcweir 
673cdf0e10cSrcweir 		// now we have access to the cached info about the property affected
674cdf0e10cSrcweir 		// and are able to decide wether or not we need an undo action
675cdf0e10cSrcweir 
676cdf0e10cSrcweir         bool bAddUndoAction = rModel.IsUndoEnabled();
677cdf0e10cSrcweir         // no UNDO for transient/readonly properties
678cdf0e10cSrcweir         if ( bAddUndoAction && aPropertyPos->second.bIsTransientOrReadOnly )
679cdf0e10cSrcweir             bAddUndoAction = false;
680cdf0e10cSrcweir 
681cdf0e10cSrcweir 		if ( bAddUndoAction && aPropertyPos->second.bIsValueProperty )
682cdf0e10cSrcweir 		{
683cdf0e10cSrcweir             // no UNDO when the "value" property changes, but the ControlSource is non-empty
684cdf0e10cSrcweir             // (in this case the control is intended to be bound to a database column)
685cdf0e10cSrcweir             if ( !aSetPos->second.bHasEmptyControlSource )
686cdf0e10cSrcweir                 bAddUndoAction = false;
687cdf0e10cSrcweir 
688cdf0e10cSrcweir             // no UNDO if the control is currently bound to an external value
689cdf0e10cSrcweir             if ( bAddUndoAction )
690cdf0e10cSrcweir             {
691cdf0e10cSrcweir                 Reference< XBindableValue > xBindable( evt.Source, UNO_QUERY );
692cdf0e10cSrcweir                 Reference< XValueBinding > xBinding;
693cdf0e10cSrcweir                 if ( xBindable.is() )
694cdf0e10cSrcweir                     xBinding = xBindable->getValueBinding();
695cdf0e10cSrcweir 
696cdf0e10cSrcweir                 Reference< XPropertySet > xBindingProps;
697cdf0e10cSrcweir                 Reference< XPropertySetInfo > xBindingPropsPSI;
698cdf0e10cSrcweir                 if ( xBindable.is() )
699cdf0e10cSrcweir                     xBindingProps.set( xBinding, UNO_QUERY );
700cdf0e10cSrcweir                 if ( xBindingProps.is() )
701cdf0e10cSrcweir                     xBindingPropsPSI = xBindingProps->getPropertySetInfo();
702cdf0e10cSrcweir                 // TODO: we should cache all those things, else this might be too expensive.
703cdf0e10cSrcweir                 // However, this requires we're notified of changes in the value binding
704cdf0e10cSrcweir 
705cdf0e10cSrcweir                 static const ::rtl::OUString s_sExternalData( RTL_CONSTASCII_USTRINGPARAM( "ExternalData" ) );
706cdf0e10cSrcweir                 if ( xBindingPropsPSI.is() && xBindingPropsPSI->hasPropertyByName( s_sExternalData ) )
707cdf0e10cSrcweir                 {
708cdf0e10cSrcweir                     sal_Bool bExternalData = sal_True;
709cdf0e10cSrcweir                     OSL_VERIFY( xBindingProps->getPropertyValue( s_sExternalData ) >>= bExternalData );
710cdf0e10cSrcweir                     bAddUndoAction = !bExternalData;
711cdf0e10cSrcweir                 }
712cdf0e10cSrcweir                 else
713cdf0e10cSrcweir                     bAddUndoAction = !xBinding.is();
714cdf0e10cSrcweir             }
715cdf0e10cSrcweir         }
716cdf0e10cSrcweir 
717cdf0e10cSrcweir         if ( bAddUndoAction && ( evt.PropertyName == FM_PROP_STRINGITEMLIST ) )
718cdf0e10cSrcweir         {
719cdf0e10cSrcweir             Reference< XListEntrySink > xSink( evt.Source, UNO_QUERY );
720cdf0e10cSrcweir             if ( xSink.is() && xSink->getListEntrySource().is() )
721cdf0e10cSrcweir                 // #i41029# / 2005-01-31 / frank.schoenheit@sun.com
722cdf0e10cSrcweir                 bAddUndoAction = false;
723cdf0e10cSrcweir         }
724cdf0e10cSrcweir 
725cdf0e10cSrcweir         if ( bAddUndoAction )
726cdf0e10cSrcweir         {
727cdf0e10cSrcweir             aGuard.clear();
728cdf0e10cSrcweir             // TODO: this is a potential race condition: two threads here could in theory
729cdf0e10cSrcweir             // add their undo actions out-of-order
730cdf0e10cSrcweir 
731cdf0e10cSrcweir             ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
732cdf0e10cSrcweir             rModel.AddUndo(new FmUndoPropertyAction(rModel, evt));
733cdf0e10cSrcweir         }
734cdf0e10cSrcweir 	}
735cdf0e10cSrcweir 	else
736cdf0e10cSrcweir 	{
737cdf0e10cSrcweir 		// if it's the DataField property we may have to adjust our cache
738cdf0e10cSrcweir 		if (m_pPropertySetCache && evt.PropertyName.equals(FM_PROP_CONTROLSOURCE))
739cdf0e10cSrcweir 		{
740cdf0e10cSrcweir 			Reference< XPropertySet >  xSet(evt.Source, UNO_QUERY);
741cdf0e10cSrcweir 			PropertySetInfoCache* pCache = static_cast<PropertySetInfoCache*>(m_pPropertySetCache);
742cdf0e10cSrcweir 			PropertySetInfo& rSetInfo = (*pCache)[xSet];
743cdf0e10cSrcweir 			rSetInfo.bHasEmptyControlSource = !evt.NewValue.hasValue() || (::comphelper::getString(evt.NewValue).getLength() == 0);
744cdf0e10cSrcweir 		}
745cdf0e10cSrcweir 	}
746cdf0e10cSrcweir }
747cdf0e10cSrcweir 
748cdf0e10cSrcweir // XContainerListener
749cdf0e10cSrcweir //------------------------------------------------------------------------------
elementInserted(const ContainerEvent & evt)750cdf0e10cSrcweir void SAL_CALL FmXUndoEnvironment::elementInserted(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
751cdf0e10cSrcweir {
752cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementInserted" );
753cdf0e10cSrcweir 	::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
754cdf0e10cSrcweir     ::osl::MutexGuard aGuard( m_aMutex );
755cdf0e10cSrcweir 
756cdf0e10cSrcweir 	// neues Object zum lauschen
757cdf0e10cSrcweir 	Reference< XInterface >  xIface;
758cdf0e10cSrcweir 	evt.Element >>= xIface;
759cdf0e10cSrcweir 	OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementInserted: invalid container notification!");
760cdf0e10cSrcweir 	AddElement(xIface);
761cdf0e10cSrcweir 
762cdf0e10cSrcweir     implSetModified();
763cdf0e10cSrcweir }
764cdf0e10cSrcweir 
765cdf0e10cSrcweir //------------------------------------------------------------------------------
implSetModified()766cdf0e10cSrcweir void FmXUndoEnvironment::implSetModified()
767cdf0e10cSrcweir {
768cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::implSetModified" );
769cdf0e10cSrcweir 	if ( !IsLocked() && rModel.GetObjectShell() )
770cdf0e10cSrcweir 	{
771cdf0e10cSrcweir 		rModel.GetObjectShell()->SetModified( sal_True );
772cdf0e10cSrcweir 	}
773cdf0e10cSrcweir }
774cdf0e10cSrcweir 
775cdf0e10cSrcweir //------------------------------------------------------------------------------
elementReplaced(const ContainerEvent & evt)776cdf0e10cSrcweir void SAL_CALL FmXUndoEnvironment::elementReplaced(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
777cdf0e10cSrcweir {
778cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementReplaced" );
779cdf0e10cSrcweir 	::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
780cdf0e10cSrcweir     ::osl::MutexGuard aGuard( m_aMutex );
781cdf0e10cSrcweir 
782cdf0e10cSrcweir     Reference< XInterface >  xIface;
783cdf0e10cSrcweir 	evt.ReplacedElement >>= xIface;
784cdf0e10cSrcweir 	OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementReplaced: invalid container notification!");
785cdf0e10cSrcweir 	RemoveElement(xIface);
786cdf0e10cSrcweir 
787cdf0e10cSrcweir 	evt.Element >>= xIface;
788cdf0e10cSrcweir 	AddElement(xIface);
789cdf0e10cSrcweir 
790cdf0e10cSrcweir     implSetModified();
791cdf0e10cSrcweir }
792cdf0e10cSrcweir 
793cdf0e10cSrcweir //------------------------------------------------------------------------------
elementRemoved(const ContainerEvent & evt)794cdf0e10cSrcweir void SAL_CALL FmXUndoEnvironment::elementRemoved(const ContainerEvent& evt) throw(::com::sun::star::uno::RuntimeException)
795cdf0e10cSrcweir {
796cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::elementRemoved" );
797cdf0e10cSrcweir 	::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
798cdf0e10cSrcweir     ::osl::MutexGuard aGuard( m_aMutex );
799cdf0e10cSrcweir 
800cdf0e10cSrcweir     Reference< XInterface >  xIface( evt.Element, UNO_QUERY );
801cdf0e10cSrcweir 	OSL_ENSURE(xIface.is(), "FmXUndoEnvironment::elementRemoved: invalid container notification!");
802cdf0e10cSrcweir 	RemoveElement(xIface);
803cdf0e10cSrcweir 
804cdf0e10cSrcweir     implSetModified();
805cdf0e10cSrcweir }
806cdf0e10cSrcweir 
807cdf0e10cSrcweir //------------------------------------------------------------------------------
modified(const EventObject &)808cdf0e10cSrcweir void SAL_CALL FmXUndoEnvironment::modified( const EventObject& /*aEvent*/ ) throw (RuntimeException)
809cdf0e10cSrcweir {
810cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::modified" );
811cdf0e10cSrcweir     implSetModified();
812cdf0e10cSrcweir }
813cdf0e10cSrcweir 
814cdf0e10cSrcweir //------------------------------------------------------------------------------
AddForms(const Reference<XNameContainer> & rForms)815cdf0e10cSrcweir void FmXUndoEnvironment::AddForms(const Reference< XNameContainer > & rForms)
816cdf0e10cSrcweir {
817cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddForms" );
818cdf0e10cSrcweir 	Lock();
819cdf0e10cSrcweir 	Reference< XInterface >  xInt(rForms, UNO_QUERY);
820cdf0e10cSrcweir 	AddElement(xInt);
821cdf0e10cSrcweir 	UnLock();
822cdf0e10cSrcweir }
823cdf0e10cSrcweir 
824cdf0e10cSrcweir //------------------------------------------------------------------------------
RemoveForms(const Reference<XNameContainer> & rForms)825cdf0e10cSrcweir void FmXUndoEnvironment::RemoveForms(const Reference< XNameContainer > & rForms)
826cdf0e10cSrcweir {
827cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveForms" );
828cdf0e10cSrcweir 	Lock();
829cdf0e10cSrcweir 	Reference< XInterface >  xInt(rForms, UNO_QUERY);
830cdf0e10cSrcweir 	RemoveElement(xInt);
831cdf0e10cSrcweir 	UnLock();
832cdf0e10cSrcweir }
833cdf0e10cSrcweir 
834cdf0e10cSrcweir //------------------------------------------------------------------------------
TogglePropertyListening(const Reference<XInterface> & Element)835cdf0e10cSrcweir void FmXUndoEnvironment::TogglePropertyListening(const Reference< XInterface > & Element)
836cdf0e10cSrcweir {
837cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::TogglePropertyListening" );
838cdf0e10cSrcweir 	// am Container horchen
839cdf0e10cSrcweir 	Reference< XIndexContainer >  xContainer(Element, UNO_QUERY);
840cdf0e10cSrcweir 	if (xContainer.is())
841cdf0e10cSrcweir 	{
842cdf0e10cSrcweir 		sal_uInt32 nCount = xContainer->getCount();
843cdf0e10cSrcweir 		Reference< XInterface >  xIface;
844cdf0e10cSrcweir 		for (sal_uInt32 i = 0; i < nCount; i++)
845cdf0e10cSrcweir 		{
846cdf0e10cSrcweir 			xContainer->getByIndex(i) >>= xIface;
847cdf0e10cSrcweir 			TogglePropertyListening(xIface);
848cdf0e10cSrcweir 		}
849cdf0e10cSrcweir 	}
850cdf0e10cSrcweir 
851cdf0e10cSrcweir 	Reference< XPropertySet >  xSet(Element, UNO_QUERY);
852cdf0e10cSrcweir 	if (xSet.is())
853cdf0e10cSrcweir 	{
854cdf0e10cSrcweir 		if (!bReadOnly)
855cdf0e10cSrcweir 			xSet->addPropertyChangeListener( ::rtl::OUString(), this );
856cdf0e10cSrcweir 		else
857cdf0e10cSrcweir 			xSet->removePropertyChangeListener( ::rtl::OUString(), this );
858cdf0e10cSrcweir 	}
859cdf0e10cSrcweir }
860cdf0e10cSrcweir 
861cdf0e10cSrcweir 
862cdf0e10cSrcweir //------------------------------------------------------------------------------
switchListening(const Reference<XIndexContainer> & _rxContainer,bool _bStartListening)863cdf0e10cSrcweir void FmXUndoEnvironment::switchListening( const Reference< XIndexContainer >& _rxContainer, bool _bStartListening ) SAL_THROW(())
864cdf0e10cSrcweir {
865cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
866cdf0e10cSrcweir     OSL_PRECOND( _rxContainer.is(), "FmXUndoEnvironment::switchListening: invalid container!" );
867cdf0e10cSrcweir     if ( !_rxContainer.is() )
868cdf0e10cSrcweir         return;
869cdf0e10cSrcweir 
870cdf0e10cSrcweir     try
871cdf0e10cSrcweir     {
872cdf0e10cSrcweir 	    // if it's an EventAttacherManager, then we need to listen for
873cdf0e10cSrcweir         // script events
874cdf0e10cSrcweir 	    Reference< XEventAttacherManager > xManager( _rxContainer, UNO_QUERY );
875cdf0e10cSrcweir 	    if ( xManager.is() )
876cdf0e10cSrcweir 	    {
877cdf0e10cSrcweir             if ( _bStartListening )
878cdf0e10cSrcweir             {
879cdf0e10cSrcweir 		        m_pScriptingEnv->registerEventAttacherManager( xManager );
880cdf0e10cSrcweir                 if ( m_vbaListener.is() )
881cdf0e10cSrcweir                     xManager->addScriptListener( m_vbaListener );
882cdf0e10cSrcweir             }
883cdf0e10cSrcweir             else
884cdf0e10cSrcweir             {
885cdf0e10cSrcweir 		        m_pScriptingEnv->revokeEventAttacherManager( xManager );
886cdf0e10cSrcweir                 if ( m_vbaListener.is() )
887cdf0e10cSrcweir                     xManager->removeScriptListener( m_vbaListener );
888cdf0e10cSrcweir             }
889cdf0e10cSrcweir 		}
890cdf0e10cSrcweir 
891cdf0e10cSrcweir         // also handle all children of this element
892cdf0e10cSrcweir 	    sal_uInt32 nCount = _rxContainer->getCount();
893cdf0e10cSrcweir 	    Reference< XInterface > xInterface;
894cdf0e10cSrcweir 	    for ( sal_uInt32 i = 0; i < nCount; ++i )
895cdf0e10cSrcweir 	    {
896cdf0e10cSrcweir 		    _rxContainer->getByIndex( i ) >>= xInterface;
897cdf0e10cSrcweir             if ( _bStartListening )
898cdf0e10cSrcweir 		        AddElement( xInterface );
899cdf0e10cSrcweir             else
900cdf0e10cSrcweir 		        RemoveElement( xInterface );
901cdf0e10cSrcweir 	    }
902cdf0e10cSrcweir 
903cdf0e10cSrcweir         // be notified of any changes in the container elements
904cdf0e10cSrcweir 	    Reference< XContainer > xSimpleContainer( _rxContainer, UNO_QUERY );
905cdf0e10cSrcweir         OSL_ENSURE( xSimpleContainer.is(), "FmXUndoEnvironment::switchListening: how are we expected to be notified of changes in the container?" );
906cdf0e10cSrcweir 	    if ( xSimpleContainer.is() )
907cdf0e10cSrcweir 	    {
908cdf0e10cSrcweir             if ( _bStartListening )
909cdf0e10cSrcweir 		        xSimpleContainer->addContainerListener( this );
910cdf0e10cSrcweir             else
911cdf0e10cSrcweir 		        xSimpleContainer->removeContainerListener( this );
912cdf0e10cSrcweir 	    }
913cdf0e10cSrcweir     }
914cdf0e10cSrcweir     catch( const Exception& )
915cdf0e10cSrcweir     {
916cdf0e10cSrcweir     	OSL_ENSURE( sal_False, "FmXUndoEnvironment::switchListening: caught an exception!" );
917cdf0e10cSrcweir     }
918cdf0e10cSrcweir }
919cdf0e10cSrcweir 
920cdf0e10cSrcweir //------------------------------------------------------------------------------
switchListening(const Reference<XInterface> & _rxObject,bool _bStartListening)921cdf0e10cSrcweir void FmXUndoEnvironment::switchListening( const Reference< XInterface >& _rxObject, bool _bStartListening ) SAL_THROW(())
922cdf0e10cSrcweir {
923cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::switchListening" );
924cdf0e10cSrcweir     OSL_PRECOND( _rxObject.is(), "FmXUndoEnvironment::switchListening: how should I listen at a NULL object?" );
925cdf0e10cSrcweir 
926cdf0e10cSrcweir     try
927cdf0e10cSrcweir     {
928cdf0e10cSrcweir         if ( !bReadOnly )
929cdf0e10cSrcweir         {
930cdf0e10cSrcweir             Reference< XPropertySet > xProps( _rxObject, UNO_QUERY );
931cdf0e10cSrcweir 	        if ( xProps.is() )
932cdf0e10cSrcweir 	        {
933cdf0e10cSrcweir                 if ( _bStartListening )
934cdf0e10cSrcweir     		        xProps->addPropertyChangeListener( ::rtl::OUString(), this );
935cdf0e10cSrcweir                 else
936cdf0e10cSrcweir     	    	    xProps->removePropertyChangeListener( ::rtl::OUString(), this );
937cdf0e10cSrcweir 	        }
938cdf0e10cSrcweir         }
939cdf0e10cSrcweir 
940cdf0e10cSrcweir         Reference< XModifyBroadcaster > xBroadcaster( _rxObject, UNO_QUERY );
941cdf0e10cSrcweir         if ( xBroadcaster.is() )
942cdf0e10cSrcweir         {
943cdf0e10cSrcweir             if ( _bStartListening )
944cdf0e10cSrcweir                 xBroadcaster->addModifyListener( this );
945cdf0e10cSrcweir             else
946cdf0e10cSrcweir                 xBroadcaster->removeModifyListener( this );
947cdf0e10cSrcweir         }
948cdf0e10cSrcweir     }
949cdf0e10cSrcweir     catch( const Exception& )
950cdf0e10cSrcweir     {
951cdf0e10cSrcweir     	OSL_ENSURE( sal_False, "FmXUndoEnvironment::switchListening: caught an exception!" );
952cdf0e10cSrcweir     }
953cdf0e10cSrcweir }
954cdf0e10cSrcweir 
955cdf0e10cSrcweir //------------------------------------------------------------------------------
AddElement(const Reference<XInterface> & _rxElement)956cdf0e10cSrcweir void FmXUndoEnvironment::AddElement(const Reference< XInterface >& _rxElement )
957cdf0e10cSrcweir {
958cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::AddElement" );
959cdf0e10cSrcweir     OSL_ENSURE( !m_bDisposed, "FmXUndoEnvironment::AddElement: not when I'm already disposed!" );
960cdf0e10cSrcweir 
961cdf0e10cSrcweir     // am Container horchen
962cdf0e10cSrcweir 	Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
963cdf0e10cSrcweir 	if ( xContainer.is() )
964cdf0e10cSrcweir         switchListening( xContainer, true );
965cdf0e10cSrcweir 
966cdf0e10cSrcweir     switchListening( _rxElement, true );
967cdf0e10cSrcweir }
968cdf0e10cSrcweir 
969cdf0e10cSrcweir //------------------------------------------------------------------------------
RemoveElement(const Reference<XInterface> & _rxElement)970cdf0e10cSrcweir void FmXUndoEnvironment::RemoveElement(const Reference< XInterface >& _rxElement)
971cdf0e10cSrcweir {
972cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmXUndoEnvironment::RemoveElement" );
973cdf0e10cSrcweir     if ( m_bDisposed )
974cdf0e10cSrcweir         return;
975cdf0e10cSrcweir 
976cdf0e10cSrcweir     switchListening( _rxElement, false );
977cdf0e10cSrcweir 
978cdf0e10cSrcweir 	if (!bReadOnly)
979cdf0e10cSrcweir     {
980cdf0e10cSrcweir 		// reset the ActiveConnection if the form is to be removed. This will (should) free the resources
981cdf0e10cSrcweir 		// associated with this connection
982cdf0e10cSrcweir 		// 86299 - 05/02/2001 - frank.schoenheit@germany.sun.com
983cdf0e10cSrcweir         Reference< XForm > xForm( _rxElement, UNO_QUERY );
984cdf0e10cSrcweir         Reference< XPropertySet > xFormProperties( xForm, UNO_QUERY );
985cdf0e10cSrcweir 		if ( xFormProperties.is() )
986cdf0e10cSrcweir             if ( !::svxform::OStaticDataAccessTools().isEmbeddedInDatabase( _rxElement ) )
987cdf0e10cSrcweir                 // (if there is a connection in the context of the component, setting
988cdf0e10cSrcweir                 // a new connection would be vetoed, anyway)
989cdf0e10cSrcweir                 // #i34196# - 2004-09-21 - fs@openoffice.org
990cdf0e10cSrcweir 			    xFormProperties->setPropertyValue( FM_PROP_ACTIVE_CONNECTION, Any() );
991cdf0e10cSrcweir 	}
992cdf0e10cSrcweir 
993cdf0e10cSrcweir 	Reference< XIndexContainer > xContainer( _rxElement, UNO_QUERY );
994cdf0e10cSrcweir     if ( xContainer.is() )
995cdf0e10cSrcweir         switchListening( xContainer, false );
996cdf0e10cSrcweir }
997cdf0e10cSrcweir 
998cdf0e10cSrcweir 
999cdf0e10cSrcweir //------------------------------------------------------------------------------
FmUndoPropertyAction(FmFormModel & rNewMod,const PropertyChangeEvent & evt)1000cdf0e10cSrcweir FmUndoPropertyAction::FmUndoPropertyAction(FmFormModel& rNewMod, const PropertyChangeEvent& evt)
1001cdf0e10cSrcweir 					 :SdrUndoAction(rNewMod)
1002cdf0e10cSrcweir 					 ,xObj(evt.Source, UNO_QUERY)
1003cdf0e10cSrcweir 					 ,aPropertyName(evt.PropertyName)
1004cdf0e10cSrcweir 					 ,aNewValue(evt.NewValue)
1005cdf0e10cSrcweir 					 ,aOldValue(evt.OldValue)
1006cdf0e10cSrcweir {
1007cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::FmUndoPropertyAction" );
1008cdf0e10cSrcweir 	if (rNewMod.GetObjectShell())
1009cdf0e10cSrcweir 		rNewMod.GetObjectShell()->SetModified(sal_True);
1010cdf0e10cSrcweir 	if(static_STR_UNDO_PROPERTY.Len() == 0)
1011cdf0e10cSrcweir 		static_STR_UNDO_PROPERTY = SVX_RES(RID_STR_UNDO_PROPERTY);
1012cdf0e10cSrcweir }
1013cdf0e10cSrcweir 
1014cdf0e10cSrcweir 
1015cdf0e10cSrcweir //------------------------------------------------------------------------------
Undo()1016cdf0e10cSrcweir void FmUndoPropertyAction::Undo()
1017cdf0e10cSrcweir {
1018cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Undo" );
1019cdf0e10cSrcweir 	FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
1020cdf0e10cSrcweir 
1021cdf0e10cSrcweir 	if (xObj.is() && !rEnv.IsLocked())
1022cdf0e10cSrcweir 	{
1023cdf0e10cSrcweir 		rEnv.Lock();
1024cdf0e10cSrcweir         try
1025cdf0e10cSrcweir         {
1026cdf0e10cSrcweir 		    xObj->setPropertyValue( aPropertyName, aOldValue );
1027cdf0e10cSrcweir         }
1028cdf0e10cSrcweir         catch( const Exception& )
1029cdf0e10cSrcweir         {
1030cdf0e10cSrcweir         	OSL_ENSURE( sal_False, "FmUndoPropertyAction::Undo: caught an exception!" );
1031cdf0e10cSrcweir         }
1032cdf0e10cSrcweir 		rEnv.UnLock();
1033cdf0e10cSrcweir 	}
1034cdf0e10cSrcweir }
1035cdf0e10cSrcweir 
1036cdf0e10cSrcweir //------------------------------------------------------------------------------
Redo()1037cdf0e10cSrcweir void FmUndoPropertyAction::Redo()
1038cdf0e10cSrcweir {
1039cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::Redo" );
1040cdf0e10cSrcweir 	FmXUndoEnvironment& rEnv = ((FmFormModel&)rMod).GetUndoEnv();
1041cdf0e10cSrcweir 
1042cdf0e10cSrcweir 	if (xObj.is() && !rEnv.IsLocked())
1043cdf0e10cSrcweir 	{
1044cdf0e10cSrcweir 		rEnv.Lock();
1045cdf0e10cSrcweir         try
1046cdf0e10cSrcweir         {
1047cdf0e10cSrcweir 		    xObj->setPropertyValue( aPropertyName, aNewValue );
1048cdf0e10cSrcweir         }
1049cdf0e10cSrcweir         catch( const Exception& )
1050cdf0e10cSrcweir         {
1051cdf0e10cSrcweir         	OSL_ENSURE( sal_False, "FmUndoPropertyAction::Redo: caught an exception!" );
1052cdf0e10cSrcweir         }
1053cdf0e10cSrcweir 		rEnv.UnLock();
1054cdf0e10cSrcweir 	}
1055cdf0e10cSrcweir }
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir //------------------------------------------------------------------------------
GetComment() const1058cdf0e10cSrcweir String FmUndoPropertyAction::GetComment() const
1059cdf0e10cSrcweir {
1060cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoPropertyAction::GetComment" );
1061cdf0e10cSrcweir 	String aStr(static_STR_UNDO_PROPERTY);
1062cdf0e10cSrcweir 
1063cdf0e10cSrcweir 	aStr.SearchAndReplace( '#', aPropertyName );
1064cdf0e10cSrcweir 	return aStr;
1065cdf0e10cSrcweir }
1066cdf0e10cSrcweir 
1067cdf0e10cSrcweir 
1068cdf0e10cSrcweir DBG_NAME(FmUndoContainerAction);
1069cdf0e10cSrcweir //------------------------------------------------------------------------------
FmUndoContainerAction(FmFormModel & _rMod,Action _eAction,const Reference<XIndexContainer> & xCont,const Reference<XInterface> & xElem,sal_Int32 nIdx)1070cdf0e10cSrcweir FmUndoContainerAction::FmUndoContainerAction(FmFormModel& _rMod,
1071cdf0e10cSrcweir 											 Action _eAction,
1072cdf0e10cSrcweir 											 const Reference< XIndexContainer > & xCont,
1073cdf0e10cSrcweir 											 const Reference< XInterface > & xElem,
1074cdf0e10cSrcweir 											 sal_Int32 nIdx)
1075cdf0e10cSrcweir 					  :SdrUndoAction( _rMod )
1076cdf0e10cSrcweir 					  ,m_xContainer( xCont )
1077cdf0e10cSrcweir 					  ,m_nIndex( nIdx )
1078cdf0e10cSrcweir 					  ,m_eAction( _eAction )
1079cdf0e10cSrcweir {
1080cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::FmUndoContainerAction" );
1081cdf0e10cSrcweir     OSL_ENSURE( nIdx >= 0, "FmUndoContainerAction::FmUndoContainerAction: invalid index!" );
1082cdf0e10cSrcweir         // some old code suggested this could be a valid argument. However, this code was
1083cdf0e10cSrcweir         // buggy, and it *seemed* that nobody used it - so it was removed.
1084cdf0e10cSrcweir 
1085cdf0e10cSrcweir 	DBG_CTOR(FmUndoContainerAction,NULL);
1086cdf0e10cSrcweir 	if ( xCont.is() && xElem.is() )
1087cdf0e10cSrcweir 	{
1088cdf0e10cSrcweir 		// normalize
1089cdf0e10cSrcweir         m_xElement = m_xElement.query( xElem );
1090cdf0e10cSrcweir         if ( m_eAction == Removed )
1091cdf0e10cSrcweir         {
1092cdf0e10cSrcweir 			if (m_nIndex >= 0)
1093cdf0e10cSrcweir 			{
1094cdf0e10cSrcweir 				Reference< XEventAttacherManager >	xManager( xCont, UNO_QUERY );
1095cdf0e10cSrcweir 				if ( xManager.is() )
1096cdf0e10cSrcweir 					m_aEvents = xManager->getScriptEvents(m_nIndex);
1097cdf0e10cSrcweir 			}
1098cdf0e10cSrcweir 			else
1099cdf0e10cSrcweir 				m_xElement = NULL;
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir             // we now own the element
1102cdf0e10cSrcweir 			m_xOwnElement = m_xElement;
1103cdf0e10cSrcweir         }
1104cdf0e10cSrcweir 	}
1105cdf0e10cSrcweir }
1106cdf0e10cSrcweir 
1107cdf0e10cSrcweir //------------------------------------------------------------------------------
~FmUndoContainerAction()1108cdf0e10cSrcweir FmUndoContainerAction::~FmUndoContainerAction()
1109cdf0e10cSrcweir {
1110cdf0e10cSrcweir     // if we own the object ....
1111cdf0e10cSrcweir 	DisposeElement( m_xOwnElement );
1112cdf0e10cSrcweir 	DBG_DTOR(FmUndoContainerAction,NULL);
1113cdf0e10cSrcweir }
1114cdf0e10cSrcweir 
1115cdf0e10cSrcweir //------------------------------------------------------------------------------
1116cdf0e10cSrcweir 
DisposeElement(const Reference<XInterface> & xElem)1117cdf0e10cSrcweir void FmUndoContainerAction::DisposeElement( const Reference< XInterface > & xElem )
1118cdf0e10cSrcweir {
1119cdf0e10cSrcweir 	Reference< XComponent > xComp( xElem, UNO_QUERY );
1120cdf0e10cSrcweir 	if ( xComp.is() )
1121cdf0e10cSrcweir 	{
1122cdf0e10cSrcweir         // and the object does not have a parent
1123cdf0e10cSrcweir 		Reference< XChild >  xChild( xElem, UNO_QUERY );
1124cdf0e10cSrcweir 		if ( xChild.is() && !xChild->getParent().is() )
1125cdf0e10cSrcweir             // -> dispose it
1126cdf0e10cSrcweir 			xComp->dispose();
1127cdf0e10cSrcweir 	}
1128cdf0e10cSrcweir }
1129cdf0e10cSrcweir 
1130cdf0e10cSrcweir //------------------------------------------------------------------------------
implReInsert()1131cdf0e10cSrcweir void FmUndoContainerAction::implReInsert( ) SAL_THROW( ( Exception ) )
1132cdf0e10cSrcweir {
1133cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReInsert" );
1134cdf0e10cSrcweir 	if ( m_xContainer->getCount() >= m_nIndex )
1135cdf0e10cSrcweir 	{
1136cdf0e10cSrcweir         // insert the element
1137cdf0e10cSrcweir 		Any aVal;
1138cdf0e10cSrcweir 		if ( m_xContainer->getElementType() == ::getCppuType( static_cast< const Reference< XFormComponent >* >( NULL ) ) )
1139cdf0e10cSrcweir 		{
1140cdf0e10cSrcweir 			aVal <<= Reference< XFormComponent >( m_xElement, UNO_QUERY );
1141cdf0e10cSrcweir 		}
1142cdf0e10cSrcweir 		else
1143cdf0e10cSrcweir 		{
1144cdf0e10cSrcweir 			aVal <<= Reference< XForm >( m_xElement, UNO_QUERY );
1145cdf0e10cSrcweir 		}
1146cdf0e10cSrcweir 		m_xContainer->insertByIndex( m_nIndex, aVal );
1147cdf0e10cSrcweir 
1148cdf0e10cSrcweir         OSL_ENSURE( getElementPos( m_xContainer.get(), m_xElement ) == m_nIndex, "FmUndoContainerAction::implReInsert: insertion did not work!" );
1149cdf0e10cSrcweir 
1150cdf0e10cSrcweir         // register the events
1151cdf0e10cSrcweir         Reference< XEventAttacherManager >	xManager( m_xContainer, UNO_QUERY );
1152cdf0e10cSrcweir 		if ( xManager.is() )
1153cdf0e10cSrcweir 			xManager->registerScriptEvents( m_nIndex, m_aEvents );
1154cdf0e10cSrcweir 
1155cdf0e10cSrcweir         // we don't own the object anymore
1156cdf0e10cSrcweir 		m_xOwnElement = NULL;
1157cdf0e10cSrcweir 	}
1158cdf0e10cSrcweir }
1159cdf0e10cSrcweir 
1160cdf0e10cSrcweir //------------------------------------------------------------------------------
implReRemove()1161cdf0e10cSrcweir void FmUndoContainerAction::implReRemove( ) SAL_THROW( ( Exception ) )
1162cdf0e10cSrcweir {
1163cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::implReRemove" );
1164cdf0e10cSrcweir     Reference< XInterface > xElement;
1165cdf0e10cSrcweir     if ( ( m_nIndex >= 0 ) && ( m_nIndex < m_xContainer->getCount() ) )
1166cdf0e10cSrcweir     	m_xContainer->getByIndex( m_nIndex ) >>= xElement;
1167cdf0e10cSrcweir 
1168cdf0e10cSrcweir 	if ( xElement != m_xElement )
1169cdf0e10cSrcweir     {
1170cdf0e10cSrcweir         // the indexes in the container changed. Okay, so go the long way and
1171cdf0e10cSrcweir         // manually determine the index
1172cdf0e10cSrcweir         m_nIndex = getElementPos( m_xContainer.get(), m_xElement );
1173cdf0e10cSrcweir         if ( m_nIndex != -1 )
1174cdf0e10cSrcweir             xElement = m_xElement;
1175cdf0e10cSrcweir     }
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir     OSL_ENSURE( xElement == m_xElement, "FmUndoContainerAction::implReRemove: cannot find the element which I'm responsible for!" );
1178cdf0e10cSrcweir     if ( xElement == m_xElement )
1179cdf0e10cSrcweir 	{
1180cdf0e10cSrcweir 		Reference< XEventAttacherManager >	xManager( m_xContainer, UNO_QUERY );
1181cdf0e10cSrcweir 		if ( xManager.is() )
1182cdf0e10cSrcweir 			m_aEvents = xManager->getScriptEvents( m_nIndex );
1183cdf0e10cSrcweir 		m_xContainer->removeByIndex( m_nIndex );
1184cdf0e10cSrcweir         // from now on, we own this object
1185cdf0e10cSrcweir 		m_xOwnElement = m_xElement;
1186cdf0e10cSrcweir 	}
1187cdf0e10cSrcweir }
1188cdf0e10cSrcweir 
1189cdf0e10cSrcweir //------------------------------------------------------------------------------
Undo()1190cdf0e10cSrcweir void FmUndoContainerAction::Undo()
1191cdf0e10cSrcweir {
1192cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Undo" );
1193cdf0e10cSrcweir 	FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
1194cdf0e10cSrcweir 
1195cdf0e10cSrcweir 	if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
1196cdf0e10cSrcweir 	{
1197cdf0e10cSrcweir 		rEnv.Lock();
1198cdf0e10cSrcweir         try
1199cdf0e10cSrcweir         {
1200cdf0e10cSrcweir 		    switch ( m_eAction )
1201cdf0e10cSrcweir 		    {
1202cdf0e10cSrcweir 			case Inserted:
1203cdf0e10cSrcweir                 implReRemove();
1204cdf0e10cSrcweir                 break;
1205cdf0e10cSrcweir 
1206cdf0e10cSrcweir 			case Removed:
1207cdf0e10cSrcweir                 implReInsert();
1208cdf0e10cSrcweir                 break;
1209cdf0e10cSrcweir     	    }
1210cdf0e10cSrcweir         }
1211cdf0e10cSrcweir         catch( const Exception& )
1212cdf0e10cSrcweir         {
1213cdf0e10cSrcweir         	OSL_ENSURE( sal_False, "FmUndoContainerAction::Undo: caught an exception!" );
1214cdf0e10cSrcweir         }
1215cdf0e10cSrcweir 		rEnv.UnLock();
1216cdf0e10cSrcweir 	}
1217cdf0e10cSrcweir }
1218cdf0e10cSrcweir 
1219cdf0e10cSrcweir //------------------------------------------------------------------------------
Redo()1220cdf0e10cSrcweir void FmUndoContainerAction::Redo()
1221cdf0e10cSrcweir {
1222cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoContainerAction::Redo" );
1223cdf0e10cSrcweir 	FmXUndoEnvironment& rEnv = static_cast< FmFormModel& >( rMod ).GetUndoEnv();
1224cdf0e10cSrcweir 	if ( m_xContainer.is() && !rEnv.IsLocked() && m_xElement.is() )
1225cdf0e10cSrcweir 	{
1226cdf0e10cSrcweir 		rEnv.Lock();
1227cdf0e10cSrcweir         try
1228cdf0e10cSrcweir         {
1229cdf0e10cSrcweir 	    	switch ( m_eAction )
1230cdf0e10cSrcweir 		    {
1231cdf0e10cSrcweir 			case Inserted:
1232cdf0e10cSrcweir                 implReInsert();
1233cdf0e10cSrcweir                 break;
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir 			case Removed:
1236cdf0e10cSrcweir                 implReRemove();
1237cdf0e10cSrcweir 			    break;
1238cdf0e10cSrcweir     		}
1239cdf0e10cSrcweir         }
1240cdf0e10cSrcweir         catch( const Exception& )
1241cdf0e10cSrcweir         {
1242cdf0e10cSrcweir         	OSL_ENSURE( sal_False, "FmUndoContainerAction::Redo: caught an exception!" );
1243cdf0e10cSrcweir         }
1244cdf0e10cSrcweir 		rEnv.UnLock();
1245cdf0e10cSrcweir 	}
1246cdf0e10cSrcweir }
1247cdf0e10cSrcweir 
1248cdf0e10cSrcweir //------------------------------------------------------------------------------
FmUndoModelReplaceAction(FmFormModel & _rMod,SdrUnoObj * _pObject,const Reference<XControlModel> & _xReplaced)1249cdf0e10cSrcweir FmUndoModelReplaceAction::FmUndoModelReplaceAction(FmFormModel& _rMod, SdrUnoObj* _pObject, const Reference< XControlModel > & _xReplaced)
1250cdf0e10cSrcweir 	:SdrUndoAction(_rMod)
1251cdf0e10cSrcweir 	,m_xReplaced(_xReplaced)
1252cdf0e10cSrcweir 	,m_pObject(_pObject)
1253cdf0e10cSrcweir {
1254cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::FmUndoModelReplaceAction" );
1255cdf0e10cSrcweir }
1256cdf0e10cSrcweir 
1257cdf0e10cSrcweir //------------------------------------------------------------------------------
~FmUndoModelReplaceAction()1258cdf0e10cSrcweir FmUndoModelReplaceAction::~FmUndoModelReplaceAction()
1259cdf0e10cSrcweir {
1260cdf0e10cSrcweir 	// dispose our element if nobody else is responsible for
1261cdf0e10cSrcweir 	DisposeElement(m_xReplaced);
1262cdf0e10cSrcweir }
1263cdf0e10cSrcweir 
1264cdf0e10cSrcweir //------------------------------------------------------------------------------
1265cdf0e10cSrcweir 
DisposeElement(const::com::sun::star::uno::Reference<::com::sun::star::awt::XControlModel> & xReplaced)1266cdf0e10cSrcweir void FmUndoModelReplaceAction::DisposeElement( const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlModel>& xReplaced )
1267cdf0e10cSrcweir {
1268cdf0e10cSrcweir 	Reference< XComponent >  xComp(xReplaced, UNO_QUERY);
1269cdf0e10cSrcweir 	if (xComp.is())
1270cdf0e10cSrcweir 	{
1271cdf0e10cSrcweir 		Reference< XChild >  xChild(xReplaced, UNO_QUERY);
1272cdf0e10cSrcweir 		if (!xChild.is() || !xChild->getParent().is())
1273cdf0e10cSrcweir 			xComp->dispose();
1274cdf0e10cSrcweir 	}
1275cdf0e10cSrcweir }
1276cdf0e10cSrcweir 
1277cdf0e10cSrcweir //------------------------------------------------------------------------------
Undo()1278cdf0e10cSrcweir void FmUndoModelReplaceAction::Undo()
1279cdf0e10cSrcweir {
1280cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::Undo" );
1281cdf0e10cSrcweir 	try
1282cdf0e10cSrcweir 	{
1283cdf0e10cSrcweir 		Reference< XControlModel > xCurrentModel( m_pObject->GetUnoControlModel() );
1284cdf0e10cSrcweir 
1285cdf0e10cSrcweir 		// replace the model within the parent
1286cdf0e10cSrcweir 		Reference< XChild > xCurrentAsChild( xCurrentModel, UNO_QUERY );
1287cdf0e10cSrcweir 		Reference< XNameContainer > xCurrentsParent;
1288cdf0e10cSrcweir 		if ( xCurrentAsChild.is() )
1289cdf0e10cSrcweir 			xCurrentsParent = xCurrentsParent.query( xCurrentAsChild->getParent() );
1290cdf0e10cSrcweir 		DBG_ASSERT( xCurrentsParent.is(), "FmUndoModelReplaceAction::Undo: invalid current model!" );
1291cdf0e10cSrcweir 
1292cdf0e10cSrcweir 		if ( xCurrentsParent.is() )
1293cdf0e10cSrcweir 		{
1294cdf0e10cSrcweir 			// the form container works with FormComponents
1295cdf0e10cSrcweir 			Reference< XFormComponent > xComponent( m_xReplaced, UNO_QUERY );
1296cdf0e10cSrcweir 			DBG_ASSERT( xComponent.is(), "FmUndoModelReplaceAction::Undo: the new model is no form component !" );
1297cdf0e10cSrcweir 
1298cdf0e10cSrcweir 			Reference< XPropertySet > xCurrentAsSet( xCurrentModel, UNO_QUERY );
1299cdf0e10cSrcweir 			DBG_ASSERT( ::comphelper::hasProperty(FM_PROP_NAME, xCurrentAsSet ), "FmUndoModelReplaceAction::Undo : one of the models is invalid !");
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir 			::rtl::OUString sName;
1302cdf0e10cSrcweir 			xCurrentAsSet->getPropertyValue( FM_PROP_NAME ) >>= sName;
1303cdf0e10cSrcweir 			xCurrentsParent->replaceByName( sName, makeAny( xComponent ) );
1304cdf0e10cSrcweir 
1305cdf0e10cSrcweir 			m_pObject->SetUnoControlModel(m_xReplaced);
1306cdf0e10cSrcweir 			m_pObject->SetChanged();
1307cdf0e10cSrcweir 
1308cdf0e10cSrcweir 			m_xReplaced = xCurrentModel;
1309cdf0e10cSrcweir 		}
1310cdf0e10cSrcweir 	}
1311cdf0e10cSrcweir 	catch(Exception&)
1312cdf0e10cSrcweir 	{
1313cdf0e10cSrcweir 		DBG_ERROR("FmUndoModelReplaceAction::Undo : could not replace the model !");
1314cdf0e10cSrcweir 	}
1315cdf0e10cSrcweir }
1316cdf0e10cSrcweir 
1317cdf0e10cSrcweir //------------------------------------------------------------------------------
GetComment() const1318cdf0e10cSrcweir String FmUndoModelReplaceAction::GetComment() const
1319cdf0e10cSrcweir {
1320cdf0e10cSrcweir     RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmUndoModelReplaceAction::GetComment" );
1321cdf0e10cSrcweir 	return SVX_RES(RID_STR_UNDO_MODEL_REPLACE);
1322cdf0e10cSrcweir }
1323