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