Tag: cws_dev300_odbmacros3
User: fs      
Date: 2008-07-28 06:25:03+0000
Modified:
   dba/dbaccess/source/core/dataaccess/databasedocument.cxx
   dba/dbaccess/source/core/dataaccess/databasedocument.hxx

Log:
 #i76128# event notifications

File Changes:

Directory: /dba/dbaccess/source/core/dataaccess/
================================================

File [changed]: databasedocument.cxx
Url: 
http://dba.openoffice.org/source/browse/dba/dbaccess/source/core/dataaccess/databasedocument.cxx?r1=1.40.6.11&r2=1.40.6.12
Delta lines:  +200 -170
-----------------------
--- databasedocument.cxx        2008-07-24 05:34:15+0000        1.40.6.11
+++ databasedocument.cxx        2008-07-28 06:25:00+0000        1.40.6.12
@@ -7,7 +7,7 @@
  * OpenOffice.org - a multi-platform office productivity suite
  *
  * $RCSfile: databasedocument.cxx,v $
- * $Revision: 1.40.6.11 $
+ * $Revision: 1.40.6.12 $
  *
  * This file is part of OpenOffice.org.
  *
@@ -105,7 +105,40 @@
 //........................................................................
 
 //============================================================
-//= ODatabaseContext
+//= ViewMonitor
+//============================================================
+//--------------------------------------------------------------------------
+bool ViewMonitor::onControllerConnected( const Reference< XController >& 
_rxController )
+{
+    bool bFirstControllerEver = ( m_bEverHadController == false );
+    m_bEverHadController = true;
+
+    m_xLastConnectedController = _rxController;
+    m_bLastIsFirstEverController = bFirstControllerEver;
+
+    return bFirstControllerEver;
+}
+
+//--------------------------------------------------------------------------
+void ViewMonitor::onSetCurrentController( const Reference< XController >& 
_rxController )
+{
+    // we interpret this as "creation of a new view has been finished", if and 
only if
+    // the controller is the same which was recently connected to the document
+    bool bViewCreated = ( _rxController == m_xLastConnectedController );
+
+    // also, we interpret this as "loading the document (including UI) is 
finished",
+    // if and only if this was the first-ever controller
+    bool bLoadFinished = bViewCreated && m_bLastIsFirstEverController;
+
+    // notify the respective events
+    if ( bLoadFinished )
+        m_rEventNotifier.notifyDocumentEventAsync( "OnLoad" );
+    if ( bViewCreated )
+        m_rEventNotifier.notifyDocumentEventAsync( "OnViewCreated" );
+}
+
+//============================================================
+//= ODatabaseDocument
 //============================================================
 DBG_NAME(ODatabaseDocument)
 //--------------------------------------------------------------------------
@@ -120,10 +153,11 @@
             ,ODatabaseDocument_OfficeDocument( getMutex() )
             ,m_aModifyListeners( getMutex() )
                        ,m_aCloseListener( getMutex() )
-            ,m_aDocEventListeners( getMutex() )
             ,m_aStorageListeners( getMutex() )
             ,m_pEventContainer( new DocumentEvents( *this, getMutex() ) )
             ,m_pEventExecutor( NULL )   // initialized below, 
ref-count-protected
+            ,m_aEventNotifier( *this, getMutex() )
+            ,m_aViewMonitor( m_aEventNotifier )
 {
        DBG_CTOR(ODatabaseDocument,NULL);
 
@@ -309,10 +343,8 @@
 }
 
 // 
-----------------------------------------------------------------------------
-bool ODatabaseDocument::impl_import_throw( const 
::comphelper::NamedValueCollection& _rResource )
+void ODatabaseDocument::impl_import_throw( const 
::comphelper::NamedValueCollection& _rResource )
 {
-       try
-       {
                Sequence< Any > aFilterArgs;
         Reference< XStatusIndicator > xStatusIndicator;
         lcl_extractAndStartStatusIndicator( _rResource, xStatusIndicator, 
aFilterArgs );
@@ -329,21 +361,12 @@
 
         if ( xStatusIndicator.is() )
             xStatusIndicator->end();
-       }
-       catch( const RuntimeException& e )
-       {
-               throw e;
-       }
-       catch( const Exception& )
-       {
-               return false;
-       }
-    return true;
 }
 
 // 
-----------------------------------------------------------------------------
 void SAL_CALL ODatabaseDocument::initNew(  ) throw 
