Branch libreoffice-5-0-4
[LibreOffice.git] / sfx2 / source / notify / globalevents.cxx
blob25d15144cdf46b51fac1857cca518f6ef1bea288
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
45 #include <vector>
47 using namespace css;
49 namespace {
51 struct ModelCollectionMutexBase
53 public:
54 osl::Mutex m_aLock;
57 typedef ::std::vector< css::uno::Reference< css::frame::XModel > > TModelList;
59 class ModelCollectionEnumeration : public ModelCollectionMutexBase
60 , public ::cppu::WeakImplHelper1< css::container::XEnumeration >
62 private:
63 TModelList m_lModels;
64 TModelList::iterator m_pEnumerationIt;
66 public:
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;
93 TModelList m_lModels;
94 GlobalEventConfig* pImp;
96 public:
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";
117 return aSeq;
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;
171 private:
173 // threadsafe
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);
178 // not threadsafe
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)
194 // SAFE ->
195 ::osl::ResettableMutexGuard aLock(m_aLock);
196 m_lModels = rList;
197 m_pEnumerationIt = m_lModels.begin();
198 aLock.clear();
199 // <- SAFE
202 sal_Bool SAL_CALL ModelCollectionEnumeration::hasMoreElements()
203 throw(uno::RuntimeException, std::exception)
205 // SAFE ->
206 ::osl::ResettableMutexGuard aLock(m_aLock);
207 return (m_pEnumerationIt != m_lModels.end());
208 // <- SAFE
211 uno::Any SAL_CALL ModelCollectionEnumeration::nextElement()
212 throw(container::NoSuchElementException,
213 lang::WrappedTargetException ,
214 uno::RuntimeException, std::exception )
216 // SAFE ->
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);
223 ++m_pEnumerationIt;
224 aLock.clear();
225 // <- SAFE
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)
236 , pImp (0 )
238 m_refCount++;
239 SfxGetpApp();
240 pImp = new GlobalEventConfig();
241 m_xEvents = pImp;
242 m_refCount--;
246 SfxGlobalEvents_Impl::~SfxGlobalEvents_Impl()
251 uno::Reference< container::XNameReplace > SAL_CALL SfxGlobalEvents_Impl::getEvents()
252 throw(uno::RuntimeException, std::exception)
254 // SAFE ->
255 ::osl::ResettableMutexGuard aLock(m_aLock);
256 return m_xEvents;
257 // <- SAFE
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);
324 // SAFE ->
325 ::osl::ResettableMutexGuard aLock(m_aLock);
326 TModelList::iterator pIt = impl_searchDoc(xDoc);
327 if (pIt != m_lModels.end())
328 m_lModels.erase(pIt);
329 aLock.clear();
330 // <- SAFE
334 sal_Bool SAL_CALL SfxGlobalEvents_Impl::has(const uno::Any& aElement)
335 throw (uno::RuntimeException, std::exception)
337 uno::Reference< frame::XModel > xDoc;
338 aElement >>= xDoc;
340 bool bHas = false;
342 // SAFE ->
343 ::osl::ResettableMutexGuard aLock(m_aLock);
344 TModelList::iterator pIt = impl_searchDoc(xDoc);
345 if (pIt != m_lModels.end())
346 bHas = true;
347 aLock.clear();
348 // <- SAFE
350 return bHas;
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;
360 aElement >>= xDoc;
361 if (!xDoc.is())
362 throw lang::IllegalArgumentException(
363 OUString("Can not locate at least the model parameter."),
364 static_cast< container::XSet* >(this),
367 // SAFE ->
368 ::osl::ResettableMutexGuard aLock(m_aLock);
369 TModelList::iterator pIt = impl_searchDoc(xDoc);
370 if (pIt != m_lModels.end())
371 throw container::ElementExistException(
372 OUString(),
373 static_cast< container::XSet* >(this));
374 m_lModels.push_back(xDoc);
375 aLock.clear();
376 // <- SAFE
378 uno::Reference< document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, uno::UNO_QUERY );
379 if (xDocBroadcaster.is())
380 xDocBroadcaster->addDocumentEventListener(this);
381 else
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;
397 aElement >>= xDoc;
398 if (!xDoc.is())
399 throw lang::IllegalArgumentException(
400 OUString("Can not locate at least the model parameter."),
401 static_cast< container::XSet* >(this),
404 // SAFE ->
405 ::osl::ResettableMutexGuard aLock(m_aLock);
406 TModelList::iterator pIt = impl_searchDoc(xDoc);
407 if (pIt == m_lModels.end())
408 throw container::NoSuchElementException(
409 OUString(),
410 static_cast< container::XSet* >(this));
411 m_lModels.erase(pIt);
412 aLock.clear();
413 // <- SAFE
415 uno::Reference< document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, uno::UNO_QUERY );
416 if (xDocBroadcaster.is())
417 xDocBroadcaster->removeDocumentEventListener(this);
418 else
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)
431 // SAFE ->
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),
437 uno::UNO_QUERY);
438 aLock.clear();
439 // <- SAFE
441 return xEnum;
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)
455 // SAFE ->
456 ::osl::ResettableMutexGuard aLock(m_aLock);
457 return (m_lModels.size()>0);
458 // <- SAFE
462 void SfxGlobalEvents_Impl::implts_notifyJobExecution(const document::EventObject& aEvent)
466 m_xJobExecutorListener->notifyEvent(aEvent);
468 catch(const uno::RuntimeException&)
469 { throw; }
470 catch(const uno::Exception&)
475 void SfxGlobalEvents_Impl::implts_checkAndExecuteEventBindings(const document::DocumentEvent& aEvent)
479 // SAFE ->
480 ::osl::ResettableMutexGuard aLock(m_aLock);
481 uno::Reference< container::XNameReplace > xEvents = m_xEvents;
482 aLock.clear();
483 // <- SAFE
485 uno::Any aAny;
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 & )
492 throw;
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)
514 if (!xModel.is())
515 return m_lModels.end();
517 TModelList::iterator pIt;
518 for ( pIt = m_lModels.begin();
519 pIt != m_lModels.end() ;
520 ++pIt )
522 uno::Reference< frame::XModel > xContainerDoc(*pIt, uno::UNO_QUERY);
523 if (xContainerDoc == xModel)
524 break;
527 return pIt;
530 struct Instance {
531 explicit Instance(
532 css::uno::Reference<css::uno::XComponentContext> const & context):
533 instance(
534 static_cast<cppu::OWeakObject *>(new SfxGlobalEvents_Impl(context)))
537 rtl::Reference<css::uno::XInterface> instance;
540 struct Singleton:
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: */