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"
21 using ::rtl::OUString
;
23 #define A2S(s) ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
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
),
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());
64 // Unregister from the focus object.
65 Reference
<lang::XComponent
> xComponent (iContainer
->first
, UNO_QUERY
);
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
;
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),
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
);
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 (
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());
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());
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
);
245 xComponent
->addEventListener(this);
247 // Create a new listener container for the event focus.
248 iDescriptor
= maListeners
.insert(
249 ListenerMap::value_type(
251 FocusDescriptor())).first
;
253 if (iDescriptor
!= maListeners
.end())
254 return &iDescriptor
->second
;
262 // XSingleComponentFactory
264 cssu::Reference
<cssu::XInterface
> SAL_CALL
ContextChangeEventMultiplexer::createInstanceWithContext (
265 const cssu::Reference
<cssu::XComponentContext
>& rxContext
)
266 throw (cssu::Exception
, cssu::RuntimeException
)
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
)
282 return cssu::Reference
<cssu::XInterface
>();
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());
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
);
383 } // end of namespace framework