(DoubleInitializationException, IOException, Exception, RuntimeException)
 {
+    // SYNCHRONIZED ->
     ModelMethodGuard aGuard( *this, ModelMethodGuard::InitMethod );
 
     impl_reset_nothrow();
@@ -362,13 +385,18 @@
 
     m_pImpl->setInitialized();
 
-    impl_setModified_throw( sal_False, aGuard );
+    impl_setModified_nothrow( sal_False, aGuard );
+    // <- SYNCHRONIZED
+
+    m_aEventNotifier.notifyDocumentEvent( "OnCreate" );
+
     impl_notifyStorageChange_nolck_nothrow( xTempStor );
 }
 
 // 
-----------------------------------------------------------------------------
 void SAL_CALL ODatabaseDocument::load( const Sequence< PropertyValue >& 
_Arguments ) throw (DoubleInitializationException, IOException, Exception, 
RuntimeException)
 {
+    // SYNCHRONIZED ->
     ModelMethodGuard aGuard( *this, ModelMethodGuard::InitMethod );
 
     impl_reset_nothrow();
@@ -383,25 +411,34 @@
     m_pImpl->setInitializing();
     try
     {
-        if ( !impl_import_throw( aResource ) )
-            impl_reset_nothrow();
+        impl_import_throw( aResource );
     }
     catch( const Exception& )
     {
         impl_reset_nothrow();
         throw;
     }
-    m_pImpl->setInitialized();
+    // note that we do *not* call m_pImpl->setInitialized here: The 
initialization is only complete
+    // when the XModel::attachResource has been called, not sooner.
 
-    impl_setModified_throw( sal_False, aGuard );
+    impl_setModified_nothrow( sal_False, aGuard );
+    // <- SYNCHRONIZED
 }
 
 // 
-----------------------------------------------------------------------------
 // XModel
 sal_Bool SAL_CALL ODatabaseDocument::attachResource( const ::rtl::OUString& 
_rURL, const Sequence< PropertyValue >& _rArguments ) throw (RuntimeException)
 {
-    ModelMethodGuard aGuard( *this );
+    ModelMethodGuard aGuard( *this, ModelMethodGuard::MethodUsedDuringInit );
     m_pImpl->attachResource( _rURL, _rArguments );
+
+    if ( m_pImpl->isInitializing() )
+    {   // this means we've just been loaded, and this is the attachResource 
call which follows
+        // the load call.
+        m_pImpl->setInitialized();
+        m_aEventNotifier.notifyDocumentEvent( "OnLoadFinished" );
+    }
+
     return sal_True;
 }
 
@@ -426,23 +463,11 @@
 
     m_aControllers.push_back( _xController );
 
-    if ( m_aControllers.size() != 1 )
+    bool bFirstControllerEver = m_aViewMonitor.onControllerConnected( 
_xController );
+    if ( !bFirstControllerEver )
         return;
 
-    // it's the first controller
-
-    // check/adjust our macro mode. Note: This is only temporary. When we 
fully support the
-    // XEmbeddedScripts interface, plus related functionality, then the 
controller is able
-    // to do this itself, since we'll then have a UNO method for this.
-    //
-    // Also, the same has to happen in the loader then, since the checks must 
be made
-    // *before* OnLoad events are triggered - finally, the user can bind 
events to OnLoad ...
-    // (This, at the latest, implies we need a UNO equivalent for 
checkMacrosOnLoading, else
-    //  the loader can't call it.)
-    //
-    // For now, as long as we do not have own macros, but only those in the 
embedded
-    // forms/reports, it's sufficient to do the check here.
-    //
+    // check/adjust our macro mode.
     m_pImpl->checkMacrosOnLoading();
 }
 
@@ -450,7 +475,6 @@
 void SAL_CALL ODatabaseDocument::disconnectController( const Reference< 
XController >& _xController ) throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
     Controllers::iterator pos = ::std::find( m_aControllers.begin(), 
m_aControllers.end(), _xController );
     OSL_ENSURE( pos != m_aControllers.end(), 
"ODatabaseDocument::disconnectController: don't know this controller!" );
@@ -484,7 +508,6 @@
 void SAL_CALL ODatabaseDocument::lockControllers(  ) throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
     ++m_pImpl->m_nControllerLockCount;
 }
