diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /UnoControls/source/base | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'UnoControls/source/base')
-rw-r--r-- | UnoControls/source/base/basecontainercontrol.cxx | 387 | ||||
-rw-r--r-- | UnoControls/source/base/basecontrol.cxx | 749 | ||||
-rw-r--r-- | UnoControls/source/base/multiplexer.cxx | 441 |
3 files changed, 1577 insertions, 0 deletions
diff --git a/UnoControls/source/base/basecontainercontrol.cxx b/UnoControls/source/base/basecontainercontrol.cxx new file mode 100644 index 000000000..20eea9eb3 --- /dev/null +++ b/UnoControls/source/base/basecontainercontrol.cxx @@ -0,0 +1,387 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <basecontainercontrol.hxx> + +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/typeprovider.hxx> + +#include <com/sun/star/container/ContainerEvent.hpp> +#include <com/sun/star/container/XContainerListener.hpp> +#include <com/sun/star/awt/XControlContainer.hpp> + +// namespaces + +using namespace ::cppu; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::container; + +namespace unocontrols { + +// construct/destruct + +BaseContainerControl::BaseContainerControl( const Reference< XComponentContext >& rxContext ) + : BaseControl ( rxContext ) + , m_aListeners ( m_aMutex ) +{ +} + +BaseContainerControl::~BaseContainerControl() +{ +} + +// XInterface + +Any SAL_CALL BaseContainerControl::queryInterface( const Type& rType ) +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + Any aReturn; + Reference< XInterface > xDel = BaseControl::impl_getDelegator(); + if ( xDel.is() ) + { + // If a delegator exists, forward question to its queryInterface. + // Delegator will ask its own queryAggregation! + aReturn = xDel->queryInterface( rType ); + } + else + { + // If a delegator is unknown, forward question to own queryAggregation. + aReturn = queryAggregation( rType ); + } + + return aReturn; +} + +// XTypeProvider + +Sequence< Type > SAL_CALL BaseContainerControl::getTypes() +{ + static OTypeCollection ourTypeCollection( + cppu::UnoType<XControlModel>::get(), + cppu::UnoType<XControlContainer>::get(), + BaseControl::getTypes() ); + + return ourTypeCollection.getTypes(); +} + +// XAggregation + +Any SAL_CALL BaseContainerControl::queryAggregation( const Type& aType ) +{ + // Ask for my own supported interfaces ... + // Attention: XTypeProvider and XInterface are supported by OComponentHelper! + Any aReturn ( ::cppu::queryInterface( aType , + static_cast< XControlModel* > ( this ) , + static_cast< XControlContainer* > ( this ) + ) + ); + + // If searched interface supported by this class ... + if ( aReturn.hasValue() ) + { + // ... return this information. + return aReturn; + } + else + { + // Else; ... ask baseclass for interfaces! + return BaseControl::queryAggregation( aType ); + } +} + +// XControl + +void SAL_CALL BaseContainerControl::createPeer( const Reference< XToolkit >& xToolkit , + const Reference< XWindowPeer >& xParent ) +{ + if ( getPeer().is() ) + return; + + // create own peer + BaseControl::createPeer( xToolkit, xParent ); + + // create peers at all children + Sequence< Reference< XControl > > seqControlList = getControls(); + + for ( auto& rxControl : asNonConstRange(seqControlList) ) + { + rxControl->createPeer( xToolkit, getPeer() ); + } +} + +// XControl + +sal_Bool SAL_CALL BaseContainerControl::setModel( const Reference< XControlModel >& ) +{ + // This object has NO model. + return false; +} + +// XControl + +Reference< XControlModel > SAL_CALL BaseContainerControl::getModel() +{ + // This object has NO model. + // return (XControlModel*)this; + return Reference< XControlModel >(); +} + +// XComponent + +void SAL_CALL BaseContainerControl::dispose() +{ + // Tell everything that this container is now gone. + // It's faster if you listen to both the control and the container. + + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + // remove listeners + EventObject aObject; + + aObject.Source.set( static_cast<XControlContainer*>(this), UNO_QUERY ); + m_aListeners.disposeAndClear( aObject ); + + // remove controls + const Sequence< Reference< XControl > > seqCtrls = getControls(); + + maControlInfoList.clear(); + + for ( Reference< XControl > const & control : seqCtrls ) + { + control->removeEventListener ( static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) ) ); + control->dispose ( ); + } + + // call baseclass + BaseControl::dispose(); +} + +// XEventListener + +void SAL_CALL BaseContainerControl::disposing( const EventObject& rEvent ) +{ + Reference< XControl > xControl( rEvent.Source, UNO_QUERY ); + + // "removeControl" remove only, when control is an active control + removeControl( xControl ); +} + +// XControlContainer + +void SAL_CALL BaseContainerControl::addControl ( const OUString& rName, const Reference< XControl > & rControl ) +{ + if ( !rControl.is () ) + return; + + // take memory for new item + IMPL_ControlInfo aNewControl; + + // Ready for multithreading + MutexGuard aGuard (m_aMutex); + + // set control + aNewControl.sName = rName; + aNewControl.xControl = rControl; + + // and insert in list + maControlInfoList.emplace_back( aNewControl ); + + // initialize new control + aNewControl.xControl->setContext ( static_cast<OWeakObject*>(this) ); + aNewControl.xControl->addEventListener ( static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) ) ); + + // when container has a peer... + if (getPeer().is()) + { + // ... then create a peer on child + aNewControl.xControl->createPeer ( getPeer()->getToolkit(), getPeer() ); + } + + // Send message to all listener + comphelper::OInterfaceContainerHelper2* pInterfaceContainer = m_aListeners.getContainer( cppu::UnoType<XContainerListener>::get()); + + if (!pInterfaceContainer) + return; + + // Build event + ContainerEvent aEvent; + + aEvent.Source = *this; + aEvent.Element <<= rControl; + + // Get all listener + comphelper::OInterfaceIteratorHelper2 aIterator (*pInterfaceContainer); + + // Send event + while ( aIterator.hasMoreElements() ) + { + static_cast<XContainerListener*>(aIterator.next())->elementInserted (aEvent); + } +} + +// XControlContainer + +void SAL_CALL BaseContainerControl::removeControl ( const Reference< XControl > & rControl ) +{ + if ( !rControl.is() ) + return; + + // Ready for multithreading + MutexGuard aGuard (m_aMutex); + + size_t nControls = maControlInfoList.size(); + + for ( size_t n = 0; n < nControls; n++ ) + { + // Search for right control + IMPL_ControlInfo* pControl = &maControlInfoList[ n ]; + if ( rControl == pControl->xControl ) + { + //.is it found ... remove listener from control + pControl->xControl->removeEventListener (static_cast< XEventListener* >( static_cast< XWindowListener* >( this ) )); + pControl->xControl->setContext ( Reference< XInterface > () ); + + // ... free memory + maControlInfoList.erase(maControlInfoList.begin() + n); + + // Send message to all other listener + comphelper::OInterfaceContainerHelper2 * pInterfaceContainer = m_aListeners.getContainer( cppu::UnoType<XContainerListener>::get()); + + if (pInterfaceContainer) + { + ContainerEvent aEvent; + + aEvent.Source = *this; + aEvent.Element <<= rControl; + + comphelper::OInterfaceIteratorHelper2 aIterator (*pInterfaceContainer); + + while ( aIterator.hasMoreElements() ) + { + static_cast<XContainerListener*>(aIterator.next())->elementRemoved (aEvent); + } + } + // Break "for" ! + break; + } + } +} + +// XControlContainer + +void SAL_CALL BaseContainerControl::setStatusText ( const OUString& rStatusText ) +{ + // go down to each parent + Reference< XControlContainer > xContainer ( getContext(), UNO_QUERY ); + + if ( xContainer.is () ) + { + xContainer->setStatusText ( rStatusText ); + } +} + +// XControlContainer + +Reference< XControl > SAL_CALL BaseContainerControl::getControl ( const OUString& rName ) +{ + // Ready for multithreading + MutexGuard aGuard ( Mutex::getGlobalMutex() ); + + // Search for right control + for( const IMPL_ControlInfo& rSearchControl : maControlInfoList ) + { + if ( rSearchControl.sName == rName ) + { + // We have found it ... + // Break operation and return. + return rSearchControl.xControl; + } + } + + // We have not found it ... return NULL. + return Reference< XControl > (); +} + +// XControlContainer + +Sequence< Reference< XControl > > SAL_CALL BaseContainerControl::getControls () +{ + // Ready for multithreading + MutexGuard aGuard ( Mutex::getGlobalMutex() ); + + size_t nControls = maControlInfoList.size(); + size_t nCount = 0; + Sequence< Reference< XControl > > aDescriptor ( nControls ); + Reference< XControl > * pDestination = aDescriptor.getArray (); + + // Copy controls to sequence + for( const IMPL_ControlInfo& rCopyControl : maControlInfoList ) + { + pDestination [ nCount++ ] = rCopyControl.xControl; + } + + // Return sequence + return aDescriptor; +} + +// XWindow + +void SAL_CALL BaseContainerControl::setVisible ( sal_Bool bVisible ) +{ + // override baseclass definition + BaseControl::setVisible ( bVisible ); + + // is it a top window ? + if ( !getContext().is() && bVisible ) + { + // then show it automatically + createPeer ( Reference< XToolkit > (), Reference< XWindowPeer > () ); + } +} + +// protected method + +WindowDescriptor BaseContainerControl::impl_getWindowDescriptor ( const Reference< XWindowPeer > & rParentPeer ) +{ + WindowDescriptor aDescriptor; + + aDescriptor.Type = WindowClass_CONTAINER; + aDescriptor.WindowServiceName = "window"; + aDescriptor.ParentIndex = -1; + aDescriptor.Parent = rParentPeer; + aDescriptor.Bounds = getPosSize (); + aDescriptor.WindowAttributes = 0; + + return aDescriptor; +} + +// protected method + +void BaseContainerControl::impl_paint ( sal_Int32 /*nX*/, sal_Int32 /*nY*/, const Reference< XGraphics > & /*rGraphics*/ ) +{ +} + +} // namespace unocontrols + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/UnoControls/source/base/basecontrol.cxx b/UnoControls/source/base/basecontrol.cxx new file mode 100644 index 000000000..c2e2f23b1 --- /dev/null +++ b/UnoControls/source/base/basecontrol.cxx @@ -0,0 +1,749 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <basecontrol.hxx> +#include <multiplexer.hxx> + +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/awt/PosSize.hpp> +#include <com/sun/star/awt/Toolkit.hpp> +#include <cppuhelper/supportsservice.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <cppuhelper/typeprovider.hxx> + +// namespaces + +using namespace ::cppu; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::awt; + +namespace unocontrols { + +constexpr sal_Int32 DEFAULT_X = 0; +constexpr sal_Int32 DEFAULT_Y = 0; +constexpr sal_Int32 DEFAULT_WIDTH = 100; +constexpr sal_Int32 DEFAULT_HEIGHT = 100; +constexpr bool DEFAULT_VISIBLE = false; +constexpr bool DEFAULT_INDESIGNMODE = false; +constexpr bool DEFAULT_ENABLE = true; + +// construct/destruct + +BaseControl::BaseControl( const Reference< XComponentContext >& rxContext ) + : OComponentHelper ( m_aMutex ) + , m_xComponentContext ( rxContext ) + , m_nX ( DEFAULT_X ) + , m_nY ( DEFAULT_Y ) + , m_nWidth ( DEFAULT_WIDTH ) + , m_nHeight ( DEFAULT_HEIGHT ) + , m_bVisible ( DEFAULT_VISIBLE ) + , m_bInDesignMode ( DEFAULT_INDESIGNMODE ) + , m_bEnable ( DEFAULT_ENABLE ) +{ +} + +BaseControl::~BaseControl() +{ +} + +// XInterface + +Any SAL_CALL BaseControl::queryInterface( const Type& rType ) +{ + Any aReturn; + if ( m_xDelegator.is() ) + { + // If a delegator exists, forward question to its queryInterface. + // Delegator will ask its own queryAggregation! + aReturn = m_xDelegator->queryInterface( rType ); + } + else + { + // If a delegator is unknown, forward question to own queryAggregation. + aReturn = queryAggregation( rType ); + } + + return aReturn; +} + +// XInterface + +void SAL_CALL BaseControl::acquire() noexcept +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + + // Forward to baseclass + OComponentHelper::acquire(); +} + +// XInterface + +void SAL_CALL BaseControl::release() noexcept +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + + // Forward to baseclass + OComponentHelper::release(); +} + +// XTypeProvider + +Sequence< Type > SAL_CALL BaseControl::getTypes() +{ + static OTypeCollection ourTypeCollection( + cppu::UnoType<XPaintListener>::get(), + cppu::UnoType<XWindowListener>::get(), + cppu::UnoType<XView>::get(), + cppu::UnoType<XWindow>::get(), + cppu::UnoType<XServiceInfo>::get(), + cppu::UnoType<XControl>::get(), + OComponentHelper::getTypes() ); + + return ourTypeCollection.getTypes(); +} + +// XTypeProvider + +Sequence< sal_Int8 > SAL_CALL BaseControl::getImplementationId() +{ + return css::uno::Sequence<sal_Int8>(); +} + +// XAggregation + +void SAL_CALL BaseControl::setDelegator( const Reference< XInterface >& xDel ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + m_xDelegator = xDel; +} + +// XAggregation + +Any SAL_CALL BaseControl::queryAggregation( const Type& aType ) +{ + // Ask for my own supported interfaces ... + // Attention: XTypeProvider and XInterface are supported by OComponentHelper! + Any aReturn ( ::cppu::queryInterface( aType , + static_cast< XPaintListener*> ( this ) , + static_cast< XWindowListener*> ( this ) , + static_cast< XView* > ( this ) , + static_cast< XWindow* > ( this ) , + static_cast< XServiceInfo* > ( this ) , + static_cast< XControl* > ( this ) + ) + ); + + // If searched interface supported by this class ... + if ( aReturn.hasValue() ) + { + // ... return this information. + return aReturn; + } + else + { + // Else; ... ask baseclass for interfaces! + return OComponentHelper::queryAggregation( aType ); + } +} + +// XServiceInfo + +OUString SAL_CALL BaseControl::getImplementationName() +{ + return OUString(); +} + +// XServiceInfo + +sal_Bool SAL_CALL BaseControl::supportsService( const OUString& sServiceName ) +{ + return cppu::supportsService(this, sServiceName); +} + +// XServiceInfo + +Sequence< OUString > SAL_CALL BaseControl::getSupportedServiceNames() +{ + return Sequence< OUString >(); +} + +// XComponent + +void SAL_CALL BaseControl::dispose() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + if ( m_xMultiplexer.is() ) + { + // to all other paint, focus, etc. + m_xMultiplexer->disposeAndClear(); + } + + // set the service manager to disposed + OComponentHelper::dispose(); + + // release context and peer + m_xContext.clear(); + if ( m_xPeer.is() ) + { + if ( m_xGraphicsPeer.is() ) + { + removePaintListener( this ); + removeWindowListener( this ); + m_xGraphicsPeer.clear(); + } + + m_xPeer->dispose(); + m_xPeerWindow.clear(); + m_xPeer.clear(); + + if ( m_xMultiplexer.is() ) + { + // take changes on multiplexer + m_xMultiplexer->setPeer( Reference< XWindow >() ); + } + } + + // release view + if ( m_xGraphicsView.is() ) + { + m_xGraphicsView.clear(); + } +} + +// XComponent + +void SAL_CALL BaseControl::addEventListener( const Reference< XEventListener >& xListener ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + OComponentHelper::addEventListener( xListener ); +} + +// XComponent + +void SAL_CALL BaseControl::removeEventListener( const Reference< XEventListener >& xListener ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + OComponentHelper::removeEventListener( xListener ); +} + +// XControl + +void SAL_CALL BaseControl::createPeer( const Reference< XToolkit >& xToolkit , + const Reference< XWindowPeer >& xParentPeer ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + if ( m_xPeer.is() ) + return; + + // use method "BaseControl::getWindowDescriptor()" to change window attributes! + WindowDescriptor aDescriptor = impl_getWindowDescriptor( xParentPeer ); + + if ( m_bVisible ) + { + aDescriptor.WindowAttributes |= WindowAttribute::SHOW; + } + + // very slow under remote conditions! + // create the window on the server + Reference< XToolkit > xLocalToolkit = xToolkit; + if ( !xLocalToolkit.is() ) + { + // but first create well known toolkit, if it not exist + xLocalToolkit.set( Toolkit::create(m_xComponentContext), UNO_QUERY_THROW ); + } + m_xPeer = xLocalToolkit->createWindow( aDescriptor ); + m_xPeerWindow.set( m_xPeer, UNO_QUERY ); + + if ( !m_xPeerWindow.is() ) + return; + + if ( m_xMultiplexer.is() ) + { + m_xMultiplexer->setPeer( m_xPeerWindow ); + } + + // create new reference to xgraphics for painting on a peer + // and add a paint listener + Reference< XDevice > xDevice( m_xPeerWindow, UNO_QUERY ); + + if ( xDevice.is() ) + { + m_xGraphicsPeer = xDevice->createGraphics(); + } + + if ( m_xGraphicsPeer.is() ) + { + addPaintListener( this ); + addWindowListener( this ); + } + + m_xPeerWindow->setPosSize( m_nX, m_nY, m_nWidth, m_nHeight, PosSize::POSSIZE ); + m_xPeerWindow->setEnable( m_bEnable ); + m_xPeerWindow->setVisible( m_bVisible && !m_bInDesignMode ); +} + +// XControl + +void SAL_CALL BaseControl::setContext( const Reference< XInterface >& xContext ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + m_xContext = xContext; +} + +// XControl + +void SAL_CALL BaseControl::setDesignMode( sal_Bool bOn ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + m_bInDesignMode = bOn; +} + +// XControl + +Reference< XInterface > SAL_CALL BaseControl::getContext() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + return m_xContext; +} + +// XControl + +Reference< XWindowPeer > SAL_CALL BaseControl::getPeer() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + return m_xPeer; +} + +// XControl + +Reference< XView > SAL_CALL BaseControl::getView() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + return this; +} + +// XControl + +sal_Bool SAL_CALL BaseControl::isDesignMode() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + return m_bInDesignMode; +} + +// XControl + +sal_Bool SAL_CALL BaseControl::isTransparent() +{ + return false; +} + +// XWindow + +void SAL_CALL BaseControl::setPosSize( sal_Int32 nX , + sal_Int32 nY , + sal_Int32 nWidth , + sal_Int32 nHeight , + sal_Int16 nFlags ) +{ + // - change size and position of window and save the values + + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + bool bChanged = false; + + if ( nFlags & PosSize::X ) + { + bChanged |= m_nX != nX; + m_nX = nX; + } + + if ( nFlags & PosSize::Y ) + { + bChanged |= m_nY != nY; + m_nY = nY; + } + + if ( nFlags & PosSize::WIDTH ) + { + bChanged |= m_nWidth != nWidth; + m_nWidth = nWidth; + } + + if ( nFlags & PosSize::HEIGHT ) + { + bChanged |= m_nHeight != nHeight; + m_nHeight = nHeight; + } + + if ( bChanged && m_xPeerWindow.is() ) + { + m_xPeerWindow->setPosSize( m_nX, m_nY, m_nWidth, m_nHeight, nFlags ); + } +} + +// XWindow + +void SAL_CALL BaseControl::setVisible( sal_Bool bVisible ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + // Set new state of flag + m_bVisible = bVisible; + + if ( m_xPeerWindow.is() ) + { + // Set it also on peerwindow + m_xPeerWindow->setVisible( m_bVisible ); + } +} + +// XWindow + +void SAL_CALL BaseControl::setEnable( sal_Bool bEnable ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + // Set new state of flag + m_bEnable = bEnable; + + if ( m_xPeerWindow.is() ) + { + // Set it also on peerwindow + m_xPeerWindow->setEnable( m_bEnable ); + } +} + +// XWindow + +void SAL_CALL BaseControl::setFocus() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + if ( m_xPeerWindow.is() ) + { + m_xPeerWindow->setFocus(); + } +} + +// XWindow + +Rectangle SAL_CALL BaseControl::getPosSize() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + return Rectangle( m_nX, m_nY , m_nWidth, m_nHeight ); +} + +// XWindow + +void SAL_CALL BaseControl::addWindowListener( const Reference< XWindowListener >& xListener ) +{ + impl_getMultiplexer()->advise( cppu::UnoType<XWindowListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::addFocusListener( const Reference< XFocusListener >& xListener ) +{ + impl_getMultiplexer()->advise( cppu::UnoType<XFocusListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::addKeyListener( const Reference< XKeyListener >& xListener ) +{ + impl_getMultiplexer()->advise( cppu::UnoType<XKeyListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::addMouseListener( const Reference< XMouseListener >& xListener ) +{ + impl_getMultiplexer()->advise( cppu::UnoType<XMouseListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::addMouseMotionListener( const Reference< XMouseMotionListener >& xListener ) +{ + impl_getMultiplexer()->advise( cppu::UnoType<XMouseMotionListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::addPaintListener( const Reference< XPaintListener >& xListener ) +{ + impl_getMultiplexer()->advise( cppu::UnoType<XPaintListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::removeWindowListener( const Reference< XWindowListener >& xListener ) +{ + impl_getMultiplexer()->unadvise( cppu::UnoType<XWindowListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::removeFocusListener( const Reference< XFocusListener >& xListener ) +{ + impl_getMultiplexer()->unadvise( cppu::UnoType<XFocusListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::removeKeyListener( const Reference< XKeyListener >& xListener ) +{ + impl_getMultiplexer()->unadvise( cppu::UnoType<XKeyListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::removeMouseListener( const Reference< XMouseListener >& xListener ) +{ + impl_getMultiplexer()->unadvise( cppu::UnoType<XMouseListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::removeMouseMotionListener( const Reference< XMouseMotionListener >& xListener ) +{ + impl_getMultiplexer()->unadvise( cppu::UnoType<XMouseMotionListener>::get(), xListener ); +} + +// XWindow + +void SAL_CALL BaseControl::removePaintListener( const Reference< XPaintListener >& xListener ) +{ + impl_getMultiplexer()->unadvise( cppu::UnoType<XPaintListener>::get(), xListener ); +} + +// XView + +void SAL_CALL BaseControl::draw( sal_Int32 nX , + sal_Int32 nY ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + // - paint to a view + // - use the method "paint()" + // - see also "windowPaint()" + impl_paint( nX, nY, m_xGraphicsView ); +} + +// XView + +sal_Bool SAL_CALL BaseControl::setGraphics( const Reference< XGraphics >& xDevice ) +{ + // - set the graphics for a view + // - in this class exist 2 graphics-member ... one for peer[_xGraphicsPeer] and one for view[_xGraphicsView] + // - they are used by "windowPaint() and draw()", forwarded to "paint ()" + bool bReturn = false; + if ( xDevice.is() ) + { + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + m_xGraphicsView = xDevice; + bReturn = true; + } + + return bReturn; +} + +// XView + +void SAL_CALL BaseControl::setZoom( float /*fZoomX*/ , + float /*fZoomY*/ ) +{ + // Not implemented yet +} + +// XView + +Reference< XGraphics > SAL_CALL BaseControl::getGraphics() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + return m_xGraphicsView; +} + +// XView + +Size SAL_CALL BaseControl::getSize() +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + return Size( m_nWidth, m_nHeight ); +} + +// XEventListener + +void SAL_CALL BaseControl::disposing( const EventObject& /*aSource*/ ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + // - release ALL references + // - it must be !!! + if ( m_xGraphicsPeer.is() ) + { + removePaintListener( this ); + removeWindowListener( this ); + m_xGraphicsPeer.clear(); + } + + if ( m_xGraphicsView.is() ) + { + m_xGraphicsView.clear(); + } +} + +// XPaintListener + +void SAL_CALL BaseControl::windowPaint( const PaintEvent& /*aEvent*/ ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + // - repaint the peer + // - use the method "paint ()" for painting on a peer and a print device !!! + // - see also "draw ()" + impl_paint( 0, 0, m_xGraphicsPeer ); +} + +// XWindowListener + +void SAL_CALL BaseControl::windowResized( const WindowEvent& aEvent ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + m_nWidth = aEvent.Width; + m_nHeight = aEvent.Height; + WindowEvent aMappedEvent = aEvent; + aMappedEvent.X = 0; + aMappedEvent.Y = 0; + impl_recalcLayout( aMappedEvent ); +} + +// XWindowListener + +void SAL_CALL BaseControl::windowMoved( const WindowEvent& aEvent ) +{ + // Ready for multithreading + MutexGuard aGuard( m_aMutex ); + + m_nWidth = aEvent.Width; + m_nHeight = aEvent.Height; + WindowEvent aMappedEvent = aEvent; + aMappedEvent.X = 0; + aMappedEvent.Y = 0; + impl_recalcLayout( aMappedEvent ); +} + +// XWindowListener + +void SAL_CALL BaseControl::windowShown( const EventObject& /*aEvent*/ ) +{ +} + +// XWindowListener + +void SAL_CALL BaseControl::windowHidden( const EventObject& /*aEvent*/ ) +{ +} + +// protected method + +WindowDescriptor BaseControl::impl_getWindowDescriptor( const Reference< XWindowPeer >& xParentPeer ) +{ + // - used from "createPeer()" to set the values of a css::awt::WindowDescriptor !!! + // - if you will change the descriptor-values, you must override this virtual function + // - the caller must release the memory for this dynamical descriptor !!! + + WindowDescriptor aDescriptor; + + aDescriptor.Type = WindowClass_SIMPLE; + aDescriptor.WindowServiceName = "window"; + aDescriptor.ParentIndex = -1; + aDescriptor.Parent = xParentPeer; + aDescriptor.Bounds = getPosSize (); + aDescriptor.WindowAttributes = 0; + + return aDescriptor; +} + +// protected method + +void BaseControl::impl_paint( sal_Int32 /*nX*/ , + sal_Int32 /*nY*/ , + const Reference< XGraphics >& /*xGraphics*/ ) +{ + // - one paint method for peer AND view !!! + // (see also => "windowPaint()" and "draw()") + // - not used in this implementation, but it's not necessary to make it pure virtual !!! +} + +// protected method + +void BaseControl::impl_recalcLayout( const WindowEvent& /*aEvent*/ ) +{ + // We need as virtual function to support automatically resizing of derived controls! + // But we make it not pure virtual because it's not necessary for all derived classes! +} + +// private method + +OMRCListenerMultiplexerHelper* BaseControl::impl_getMultiplexer() +{ + if ( !m_xMultiplexer.is() ) + { + m_xMultiplexer = new OMRCListenerMultiplexerHelper( static_cast<XWindow*>(this), m_xPeerWindow ); + } + + return m_xMultiplexer.get(); +} + +} // namespace unocontrols + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/UnoControls/source/base/multiplexer.cxx b/UnoControls/source/base/multiplexer.cxx new file mode 100644 index 000000000..c7bf65c17 --- /dev/null +++ b/UnoControls/source/base/multiplexer.cxx @@ -0,0 +1,441 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <multiplexer.hxx> + +#include <osl/diagnose.h> +#include <cppuhelper/queryinterface.hxx> + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> + +using namespace ::cppu; +using namespace ::osl; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::awt; +using namespace ::com::sun::star::lang; + +namespace unocontrols { + +// macros + +#define MULTIPLEX( INTERFACE, METHOD, EVENTTYP, EVENT ) \ + \ + /* First get all interfaces from container with right type.*/ \ + comphelper::OInterfaceContainerHelper2* pContainer = m_aListenerHolder.getContainer( cppu::UnoType<INTERFACE>::get() ); \ + /* Do the follow only, if elements in container exist.*/ \ + if( !pContainer ) \ + return; \ + comphelper::OInterfaceIteratorHelper2 aIterator( *pContainer ); \ + EVENTTYP aLocalEvent = EVENT; \ + /* Remark: The control is the event source not the peer.*/ \ + /* We must change the source of the event. */ \ + aLocalEvent.Source = m_xControl; \ + /* Is the control not destroyed? */ \ + if( !aLocalEvent.Source ) \ + return; \ + if( !aIterator.hasMoreElements() ) \ + return; \ + INTERFACE * pListener = static_cast<INTERFACE *>(aIterator.next()); \ + try \ + { \ + pListener->METHOD( aLocalEvent ); \ + } \ + catch(const RuntimeException& ) \ + { \ + /* Ignore all system exceptions from the listener! */ \ + } + +// construct/destruct + +OMRCListenerMultiplexerHelper::OMRCListenerMultiplexerHelper( const Reference< XWindow >& xControl , + const Reference< XWindow >& xPeer ) + : m_xPeer ( xPeer ) + , m_xControl ( xControl ) + , m_aListenerHolder ( m_aMutex ) +{ +} + +OMRCListenerMultiplexerHelper::OMRCListenerMultiplexerHelper( const OMRCListenerMultiplexerHelper& aCopyInstance ) + : XFocusListener() + , XWindowListener() + , XKeyListener() + , XMouseListener() + , XMouseMotionListener() + , XPaintListener() + , XTopWindowListener() + , OWeakObject(aCopyInstance) + , m_aListenerHolder ( m_aMutex ) +{ +} + +OMRCListenerMultiplexerHelper::~OMRCListenerMultiplexerHelper() +{ +} + +// XInterface + +Any SAL_CALL OMRCListenerMultiplexerHelper::queryInterface( const Type& rType ) +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + + // Ask for my own supported interfaces ... + // Attention: XTypeProvider and XInterface are supported by OComponentHelper! + Any aReturn ( ::cppu::queryInterface( rType , + static_cast< XWindowListener* > ( this ) , + static_cast< XKeyListener* > ( this ) , + static_cast< XFocusListener* > ( this ) , + static_cast< XMouseListener* > ( this ) , + static_cast< XMouseMotionListener* > ( this ) , + static_cast< XPaintListener* > ( this ) , + static_cast< XTopWindowListener* > ( this ) , + static_cast< XTopWindowListener* > ( this ) + ) + ); + + // If searched interface supported by this class ... + if ( aReturn.hasValue() ) + { + // ... return this information. + return aReturn; + } + else + { + // Else; ... ask baseclass for interfaces! + return OWeakObject::queryInterface( rType ); + } +} + +// XInterface + +void SAL_CALL OMRCListenerMultiplexerHelper::acquire() noexcept +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + + // Forward to baseclass + OWeakObject::acquire(); +} + +// XInterface + +void SAL_CALL OMRCListenerMultiplexerHelper::release() noexcept +{ + // Attention: + // Don't use mutex or guard in this method!!! Is a method of XInterface. + + // Forward to baseclass + OWeakObject::release(); +} + +// container method + +void OMRCListenerMultiplexerHelper::setPeer( const Reference< XWindow >& xPeer ) +{ + MutexGuard aGuard( m_aMutex ); + if( m_xPeer == xPeer ) + return; + + if( m_xPeer.is() ) + { + // get all types from the listener added to the peer + const std::vector< Type > aContainedTypes = m_aListenerHolder.getContainedTypes(); + // loop over all listener types and remove the listeners from the peer + for( const auto& rContainedType : aContainedTypes ) + impl_unadviseFromPeer( m_xPeer, rContainedType ); + } + m_xPeer = xPeer; + if( m_xPeer.is() ) + { + // get all types from the listener added to the peer + const std::vector< Type > aContainedTypes = m_aListenerHolder.getContainedTypes(); + // loop over all listener types and add the listeners to the peer + for( const auto& rContainedType : aContainedTypes ) + impl_adviseToPeer( m_xPeer, rContainedType ); + } +} + +// container method + +void OMRCListenerMultiplexerHelper::disposeAndClear() +{ + EventObject aEvent; + aEvent.Source = m_xControl; + m_aListenerHolder.disposeAndClear( aEvent ); +} + +// container method + +void OMRCListenerMultiplexerHelper::advise( const Type& aType , + const Reference< XInterface >& xListener ) +{ + MutexGuard aGuard( m_aMutex ); + if( m_aListenerHolder.addInterface( aType, xListener ) == 1 ) + { + // the first listener is added + if( m_xPeer.is() ) + { + impl_adviseToPeer( m_xPeer, aType ); + } + } +} + +// container method + +void OMRCListenerMultiplexerHelper::unadvise( const Type& aType , + const Reference< XInterface >& xListener ) +{ + MutexGuard aGuard( m_aMutex ); + if( m_aListenerHolder.removeInterface( aType, xListener ) == 0 ) + { + // the last listener is removed + if ( m_xPeer.is() ) + { + impl_unadviseFromPeer( m_xPeer, aType ); + } + } +} + +// XEventListener + +void SAL_CALL OMRCListenerMultiplexerHelper::disposing( const EventObject& /*aSource*/ ) +{ + MutexGuard aGuard( m_aMutex ); + // peer is disposed, clear the reference + m_xPeer.clear(); +} + +// XFcousListener + +void OMRCListenerMultiplexerHelper::focusGained(const FocusEvent& aEvent ) +{ + MULTIPLEX( XFocusListener, focusGained, FocusEvent, aEvent ) +} + +// XFcousListener + +void OMRCListenerMultiplexerHelper::focusLost(const FocusEvent& aEvent ) +{ + MULTIPLEX( XFocusListener, focusLost, FocusEvent, aEvent ) +} + +// XWindowListener + +void OMRCListenerMultiplexerHelper::windowResized(const WindowEvent& aEvent ) +{ + MULTIPLEX( XWindowListener, windowResized, WindowEvent, aEvent ) +} + +// XWindowListener + +void OMRCListenerMultiplexerHelper::windowMoved(const WindowEvent& aEvent ) +{ + MULTIPLEX( XWindowListener, windowMoved, WindowEvent, aEvent ) +} + +// XWindowListener + +void OMRCListenerMultiplexerHelper::windowShown(const EventObject& aEvent ) +{ + MULTIPLEX( XWindowListener, windowShown, EventObject, aEvent ) +} + +// XWindowListener + +void OMRCListenerMultiplexerHelper::windowHidden(const EventObject& aEvent ) +{ + MULTIPLEX( XWindowListener, windowHidden, EventObject, aEvent ) +} + +// XKeyListener + +void OMRCListenerMultiplexerHelper::keyPressed(const KeyEvent& aEvent) +{ + MULTIPLEX( XKeyListener, keyPressed, KeyEvent, aEvent ) +} + +// XKeyListener + +void OMRCListenerMultiplexerHelper::keyReleased(const KeyEvent& aEvent) +{ + MULTIPLEX( XKeyListener, keyReleased, KeyEvent, aEvent ) +} + +// XMouseListener + +void OMRCListenerMultiplexerHelper::mousePressed(const MouseEvent& aEvent) +{ + MULTIPLEX( XMouseListener, mousePressed, MouseEvent, aEvent ) +} + +// XMouseListener + +void OMRCListenerMultiplexerHelper::mouseReleased(const MouseEvent& aEvent) +{ + MULTIPLEX( XMouseListener, mouseReleased, MouseEvent, aEvent ) +} + +// XMouseListener + +void OMRCListenerMultiplexerHelper::mouseEntered(const MouseEvent& aEvent) +{ + MULTIPLEX( XMouseListener, mouseEntered, MouseEvent, aEvent ) +} + +// XMouseListener + +void OMRCListenerMultiplexerHelper::mouseExited(const MouseEvent& aEvent) +{ + MULTIPLEX( XMouseListener, mouseExited, MouseEvent, aEvent ) +} + +// XMouseMotionListener + +void OMRCListenerMultiplexerHelper::mouseDragged(const MouseEvent& aEvent) +{ + MULTIPLEX( XMouseMotionListener, mouseDragged, MouseEvent, aEvent ) +} + +// XMouseMotionListener + +void OMRCListenerMultiplexerHelper::mouseMoved(const MouseEvent& aEvent) +{ + MULTIPLEX( XMouseMotionListener, mouseMoved, MouseEvent, aEvent ) +} + +// XPaintListener + +void OMRCListenerMultiplexerHelper::windowPaint(const PaintEvent& aEvent) +{ + MULTIPLEX( XPaintListener, windowPaint, PaintEvent, aEvent ) +} + +// XTopWindowListener + +void OMRCListenerMultiplexerHelper::windowOpened(const EventObject& aEvent) +{ + MULTIPLEX( XTopWindowListener, windowOpened, EventObject, aEvent ) +} + +// XTopWindowListener + +void OMRCListenerMultiplexerHelper::windowClosing( const EventObject& aEvent ) +{ + MULTIPLEX( XTopWindowListener, windowClosing, EventObject, aEvent ) +} + +// XTopWindowListener + +void OMRCListenerMultiplexerHelper::windowClosed( const EventObject& aEvent ) +{ + MULTIPLEX( XTopWindowListener, windowClosed, EventObject, aEvent ) +} + +// XTopWindowListener + +void OMRCListenerMultiplexerHelper::windowMinimized( const EventObject& aEvent ) +{ + MULTIPLEX( XTopWindowListener, windowMinimized, EventObject, aEvent ) +} + +// XTopWindowListener + +void OMRCListenerMultiplexerHelper::windowNormalized( const EventObject& aEvent ) +{ + MULTIPLEX( XTopWindowListener, windowNormalized, EventObject, aEvent ) +} + +// XTopWindowListener + +void OMRCListenerMultiplexerHelper::windowActivated( const EventObject& aEvent ) +{ + MULTIPLEX( XTopWindowListener, windowActivated, EventObject, aEvent ) +} + +// XTopWindowListener + +void OMRCListenerMultiplexerHelper::windowDeactivated( const EventObject& aEvent ) +{ + MULTIPLEX( XTopWindowListener, windowDeactivated, EventObject, aEvent ) +} + +// protected method + +void OMRCListenerMultiplexerHelper::impl_adviseToPeer( const Reference< XWindow >& xPeer , + const Type& aType ) +{ + // add a listener to the source (peer) + if( aType == cppu::UnoType<XWindowListener>::get()) + xPeer->addWindowListener( this ); + else if( aType == cppu::UnoType<XKeyListener>::get()) + xPeer->addKeyListener( this ); + else if( aType == cppu::UnoType<XFocusListener>::get()) + xPeer->addFocusListener( this ); + else if( aType == cppu::UnoType<XMouseListener>::get()) + xPeer->addMouseListener( this ); + else if( aType == cppu::UnoType<XMouseMotionListener>::get()) + xPeer->addMouseMotionListener( this ); + else if( aType == cppu::UnoType<XPaintListener>::get()) + xPeer->addPaintListener( this ); + else if( aType == cppu::UnoType<XTopWindowListener>::get()) + { + Reference< XTopWindow > xTop( xPeer, UNO_QUERY ); + if( xTop.is() ) + xTop->addTopWindowListener( this ); + } + else + { + OSL_FAIL( "unknown listener" ); + } +} + +// protected method + +void OMRCListenerMultiplexerHelper::impl_unadviseFromPeer( const Reference< XWindow >& xPeer , + const Type& aType ) +{ + // the last listener is removed, remove the listener from the source (peer) + if( aType == cppu::UnoType<XWindowListener>::get()) + xPeer->removeWindowListener( this ); + else if( aType == cppu::UnoType<XKeyListener>::get()) + xPeer->removeKeyListener( this ); + else if( aType == cppu::UnoType<XFocusListener>::get()) + xPeer->removeFocusListener( this ); + else if( aType == cppu::UnoType<XMouseListener>::get()) + xPeer->removeMouseListener( this ); + else if( aType == cppu::UnoType<XMouseMotionListener>::get()) + xPeer->removeMouseMotionListener( this ); + else if( aType == cppu::UnoType<XPaintListener>::get()) + xPeer->removePaintListener( this ); + else if( aType == cppu::UnoType<XTopWindowListener>::get()) + { + Reference< XTopWindow > xTop( xPeer, UNO_QUERY ); + if( xTop.is() ) + xTop->removeTopWindowListener( this ); + } + else + { + OSL_FAIL( "unknown listener" ); + } +} + +} // namespace unocontrols + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |