Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 : #include "services/ContextChangeEventMultiplexer.hxx"
20 : #include "services.h"
21 :
22 : using ::rtl::OUString;
23 :
24 : #define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
25 :
26 : using namespace css;
27 : using namespace cssu;
28 :
29 : namespace framework {
30 :
31 : #define IMPLEMENTATION_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexer"
32 : #define SERVICE_NAME "com.sun.star.ui.ContextChangeEventMultiplexer"
33 : #define SINGLETON_NAME "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexerSigleton"
34 :
35 :
36 56 : ContextChangeEventMultiplexer::ContextChangeEventMultiplexer (
37 : const cssu::Reference<cssu::XComponentContext>& rxContext)
38 : : ContextChangeEventMultiplexerInterfaceBase(m_aMutex),
39 56 : maListeners()
40 : {
41 : (void)rxContext;
42 56 : }
43 :
44 :
45 :
46 :
47 112 : ContextChangeEventMultiplexer::~ContextChangeEventMultiplexer (void)
48 : {
49 112 : }
50 :
51 :
52 :
53 :
54 56 : void SAL_CALL ContextChangeEventMultiplexer::disposing (void)
55 : {
56 56 : ListenerMap aListeners;
57 56 : aListeners.swap(maListeners);
58 :
59 112 : cssu::Reference<cssu::XInterface> xThis (static_cast<XWeak*>(this));
60 112 : css::lang::EventObject aEvent (xThis);
61 58 : for (ListenerMap::const_iterator iContainer(aListeners.begin()), iEnd(aListeners.end());
62 : iContainer!=iEnd;
63 : ++iContainer)
64 : {
65 : // Unregister from the focus object.
66 2 : Reference<lang::XComponent> xComponent (iContainer->first, UNO_QUERY);
67 2 : if (xComponent.is())
68 2 : xComponent->removeEventListener(this);
69 :
70 : // Tell all listeners that we are being disposed.
71 2 : const FocusDescriptor& rFocusDescriptor (iContainer->second);
72 2 : for (ListenerContainer::const_iterator
73 2 : iListener(rFocusDescriptor.maListeners.begin()),
74 2 : iContainerEnd(rFocusDescriptor.maListeners.end());
75 : iListener!=iContainerEnd;
76 : ++iListener)
77 : {
78 0 : (*iListener)->disposing(aEvent);
79 : }
80 58 : }
81 56 : }
82 :
83 :
84 :
85 :
86 : // XContextChangeEventMultiplexer
87 :
88 0 : void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener (
89 : const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
90 : const cssu::Reference<cssu::XInterface>& rxEventFocus)
91 : throw(cssu::RuntimeException,cssl::IllegalArgumentException)
92 : {
93 0 : if ( ! rxListener.is())
94 : throw css::lang::IllegalArgumentException(
95 0 : A2S("can not add an empty reference"),
96 : static_cast<XWeak*>(this),
97 0 : 0);
98 :
99 0 : FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, true);
100 0 : if (pFocusDescriptor != NULL)
101 : {
102 0 : ListenerContainer& rContainer (pFocusDescriptor->maListeners);
103 0 : if (::std::find(rContainer.begin(), rContainer.end(), rxListener) == rContainer.end())
104 0 : rContainer.push_back(rxListener);
105 : else
106 : {
107 : // The listener was added for the same event focus
108 : // previously. That is an error.
109 0 : throw cssl::IllegalArgumentException(A2S("listener added twice"), static_cast<XWeak*>(this), 0);
110 : }
111 : }
112 :
113 : // Send out an initial event that informs the new listener about
114 : // the current context.
115 0 : if (rxEventFocus.is() && pFocusDescriptor!=NULL)
116 : {
117 : css::ui::ContextChangeEventObject aEvent (
118 : NULL,
119 : pFocusDescriptor->msCurrentApplicationName,
120 0 : pFocusDescriptor->msCurrentContextName);
121 0 : rxListener->notifyContextChangeEvent(aEvent);
122 : }
123 0 : }
124 :
125 :
126 :
127 :
128 0 : void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener (
129 : const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener,
130 : const cssu::Reference<cssu::XInterface>& rxEventFocus)
131 : throw(cssu::RuntimeException,cssl::IllegalArgumentException)
132 : {
133 0 : if ( ! rxListener.is())
134 : throw cssl::IllegalArgumentException(
135 0 : A2S("can not remove an empty reference"),
136 0 : static_cast<XWeak*>(this), 0);
137 :
138 0 : FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, false);
139 0 : if (pFocusDescriptor != NULL)
140 : {
141 0 : ListenerContainer& rContainer (pFocusDescriptor->maListeners);
142 : const ListenerContainer::iterator iListener (
143 0 : ::std::find(rContainer.begin(), rContainer.end(), rxListener));
144 0 : if (iListener != rContainer.end())
145 : {
146 0 : rContainer.erase(iListener);
147 :
148 : // We hold on to the focus descriptor even when the last listener has been removed.
149 : // This allows us to keep track of the current context and send it to new listeners.
150 : }
151 : }
152 :
153 0 : }
154 :
155 :
156 :
157 :
158 0 : void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners (
159 : const cssu::Reference<css::ui::XContextChangeEventListener>& rxListener)
160 : throw(cssu::RuntimeException,cssl::IllegalArgumentException)
161 : {
162 0 : if ( ! rxListener.is())
163 : throw cssl::IllegalArgumentException(
164 0 : A2S("can not remove an empty reference"),
165 0 : static_cast<XWeak*>(this), 0);
166 :
167 0 : for (ListenerMap::iterator
168 0 : iContainer(maListeners.begin()),
169 0 : iEnd(maListeners.end());
170 : iContainer!=iEnd;
171 : ++iContainer)
172 : {
173 : const ListenerContainer::iterator iListener (
174 0 : ::std::find(iContainer->second.maListeners.begin(), iContainer->second.maListeners.end(), rxListener));
175 0 : if (iListener != iContainer->second.maListeners.end())
176 : {
177 0 : iContainer->second.maListeners.erase(iListener);
178 :
179 : // We hold on to the focus descriptor even when the last listener has been removed.
180 : // This allows us to keep track of the current context and send it to new listeners.
181 : }
182 : }
183 0 : }
184 :
185 :
186 :
187 :
188 1510 : void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent (
189 : const css::ui::ContextChangeEventObject& rEventObject,
190 : const cssu::Reference<cssu::XInterface>& rxEventFocus)
191 : throw(cssu::RuntimeException)
192 : {
193 : // Remember the current context.
194 1510 : if (rxEventFocus.is())
195 : {
196 1510 : FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, true);
197 1510 : if (pFocusDescriptor != NULL)
198 : {
199 1510 : pFocusDescriptor->msCurrentApplicationName = rEventObject.ApplicationName;
200 1510 : pFocusDescriptor->msCurrentContextName = rEventObject.ContextName;
201 : }
202 : }
203 :
204 1510 : BroadcastEventToSingleContainer(rEventObject, rxEventFocus);
205 1510 : if (rxEventFocus.is())
206 1510 : BroadcastEventToSingleContainer(rEventObject, NULL);
207 1510 : }
208 :
209 :
210 :
211 :
212 3020 : void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer (
213 : const css::ui::ContextChangeEventObject& rEventObject,
214 : const cssu::Reference<cssu::XInterface>& rxEventFocus)
215 : {
216 3020 : FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus, false);
217 3020 : if (pFocusDescriptor != NULL)
218 : {
219 : // Create a copy of the listener container to avoid problems
220 : // when one of the called listeners calls add... or remove...
221 1510 : ListenerContainer aContainer (pFocusDescriptor->maListeners);
222 1510 : for (ListenerContainer::const_iterator
223 1510 : iListener(aContainer.begin()),
224 1510 : iEnd(aContainer.end());
225 : iListener!=iEnd;
226 : ++iListener)
227 : {
228 0 : (*iListener)->notifyContextChangeEvent(rEventObject);
229 1510 : }
230 : }
231 3020 : }
232 :
233 :
234 :
235 :
236 4530 : ContextChangeEventMultiplexer::FocusDescriptor* ContextChangeEventMultiplexer::GetFocusDescriptor (
237 : const cssu::Reference<cssu::XInterface>& rxEventFocus,
238 : const bool bCreateWhenMissing)
239 : {
240 4530 : ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
241 4530 : if (iDescriptor == maListeners.end() && bCreateWhenMissing)
242 : {
243 : // Listen for the focus being disposed.
244 1045 : Reference<lang::XComponent> xComponent (rxEventFocus, UNO_QUERY);
245 1045 : if (xComponent.is())
246 1045 : xComponent->addEventListener(this);
247 :
248 : // Create a new listener container for the event focus.
249 : iDescriptor = maListeners.insert(
250 : ListenerMap::value_type(
251 : rxEventFocus,
252 1045 : FocusDescriptor())).first;
253 : }
254 4530 : if (iDescriptor != maListeners.end())
255 3020 : return &iDescriptor->second;
256 : else
257 1510 : return NULL;
258 : }
259 :
260 :
261 :
262 :
263 : // XSingleComponentFactory
264 :
265 0 : cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::createInstanceWithContext (
266 : const cssu::Reference<cssu::XComponentContext>& rxContext)
267 : throw (cssu::Exception, cssu::RuntimeException)
268 : {
269 : (void)rxContext;
270 0 : return cssu::Reference<cssu::XInterface>();
271 : }
272 :
273 :
274 :
275 :
276 0 : cssu::Reference<cssu::XInterface > SAL_CALL ContextChangeEventMultiplexer::createInstanceWithArgumentsAndContext (
277 : const cssu::Sequence<cssu::Any>& rArguments,
278 : const cssu::Reference<cssu::XComponentContext>& rxContext)
279 : throw (cssu::Exception, cssu::RuntimeException)
280 : {
281 : (void)rArguments;
282 : (void)rxContext;
283 0 : return cssu::Reference<cssu::XInterface>();
284 : }
285 :
286 :
287 :
288 :
289 : // XServiceInfo
290 :
291 0 : ::rtl::OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName (void)
292 : throw(cssu::RuntimeException)
293 : {
294 0 : return impl_getStaticImplementationName();
295 : }
296 :
297 :
298 :
299 :
300 :
301 0 : sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService (
302 : const ::rtl::OUString& rsServiceName)
303 : throw (cssu::RuntimeException)
304 : {
305 0 : return ::comphelper::findValue(static_GetSupportedServiceNames(), rsServiceName, sal_True).getLength() != 0;
306 : }
307 :
308 :
309 :
310 :
311 0 : cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames (void)
312 : throw (cssu::RuntimeException)
313 : {
314 0 : return static_GetSupportedServiceNames();
315 : }
316 :
317 :
318 :
319 :
320 1043 : void SAL_CALL ContextChangeEventMultiplexer::disposing (
321 : const css::lang::EventObject& rEvent)
322 : throw (cssu::RuntimeException)
323 : {
324 1043 : ListenerMap::iterator iDescriptor (maListeners.find(rEvent.Source));
325 :
326 1043 : if (iDescriptor == maListeners.end())
327 : {
328 : OSL_ASSERT(iDescriptor != maListeners.end());
329 1043 : return;
330 : }
331 :
332 : // Should we notify the remaining listeners?
333 :
334 1043 : maListeners.erase(iDescriptor);
335 : }
336 :
337 :
338 :
339 :
340 : // Local and static methods.
341 :
342 152 : OUString SAL_CALL ContextChangeEventMultiplexer::impl_getStaticImplementationName (void)
343 : {
344 152 : return A2S(IMPLEMENTATION_NAME);
345 : }
346 :
347 :
348 :
349 :
350 56 : cssu::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::static_GetSupportedServiceNames (void)
351 : {
352 56 : cssu::Sequence<OUString> aServiceNames (2);
353 56 : aServiceNames[0] = A2S(SERVICE_NAME);
354 56 : aServiceNames[1] = A2S(SINGLETON_NAME);
355 56 : return aServiceNames;
356 : }
357 :
358 :
359 :
360 :
361 56 : cssu::Reference<cssu::XInterface> ContextChangeEventMultiplexer::impl_createFactory (
362 : const cssu::Reference<cssl::XMultiServiceFactory>& rxServiceManager)
363 : {
364 : (void)rxServiceManager;
365 : return cppu::createSingleComponentFactory(
366 : ContextChangeEventMultiplexer::static_CreateInstance,
367 : ContextChangeEventMultiplexer::impl_getStaticImplementationName(),
368 : ContextChangeEventMultiplexer::static_GetSupportedServiceNames()
369 56 : );
370 : }
371 :
372 :
373 :
374 :
375 56 : cssu::Reference<cssu::XInterface> SAL_CALL ContextChangeEventMultiplexer::static_CreateInstance (
376 : const cssu::Reference<cssu::XComponentContext>& rxComponentContext)
377 : throw (cssu::Exception)
378 : {
379 56 : ContextChangeEventMultiplexer* pObject = new ContextChangeEventMultiplexer(rxComponentContext);
380 56 : cssu::Reference<cssu::XInterface> xService (static_cast<XWeak*>(pObject), cssu::UNO_QUERY);
381 56 : return xService;
382 : }
383 :
384 : } // end of namespace framework
385 :
386 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|