@@ -493,7 +516,6 @@
 void SAL_CALL ODatabaseDocument::unlockControllers(  ) throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        --m_pImpl->m_nControllerLockCount;
 }
@@ -502,7 +524,6 @@
 sal_Bool SAL_CALL ODatabaseDocument::hasControllersLocked(  ) throw 
(RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        return m_pImpl->m_nControllerLockCount != 0;
 }
@@ -511,7 +532,6 @@
 Reference< XController > SAL_CALL ODatabaseDocument::getCurrentController() 
throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        return m_xCurrentController.is() ? m_xCurrentController : ( 
m_aControllers.empty() ? Reference< XController >() : *m_aControllers.begin() );
 }
@@ -520,15 +540,15 @@
 void SAL_CALL ODatabaseDocument::setCurrentController( const Reference< 
XController >& _xController ) throw (NoSuchElementException, RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        m_xCurrentController = _xController;
+
+    m_aViewMonitor.onSetCurrentController( _xController );
 }
 // 
-----------------------------------------------------------------------------
 Reference< XInterface > SAL_CALL ODatabaseDocument::getCurrentSelection(  ) 
throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        Reference< XInterface > xRet;
        Reference< XSelectionSupplier >  xDocView( getCurrentController(), 
UNO_QUERY );
@@ -555,7 +575,6 @@
 sal_Bool SAL_CALL ODatabaseDocument::isReadonly(  ) throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        return m_pImpl->m_bDocumentReadOnly;
 }
@@ -568,16 +587,27 @@
         if ( m_pImpl->m_bDocumentReadOnly )
             throw IOException();
 
-    impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getResource(), 
"OnSaveDone", aGuard );
+    impl_storeAs_throw( m_pImpl->getURL(), m_pImpl->getResource(), SAVE, 
aGuard );
 }
 
 // 
-----------------------------------------------------------------------------
 void ODatabaseDocument::impl_storeAs_throw( const ::rtl::OUString& _rURL, 
const Sequence< PropertyValue>& _rArguments,
-        const sal_Char* _pAsciiDocumentEventName, ModelMethodGuard& _rGuard )
+    const StoreType _eType, ModelMethodGuard& _rGuard )
 {
+    OSL_PRECOND( ( _eType == SAVE ) || ( _eType == SAVE_AS ),
+        "ODatabaseDocument::impl_storeAs_throw: you introduced a new type 
which cannot be handled here!" );
+
+    {
+        _rGuard.clear();
+       m_aEventNotifier.notifyDocumentEvent( _eType == SAVE ? "OnSave" : 
"OnSaveAs" );
+        _rGuard.reset();
+    }
+
     Reference< XStorage > xNewRootStorage;
         // will be non-NULL if our storage changed
 
+    try
+    {
     sal_Bool bLocationChanged = ( _rURL != m_pImpl->getLocation() );
        if ( bLocationChanged )
        {
@@ -611,18 +641,22 @@
     // success - tell our impl
     m_pImpl->attachResource( _rURL, aMediaDescriptor );
 
-    // create a document event (mutex still locked)
-    document::EventObject aEvent( *this, ::rtl::OUString::createFromAscii( 
_pAsciiDocumentEventName ) );
-
     // if we are in an initialization process, then this is finished, now that 
we stored the document
     if ( m_pImpl->isInitializing() )
         m_pImpl->setInitialized();
-
-    // reset our "modified" flag, and clear the guard
-    impl_setModified_throw( sal_False, _rGuard );
+    }
+    catch( const Exception& )
+    {
+        // notify the failure
+        m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? 
"OnSaveFailed" : "OnSaveAsFailed" );
+        throw;
+    }
 
     // notify the document event
-    impl_notifyEvent_nolck_nothrow( aEvent );
+    m_aEventNotifier.notifyDocumentEventAsync( _eType == SAVE ? "OnSaveDone" : 
"OnSaveAsDone" );
+
+    // reset our "modified" flag, and clear the guard
+    impl_setModified_nothrow( sal_False, _rGuard );
 
     // notify storage listeners
     impl_notifyStorageChange_nolck_nothrow( xNewRootStorage );
@@ -642,27 +676,33 @@
 // 
-----------------------------------------------------------------------------
 void SAL_CALL ODatabaseDocument::storeAsURL( const ::rtl::OUString& _rURL, 
const Sequence< PropertyValue >& _rArguments ) throw (IOException, 
RuntimeException)
 {
+    // SYNCHRONIZED ->
     ModelMethodGuard aGuard( *this, ModelMethodGuard::MethodWithoutInit );
 
     // Normally, a document initialization is done via XLoadable::load or 
XLoadable::initNew. For convenience
     // reasons, and to not break existing API clients, it's allowed to call 
storeAsURL without having initialized
     // the document, in which case the initialization will be done implicitly.
-    if ( m_pImpl->isInitializing() )
+    bool bImplicitInitialization = !m_pImpl->isInitialized();
         // implicit initialization while another initialization is just 
running is not possible
+    if ( bImplicitInitialization && m_pImpl->isInitializing() )
         throw DoubleInitializationException();
 
-    if ( !m_pImpl->isInitialized() )
+    if ( bImplicitInitialization )
         m_pImpl->setInitializing();
 
     try
     {
-        impl_storeAs_throw( _rURL, _rArguments, "OnSaveAsDone", aGuard );
+        impl_storeAs_throw( _rURL, _rArguments, SAVE_AS, aGuard );
     }
     catch( const Exception& )
     {
         impl_reset_nothrow();
         throw;
     }
+    // <- SYNCHRONIZED
+
+    if ( bImplicitInitialization )
+           m_aEventNotifier.notifyDocumentEvent( "OnCreate" );
 }
 
 // 
-----------------------------------------------------------------------------
@@ -723,14 +763,14 @@
 // XModifyBroadcaster
 void SAL_CALL ODatabaseDocument::addModifyListener( const Reference< 
XModifyListener >& _xListener ) throw (RuntimeException)
 {
-       
::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed);
+    ModelMethodGuard aGuard( *this );
        m_aModifyListeners.addInterface(_xListener);
 }
 
 // 
-----------------------------------------------------------------------------
 void SAL_CALL ODatabaseDocument::removeModifyListener( const Reference< 
XModifyListener >& _xListener ) throw (RuntimeException)
 {
-       
::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed);
+    ModelMethodGuard aGuard( *this );
        m_aModifyListeners.removeInterface(_xListener);
 }
 
