tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sd / source / ui / tools / EventMultiplexer.cxx
blob20f3b6e5e518a14e5939717cb39e4f16803cc114
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <EventMultiplexer.hxx>
22 #include <ViewShellBase.hxx>
23 #include <drawdoc.hxx>
24 #include <DrawController.hxx>
25 #include <SlideSorterViewShell.hxx>
26 #include <framework/FrameworkHelper.hxx>
27 #include <framework/ConfigurationController.hxx>
28 #include <sal/log.hxx>
29 #include <tools/debug.hxx>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/frame/XFrame.hpp>
33 #include <com/sun/star/lang/DisposedException.hpp>
34 #include <com/sun/star/drawing/framework/XConfigurationChangeListener.hpp>
35 #include <com/sun/star/drawing/framework/XView.hpp>
36 #include <comphelper/compbase.hxx>
37 #include <sfx2/viewfrm.hxx>
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star::drawing::framework;
44 using ::sd::framework::FrameworkHelper;
46 class SdDrawDocument;
48 namespace {
49 const sal_Int32 ResourceActivationEvent = 0;
50 const sal_Int32 ResourceDeactivationEvent = 1;
51 const sal_Int32 ConfigurationUpdateEvent = 2;
54 namespace sd::tools {
56 typedef comphelper::WeakComponentImplHelper<
57 css::beans::XPropertyChangeListener,
58 css::frame::XFrameActionListener,
59 css::view::XSelectionChangeListener,
60 css::drawing::framework::XConfigurationChangeListener
61 > EventMultiplexerImplementationInterfaceBase;
63 class EventMultiplexer::Implementation
64 : public EventMultiplexerImplementationInterfaceBase,
65 public SfxListener
67 public:
68 explicit Implementation (ViewShellBase& rBase);
69 virtual ~Implementation() override;
71 void AddEventListener (
72 const Link<EventMultiplexerEvent&,void>& rCallback);
74 void RemoveEventListener (
75 const Link<EventMultiplexerEvent&,void>& rCallback);
77 void CallListeners (EventMultiplexerEvent& rEvent);
79 //===== lang::XEventListener ==============================================
80 virtual void SAL_CALL
81 disposing (const css::lang::EventObject& rEventObject) override;
83 //===== beans::XPropertySetListener =======================================
84 virtual void SAL_CALL
85 propertyChange (
86 const css::beans::PropertyChangeEvent& rEvent) override;
88 //===== view::XSelectionChangeListener ====================================
89 virtual void SAL_CALL
90 selectionChanged (
91 const css::lang::EventObject& rEvent) override;
93 //===== frame::XFrameActionListener ======================================
94 /** For certain actions the listener connects to a new controller of the
95 frame it is listening to. This usually happens when the view shell
96 in the center pane is replaced by another view shell.
98 virtual void SAL_CALL
99 frameAction (const css::frame::FrameActionEvent& rEvent) override;
101 //===== drawing::framework::XConfigurationChangeListener ==================
102 virtual void SAL_CALL
103 notifyConfigurationChange (
104 const css::drawing::framework::ConfigurationChangeEvent& rEvent) override;
106 virtual void disposing(std::unique_lock<std::mutex>&) override;
108 protected:
109 virtual void Notify (
110 SfxBroadcaster& rBroadcaster,
111 const SfxHint& rHint) override;
113 private:
114 ViewShellBase& mrBase;
115 typedef ::std::vector<Link<EventMultiplexerEvent&,void>> ListenerList;
116 ListenerList maListeners;
118 /// Remember whether we are listening to the UNO controller.
119 bool mbListeningToController;
120 /// Remember whether we are listening to the frame.
121 bool mbListeningToFrame;
123 css::uno::WeakReference<css::frame::XController> mxControllerWeak;
124 css::uno::WeakReference<css::frame::XFrame> mxFrameWeak;
125 SdDrawDocument* mpDocument;
126 unotools::WeakReference<sd::framework::ConfigurationController>
127 mxConfigurationControllerWeak;
129 void ReleaseListeners();
131 void ConnectToController();
132 void DisconnectFromController();
134 void CallListeners (
135 EventMultiplexerEventId eId,
136 void const * pUserData = nullptr,
137 const css::uno::Reference<css::uno::XInterface>& xUserData = {});
139 DECL_LINK(SlideSorterSelectionChangeListener, LinkParamNone*, void);
142 constexpr OUString aCurrentPagePropertyName = u"CurrentPage"_ustr;
143 constexpr OUString aEditModePropertyName = u"IsMasterPageMode"_ustr;
145 //===== EventMultiplexer ======================================================
147 EventMultiplexer::EventMultiplexer (ViewShellBase& rBase)
148 : mpImpl (new EventMultiplexer::Implementation(rBase))
152 EventMultiplexer::~EventMultiplexer()
156 mpImpl->dispose();
158 catch (const RuntimeException&)
161 catch (const Exception&)
166 void EventMultiplexer::AddEventListener (
167 const Link<EventMultiplexerEvent&,void>& rCallback)
169 mpImpl->AddEventListener(rCallback);
172 void EventMultiplexer::RemoveEventListener (
173 const Link<EventMultiplexerEvent&,void>& rCallback)
175 mpImpl->RemoveEventListener(rCallback);
178 void EventMultiplexer::MultiplexEvent(EventMultiplexerEventId eEventId, void const* pUserData,
179 const css::uno::Reference<css::uno::XInterface>& xUserData)
181 EventMultiplexerEvent aEvent(eEventId, pUserData, xUserData);
182 mpImpl->CallListeners(aEvent);
185 //===== EventMultiplexer::Implementation ======================================
187 EventMultiplexer::Implementation::Implementation (ViewShellBase& rBase)
188 : mrBase (rBase),
189 mbListeningToController (false),
190 mbListeningToFrame (false),
191 mxControllerWeak(nullptr),
192 mxFrameWeak(nullptr),
193 mpDocument(nullptr)
195 // Connect to the frame to listen for controllers being exchanged.
196 // Listen to changes of certain properties.
197 Reference<frame::XFrame> xFrame;
198 if (SfxViewFrame* pFrame = mrBase.GetFrame())
199 xFrame = pFrame->GetFrame().GetFrameInterface();
200 mxFrameWeak = xFrame;
201 if (xFrame.is())
203 xFrame->addFrameActionListener ( Reference<frame::XFrameActionListener>(this) );
204 mbListeningToFrame = true;
207 // Connect to the current controller.
208 ConnectToController ();
210 // Listen for document changes.
211 mpDocument = mrBase.GetDocument();
212 if (mpDocument != nullptr)
213 StartListening (*mpDocument);
215 // Listen for configuration changes.
216 DrawController& rDrawController = *mrBase.GetDrawController();
218 rtl::Reference<sd::framework::ConfigurationController> xConfigurationController (
219 rDrawController.getConfigurationControllerImpl());
220 mxConfigurationControllerWeak = xConfigurationController.get();
221 if (!xConfigurationController.is())
222 return;
224 xConfigurationController->addEventListener(static_cast<beans::XPropertyChangeListener*>(this));
226 xConfigurationController->addConfigurationChangeListener(
227 this,
228 FrameworkHelper::msResourceActivationEvent,
229 Any(ResourceActivationEvent));
230 xConfigurationController->addConfigurationChangeListener(
231 this,
232 FrameworkHelper::msResourceDeactivationEvent,
233 Any(ResourceDeactivationEvent));
234 xConfigurationController->addConfigurationChangeListener(
235 this,
236 FrameworkHelper::msConfigurationUpdateEndEvent,
237 Any(ConfigurationUpdateEvent));
240 EventMultiplexer::Implementation::~Implementation()
242 DBG_ASSERT( !mbListeningToFrame,
243 "sd::EventMultiplexer::Implementation::~Implementation(), disposing was not called!" );
246 void EventMultiplexer::Implementation::ReleaseListeners()
248 if (mbListeningToFrame)
250 mbListeningToFrame = false;
252 // Stop listening for changes of certain properties.
253 Reference<frame::XFrame> xFrame (mxFrameWeak);
254 if (xFrame.is())
256 xFrame->removeFrameActionListener (
257 Reference<frame::XFrameActionListener>(this) );
261 DisconnectFromController ();
263 if (mpDocument != nullptr)
265 EndListening (*mpDocument);
266 mpDocument = nullptr;
269 // Stop listening for configuration changes.
270 rtl::Reference<sd::framework::ConfigurationController> xConfigurationController (mxConfigurationControllerWeak.get());
271 if (xConfigurationController.is())
273 xConfigurationController->removeEventListener(static_cast<beans::XPropertyChangeListener*>(this));
274 xConfigurationController->removeConfigurationChangeListener(this);
278 void EventMultiplexer::Implementation::AddEventListener (
279 const Link<EventMultiplexerEvent&,void>& rCallback)
281 for (auto const & i : maListeners)
282 if (i == rCallback)
283 return;
284 maListeners.push_back(rCallback);
287 void EventMultiplexer::Implementation::RemoveEventListener (
288 const Link<EventMultiplexerEvent&,void>& rCallback)
290 auto iListener = std::find(maListeners.begin(), maListeners.end(), rCallback);
291 if (iListener != maListeners.end())
292 maListeners.erase(iListener);
295 void EventMultiplexer::Implementation::ConnectToController()
297 // Just in case that we missed some event we now disconnect from the old
298 // controller.
299 DisconnectFromController ();
301 // Register at the controller of the main view shell.
303 // We have to store a (weak) reference to the controller so that we can
304 // unregister without having to ask the mrBase member (which at that
305 // time may be destroyed.)
306 Reference<frame::XController> xController = mrBase.GetController();
307 mxControllerWeak = mrBase.GetController();
311 // Listen for disposing events.
312 if (xController.is())
314 xController->addEventListener (
315 Reference<lang::XEventListener>(
316 static_cast<XWeak*>(this), UNO_QUERY));
317 mbListeningToController = true;
320 // Listen to changes of certain properties.
321 Reference<beans::XPropertySet> xSet (xController, UNO_QUERY);
322 if (xSet.is())
326 xSet->addPropertyChangeListener(aCurrentPagePropertyName, this);
328 catch (const beans::UnknownPropertyException&)
330 SAL_WARN("sd", "EventMultiplexer::ConnectToController: CurrentPage unknown");
335 xSet->addPropertyChangeListener(aEditModePropertyName, this);
337 catch (const beans::UnknownPropertyException&)
339 SAL_WARN("sd", "EventMultiplexer::ConnectToController: IsMasterPageMode unknown");
343 // Listen for selection change events.
344 Reference<view::XSelectionSupplier> xSelection (xController, UNO_QUERY);
345 if (xSelection.is())
347 xSelection->addSelectionChangeListener(this);
350 catch (const lang::DisposedException&)
352 mbListeningToController = false;
356 void EventMultiplexer::Implementation::DisconnectFromController()
358 if (!mbListeningToController)
359 return;
361 mbListeningToController = false;
363 Reference<frame::XController> xController = mxControllerWeak;
365 Reference<beans::XPropertySet> xSet (xController, UNO_QUERY);
366 // Remove the property listener.
367 if (xSet.is())
371 xSet->removePropertyChangeListener(aCurrentPagePropertyName, this);
373 catch (const beans::UnknownPropertyException&)
375 SAL_WARN("sd", "DisconnectFromController: CurrentPage unknown");
380 xSet->removePropertyChangeListener(aEditModePropertyName, this);
382 catch (const beans::UnknownPropertyException&)
384 SAL_WARN("sd", "DisconnectFromController: IsMasterPageMode unknown");
388 // Remove selection change listener.
389 Reference<view::XSelectionSupplier> xSelection (xController, UNO_QUERY);
390 if (xSelection.is())
392 xSelection->removeSelectionChangeListener(this);
395 // Remove listener for disposing events.
396 if (xController.is())
398 xController->removeEventListener (
399 Reference<lang::XEventListener>(static_cast<XWeak*>(this), UNO_QUERY));
403 //===== lang::XEventListener ================================================
405 void SAL_CALL EventMultiplexer::Implementation::disposing (
406 const lang::EventObject& rEventObject)
408 if (mbListeningToController)
410 Reference<frame::XController> xController (mxControllerWeak);
411 if (rEventObject.Source == xController)
413 mbListeningToController = false;
417 rtl::Reference<sd::framework::ConfigurationController> xConfigurationController (
418 mxConfigurationControllerWeak);
419 if (xConfigurationController.is()
420 && rEventObject.Source == cppu::getXWeak(xConfigurationController.get()))
422 mxConfigurationControllerWeak.clear();
426 //===== beans::XPropertySetListener =========================================
428 void SAL_CALL EventMultiplexer::Implementation::propertyChange (
429 const beans::PropertyChangeEvent& rEvent)
431 if (m_bDisposed)
433 throw lang::DisposedException (
434 u"SlideSorterController object has already been disposed"_ustr,
435 static_cast<uno::XWeak*>(this));
438 if ( rEvent.PropertyName == aCurrentPagePropertyName )
440 CallListeners(EventMultiplexerEventId::CurrentPageChanged);
442 else if ( rEvent.PropertyName == aEditModePropertyName )
444 bool bIsMasterPageMode (false);
445 rEvent.NewValue >>= bIsMasterPageMode;
446 if (bIsMasterPageMode)
447 CallListeners(EventMultiplexerEventId::EditModeMaster);
448 else
449 CallListeners(EventMultiplexerEventId::EditModeNormal);
453 //===== frame::XFrameActionListener ==========================================
455 void SAL_CALL EventMultiplexer::Implementation::frameAction (
456 const frame::FrameActionEvent& rEvent)
458 Reference<frame::XFrame> xFrame (mxFrameWeak);
459 if (rEvent.Frame != xFrame)
460 return;
462 switch (rEvent.Action)
464 case frame::FrameAction_COMPONENT_DETACHING:
465 DisconnectFromController();
466 CallListeners (EventMultiplexerEventId::ControllerDetached);
467 break;
469 case frame::FrameAction_COMPONENT_REATTACHED:
470 CallListeners (EventMultiplexerEventId::ControllerDetached);
471 DisconnectFromController();
472 ConnectToController();
473 CallListeners (EventMultiplexerEventId::ControllerAttached);
474 break;
476 case frame::FrameAction_COMPONENT_ATTACHED:
477 ConnectToController();
478 CallListeners (EventMultiplexerEventId::ControllerAttached);
479 break;
481 default:
482 break;
486 //===== view::XSelectionChangeListener ========================================
488 void SAL_CALL EventMultiplexer::Implementation::selectionChanged (
489 const lang::EventObject& )
491 CallListeners (EventMultiplexerEventId::EditViewSelection);
494 //===== drawing::framework::XConfigurationChangeListener ==================
496 void SAL_CALL EventMultiplexer::Implementation::notifyConfigurationChange (
497 const ConfigurationChangeEvent& rEvent)
499 sal_Int32 nEventType = 0;
500 rEvent.UserData >>= nEventType;
501 switch (nEventType)
503 case ResourceActivationEvent:
504 if (rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix))
506 CallListeners (EventMultiplexerEventId::ViewAdded);
508 if (rEvent.ResourceId->isBoundToURL(
509 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
511 CallListeners (EventMultiplexerEventId::MainViewAdded);
514 // Add selection change listener at slide sorter.
515 if (rEvent.ResourceId->getResourceURL() == FrameworkHelper::msSlideSorterURL)
517 slidesorter::SlideSorterViewShell* pViewShell
518 = dynamic_cast<slidesorter::SlideSorterViewShell*>(
519 FrameworkHelper::GetViewShell(
520 Reference<XView>(rEvent.ResourceObject,UNO_QUERY)).get());
521 if (pViewShell != nullptr)
522 pViewShell->AddSelectionChangeListener (
523 LINK(this,
524 EventMultiplexer::Implementation,
525 SlideSorterSelectionChangeListener));
528 break;
530 case ResourceDeactivationEvent:
531 if (rEvent.ResourceId->getResourceURL().match(FrameworkHelper::msViewURLPrefix))
533 if (rEvent.ResourceId->isBoundToURL(
534 FrameworkHelper::msCenterPaneURL, AnchorBindingMode_DIRECT))
536 CallListeners (EventMultiplexerEventId::MainViewRemoved);
539 // Remove selection change listener from slide sorter. Add
540 // selection change listener at slide sorter.
541 if (rEvent.ResourceId->getResourceURL() == FrameworkHelper::msSlideSorterURL)
543 slidesorter::SlideSorterViewShell* pViewShell
544 = dynamic_cast<slidesorter::SlideSorterViewShell*>(
545 FrameworkHelper::GetViewShell(
546 Reference<XView>(rEvent.ResourceObject, UNO_QUERY)).get());
547 if (pViewShell != nullptr)
548 pViewShell->RemoveSelectionChangeListener (
549 LINK(this,
550 EventMultiplexer::Implementation,
551 SlideSorterSelectionChangeListener));
554 break;
556 case ConfigurationUpdateEvent:
557 CallListeners (EventMultiplexerEventId::ConfigurationUpdated);
558 break;
563 void EventMultiplexer::Implementation::disposing(std::unique_lock<std::mutex>& rGuard)
565 ListenerList aCopyListeners( maListeners );
567 rGuard.unlock();
569 EventMultiplexerEvent rEvent(EventMultiplexerEventId::Disposing, nullptr);
570 for (const auto& rListener : aCopyListeners)
571 rListener.Call(rEvent);
573 rGuard.lock();
575 ReleaseListeners();
578 void EventMultiplexer::Implementation::Notify (
579 SfxBroadcaster&,
580 const SfxHint& rHint)
582 if (rHint.GetId() == SfxHintId::ThisIsAnSdrHint)
584 const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
585 switch (pSdrHint->GetKind())
587 case SdrHintKind::ModelCleared:
588 case SdrHintKind::PageOrderChange:
589 CallListeners (EventMultiplexerEventId::PageOrder);
590 break;
592 case SdrHintKind::SwitchToPage:
593 CallListeners (EventMultiplexerEventId::CurrentPageChanged);
594 break;
596 case SdrHintKind::ObjectChange:
597 CallListeners(EventMultiplexerEventId::ShapeChanged,
598 static_cast<const void*>(pSdrHint->GetPage()));
599 break;
601 case SdrHintKind::ObjectInserted:
602 CallListeners(EventMultiplexerEventId::ShapeInserted,
603 static_cast<const void*>(pSdrHint->GetPage()));
604 break;
606 case SdrHintKind::ObjectRemoved:
607 CallListeners(EventMultiplexerEventId::ShapeRemoved,
608 static_cast<const void*>(pSdrHint->GetPage()));
609 break;
610 default:
611 break;
614 else
616 if (rHint.GetId() == SfxHintId::Dying)
617 mpDocument = nullptr;
621 void EventMultiplexer::Implementation::CallListeners(
622 EventMultiplexerEventId eId, void const* pUserData,
623 const css::uno::Reference<css::uno::XInterface>& xUserData)
625 EventMultiplexerEvent aEvent(eId, pUserData, xUserData);
626 CallListeners(aEvent);
629 void EventMultiplexer::Implementation::CallListeners (EventMultiplexerEvent& rEvent)
631 ListenerList aCopyListeners( maListeners );
632 for (const auto& rListener : aCopyListeners)
634 rListener.Call(rEvent);
638 IMPL_LINK_NOARG(EventMultiplexer::Implementation, SlideSorterSelectionChangeListener, LinkParamNone*, void)
640 CallListeners(EventMultiplexerEventId::SlideSortedSelection);
643 //===== EventMultiplexerEvent =================================================
645 EventMultiplexerEvent::EventMultiplexerEvent (
646 EventMultiplexerEventId eEventId,
647 const void* pUserData,
648 const css::uno::Reference<css::uno::XInterface>& xUserData)
649 : meEventId(eEventId),
650 mpUserData(pUserData),
651 mxUserData(xUserData)
655 } // end of namespace ::sd::tools
657 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */