1*31598a22SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*31598a22SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*31598a22SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*31598a22SAndrew Rist  * distributed with this work for additional information
6*31598a22SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*31598a22SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*31598a22SAndrew Rist  * "License"); you may not use this file except in compliance
9*31598a22SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*31598a22SAndrew Rist  *
11*31598a22SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*31598a22SAndrew Rist  *
13*31598a22SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*31598a22SAndrew Rist  * software distributed under the License is distributed on an
15*31598a22SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*31598a22SAndrew Rist  * KIND, either express or implied.  See the License for the
17*31598a22SAndrew Rist  * specific language governing permissions and limitations
18*31598a22SAndrew Rist  * under the License.
19*31598a22SAndrew Rist  *
20*31598a22SAndrew Rist  *************************************************************/
21*31598a22SAndrew Rist 
22*31598a22SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_basctl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "doceventnotifier.hxx"
28cdf0e10cSrcweir #include "scriptdocument.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir /** === begin UNO includes === **/
31cdf0e10cSrcweir #include <com/sun/star/document/XEventBroadcaster.hpp>
32cdf0e10cSrcweir /** === end UNO includes === **/
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <vcl/svapp.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include <tools/diagnose_ex.h>
37cdf0e10cSrcweir 
38cdf0e10cSrcweir #include <comphelper/componentcontext.hxx>
39cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
40cdf0e10cSrcweir 
41cdf0e10cSrcweir #include <vos/mutex.hxx>
42cdf0e10cSrcweir 
43cdf0e10cSrcweir #include <cppuhelper/compbase1.hxx>
44cdf0e10cSrcweir #include <cppuhelper/basemutex.hxx>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir //........................................................................
47cdf0e10cSrcweir namespace basctl
48cdf0e10cSrcweir {
49cdf0e10cSrcweir //........................................................................
50cdf0e10cSrcweir 
51cdf0e10cSrcweir 	/** === begin UNO using === **/
52cdf0e10cSrcweir     using ::com::sun::star::document::XEventBroadcaster;
53cdf0e10cSrcweir     using ::com::sun::star::document::XEventListener;
54cdf0e10cSrcweir     using ::com::sun::star::document::EventObject;
55cdf0e10cSrcweir     using ::com::sun::star::uno::RuntimeException;
56cdf0e10cSrcweir     using ::com::sun::star::uno::Reference;
57cdf0e10cSrcweir     using ::com::sun::star::uno::UNO_QUERY_THROW;
58cdf0e10cSrcweir     using ::com::sun::star::uno::Exception;
59cdf0e10cSrcweir     using ::com::sun::star::frame::XModel;
60cdf0e10cSrcweir     using ::com::sun::star::uno::UNO_QUERY;
61cdf0e10cSrcweir 	/** === end UNO using === **/
62cdf0e10cSrcweir     namespace csslang = ::com::sun::star::lang;
63cdf0e10cSrcweir 
64cdf0e10cSrcweir 	//====================================================================
65cdf0e10cSrcweir 	//= DocumentEventNotifier_Impl
66cdf0e10cSrcweir 	//====================================================================
67cdf0e10cSrcweir     typedef ::cppu::WeakComponentImplHelper1    <   XEventListener
68cdf0e10cSrcweir                                                 >   DocumentEventNotifier_Impl_Base;
69cdf0e10cSrcweir 
70cdf0e10cSrcweir     enum ListenerAction
71cdf0e10cSrcweir     {
72cdf0e10cSrcweir         RegisterListener,
73cdf0e10cSrcweir         RemoveListener
74cdf0e10cSrcweir     };
75cdf0e10cSrcweir 
76cdf0e10cSrcweir     /** impl class for DocumentEventNotifier
77cdf0e10cSrcweir     */
78cdf0e10cSrcweir     class DocumentEventNotifier_Impl    :public ::boost::noncopyable
79cdf0e10cSrcweir                                         ,public ::cppu::BaseMutex
80cdf0e10cSrcweir                                         ,public DocumentEventNotifier_Impl_Base
81cdf0e10cSrcweir     {
82cdf0e10cSrcweir     public:
83cdf0e10cSrcweir         DocumentEventNotifier_Impl( DocumentEventListener& _rListener, const Reference< XModel >& _rxDocument );
84cdf0e10cSrcweir 
85cdf0e10cSrcweir         // document::XEventListener
86cdf0e10cSrcweir         virtual void SAL_CALL notifyEvent( const EventObject& Event ) throw (RuntimeException);
87cdf0e10cSrcweir 
88cdf0e10cSrcweir         // lang::XEventListener
89cdf0e10cSrcweir         virtual void SAL_CALL disposing( const csslang::EventObject& Event ) throw (RuntimeException);
90cdf0e10cSrcweir 
91cdf0e10cSrcweir         // ComponentHelper
92cdf0e10cSrcweir         virtual void SAL_CALL disposing();
93cdf0e10cSrcweir 
94cdf0e10cSrcweir     protected:
95cdf0e10cSrcweir         ~DocumentEventNotifier_Impl();
96cdf0e10cSrcweir 
97cdf0e10cSrcweir     private:
98cdf0e10cSrcweir         /// determines whether the instance is already disposed
impl_isDisposed_nothrow() const99cdf0e10cSrcweir         bool    impl_isDisposed_nothrow() const { return m_pListener == NULL; }
100cdf0e10cSrcweir 
101cdf0e10cSrcweir         /// disposes the instance
102cdf0e10cSrcweir         void    impl_dispose_nothrow();
103cdf0e10cSrcweir 
104cdf0e10cSrcweir         /// registers or revokes the instance as listener at the global event broadcaster
105cdf0e10cSrcweir         void    impl_listenerAction_nothrow( ListenerAction _eAction );
106cdf0e10cSrcweir 
107cdf0e10cSrcweir     private:
108cdf0e10cSrcweir         DocumentEventListener*  m_pListener;
109cdf0e10cSrcweir         Reference< XModel >     m_xModel;
110cdf0e10cSrcweir     };
111cdf0e10cSrcweir 
112cdf0e10cSrcweir 	//--------------------------------------------------------------------
DocumentEventNotifier_Impl(DocumentEventListener & _rListener,const Reference<XModel> & _rxDocument)113cdf0e10cSrcweir     DocumentEventNotifier_Impl::DocumentEventNotifier_Impl( DocumentEventListener& _rListener, const Reference< XModel >& _rxDocument )
114cdf0e10cSrcweir         :DocumentEventNotifier_Impl_Base( m_aMutex )
115cdf0e10cSrcweir         ,m_pListener( &_rListener )
116cdf0e10cSrcweir         ,m_xModel( _rxDocument )
117cdf0e10cSrcweir     {
118cdf0e10cSrcweir         osl_incrementInterlockedCount( &m_refCount );
119cdf0e10cSrcweir         impl_listenerAction_nothrow( RegisterListener );
120cdf0e10cSrcweir         osl_decrementInterlockedCount( &m_refCount );
121cdf0e10cSrcweir     }
122cdf0e10cSrcweir 
123cdf0e10cSrcweir 	//--------------------------------------------------------------------
~DocumentEventNotifier_Impl()124cdf0e10cSrcweir     DocumentEventNotifier_Impl::~DocumentEventNotifier_Impl()
125cdf0e10cSrcweir     {
126cdf0e10cSrcweir         if ( !impl_isDisposed_nothrow() )
127cdf0e10cSrcweir         {
128cdf0e10cSrcweir             acquire();
129cdf0e10cSrcweir             dispose();
130cdf0e10cSrcweir         }
131cdf0e10cSrcweir     }
132cdf0e10cSrcweir 
133cdf0e10cSrcweir     //--------------------------------------------------------------------
notifyEvent(const EventObject & _rEvent)134cdf0e10cSrcweir     void SAL_CALL DocumentEventNotifier_Impl::notifyEvent( const EventObject& _rEvent ) throw (RuntimeException)
135cdf0e10cSrcweir     {
136cdf0e10cSrcweir         ::osl::ClearableMutexGuard aGuard( m_aMutex );
137cdf0e10cSrcweir 
138cdf0e10cSrcweir         OSL_PRECOND( !impl_isDisposed_nothrow(), "DocumentEventNotifier_Impl::notifyEvent: disposed, but still getting events?" );
139cdf0e10cSrcweir         if ( impl_isDisposed_nothrow() )
140cdf0e10cSrcweir             return;
141cdf0e10cSrcweir 
142cdf0e10cSrcweir         Reference< XModel > xDocument( _rEvent.Source, UNO_QUERY );
143cdf0e10cSrcweir         OSL_ENSURE( xDocument.is(), "DocumentEventNotifier_Impl::notifyEvent: illegal source document!" );
144cdf0e10cSrcweir         if ( !xDocument.is() )
145cdf0e10cSrcweir             return;
146cdf0e10cSrcweir 
147cdf0e10cSrcweir         struct EventEntry
148cdf0e10cSrcweir         {
149cdf0e10cSrcweir             const sal_Char* pEventName;
150cdf0e10cSrcweir             void (DocumentEventListener::*listenerMethod)( const ScriptDocument& _rDocument );
151cdf0e10cSrcweir         };
152cdf0e10cSrcweir         EventEntry aEvents[] = {
153cdf0e10cSrcweir             { "OnNew",          &DocumentEventListener::onDocumentCreated },
154cdf0e10cSrcweir             { "OnLoad",         &DocumentEventListener::onDocumentOpened },
155cdf0e10cSrcweir             { "OnSave",         &DocumentEventListener::onDocumentSave },
156cdf0e10cSrcweir             { "OnSaveDone",     &DocumentEventListener::onDocumentSaveDone },
157cdf0e10cSrcweir             { "OnSaveAs",       &DocumentEventListener::onDocumentSaveAs },
158cdf0e10cSrcweir             { "OnSaveAsDone",   &DocumentEventListener::onDocumentSaveAsDone },
159cdf0e10cSrcweir             { "OnUnload",       &DocumentEventListener::onDocumentClosed },
160cdf0e10cSrcweir             { "OnTitleChanged", &DocumentEventListener::onDocumentTitleChanged },
161cdf0e10cSrcweir             { "OnModeChanged",  &DocumentEventListener::onDocumentModeChanged }
162cdf0e10cSrcweir         };
163cdf0e10cSrcweir 
164cdf0e10cSrcweir         for ( size_t i=0; i < sizeof( aEvents ) / sizeof( aEvents[0] ); ++i )
165cdf0e10cSrcweir         {
166cdf0e10cSrcweir             if ( !_rEvent.EventName.equalsAscii( aEvents[i].pEventName ) )
167cdf0e10cSrcweir                 continue;
168cdf0e10cSrcweir 
169cdf0e10cSrcweir             ScriptDocument aDocument( xDocument );
170cdf0e10cSrcweir             {
171cdf0e10cSrcweir                 // the listener implementations usually require the SolarMutex, so lock it here.
172cdf0e10cSrcweir                 // But ensure the proper order of locking the solar and the own mutex
173cdf0e10cSrcweir                 aGuard.clear();
174cdf0e10cSrcweir                 ::vos::OClearableGuard aSolarGuard( Application::GetSolarMutex() );
175cdf0e10cSrcweir                 ::osl::MutexGuard aGuard2( m_aMutex );
176cdf0e10cSrcweir 
177cdf0e10cSrcweir                 if ( impl_isDisposed_nothrow() )
178cdf0e10cSrcweir                     // somebody took the chance to dispose us -> bail out
179cdf0e10cSrcweir                     return;
180cdf0e10cSrcweir 
181cdf0e10cSrcweir                 (m_pListener->*aEvents[i].listenerMethod)( aDocument );
182cdf0e10cSrcweir             }
183cdf0e10cSrcweir             break;
184cdf0e10cSrcweir         }
185cdf0e10cSrcweir     }
186cdf0e10cSrcweir 
187cdf0e10cSrcweir     //--------------------------------------------------------------------
disposing(const csslang::EventObject &)188cdf0e10cSrcweir     void SAL_CALL DocumentEventNotifier_Impl::disposing( const csslang::EventObject& /*Event*/ ) throw (RuntimeException)
189cdf0e10cSrcweir     {
190cdf0e10cSrcweir         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
191cdf0e10cSrcweir         ::osl::MutexGuard aGuard( m_aMutex );
192cdf0e10cSrcweir 
193cdf0e10cSrcweir         if ( !impl_isDisposed_nothrow() )
194cdf0e10cSrcweir             impl_dispose_nothrow();
195cdf0e10cSrcweir     }
196cdf0e10cSrcweir 
197cdf0e10cSrcweir     //--------------------------------------------------------------------
disposing()198cdf0e10cSrcweir     void SAL_CALL DocumentEventNotifier_Impl::disposing()
199cdf0e10cSrcweir     {
200cdf0e10cSrcweir         impl_listenerAction_nothrow( RemoveListener );
201cdf0e10cSrcweir         impl_dispose_nothrow();
202cdf0e10cSrcweir     }
203cdf0e10cSrcweir 
204cdf0e10cSrcweir     //--------------------------------------------------------------------
impl_dispose_nothrow()205cdf0e10cSrcweir     void DocumentEventNotifier_Impl::impl_dispose_nothrow()
206cdf0e10cSrcweir     {
207cdf0e10cSrcweir         m_pListener = NULL;
208cdf0e10cSrcweir         m_xModel.clear();
209cdf0e10cSrcweir     }
210cdf0e10cSrcweir 
211cdf0e10cSrcweir     //--------------------------------------------------------------------
impl_listenerAction_nothrow(ListenerAction _eAction)212cdf0e10cSrcweir     void DocumentEventNotifier_Impl::impl_listenerAction_nothrow( ListenerAction _eAction )
213cdf0e10cSrcweir     {
214cdf0e10cSrcweir         try
215cdf0e10cSrcweir         {
216cdf0e10cSrcweir             Reference< XEventBroadcaster > xBroadcaster;
217cdf0e10cSrcweir             if ( m_xModel.is() )
218cdf0e10cSrcweir                 xBroadcaster.set( m_xModel, UNO_QUERY_THROW );
219cdf0e10cSrcweir             else
220cdf0e10cSrcweir             {
221cdf0e10cSrcweir                 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
222cdf0e10cSrcweir                 xBroadcaster.set(
223cdf0e10cSrcweir                     aContext.createComponent( "com.sun.star.frame.GlobalEventBroadcaster" ),
224cdf0e10cSrcweir                     UNO_QUERY_THROW );
225cdf0e10cSrcweir             }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir             void ( SAL_CALL XEventBroadcaster::*listenerAction )( const Reference< XEventListener >& ) =
228cdf0e10cSrcweir                 ( _eAction == RegisterListener ) ? &XEventBroadcaster::addEventListener : &XEventBroadcaster::removeEventListener;
229cdf0e10cSrcweir             (xBroadcaster.get()->*listenerAction)( this );
230cdf0e10cSrcweir         }
231cdf0e10cSrcweir         catch( const Exception& )
232cdf0e10cSrcweir         {
233cdf0e10cSrcweir         	DBG_UNHANDLED_EXCEPTION();
234cdf0e10cSrcweir         }
235cdf0e10cSrcweir     }
236cdf0e10cSrcweir 
237cdf0e10cSrcweir 	//====================================================================
238cdf0e10cSrcweir 	//= DocumentEventNotifier
239cdf0e10cSrcweir 	//====================================================================
240cdf0e10cSrcweir 	//--------------------------------------------------------------------
DocumentEventNotifier(DocumentEventListener & _rListener,const Reference<XModel> & _rxDocument)241cdf0e10cSrcweir     DocumentEventNotifier::DocumentEventNotifier( DocumentEventListener& _rListener, const Reference< XModel >& _rxDocument )
242cdf0e10cSrcweir         :m_pImpl( new DocumentEventNotifier_Impl( _rListener, _rxDocument ) )
243cdf0e10cSrcweir     {
244cdf0e10cSrcweir     }
245cdf0e10cSrcweir 
246cdf0e10cSrcweir 	//--------------------------------------------------------------------
DocumentEventNotifier(DocumentEventListener & _rListener)247cdf0e10cSrcweir     DocumentEventNotifier::DocumentEventNotifier( DocumentEventListener& _rListener )
248cdf0e10cSrcweir         :m_pImpl( new DocumentEventNotifier_Impl( _rListener, Reference< XModel >() ) )
249cdf0e10cSrcweir     {
250cdf0e10cSrcweir     }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir 	//--------------------------------------------------------------------
~DocumentEventNotifier()253cdf0e10cSrcweir     DocumentEventNotifier::~DocumentEventNotifier()
254cdf0e10cSrcweir     {
255cdf0e10cSrcweir     }
256cdf0e10cSrcweir 
257cdf0e10cSrcweir 	//--------------------------------------------------------------------
dispose()258cdf0e10cSrcweir     void DocumentEventNotifier::dispose()
259cdf0e10cSrcweir     {
260cdf0e10cSrcweir         m_pImpl->dispose();
261cdf0e10cSrcweir     }
262cdf0e10cSrcweir 
263cdf0e10cSrcweir 	//====================================================================
264cdf0e10cSrcweir 	//= DocumentEventListener
265cdf0e10cSrcweir 	//====================================================================
~DocumentEventListener()266cdf0e10cSrcweir     DocumentEventListener::~DocumentEventListener()
267cdf0e10cSrcweir     {
268cdf0e10cSrcweir     }
269cdf0e10cSrcweir 
270cdf0e10cSrcweir //........................................................................
271cdf0e10cSrcweir } // namespace basctl
272cdf0e10cSrcweir //........................................................................
273