diff options
Diffstat (limited to 'UnoControls/source/base/basecontainercontrol.cxx')
-rw-r--r-- | UnoControls/source/base/basecontainercontrol.cxx | 387 |
1 files changed, 387 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: */ |