diff options
author | Mike Kaganski <mike.kaganski@collabora.com> | 2024-11-09 16:31:55 +0500 |
---|---|---|
committer | Mike Kaganski <mike.kaganski@collabora.com> | 2024-11-09 19:33:03 +0100 |
commit | ce310aa33ad2c13776298b3b0ec282c098262aa9 (patch) | |
tree | 7bdc1c5e718a4772d7c428de90ad99fecf3b1f68 /UnoControls/inc/multiplexer.hxx | |
parent | d0ea15aacebf4cad09dee90725dc06f5dde43ade (diff) |
Use OInterfaceContainerHelper4 per listener class for type safety
Change-Id: I919fef7e981d2dbdd69eb3cce34b3236dd6ed7ad
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176309
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'UnoControls/inc/multiplexer.hxx')
-rw-r--r-- | UnoControls/inc/multiplexer.hxx | 131 |
1 files changed, 94 insertions, 37 deletions
diff --git a/UnoControls/inc/multiplexer.hxx b/UnoControls/inc/multiplexer.hxx index 095e316797e8..c321a4644b69 100644 --- a/UnoControls/inc/multiplexer.hxx +++ b/UnoControls/inc/multiplexer.hxx @@ -22,29 +22,100 @@ #include <com/sun/star/awt/XKeyListener.hpp> #include <com/sun/star/awt/XPaintListener.hpp> #include <com/sun/star/awt/XMouseMotionListener.hpp> +#include <com/sun/star/awt/XWindow.hpp> #include <com/sun/star/awt/XWindowListener.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> #include <com/sun/star/awt/XTopWindowListener.hpp> #include <com/sun/star/awt/XMouseListener.hpp> #include <com/sun/star/awt/XFocusListener.hpp> #include <comphelper/compbase.hxx> +#include <comphelper/interfacecontainer4.hxx> #include <cppuhelper/weakref.hxx> -#include <comphelper/multiinterfacecontainer4.hxx> -namespace com::sun::star::awt { class XWindow; } -namespace com::sun::star::awt { struct KeyEvent; } -namespace com::sun::star::awt { struct MouseEvent; } -namespace com::sun::star::awt { struct PaintEvent; } -namespace com::sun::star::awt { struct WindowEvent; } +#include <type_traits> namespace unocontrols { -class OMRCListenerMultiplexerHelper final : public comphelper::WeakImplHelper< css::awt::XFocusListener - , css::awt::XWindowListener - , css::awt::XKeyListener - , css::awt::XMouseListener - , css::awt::XMouseMotionListener - , css::awt::XPaintListener - , css::awt::XTopWindowListener > +template <class Listener> extern int Add; // dummy +template <class Listener> extern int Remove; // dummy + +template <> constexpr inline auto Add<css::awt::XFocusListener> = &css::awt::XWindow::addFocusListener; +template <> constexpr inline auto Remove<css::awt::XFocusListener> = &css::awt::XWindow::removeFocusListener; + +template <> constexpr inline auto Add<css::awt::XWindowListener> = &css::awt::XWindow::addWindowListener; +template <> constexpr inline auto Remove<css::awt::XWindowListener> = &css::awt::XWindow::removeWindowListener; + +template <> constexpr inline auto Add<css::awt::XKeyListener> = &css::awt::XWindow::addKeyListener; +template <> constexpr inline auto Remove<css::awt::XKeyListener> = &css::awt::XWindow::removeKeyListener; + +template <> constexpr inline auto Add<css::awt::XMouseListener> = &css::awt::XWindow::addMouseListener; +template <> constexpr inline auto Remove<css::awt::XMouseListener> = &css::awt::XWindow::removeMouseListener; + +template <> constexpr inline auto Add<css::awt::XMouseMotionListener> = &css::awt::XWindow::addMouseMotionListener; +template <> constexpr inline auto Remove<css::awt::XMouseMotionListener> = &css::awt::XWindow::removeMouseMotionListener; + +template <> constexpr inline auto Add<css::awt::XPaintListener> = &css::awt::XWindow::addPaintListener; +template <> constexpr inline auto Remove<css::awt::XPaintListener> = &css::awt::XWindow::removePaintListener; + +template <> constexpr inline auto Add<css::awt::XTopWindowListener> = &css::awt::XTopWindow::addTopWindowListener; +template <> constexpr inline auto Remove<css::awt::XTopWindowListener> = &css::awt::XTopWindow::removeTopWindowListener; + +template <class Ifc> class Listeners +{ +protected: + comphelper::OInterfaceContainerHelper4<Ifc> list; +}; + +template <class... Ifc> +class ContainersHolder : public comphelper::WeakImplHelper<Ifc...>, public Listeners<Ifc>... +{ +protected: + template <typename F> void for_each_container(F f) { (..., f(Listeners<Ifc>::list)); } + + template <class WinIfc, class Ifc1> + void notifyPeer(const css::uno::Reference<css::awt::XWindow>& peer, + void (SAL_CALL WinIfc::*func)(const css::uno::Reference<Ifc1>&)) + { + if constexpr (std::is_same_v<WinIfc, css::awt::XWindow>) + { + if (peer) + (peer.get()->*func)(this); + } + else if (auto cast_peer = peer.query<WinIfc>()) + (cast_peer.get()->*func)(this); + } + + template <class Ifc1> + void add(std::unique_lock<std::mutex>& guard, const css::uno::Reference<Ifc1>& listener, + const css::uno::Reference<css::awt::XWindow>& peer) + { + assert(listener); + if (Listeners<Ifc1>::list.addInterface(guard, listener) == 1) + { + // the first listener is added + notifyPeer(peer, Add<Ifc1>); + } + } + + template <class Ifc1> + void remove(std::unique_lock<std::mutex>& guard, const css::uno::Reference<Ifc1>& listener, + const css::uno::Reference<css::awt::XWindow>& peer) + { + if (Listeners<Ifc1>::list.removeInterface(guard, listener) == 0) + { + // the last listener is removed + notifyPeer(peer, Remove<Ifc1>); + } + } +}; + +class OMRCListenerMultiplexerHelper final : public ContainersHolder< css::awt::XFocusListener + , css::awt::XWindowListener + , css::awt::XKeyListener + , css::awt::XMouseListener + , css::awt::XMouseMotionListener + , css::awt::XPaintListener + , css::awt::XTopWindowListener > { public: @@ -81,15 +152,21 @@ public: @short Add the specified listener to the source. */ - void advise( const css::uno::Type& aType , - const css::uno::Reference< css::lang::XEventListener >& xListener ); + template <class Interface> void advise(const css::uno::Reference<Interface>& xListener) + { + std::unique_lock aGuard(m_aMutex); + add(aGuard, xListener, m_xPeer); + } /** @short Remove the specified listener from the source. */ - void unadvise( const css::uno::Type& aType , - const css::uno::Reference< css::lang::XEventListener >& xListener ); + template <class Interface> void unadvise(const css::uno::Reference<Interface>& xListener) + { + std::unique_lock aGuard(m_aMutex); + remove(aGuard, xListener, m_xPeer); + } // XEventListener @@ -154,25 +231,6 @@ public: virtual void SAL_CALL windowDeactivated( const css::lang::EventObject& aEvent ) override; private: - - /** - @short Remove the listener from the peer. - @param xPeer The peer from which the listener is removed. - @param rType The listener type, which specify the type of the listener. - */ - - void impl_adviseToPeer( const css::uno::Reference< css::awt::XWindow >& xPeer , - const css::uno::Type& aType ); - - /** - @short Add the listener to the peer. - @param xPeer The peer to which the listener is added. - @param rType The listener type, which specify the type of the listener. - */ - - void impl_unadviseFromPeer( const css::uno::Reference< css::awt::XWindow >& xPeer , - const css::uno::Type& aType ); - template <class Interface, typename Event> void Multiplex(void (SAL_CALL Interface::*method)(const Event&), const Event& event); @@ -181,7 +239,6 @@ private: private: css::uno::Reference< css::awt::XWindow > m_xPeer; /// The source of the events. Normally this is the peer object. css::uno::WeakReference< css::awt::XWindow > m_xControl; - comphelper::OMultiTypeInterfaceContainerHelperVar4<css::uno::Type, css::lang::XEventListener> m_aListenerHolder; }; } |