21#include <com/sun/star/lang/IllegalArgumentException.hpp>
22#include <com/sun/star/lang/XComponent.hpp>
23#include <com/sun/star/lang/XEventListener.hpp>
24#include <com/sun/star/lang/XServiceInfo.hpp>
25#include <com/sun/star/ui/XContextChangeEventMultiplexer.hpp>
26#include <com/sun/star/ui/ContextChangeEventMultiplexer.hpp>
27#include <com/sun/star/uno/XComponentContext.hpp>
32#include <osl/diagnose.h>
39using namespace css::uno;
44 css::ui::XContextChangeEventMultiplexer,
45 css::lang::XServiceInfo,
46 css::lang::XEventListener
47 > ContextChangeEventMultiplexerInterfaceBase;
49class ContextChangeEventMultiplexer
50 :
public ContextChangeEventMultiplexerInterfaceBase
53 ContextChangeEventMultiplexer();
54 ContextChangeEventMultiplexer(
const ContextChangeEventMultiplexer&) =
delete;
55 ContextChangeEventMultiplexer& operator=(
const ContextChangeEventMultiplexer&) =
delete;
57 virtual void disposing(std::unique_lock<std::mutex>&)
override;
60 virtual void SAL_CALL addContextChangeEventListener (
61 const css::uno::Reference<css::ui::XContextChangeEventListener>& rxListener,
62 const css::uno::Reference<css::uno::XInterface>& rxEventFocus)
override;
63 virtual void SAL_CALL removeContextChangeEventListener (
64 const css::uno::Reference<css::ui::XContextChangeEventListener>& rxListener,
65 const css::uno::Reference<css::uno::XInterface>& rxEventFocus)
override;
66 virtual void SAL_CALL removeAllContextChangeEventListeners (
67 const css::uno::Reference<css::ui::XContextChangeEventListener>& rxListener)
override;
68 virtual void SAL_CALL broadcastContextChangeEvent (
69 const css::ui::ContextChangeEventObject& rContextChangeEventObject,
70 const css::uno::Reference<css::uno::XInterface>& rxEventFocus)
override;
75 const OUString& rsServiceName)
override;
79 virtual void SAL_CALL disposing (
80 const css::lang::EventObject& rEvent)
override;
82 typedef ::std::vector<css::uno::Reference<css::ui::XContextChangeEventListener> > ListenerContainer;
86 ListenerContainer maListeners;
87 OUString msCurrentApplicationName;
88 OUString msCurrentContextName;
90 typedef ::std::map<css::uno::Reference<css::uno::XInterface>, FocusDescriptor>
ListenerMap;
99 void BroadcastEventToSingleContainer (
100 const css::ui::ContextChangeEventObject& rEventObject,
101 const css::uno::Reference<css::uno::XInterface>& rxEventFocus);
102 FocusDescriptor* GetFocusDescriptor (
103 const css::uno::Reference<css::uno::XInterface>& rxEventFocus,
104 const bool bCreateWhenMissing);
107ContextChangeEventMultiplexer::ContextChangeEventMultiplexer()
111void ContextChangeEventMultiplexer::disposing(std::unique_lock<std::mutex>& rGuard)
118 css::uno::Reference<css::uno::XInterface> xThis (
static_cast<XWeak*
>(
this));
119 css::lang::EventObject
aEvent (xThis);
120 for (
auto const& container : aListeners)
123 Reference<lang::XComponent> xComponent (container.first, UNO_QUERY);
125 xComponent->removeEventListener(
this);
128 const FocusDescriptor& rFocusDescriptor (container.second);
129 for (
auto const& listener : rFocusDescriptor.maListeners)
131 listener->disposing(aEvent);
137void SAL_CALL ContextChangeEventMultiplexer::addContextChangeEventListener (
138 const css::uno::Reference<css::ui::XContextChangeEventListener>& rxListener,
139 const css::uno::Reference<css::uno::XInterface>& rxEventFocus)
141 if ( ! rxListener.is())
142 throw css::lang::IllegalArgumentException(
143 "can not add an empty reference",
144 static_cast<XWeak*
>(
this),
147 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus,
true);
148 if (pFocusDescriptor !=
nullptr)
150 ListenerContainer& rContainer (pFocusDescriptor->maListeners);
151 if (::std::find(rContainer.begin(), rContainer.end(), rxListener) != rContainer.end())
155 throw css::lang::IllegalArgumentException(
"listener added twice",
static_cast<XWeak*
>(
this), 0);
157 rContainer.push_back(rxListener);
162 if (!(rxEventFocus.is() && pFocusDescriptor!=
nullptr))
165 css::ui::ContextChangeEventObject
aEvent (
167 pFocusDescriptor->msCurrentApplicationName,
168 pFocusDescriptor->msCurrentContextName);
169 rxListener->notifyContextChangeEvent(aEvent);
172void SAL_CALL ContextChangeEventMultiplexer::removeContextChangeEventListener (
173 const css::uno::Reference<css::ui::XContextChangeEventListener>& rxListener,
174 const css::uno::Reference<css::uno::XInterface>& rxEventFocus)
176 if ( ! rxListener.is())
177 throw css::lang::IllegalArgumentException(
178 "can not remove an empty reference",
179 static_cast<XWeak*
>(
this), 0);
181 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus,
false);
182 if (pFocusDescriptor ==
nullptr)
185 ListenerContainer& rContainer (pFocusDescriptor->maListeners);
186 const ListenerContainer::iterator iListener (
187 ::std::find(rContainer.begin(), rContainer.end(), rxListener));
188 if (iListener != rContainer.end())
190 rContainer.erase(iListener);
198void SAL_CALL ContextChangeEventMultiplexer::removeAllContextChangeEventListeners (
199 const css::uno::Reference<css::ui::XContextChangeEventListener>& rxListener)
201 if ( ! rxListener.is())
202 throw css::lang::IllegalArgumentException(
203 "can not remove an empty reference",
204 static_cast<XWeak*
>(
this), 0);
206 for (
auto& rContainer : maListeners)
208 const ListenerContainer::iterator iListener (
209 ::std::find(rContainer.second.maListeners.begin(), rContainer.second.maListeners.end(), rxListener));
210 if (iListener != rContainer.second.maListeners.end())
212 rContainer.second.maListeners.erase(iListener);
220void SAL_CALL ContextChangeEventMultiplexer::broadcastContextChangeEvent (
221 const css::ui::ContextChangeEventObject& rEventObject,
222 const css::uno::Reference<css::uno::XInterface>& rxEventFocus)
225 if (rxEventFocus.is())
227 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus,
true);
228 if (pFocusDescriptor !=
nullptr)
230 pFocusDescriptor->msCurrentApplicationName = rEventObject.ApplicationName;
231 pFocusDescriptor->msCurrentContextName = rEventObject.ContextName;
235 BroadcastEventToSingleContainer(rEventObject, rxEventFocus);
236 if (rxEventFocus.is())
237 BroadcastEventToSingleContainer(rEventObject,
nullptr);
240void ContextChangeEventMultiplexer::BroadcastEventToSingleContainer (
241 const css::ui::ContextChangeEventObject& rEventObject,
242 const css::uno::Reference<css::uno::XInterface>& rxEventFocus)
244 FocusDescriptor* pFocusDescriptor = GetFocusDescriptor(rxEventFocus,
false);
245 if (pFocusDescriptor !=
nullptr)
249 ListenerContainer aContainer (pFocusDescriptor->maListeners);
250 for (
auto const& listener : aContainer)
252 listener->notifyContextChangeEvent(rEventObject);
257ContextChangeEventMultiplexer::FocusDescriptor* ContextChangeEventMultiplexer::GetFocusDescriptor (
258 const css::uno::Reference<css::uno::XInterface>& rxEventFocus,
259 const bool bCreateWhenMissing)
261 ListenerMap::iterator iDescriptor (maListeners.find(rxEventFocus));
262 if (iDescriptor == maListeners.end() && bCreateWhenMissing)
265 Reference<lang::XComponent> xComponent (rxEventFocus, UNO_QUERY);
267 xComponent->addEventListener(
this);
270 iDescriptor = maListeners.emplace(
272 FocusDescriptor()).first;
274 if (iDescriptor != maListeners.end())
275 return &iDescriptor->second;
280OUString SAL_CALL ContextChangeEventMultiplexer::getImplementationName()
282 return "org.apache.openoffice.comp.framework.ContextChangeEventMultiplexer";
285sal_Bool SAL_CALL ContextChangeEventMultiplexer::supportsService (
const OUString& rsServiceName)
290css::uno::Sequence<OUString> SAL_CALL ContextChangeEventMultiplexer::getSupportedServiceNames()
293 return css::uno::Sequence<OUString>();
296void SAL_CALL ContextChangeEventMultiplexer::disposing (
const css::lang::EventObject& rEvent)
298 ListenerMap::iterator iDescriptor (maListeners.find(rEvent.Source));
300 if (iDescriptor == maListeners.end())
302 OSL_ASSERT(iDescriptor != maListeners.end());
308 maListeners.erase(iDescriptor);
317 css::uno::Reference<css::uno::XComponentContext>
const & xComponentContext,
318 uno::Reference<uno::XInterface>
const& xEventFocus,
319 std::function<
bool (uno::Reference<ui::XContextChangeEventListener>
const&)>
const& rPredicate)
321 assert(xEventFocus.is());
322 uno::Reference<ui::XContextChangeEventListener> xRet;
326 dynamic_cast<ContextChangeEventMultiplexer *
>(ui::ContextChangeEventMultiplexer::get(xComponentContext).get());
327 assert(pMultiplexer);
329 ContextChangeEventMultiplexer::FocusDescriptor
const*
const pFocusDescriptor(
330 pMultiplexer->GetFocusDescriptor(xEventFocus,
false));
331 if (!pFocusDescriptor)
334 for (
auto & xListener : pFocusDescriptor->maListeners)
336 if (rPredicate(xListener))
359extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
361 css::uno::XComponentContext *,
362 css::uno::Sequence<css::uno::Any>
const &)
364 return cppu::acquire(
new ContextChangeEventMultiplexer());
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * org_apache_openoffice_comp_framework_ContextChangeEventMultiplexer_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
std::multimap< xmlNodePtr, css::uno::Reference< css::xml::dom::events::XEventListener > > ListenerMap
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
auto(* g_pGetMultiplexerListener)(css::uno::Reference< css::uno::XComponentContext > const &xComponentContext, uno::Reference< uno::XInterface > const &, std::function< bool(uno::Reference< ui::XContextChangeEventListener > const &)> const &) -> uno::Reference< ui::XContextChangeEventListener >=nullptr
static uno::Reference< ui::XContextChangeEventListener > GetFirstListenerWith_ImplImpl(css::uno::Reference< css::uno::XComponentContext > const &xComponentContext, uno::Reference< uno::XInterface > const &xEventFocus, std::function< bool(uno::Reference< ui::XContextChangeEventListener > const &)> const &rPredicate)