1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/types.h>
22 #include <com/sun/star/task/theJobExecutor.hpp>
23 #include <com/sun/star/container/XNameReplace.hpp>
24 #include <com/sun/star/container/XSet.hpp>
25 #include <com/sun/star/document/XEventListener.hpp>
26 #include <com/sun/star/document/XEventBroadcaster.hpp>
27 #include <com/sun/star/document/XDocumentEventListener.hpp>
28 #include <com/sun/star/frame/XGlobalEventBroadcaster.hpp>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/uno/Type.hxx>
32 #include <cppuhelper/implbase1.hxx>
33 #include <cppuhelper/implbase3.hxx>
34 #include <cppuhelper/interfacecontainer.hxx>
35 #include <cppuhelper/supportsservice.hxx>
36 #include <rtl/ref.hxx>
37 #include <sfx2/app.hxx>
38 #include <sfx2/objsh.hxx>
39 #include <sfx2/sfxbasemodel.hxx>
40 #include <sfx2/evntconf.hxx>
41 #include <tools/diagnose_ex.h>
42 #include <unotools/eventcfg.hxx>
43 #include <eventsupplier.hxx>
51 struct ModelCollectionMutexBase
57 typedef ::std::vector
< css::uno::Reference
< css::frame::XModel
> > TModelList
;
59 class ModelCollectionEnumeration
: public ModelCollectionMutexBase
60 , public ::cppu::WeakImplHelper1
< css::container::XEnumeration
>
64 TModelList::iterator m_pEnumerationIt
;
67 ModelCollectionEnumeration();
68 virtual ~ModelCollectionEnumeration();
69 void setModelList(const TModelList
& rList
);
71 // css.container.XEnumeration
72 virtual sal_Bool SAL_CALL
hasMoreElements()
73 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
75 virtual css::uno::Any SAL_CALL
nextElement()
76 throw(css::container::NoSuchElementException
,
77 css::lang::WrappedTargetException
,
78 css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
82 //TODO: remove support of obsolete document::XEventBroadcaster/Listener
83 class SfxGlobalEvents_Impl
: public ModelCollectionMutexBase
84 , public ::cppu::WeakImplHelper3
< css::lang::XServiceInfo
85 , css::frame::XGlobalEventBroadcaster
86 , css::document::XEventListener
89 css::uno::Reference
< css::container::XNameReplace
> m_xEvents
;
90 css::uno::Reference
< css::document::XEventListener
> m_xJobExecutorListener
;
91 ::cppu::OInterfaceContainerHelper m_aLegacyListeners
;
92 ::cppu::OInterfaceContainerHelper m_aDocumentListeners
;
94 GlobalEventConfig
* pImp
;
97 SfxGlobalEvents_Impl(const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
);
98 virtual ~SfxGlobalEvents_Impl();
100 virtual OUString SAL_CALL
getImplementationName()
101 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
103 return OUString("com.sun.star.comp.sfx2.GlobalEventBroadcaster");
106 virtual sal_Bool SAL_CALL
supportsService(OUString
const & ServiceName
)
107 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
109 return cppu::supportsService(this, ServiceName
);
112 virtual css::uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames()
113 throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
115 css::uno::Sequence
< OUString
> aSeq(1);
116 aSeq
[0] = "com.sun.star.frame.GlobalEventBroadcaster";
120 // css.document.XEventBroadcaster
121 virtual css::uno::Reference
< css::container::XNameReplace
> SAL_CALL
getEvents()
122 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
124 virtual void SAL_CALL
addEventListener(const css::uno::Reference
< css::document::XEventListener
>& xListener
)
125 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
127 virtual void SAL_CALL
removeEventListener( const css::uno::Reference
< css::document::XEventListener
>& xListener
)
128 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
130 // css.document.XDocumentEventBroadcaster
131 virtual void SAL_CALL
addDocumentEventListener( const css::uno::Reference
< css::document::XDocumentEventListener
>& _Listener
) throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
132 virtual void SAL_CALL
removeDocumentEventListener( const css::uno::Reference
< css::document::XDocumentEventListener
>& _Listener
) throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
133 virtual void SAL_CALL
notifyDocumentEvent( const OUString
& _EventName
, const css::uno::Reference
< css::frame::XController2
>& _ViewController
, const css::uno::Any
& _Supplement
) throw (css::lang::IllegalArgumentException
, css::lang::NoSupportException
, css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
135 // css.document.XEventListener
136 virtual void SAL_CALL
notifyEvent(const css::document::EventObject
& aEvent
)
137 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
139 // css.document.XDocumentEventListener
140 virtual void SAL_CALL
documentEventOccured( const css::document::DocumentEvent
& Event
) throw (css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
142 // css.container.XSet
143 virtual sal_Bool SAL_CALL
has(const css::uno::Any
& aElement
)
144 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
146 virtual void SAL_CALL
insert(const css::uno::Any
& aElement
)
147 throw(css::lang::IllegalArgumentException
,
148 css::container::ElementExistException
,
149 css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
151 virtual void SAL_CALL
remove(const css::uno::Any
& aElement
)
152 throw(css::lang::IllegalArgumentException
,
153 css::container::NoSuchElementException
,
154 css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
156 // css.container.XEnumerationAccess
157 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
createEnumeration()
158 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
160 // css.container.XElementAccess
161 virtual css::uno::Type SAL_CALL
getElementType()
162 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
164 virtual sal_Bool SAL_CALL
hasElements()
165 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
167 // css.lang.XEventListener
168 virtual void SAL_CALL
disposing(const css::lang::EventObject
& aEvent
)
169 throw(css::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
174 void implts_notifyJobExecution(const css::document::EventObject
& aEvent
);
175 void implts_checkAndExecuteEventBindings(const css::document::DocumentEvent
& aEvent
);
176 void implts_notifyListener(const css::document::DocumentEvent
& aEvent
);
179 TModelList::iterator
impl_searchDoc(const css::uno::Reference
< css::frame::XModel
>& xModel
);
182 ModelCollectionEnumeration::ModelCollectionEnumeration()
183 : ModelCollectionMutexBase( )
184 , m_pEnumerationIt (m_lModels
.begin())
188 ModelCollectionEnumeration::~ModelCollectionEnumeration()
192 void ModelCollectionEnumeration::setModelList(const TModelList
& rList
)
195 ::osl::ResettableMutexGuard
aLock(m_aLock
);
197 m_pEnumerationIt
= m_lModels
.begin();
202 sal_Bool SAL_CALL
ModelCollectionEnumeration::hasMoreElements()
203 throw(uno::RuntimeException
, std::exception
)
206 ::osl::ResettableMutexGuard
aLock(m_aLock
);
207 return (m_pEnumerationIt
!= m_lModels
.end());
211 uno::Any SAL_CALL
ModelCollectionEnumeration::nextElement()
212 throw(container::NoSuchElementException
,
213 lang::WrappedTargetException
,
214 uno::RuntimeException
, std::exception
)
217 ::osl::ResettableMutexGuard
aLock(m_aLock
);
218 if (m_pEnumerationIt
== m_lModels
.end())
219 throw container::NoSuchElementException(
220 OUString("End of model enumeration reached."),
221 static_cast< container::XEnumeration
* >(this));
222 uno::Reference
< frame::XModel
> xModel(*m_pEnumerationIt
, uno::UNO_QUERY
);
227 return uno::makeAny(xModel
);
231 SfxGlobalEvents_Impl::SfxGlobalEvents_Impl( const uno::Reference
< uno::XComponentContext
>& rxContext
)
232 : ModelCollectionMutexBase( )
233 , m_xJobExecutorListener( task::theJobExecutor::get( rxContext
), uno::UNO_QUERY_THROW
)
234 , m_aLegacyListeners (m_aLock
)
235 , m_aDocumentListeners (m_aLock
)
240 pImp
= new GlobalEventConfig();
246 SfxGlobalEvents_Impl::~SfxGlobalEvents_Impl()
251 uno::Reference
< container::XNameReplace
> SAL_CALL
SfxGlobalEvents_Impl::getEvents()
252 throw(uno::RuntimeException
, std::exception
)
255 ::osl::ResettableMutexGuard
aLock(m_aLock
);
261 void SAL_CALL
SfxGlobalEvents_Impl::addEventListener(const uno::Reference
< document::XEventListener
>& xListener
)
262 throw(uno::RuntimeException
, std::exception
)
264 // container is threadsafe
265 m_aLegacyListeners
.addInterface(xListener
);
269 void SAL_CALL
SfxGlobalEvents_Impl::removeEventListener(const uno::Reference
< document::XEventListener
>& xListener
)
270 throw(uno::RuntimeException
, std::exception
)
272 // container is threadsafe
273 m_aLegacyListeners
.removeInterface(xListener
);
277 void SAL_CALL
SfxGlobalEvents_Impl::addDocumentEventListener( const uno::Reference
< document::XDocumentEventListener
>& _Listener
)
278 throw(uno::RuntimeException
, std::exception
)
280 m_aDocumentListeners
.addInterface( _Listener
);
284 void SAL_CALL
SfxGlobalEvents_Impl::removeDocumentEventListener( const uno::Reference
< document::XDocumentEventListener
>& _Listener
)
285 throw(uno::RuntimeException
, std::exception
)
287 m_aDocumentListeners
.removeInterface( _Listener
);
291 void SAL_CALL
SfxGlobalEvents_Impl::notifyDocumentEvent( const OUString
& /*_EventName*/,
292 const uno::Reference
< frame::XController2
>& /*_ViewController*/, const uno::Any
& /*_Supplement*/ )
293 throw (lang::IllegalArgumentException
, lang::NoSupportException
, uno::RuntimeException
, std::exception
)
295 // we're a multiplexer only, no chance to generate artificial events here
296 throw lang::NoSupportException(OUString(), *this);
300 void SAL_CALL
SfxGlobalEvents_Impl::notifyEvent(const document::EventObject
& aEvent
)
301 throw(uno::RuntimeException
, std::exception
)
303 document::DocumentEvent
aDocEvent(aEvent
.Source
, aEvent
.EventName
, NULL
, uno::Any());
304 implts_notifyJobExecution(aEvent
);
305 implts_checkAndExecuteEventBindings(aDocEvent
);
306 implts_notifyListener(aDocEvent
);
310 void SAL_CALL
SfxGlobalEvents_Impl::documentEventOccured( const document::DocumentEvent
& _Event
)
311 throw (uno::RuntimeException
, std::exception
)
313 implts_notifyJobExecution(document::EventObject(_Event
.Source
, _Event
.EventName
));
314 implts_checkAndExecuteEventBindings(_Event
);
315 implts_notifyListener(_Event
);
319 void SAL_CALL
SfxGlobalEvents_Impl::disposing(const lang::EventObject
& aEvent
)
320 throw(uno::RuntimeException
, std::exception
)
322 uno::Reference
< frame::XModel
> xDoc(aEvent
.Source
, uno::UNO_QUERY
);
325 ::osl::ResettableMutexGuard
aLock(m_aLock
);
326 TModelList::iterator pIt
= impl_searchDoc(xDoc
);
327 if (pIt
!= m_lModels
.end())
328 m_lModels
.erase(pIt
);
334 sal_Bool SAL_CALL
SfxGlobalEvents_Impl::has(const uno::Any
& aElement
)
335 throw (uno::RuntimeException
, std::exception
)
337 uno::Reference
< frame::XModel
> xDoc
;
343 ::osl::ResettableMutexGuard
aLock(m_aLock
);
344 TModelList::iterator pIt
= impl_searchDoc(xDoc
);
345 if (pIt
!= m_lModels
.end())
354 void SAL_CALL
SfxGlobalEvents_Impl::insert( const uno::Any
& aElement
)
355 throw (lang::IllegalArgumentException
,
356 container::ElementExistException
,
357 uno::RuntimeException
, std::exception
)
359 uno::Reference
< frame::XModel
> xDoc
;
362 throw lang::IllegalArgumentException(
363 OUString("Can not locate at least the model parameter."),
364 static_cast< container::XSet
* >(this),
368 ::osl::ResettableMutexGuard
aLock(m_aLock
);
369 TModelList::iterator pIt
= impl_searchDoc(xDoc
);
370 if (pIt
!= m_lModels
.end())
371 throw container::ElementExistException(
373 static_cast< container::XSet
* >(this));
374 m_lModels
.push_back(xDoc
);
378 uno::Reference
< document::XDocumentEventBroadcaster
> xDocBroadcaster(xDoc
, uno::UNO_QUERY
);
379 if (xDocBroadcaster
.is())
380 xDocBroadcaster
->addDocumentEventListener(this);
383 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster
384 uno::Reference
< document::XEventBroadcaster
> xBroadcaster(xDoc
, uno::UNO_QUERY
);
385 if (xBroadcaster
.is())
386 xBroadcaster
->addEventListener(static_cast< document::XEventListener
* >(this));
391 void SAL_CALL
SfxGlobalEvents_Impl::remove( const uno::Any
& aElement
)
392 throw (lang::IllegalArgumentException
,
393 container::NoSuchElementException
,
394 uno::RuntimeException
, std::exception
)
396 uno::Reference
< frame::XModel
> xDoc
;
399 throw lang::IllegalArgumentException(
400 OUString("Can not locate at least the model parameter."),
401 static_cast< container::XSet
* >(this),
405 ::osl::ResettableMutexGuard
aLock(m_aLock
);
406 TModelList::iterator pIt
= impl_searchDoc(xDoc
);
407 if (pIt
== m_lModels
.end())
408 throw container::NoSuchElementException(
410 static_cast< container::XSet
* >(this));
411 m_lModels
.erase(pIt
);
415 uno::Reference
< document::XDocumentEventBroadcaster
> xDocBroadcaster(xDoc
, uno::UNO_QUERY
);
416 if (xDocBroadcaster
.is())
417 xDocBroadcaster
->removeDocumentEventListener(this);
420 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster
421 uno::Reference
< document::XEventBroadcaster
> xBroadcaster(xDoc
, uno::UNO_QUERY
);
422 if (xBroadcaster
.is())
423 xBroadcaster
->removeEventListener(static_cast< document::XEventListener
* >(this));
428 uno::Reference
< container::XEnumeration
> SAL_CALL
SfxGlobalEvents_Impl::createEnumeration()
429 throw (uno::RuntimeException
, std::exception
)
432 ::osl::ResettableMutexGuard
aLock(m_aLock
);
433 ModelCollectionEnumeration
* pEnum
= new ModelCollectionEnumeration();
434 pEnum
->setModelList(m_lModels
);
435 uno::Reference
< container::XEnumeration
> xEnum(
436 static_cast< container::XEnumeration
* >(pEnum
),
445 uno::Type SAL_CALL
SfxGlobalEvents_Impl::getElementType()
446 throw (uno::RuntimeException
, std::exception
)
448 return cppu::UnoType
<frame::XModel
>::get();
452 sal_Bool SAL_CALL
SfxGlobalEvents_Impl::hasElements()
453 throw (uno::RuntimeException
, std::exception
)
456 ::osl::ResettableMutexGuard
aLock(m_aLock
);
457 return (m_lModels
.size()>0);
462 void SfxGlobalEvents_Impl::implts_notifyJobExecution(const document::EventObject
& aEvent
)
466 m_xJobExecutorListener
->notifyEvent(aEvent
);
468 catch(const uno::RuntimeException
&)
470 catch(const uno::Exception
&)
475 void SfxGlobalEvents_Impl::implts_checkAndExecuteEventBindings(const document::DocumentEvent
& aEvent
)
480 ::osl::ResettableMutexGuard
aLock(m_aLock
);
481 uno::Reference
< container::XNameReplace
> xEvents
= m_xEvents
;
486 if ( xEvents
.is() && xEvents
->hasByName( aEvent
.EventName
) )
487 aAny
= xEvents
->getByName(aEvent
.EventName
);
488 SfxEvents_Impl::Execute(aAny
, aEvent
, 0);
490 catch ( uno::RuntimeException
const & )
494 catch ( uno::Exception
const & )
496 DBG_UNHANDLED_EXCEPTION();
501 void SfxGlobalEvents_Impl::implts_notifyListener(const document::DocumentEvent
& aEvent
)
503 // containers are threadsafe
504 document::EventObject
aLegacyEvent(aEvent
.Source
, aEvent
.EventName
);
505 m_aLegacyListeners
.notifyEach( &document::XEventListener::notifyEvent
, aLegacyEvent
);
507 m_aDocumentListeners
.notifyEach( &document::XDocumentEventListener::documentEventOccured
, aEvent
);
511 // not threadsafe ... must be locked from outside!
512 TModelList::iterator
SfxGlobalEvents_Impl::impl_searchDoc(const uno::Reference
< frame::XModel
>& xModel
)
515 return m_lModels
.end();
517 TModelList::iterator pIt
;
518 for ( pIt
= m_lModels
.begin();
519 pIt
!= m_lModels
.end() ;
522 uno::Reference
< frame::XModel
> xContainerDoc(*pIt
, uno::UNO_QUERY
);
523 if (xContainerDoc
== xModel
)
532 css::uno::Reference
<css::uno::XComponentContext
> const & context
):
534 static_cast<cppu::OWeakObject
*>(new SfxGlobalEvents_Impl(context
)))
537 rtl::Reference
<css::uno::XInterface
> instance
;
541 public rtl::StaticWithArg
<
542 Instance
, css::uno::Reference
<css::uno::XComponentContext
>, Singleton
>
547 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
* SAL_CALL
548 com_sun_star_comp_sfx2_GlobalEventBroadcaster_get_implementation(
549 css::uno::XComponentContext
*context
,
550 css::uno::Sequence
<css::uno::Any
> const &)
552 return cppu::acquire(static_cast<cppu::OWeakObject
*>(
553 Singleton::get(context
).instance
.get()));
556 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */