LCOV - code coverage report
Current view: top level - svx/source/form - fmundo.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 539 0.0 %
Date: 2014-04-14 Functions: 0 57 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10