@@ -739,7 +779,6 @@
 sal_Bool SAL_CALL ODatabaseDocument::isModified(  ) throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        return m_pImpl->m_bModified;
 }
@@ -748,11 +787,11 @@
 void SAL_CALL ODatabaseDocument::setModified( sal_Bool _bModified ) throw 
(PropertyVetoException, RuntimeException)
 {
     ModelMethodGuard aGuard( *this, ModelMethodGuard::MethodUsedDuringInit );
-    impl_setModified_throw( _bModified, aGuard );
+    impl_setModified_nothrow( _bModified, aGuard );
 }
 
 // 
-----------------------------------------------------------------------------
-void ODatabaseDocument::impl_setModified_throw( sal_Bool _bModified, 
ModelMethodGuard& _rGuard )
+void ODatabaseDocument::impl_setModified_nothrow( sal_Bool _bModified, 
ModelMethodGuard& _rGuard )
 {
        if ( m_pImpl->m_bModified == _bModified )
         return;
@@ -762,26 +801,26 @@
 
     m_pImpl->m_bModified = _bModified;
 
-    document::EventObject aEvent( *this, ::rtl::OUString( 
RTL_CONSTASCII_USTRINGPARAM( "OnModifyChanged" ) ) );
-    _rGuard.clear();
+    m_aEventNotifier.notifyDocumentEventAsync( "OnModifyChanged" );
 
-    m_aModifyListeners.notifyEach( &XModifyListener::modified, (const 
lang::EventObject&)aEvent );
-    impl_notifyEvent_nolck_nothrow( aEvent );
+    _rGuard.clear();
+    lang::EventObject aEvent( *this );
+    m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
 }
 
 // 
-----------------------------------------------------------------------------
 // ::com::sun::star::document::XEventBroadcaster
-void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< 
document::XEventListener >& _xListener ) throw (uno::RuntimeException)
+void SAL_CALL ODatabaseDocument::addEventListener(const uno::Reference< 
document::XEventListener >& _Listener ) throw (uno::RuntimeException)
 {
-       
::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed);
-    m_aDocEventListeners.addInterface(_xListener);
+    ModelMethodGuard aGuard( *this, ModelMethodGuard::MethodWithoutInit );
+    m_aEventNotifier.addDocumentEventListener( _Listener );
 }
 
 // 
-----------------------------------------------------------------------------
-void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< 
document::XEventListener >& _xListener ) throw (uno::RuntimeException)
+void SAL_CALL ODatabaseDocument::removeEventListener( const uno::Reference< 
document::XEventListener >& _Listener ) throw (uno::RuntimeException)
 {
-       
::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed);
-    m_aDocEventListeners.removeInterface(_xListener);
+    ModelMethodGuard aGuard( *this, ModelMethodGuard::MethodWithoutInit );
+    m_aEventNotifier.removeDocumentEventListener( _Listener );
 }
 
 // 
-----------------------------------------------------------------------------
@@ -841,7 +880,7 @@
 }
 
 // 
-----------------------------------------------------------------------------
-void ODatabaseDocument::impl_closeControllerFrames( sal_Bool 
_bDeliverOwnership )
+void ODatabaseDocument::impl_closeControllerFrames_nolck_throw( sal_Bool 
_bDeliverOwnership )
 {
     Controllers aCopy = m_aControllers;
 
@@ -893,40 +932,38 @@
 }
 
 // 
-----------------------------------------------------------------------------
-void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw 
(::com::sun::star::util::CloseVetoException, RuntimeException)
+void SAL_CALL ODatabaseDocument::close( sal_Bool _bDeliverOwnership ) throw 
(CloseVetoException, RuntimeException)
 {
+    // everything below can/must be done without our mutex locked, the below 
is just for
+    // the checks for being disposed and the like
+    {
     ModelMethodGuard aGuard( *this );
+    }
 
-    document::EventObject aEvent( *this, ::rtl::OUString( 
RTL_CONSTASCII_USTRINGPARAM( "OnUnload" ) ) );
-
-    {
-        aGuard.clear();
+    // allow listeners to veto
+    lang::EventObject aEvent( *this );
         m_aCloseListener.forEach< XCloseListener >(
             boost::bind( &XCloseListener::queryClosing, _1, boost::cref( 
aEvent ), boost::cref( _bDeliverOwnership ) ) );
-        aGuard.reset();
-    }
 
-    impl_closeControllerFrames( _bDeliverOwnership );
+    // notify that we're going to unload
+       m_aEventNotifier.notifyDocumentEvent( "OnPrepareUnload" );
 
-    aGuard.clear();
+    impl_closeControllerFrames_nolck_throw( _bDeliverOwnership );
 
     m_aCloseListener.notifyEach( &XCloseListener::notifyClosing, (const 
lang::EventObject&)aEvent );
 
-    // notify the OnUnload at the earliest possibility - which is here and now
-       impl_notifyEvent_nolck_nothrow( aEvent );
-
     dispose();
 }
 // 
-----------------------------------------------------------------------------
 void SAL_CALL ODatabaseDocument::addCloseListener( const Reference< 
::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException)
 {
-       
::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed);
+    ModelMethodGuard aGuard( *this );
        m_aCloseListener.addInterface(Listener);
 }
 // 
-----------------------------------------------------------------------------
 void SAL_CALL ODatabaseDocument::removeCloseListener( const Reference< 
::com::sun::star::util::XCloseListener >& Listener ) throw (RuntimeException)
 {
-       
::connectivity::checkDisposed(ODatabaseDocument_OfficeDocument::rBHelper.bDisposed);
+    ModelMethodGuard aGuard( *this );
     m_aCloseListener.removeInterface(Listener);
 }
 // 
-----------------------------------------------------------------------------
@@ -1043,7 +1080,6 @@
 Reference< XUIConfigurationManager > SAL_CALL 
