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

Generated by: LCOV version 1.10