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

Generated by: LCOV version 1.10