update credits
[LibreOffice.git] / framework / source / services / ContextChangeEventMultiplexer.cxx
blobd4f30a40973f5d1a60696938acfc53600370c6d0
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 #include "services/ContextChangeEventMultiplexer.hxx"
19 #include "services.h"
21 using ::rtl::OUString;
23 #define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
25 using namespace css;
26 using namespace cssu;
28 namespace framework {
30 #define IMPLEMENTATION_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexer"
31 #define SERVICE_NAME "com.sun.star.ui.ContextChangeEventMultiplexer"
32 #define SINGLETON_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexerSigleton"
35 ContextChangeEventMultiplexer::ContextChangeEventMultiplexer (
36 const cssu::Reference<cssu::XComponentContext>& rxContext)
37 : ContextChangeEventMultiplexerInterfaceBase(m_aMutex),
38 maListeners()
40 (void)rxContext;
46 ContextChangeEventMultiplexer::~ContextChangeEventMultiplexer (void)
53 void SAL_CALL ContextChangeEventMultiplexer::disposing (void)
55 ListenerMap aListeners;
56 aListeners.swap(maListeners);
58 cssu::Reference<cssu::XInterface> xThis (static_cast<XWeak*>(this));
59 css::lang::EventObject aEvent (xThis);
60 for (ListenerMap::const_iterator iContainer(aListeners.begin()), iEnd(aListeners.end());
61 iContainer!=iEnd;
62 ++iContainer)
64 // Unregister from the focus object.
65 Reference<lang::XComponent> xComponent (iContainer->first, UNO_QUERY);
66 if (xComponent.is())
67 xComponent->removeEventListener(this);
69 // Tell all listeners that we are being disposed.
70 const FocusDescriptor& rFocusDescriptor (iContainer->second);
71 for (ListenerContainer::const_iterator
72 iListener(rFocusDescriptor.maListeners.begin()),
73 iContainerEnd(rFocusDescriptor.maListeners.end());
74 iListener!=iContainerEnd;
75 ++iListener)
77 (*iListener)->disposing(aEvent);
85 // XContextChangeEventMultiplexer
87 void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener (
88 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
89 const cssu::Reference<cssu::XInterface>& rxEventFocus)
90 throw(cssu::RuntimeException,cssl::IllegalArgumentException)
92 if ( ! rxListener.is())
93 throw css::lang::IllegalArgumentException(
94 A2S("can not add an empty reference"),
95 static_cast<XWeak*>(this),
96 0);
98 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, true);
99 if (pFocusDescriptor != NULL)
101 ListenerContainer& rContainer (pFocusDescriptor->maListeners);
102 if (::std::find(rContainer.begin(), rContainer.end(), rxListener) == rContainer.end())
103 rContainer.push_back(rxListener);
104 else
106 // The listener was added for the same event focus
107 // previously. That is an error.
108 throw cssl::IllegalArgumentException(A2S("listener added twice"), static_cast<XWeak*>(this), 0);
112 // Send out an initial event that informs the new listener about
113 // the current context.
114 if (rxEventFocus.is() && pFocusDescriptor!=NULL)
116 css::ui::ContextChangeEventObject aEvent (
117 NULL,
118 pFocusDescriptor->msCurrentApplicationName,
119 pFocusDescriptor->msCurrentContextName);
120 rxListener->notifyContextChangeEvent(aEvent);
127 void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener (
128 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
129 const cssu::Reference<cssu::XInterface>& rxEventFocus)
130 throw(cssu::RuntimeException,cssl::IllegalArgumentException)
132 if ( ! rxListener.is())
133 throw cssl::IllegalArgumentException(
134 A2S("can not remove an empty reference"),
135 static_cast<XWeak*>(this), 0);
137 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, false);
138 if (pFocusDescriptor != NULL)
140 ListenerContainer& rContainer (pFocusDescriptor->maListeners);
141 const ListenerContainer::iterator iListener (
142 ::std::find(rContainer.begin(), rContainer.end(), rxListener));
143 if (iListener != rContainer.end())
145 rContainer.erase(iListener);
147 // We hold on to the focus descriptor even when the last listener has been removed.
148 // This allows us to keep track of the current context and send it to new listeners.
157 void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners (
158 const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener)
159 throw(cssu::RuntimeException,cssl::IllegalArgumentException)
161 if ( ! rxListener.is())
162 throw cssl::IllegalArgumentException(
163 A2S("can not remove an empty reference"),
164 static_cast<XWeak*>(this), 0);
166 for (ListenerMap::iterator
167 iContainer(maListeners.begin()),
168 iEnd(maListeners.end());
169 iContainer!=iEnd;
170 ++iContainer)
172 const ListenerContainer::iterator iListener (
173 ::std::find(iContainer->second.maListeners.begin(), iContainer->second.maListeners.end(), rxListener));
174 if (iListener != iContainer->second.maListeners.end())
176 iContainer->second.maListeners.erase(iListener);
178 // We hold on to the focus descriptor even when the last listener has been removed.
179 // This allows us to keep track of the current context and send it to new listeners.
187 void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent (
188 const css::ui::ContextChangeEventObject& rEventObject,
189 const cssu::Reference<cssu::XInterface>& rxEventFocus)
190 throw(cssu::RuntimeException)
192 // Remember the current context.
193 if (rxEventFocus.is())
195 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, true);
196 if (pFocusDescriptor != NULL)
198 pFocusDescriptor->msCurrentApplicationName = rEventObject.ApplicationName;
199 pFocusDescriptor->msCurrentContextName = rEventObject.ContextName;
203 BroadcastEventToSingleContainer(rEventObject, rxEventFocus);
204 if (rxEventFocus.is())
205 BroadcastEventToSingleContainer(rEventObject, NULL);
211 void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer (
212 const css::ui::ContextChangeEventObject& rEventObject,
213 const cssu::Reference<cssu::XInterface>& rxEventFocus)
215 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, false);
216 if (pFocusDescriptor != NULL)
218 // Create a copy of the listener container to avoid problems
219 // when one of the called listeners calls add... or remove...
220 ListenerContainer aContainer (pFocusDescriptor->maListeners);
221 for (ListenerContainer::const_iterator
222 iListener(aContainer.begin()),
223 iEnd(aContainer.end());
224 iListener!=iEnd;
225 ++iListener)
227 (*iListener)->notifyContextChangeEvent(rEventObject);
235 ContextChangeEventMultiplexer::FocusDescriptor* ContextChangeEventMultiplexer::GetFocusDescriptor (
236 const cssu::Reference<cssu::XInterface>& rxEventFocus,
237 const bool bCreateWhenMissing)
239 ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
240 if (iDescriptor == maListeners.end() && bCreateWhenMissing)
242 // Listen for the focus being disposed.
243 Reference<lang::XComponent> xComponent (rxEventFocus, UNO_QUERY);
244 if (xComponent.is())
245 xComponent->addEventListener(this);
247 // Create a new listener container for the event focus.
248 iDescriptor = maListeners.insert(
249 ListenerMap::value_type(
250 rxEventFocus,
251 FocusDescriptor())).first;
253 if (iDescriptor != maListeners.end())
254 return &iDescriptor->second;
255 else
256 return NULL;
262 // XSingleComponentFactory
264 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::createInstanceWithContext (
265 const cssu::Reference<cssu::XComponentContext>& rxContext)
266 throw (cssu::Exception, cssu::RuntimeException)
268 (void)rxContext;
269 return cssu::Reference<cssu::XInterface>();
275 cssu::Reference<cssu::XInterface > SAL_CALL ContextChangeEventMultiplexer::createInstanceWithArgumentsAndContext (
276 const cssu::Sequence<cssu::Any>& rArguments,
277 const cssu::Reference<cssu::XComponentContext>& rxContext)
278 throw (cssu::Exception, cssu::RuntimeException)
280 (void)rArguments;
281 (void)rxContext;
282 return cssu::Reference<cssu::XInterface>();
288 // XServiceInfo
290 ::rtl::OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName (void)
291 throw(cssu::RuntimeException)
293 return impl_getStaticImplementationName();
300 sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService (
301 const ::rtl::OUString& rsServiceName)
302 throw (cssu::RuntimeException)
304 return ::comphelper::findValue(static_GetSupportedServiceNames(), rsServiceName, sal_True).getLength() != 0;
310 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames (void)
311 throw (cssu::RuntimeException)
313 return static_GetSupportedServiceNames();
319 void SAL_CALL ContextChangeEventMultiplexer::disposing (
320 const css::lang::EventObject& rEvent)
321 throw (cssu::RuntimeException)
323 ListenerMap::iterator iDescriptor (maListeners.find(rEvent.Source));
325 if (iDescriptor == maListeners.end())
327 OSL_ASSERT(iDescriptor != maListeners.end());
328 return;
331 // Should we notify the remaining listeners?
333 maListeners.erase(iDescriptor);
339 // Local and static methods.
341 OUString SAL_CALL ContextChangeEventMultiplexer::impl_getStaticImplementationName (void)
343 return A2S(IMPLEMENTATION_NAME);
349 cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::static_GetSupportedServiceNames (void)
351 cssu::Sequence<OUString> aServiceNames (2);
352 aServiceNames[0] = A2S(SERVICE_NAME);
353 aServiceNames[1] = A2S(SINGLETON_NAME);
354 return aServiceNames;
360 cssu::Reference<cssu::XInterface> ContextChangeEventMultiplexer::impl_createFactory (
361 const cssu::Reference<cssl::XMultiServiceFactory>& rxServiceManager)
363 (void)rxServiceManager;
364 return cppu::createSingleComponentFactory(
365 ContextChangeEventMultiplexer::static_CreateInstance,
366 ContextChangeEventMultiplexer::impl_getStaticImplementationName(),
367 ContextChangeEventMultiplexer::static_GetSupportedServiceNames()
374 cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::static_CreateInstance (
375 const cssu::Reference<cssu::XComponentContext>& rxComponentContext)
376 throw (cssu::Exception)
378 ContextChangeEventMultiplexer* pObject = new ContextChangeEventMultiplexer(rxComponentContext);
379 cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pObject), cssu::UNO_QUERY);
380 return xService;
383 } // end of namespace framework