ODatabaseDocument::getUIConfigurationManager(  ) throw (RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    OSL_ENSURE(m_pImpl.is(),"Impl is NULL");
 
        if ( !m_xUIConfigurationManager.is() )
     {
@@ -1093,19 +1129,6 @@
     return xStorageAccess->getDocumentSubStoragesNames();
 }
 
-// 
-----------------------------------------------------------------------------
-void ODatabaseDocument::impl_notifyEvent_nolck_nothrow( const 
document::EventObject& _rEvent )
-{
-       try
-       {
-        m_aDocEventListeners.notifyEach( 
&document::XEventListener::notifyEvent, _rEvent );
-       }
-       catch(const Exception&)
-       {
-        DBG_UNHANDLED_EXCEPTION();
-       }
-}
-
 
//------------------------------------------------------------------------------
 void ODatabaseDocument::impl_notifyStorageChange_nolck_nothrow( const 
Reference< XStorage >& _rxNewRootStorage )
 {
@@ -1125,18 +1148,24 @@
         return;
     }
 
-    DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there 
still are controllers!" );
-        // normally, nobody should explicitly dispose, but only 
XCloseable::close the document. And upon
-        // closing, our controllers are closed, too
+       m_aEventNotifier.notifyDocumentEvent( "OnUnload" );
 
     Reference< XModel > xHoldAlive( this );
-    {
+
+    m_aEventNotifier.disposing();
+
            lang::EventObject aDisposeEvent(static_cast<XWeak*>(this));
            m_aModifyListeners.disposeAndClear( aDisposeEvent );
            m_aCloseListener.disposeAndClear( aDisposeEvent );
-           m_aDocEventListeners.disposeAndClear( aDisposeEvent );
         m_aStorageListeners.disposeAndClear( aDisposeEvent );
 
+    // SYNCHRONIZED ->
+    ::osl::MutexGuard aGuard( m_xMutex->getMutex() );
+
+    DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: there 
still are controllers!" );
+        // normally, nobody should explicitly dispose, but only 
XCloseable::close the document. And upon
+        // closing, our controllers are closed, too
+
         m_xUIConfigurationManager = NULL;
 
         clearObjectContainer( m_xForms );
@@ -1148,11 +1177,12 @@
         // expected to listen for our disposal, and disconnect then
         DBG_ASSERT( m_aControllers.empty(), "ODatabaseDocument::disposing: 
there still are controllers!" );
         impl_disposeControllerFrames_nothrow();
+
         m_xModuleManager.clear();
         m_xTitleHelper.clear();
-    }
 
        m_pImpl.clear();
+    // <- SYNCHRONIZED
 }
 // 
-----------------------------------------------------------------------------
 // XComponent
@@ -1257,7 +1287,7 @@
 Reference< XStorage > SAL_CALL ODatabaseDocument::getDocumentStorage(  ) throw 
(IOException, Exception, RuntimeException)
 {
     ModelMethodGuard aGuard( *this );
-    return m_pImpl->getRootStorage();
+    return m_pImpl->getOrCreateRootStorage();
 }
 
 // 
-----------------------------------------------------------------------------

File [changed]: databasedocument.hxx
Url: 
http://dba.openoffice.org/source/browse/dba/dbaccess/source/core/dataaccess/databasedocument.hxx?r1=1.20.2.6&r2=1.20.2.7
Delta lines:  +61 -13
---------------------
--- databasedocument.hxx        2008-07-24 05:34:15+0000        1.20.2.6
+++ databasedocument.hxx        2008-07-28 06:25:00+0000        1.20.2.7
@@ -7,7 +7,7 @@
  * OpenOffice.org - a multi-platform office productivity suite
  *
  * $RCSfile: databasedocument.hxx,v $
- * $Revision: 1.20.2.6 $
+ * $Revision: 1.20.2.7 $
  *
  * This file is part of OpenOffice.org.
  *
@@ -31,6 +31,7 @@
 #define _DBA_COREDATAACCESS_DATABASEDOCUMENT_HXX_
 
 #include "ModelImpl.hxx"
+#include "documenteventnotifier.hxx"
 
 /** === begin UNO includes === **/
 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
@@ -86,6 +87,45 @@
 typedef ::std::vector< ::com::sun::star::uno::Reference< 
::com::sun::star::frame::XController > >   Controllers;
 
 //============================================================
+//= ViewMonitor
+//============================================================
+/** helper class monitoring the views of a document, and firing appropriate 
events
+    when views are attached / detached
+*/
+class ViewMonitor
+{
+public:
+    ViewMonitor( DocumentEventNotifier& _rEventNotifier )
+        :m_rEventNotifier( _rEventNotifier )
+        ,m_bEverHadController( false )
+        ,m_bLastIsFirstEverController( false )
+        ,m_xLastConnectedController()
+    {
+    }
+
+    /** to be called when a view (aka controller) has been connected to the 
document
+        @return
+            <TRUE/> if and only if this was the first-ever controller 
connected to the document
+    */
+    bool    onControllerConnected(
+                const ::com::sun::star::uno::Reference< 
::com::sun::star::frame::XController >& _rxController
+             );
+
+    /**  to be called when a controller is set as current controller
+    */
+    void    onSetCurrentController(
+                const ::com::sun::star::uno::Reference< 
::com::sun::star::frame::XController >& _rxController
+             );
+
+private:
+    DocumentEventNotifier&  m_rEventNotifier;
+    bool                    m_bEverHadController;
+    bool                    m_bLastIsFirstEverController;
+    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >
+                            m_xLastConnectedController;
+};
+
+//============================================================
 //= ODatabaseDocument
 //============================================================
 typedef ::comphelper::WeakComponentImplHelper15 <   
::com::sun::star::frame::XModel2
@@ -119,13 +159,15 @@
 
     ::cppu::OInterfaceContainerHelper                                          
                                m_aModifyListeners;
        ::cppu::OInterfaceContainerHelper                                       
                                        m_aCloseListener;
-    ::cppu::OInterfaceContainerHelper                                          
                                m_aDocEventListeners;
     ::cppu::OInterfaceContainerHelper                                          
                                m_aStorageListeners;
 
-    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >   
                 m_xCurrentController;
-    Controllers                                                                
                 m_aControllers;
     DocumentEvents*                                                            
                 m_pEventContainer;
     ::rtl::Reference< DocumentEventExecutor >                                  
                 m_pEventExecutor;
+    DocumentEventNotifier                                                      
                 m_aEventNotifier;
+
+    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >   
                 m_xCurrentController;
+    Controllers                                                                
                 m_aControllers;
+    ViewMonitor                                                                
                 m_aViewMonitor;
 
        ::com::sun::star::uno::WeakReference< 
::com::sun::star::container::XNameAccess >                m_xForms;
        ::com::sun::star::uno::WeakReference< 
::com::sun::star::container::XNameAccess >                m_xReports;
@@ -136,21 +178,27 @@
     ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTitle >        
                 m_xTitleHelper;
     TNumberedController                                                        
                 m_aNumberedControllers;
 
+    enum StoreType { SAVE, SAVE_AS };
     /** stores the document to the given URL, rebases it to the respective new 
storage, if necessary, resets
         the modified flag, and notifies any listeners as required
+
+        @param _rURL
+            the URL to store the document to
+        @param _rArguments
+            arguments for storing the document (MediaDescriptor)
+        @param _eType
+            the type of the store process (Save or SaveAs). The method will 
automatically
+            notify the proper events for this type.
+        @param _rGuard
+            the instance lock to be released before doing synchronous 
notifications
     */
     void impl_storeAs_throw(
             const ::rtl::OUString& _rURL,
                        const ::com::sun::star::uno::Sequence< 
::com::sun::star::beans::PropertyValue>& _rArguments,
-            const sal_Char* _pAsciiDocumentEventName,
+            const StoreType _eType,
             ModelMethodGuard& _rGuard
          );
 
-    /** notifies the global event broadcaster 
-        The method must be called without our mutex locked
-    */
-    void impl_notifyEvent_nolck_nothrow( const 
::com::sun::star::document::EventObject& _rEvent );
-
     /** notifies our storage change listeners that our underlying storage 
changed
 
         @param _rxNewRootStorage
@@ -376,7 +424,7 @@
     @raises ::com::sun::star::util::CloseVetoException
         if the closing was vetoed by any instance
     */
-    void    impl_closeControllerFrames( sal_Bool _bDeliverOwnership );
+    void    impl_closeControllerFrames_nolck_throw( sal_Bool 
_bDeliverOwnership );
 
     /** disposes the frames of all controllers which are still left in 
m_aControllers.
     */
@@ -409,7 +457,7 @@
 
     /** imports the document from the given resource.
     */
-    bool    impl_import_throw( const ::comphelper::NamedValueCollection& 
_rResource );
+    void    impl_import_throw( const ::comphelper::NamedValueCollection& 
_rResource );
 
     /** creates a storage for the given URL, truncating it if a file with this 
name already exists
 
@@ -426,7 +474,7 @@
 
     /** clears the guard before notifying.
     */
-    void    impl_setModified_throw( sal_Bool _bModified, ModelMethodGuard& 
_rGuard );
+    void    impl_setModified_nothrow( sal_Bool _bModified, ModelMethodGuard& 
_rGuard );
 
     /** stores the document to the given storage
 




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to