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 /framework/source/helper | |
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 'framework/source/helper')
-rw-r--r-- | framework/source/helper/dockingareadefaultacceptor.cxx | 129 | ||||
-rw-r--r-- | framework/source/helper/ocomponentaccess.cxx | 167 | ||||
-rw-r--r-- | framework/source/helper/ocomponentenumeration.cxx | 117 | ||||
-rw-r--r-- | framework/source/helper/oframes.cxx | 370 | ||||
-rw-r--r-- | framework/source/helper/persistentwindowstate.cxx | 267 | ||||
-rw-r--r-- | framework/source/helper/statusindicator.cxx | 128 | ||||
-rw-r--r-- | framework/source/helper/statusindicatorfactory.cxx | 577 | ||||
-rw-r--r-- | framework/source/helper/tagwindowasmodified.cxx | 146 | ||||
-rw-r--r-- | framework/source/helper/titlebarupdate.cxx | 316 | ||||
-rw-r--r-- | framework/source/helper/uiconfigelementwrapperbase.cxx | 481 | ||||
-rw-r--r-- | framework/source/helper/uielementwrapperbase.cxx | 203 | ||||
-rw-r--r-- | framework/source/helper/vclstatusindicator.cxx | 140 | ||||
-rw-r--r-- | framework/source/helper/wakeupthread.cxx | 60 |
13 files changed, 3101 insertions, 0 deletions
diff --git a/framework/source/helper/dockingareadefaultacceptor.cxx b/framework/source/helper/dockingareadefaultacceptor.cxx new file mode 100644 index 000000000..59a43a1e3 --- /dev/null +++ b/framework/source/helper/dockingareadefaultacceptor.cxx @@ -0,0 +1,129 @@ +/* -*- 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 <helper/dockingareadefaultacceptor.hxx> + +#include <com/sun/star/awt/XDevice.hpp> +#include <com/sun/star/awt/PosSize.hpp> + +#include <vcl/svapp.hxx> + +namespace framework{ + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::cppu; +using namespace ::osl; + +// constructor + +DockingAreaDefaultAcceptor::DockingAreaDefaultAcceptor( const css::uno::Reference< XFrame >& xOwner ) + : m_xOwner ( xOwner ) +{ +} + +// destructor + +DockingAreaDefaultAcceptor::~DockingAreaDefaultAcceptor() +{ +} + +// XDockingAreaAcceptor +css::uno::Reference< css::awt::XWindow > SAL_CALL DockingAreaDefaultAcceptor::getContainerWindow() +{ + SolarMutexGuard g; + + // Try to "lock" the frame for access to taskscontainer. + css::uno::Reference< XFrame > xFrame( m_xOwner ); + //TODO: check xFrame for null? + css::uno::Reference< css::awt::XWindow > xContainerWindow( xFrame->getContainerWindow() ); + + return xContainerWindow; +} + +sal_Bool SAL_CALL DockingAreaDefaultAcceptor::requestDockingAreaSpace( const css::awt::Rectangle& RequestedSpace ) +{ + // Try to "lock" the frame for access to taskscontainer. + css::uno::Reference< XFrame > xFrame( m_xOwner ); + + if ( !xFrame.is() ) + return false; + + css::uno::Reference< css::awt::XWindow > xContainerWindow( xFrame->getContainerWindow() ); + css::uno::Reference< css::awt::XWindow > xComponentWindow( xFrame->getComponentWindow() ); + + if ( !xContainerWindow.is() || !xComponentWindow.is() ) + return false; + + css::uno::Reference< css::awt::XDevice > xDevice( xContainerWindow, css::uno::UNO_QUERY ); + // Convert relative size to output size. + css::awt::Rectangle aRectangle = xContainerWindow->getPosSize(); + css::awt::DeviceInfo aInfo = xDevice->getInfo(); + css::awt::Size aSize ( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset , + aRectangle.Height - aInfo.TopInset - aInfo.BottomInset ); + + css::awt::Size aMinSize( 0, 0 ); // = xLayoutConstraints->getMinimumSize(); + + // Check if request border space would decrease component window size below minimum size + if ((( aSize.Width - RequestedSpace.X - RequestedSpace.Width ) < aMinSize.Width ) || + (( aSize.Height - RequestedSpace.Y - RequestedSpace.Height ) < aMinSize.Height ) ) + return false; + + return true; +} + +void SAL_CALL DockingAreaDefaultAcceptor::setDockingAreaSpace( const css::awt::Rectangle& BorderSpace ) +{ + SolarMutexGuard g; + + // Try to "lock" the frame for access to taskscontainer. + css::uno::Reference< XFrame > xFrame( m_xOwner ); + if ( !xFrame.is() ) + return; + + css::uno::Reference< css::awt::XWindow > xContainerWindow( xFrame->getContainerWindow() ); + css::uno::Reference< css::awt::XWindow > xComponentWindow( xFrame->getComponentWindow() ); + + if ( !(xContainerWindow.is() && xComponentWindow.is()) ) + return; + + css::uno::Reference< css::awt::XDevice > xDevice( xContainerWindow, css::uno::UNO_QUERY ); + // Convert relative size to output size. + css::awt::Rectangle aRectangle = xContainerWindow->getPosSize(); + css::awt::DeviceInfo aInfo = xDevice->getInfo(); + css::awt::Size aSize ( aRectangle.Width - aInfo.LeftInset - aInfo.RightInset , + aRectangle.Height - aInfo.TopInset - aInfo.BottomInset ); + css::awt::Size aMinSize( 0, 0 );// = xLayoutConstraints->getMinimumSize(); + + // Check if request border space would decrease component window size below minimum size + sal_Int32 nWidth = aSize.Width - BorderSpace.X - BorderSpace.Width; + sal_Int32 nHeight = aSize.Height - BorderSpace.Y - BorderSpace.Height; + + if (( nWidth > aMinSize.Width ) && ( nHeight > aMinSize.Height )) + { + // Resize our component window. + xComponentWindow->setPosSize( BorderSpace.X, BorderSpace.Y, nWidth, nHeight, css::awt::PosSize::POSSIZE ); + } +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/ocomponentaccess.cxx b/framework/source/helper/ocomponentaccess.cxx new file mode 100644 index 000000000..ad7409990 --- /dev/null +++ b/framework/source/helper/ocomponentaccess.cxx @@ -0,0 +1,167 @@ +/* -*- 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 <helper/ocomponentaccess.hxx> +#include <helper/ocomponentenumeration.hxx> + +#include <com/sun/star/frame/FrameSearchFlag.hpp> + +#include <vcl/svapp.hxx> +#include <sal/log.hxx> + +namespace framework{ + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::cppu; +using namespace ::osl; + +// constructor + +OComponentAccess::OComponentAccess( const css::uno::Reference< XDesktop >& xOwner ) + : m_xOwner ( xOwner ) +{ + // Safe impossible cases + SAL_WARN_IF( !xOwner.is(), "fwk", "OComponentAccess::OComponentAccess(): Invalid parameter detected!" ); +} + +// destructor + +OComponentAccess::~OComponentAccess() +{ +} + +// XEnumerationAccess +css::uno::Reference< XEnumeration > SAL_CALL OComponentAccess::createEnumeration() +{ + SolarMutexGuard g; + + // Set default return value, if method failed. + // If no desktop exist and there is no task container - return an empty enumeration! + css::uno::Reference< XEnumeration > xReturn; + + // Try to "lock" the desktop for access to task container. + css::uno::Reference< XInterface > xLock = m_xOwner.get(); + if ( xLock.is() ) + { + // Desktop exist => pointer to task container must be valid. + // Initialize a new enumeration ... if some tasks and his components exist! + // (OTasksEnumeration will make an assert, if we initialize the new instance without valid values!) + + std::vector< css::uno::Reference< XComponent > > seqComponents; + impl_collectAllChildComponents( css::uno::Reference< XFramesSupplier >( xLock, UNO_QUERY ), seqComponents ); + xReturn = new OComponentEnumeration( std::move(seqComponents) ); + } + + // Return result of this operation. + return xReturn; +} + +// XElementAccess +Type SAL_CALL OComponentAccess::getElementType() +{ + // Elements in list an enumeration are components! + // Return the uno-type of XComponent. + return cppu::UnoType<XComponent>::get(); +} + +// XElementAccess +sal_Bool SAL_CALL OComponentAccess::hasElements() +{ + SolarMutexGuard g; + + // Set default return value, if method failed. + bool bReturn = false; + + // Try to "lock" the desktop for access to task container. + css::uno::Reference< XFramesSupplier > xLock( m_xOwner.get(), UNO_QUERY ); + if ( xLock.is() ) + { + // Ask container of owner for existing elements. + bReturn = xLock->getFrames()->hasElements(); + } + + // Return result of this operation. + return bReturn; +} + + +void OComponentAccess::impl_collectAllChildComponents( const css::uno::Reference< XFramesSupplier >& xNode , + std::vector< css::uno::Reference< XComponent > >& seqComponents ) +{ + // If valid node was given ... + if( !xNode.is() ) + return; + + // ... continue collection at these. + + // Get the container of current node, collect the components of existing child frames + // and go down to next level in tree (recursive!). + + const css::uno::Reference< XFrames > xContainer = xNode->getFrames(); + const Sequence< css::uno::Reference< XFrame > > seqFrames = xContainer->queryFrames( FrameSearchFlag::CHILDREN ); + + const sal_Int32 nFrameCount = seqFrames.getLength(); + for( sal_Int32 nFrame=0; nFrame<nFrameCount; ++nFrame ) + { + css::uno::Reference< XComponent > xComponent = impl_getFrameComponent( seqFrames[nFrame] ); + if( xComponent.is() ) + { + seqComponents.push_back( xComponent ); + } + } + // ... otherwise break a recursive path and go back at current stack! +} + +css::uno::Reference< XComponent > OComponentAccess::impl_getFrameComponent( const css::uno::Reference< XFrame >& xFrame ) const +{ + // Set default return value, if method failed. + css::uno::Reference< XComponent > xComponent; + // Does no controller exists? + css::uno::Reference< XController > xController = xFrame->getController(); + if ( !xController.is() ) + { + // Controller not exist - use the VCL-component. + xComponent = xFrame->getComponentWindow(); + } + else + { + // Does no model exists? + css::uno::Reference< XModel > xModel = xController->getModel(); + if ( xModel.is() ) + { + // Model exist - use the model as component. + xComponent = xModel; + } + else + { + // Model not exist - use the controller as component. + xComponent = xController; + } + } + + return xComponent; +} + + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/ocomponentenumeration.cxx b/framework/source/helper/ocomponentenumeration.cxx new file mode 100644 index 000000000..3d00f75e5 --- /dev/null +++ b/framework/source/helper/ocomponentenumeration.cxx @@ -0,0 +1,117 @@ +/* -*- 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 <helper/ocomponentenumeration.hxx> + +#include <vcl/svapp.hxx> +#include <sal/log.hxx> + +namespace framework{ + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::cppu; +using namespace ::osl; + +// constructor + +OComponentEnumeration::OComponentEnumeration( std::vector< css::uno::Reference< XComponent > >&& seqComponents ) + : m_nPosition ( 0 ) // 0 is the first position for a valid list and the right value for an invalid list to! + , m_seqComponents ( std::move(seqComponents) ) +{} + +// destructor + +OComponentEnumeration::~OComponentEnumeration() +{ + // Reset instance, free memory... + impl_resetObject(); +} + +// XEventListener +void SAL_CALL OComponentEnumeration::disposing( const EventObject& aEvent ) +{ + SolarMutexGuard g; + + // Safe impossible cases + // This method is not specified for all incoming parameters. + SAL_WARN_IF( !aEvent.Source.is(), "fwk", "OComponentEnumeration::disposing(): Invalid parameter detected!" ); + + // Reset instance to defaults, release references and free memory. + impl_resetObject(); +} + +// XEnumeration +sal_Bool SAL_CALL OComponentEnumeration::hasMoreElements() +{ + SolarMutexGuard g; + + // First position in a valid list is 0. + // => The last one is getLength() - 1! + // m_nPosition's current value is the position for the next element, which will be return, if user call "nextElement()" + // => We have more elements if current position less than the length of the list! + return ( m_nPosition < static_cast<sal_uInt32>(m_seqComponents.size()) ); +} + +// XEnumeration + +Any SAL_CALL OComponentEnumeration::nextElement() +{ + SolarMutexGuard g; + + // If we have no elements or end of enumeration is arrived ... + if ( !hasMoreElements() ) + { + // .. throw an exception! + throw NoSuchElementException(); + } + + // Else; Get next element from list ... + Any aComponent; + aComponent <<= m_seqComponents[m_nPosition]; + // ... and step to next element! + ++m_nPosition; + + // Return listitem. + return aComponent; +} + +// protected method + +void OComponentEnumeration::impl_resetObject() +{ + // Attention: + // Write this for multiple calls - NOT AT THE SAME TIME - but for more than one call again)! + // It exist two ways to call this method. From destructor and from disposing(). + // I can't say, which one is the first. Normally the disposing-call - but other way... + + // Delete list of components. + m_seqComponents.clear(); + // Reset position in list. + // The list has no elements anymore. m_nPosition is normally the current position in list for nextElement! + // But a position of 0 in a list of 0 items is an invalid state. This constellation can't work in future. + // End of enumeration is arrived! + // (see hasMoreElements() for more details...) + m_nPosition = 0; +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/oframes.cxx b/framework/source/helper/oframes.cxx new file mode 100644 index 000000000..a58949852 --- /dev/null +++ b/framework/source/helper/oframes.cxx @@ -0,0 +1,370 @@ +/* -*- 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 <helper/oframes.hxx> + +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> +#include <vcl/svapp.hxx> +#include <sal/log.hxx> + +namespace framework{ + +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::cppu; +using namespace ::osl; +using namespace ::std; + +// constructor + +OFrames::OFrames( const css::uno::Reference< XFrame >& xOwner , + FrameContainer* pFrameContainer ) + : m_xOwner ( xOwner ) + , m_pFrameContainer ( pFrameContainer ) + , m_bRecursiveSearchProtection( false ) +{ + // An instance of this class can only work with valid initialization. + // We share the mutex with our owner class, need a valid factory to instantiate new services and + // use the access to our owner for some operations. + SAL_WARN_IF( !xOwner.is() || !pFrameContainer, "fwk", "OFrames::OFrames(): Invalid parameter detected!" ); +} + +// (protected!) destructor + +OFrames::~OFrames() +{ + // Reset instance, free memory... + impl_resetObject(); +} + +// XFrames +void SAL_CALL OFrames::append( const css::uno::Reference< XFrame >& xFrame ) +{ + SolarMutexGuard g; + + // Safe impossible cases + // Method is not defined for ALL incoming parameters! + SAL_WARN_IF( !xFrame.is(), "fwk", "OFrames::append(): Invalid parameter detected!" ); + + // Do the follow only, if owner instance valid! + // Lock owner for follow operations - make a "hard reference"! + css::uno::Reference< XFramesSupplier > xOwner( m_xOwner.get(), UNO_QUERY ); + if ( xOwner.is() ) + { + // Append frame to the end of the container ... + m_pFrameContainer->append( xFrame ); + // Set owner of this instance as parent of the new frame in container! + xFrame->setCreator( xOwner ); + } + // Else; Do nothing! Our owner is dead. + SAL_WARN_IF( !xOwner.is(), "fwk", "OFrames::append():Our owner is dead - you can't append any frames ...!" ); +} + +// XFrames +void SAL_CALL OFrames::remove( const css::uno::Reference< XFrame >& xFrame ) +{ + SolarMutexGuard g; + + // Safe impossible cases + // Method is not defined for ALL incoming parameters! + SAL_WARN_IF( !xFrame.is(), "fwk", "OFrames::remove(): Invalid parameter detected!" ); + + // Do the follow only, if owner instance valid! + // Lock owner for follow operations - make a "hard reference"! + css::uno::Reference< XFramesSupplier > xOwner( m_xOwner.get(), UNO_QUERY ); + if ( xOwner.is() ) + { + // Search frame and remove it from container ... + m_pFrameContainer->remove( xFrame ); + // Don't reset owner-property of removed frame! + // This must do the caller of this method himself. + // See documentation of interface XFrames for further information. + } + // Else; Do nothing! Our owner is dead. + SAL_WARN_IF( !xOwner.is(), "fwk", "OFrames::remove(): Our owner is dead - you can't remove any frames ...!" ); +} + +// XFrames +Sequence< css::uno::Reference< XFrame > > SAL_CALL OFrames::queryFrames( sal_Int32 nSearchFlags ) +{ + SolarMutexGuard g; + + // Safe impossible cases + // Method is not defined for ALL incoming parameters! + SAL_WARN_IF( !impldbg_checkParameter_queryFrames( nSearchFlags ), "fwk", "OFrames::queryFrames(): Invalid parameter detected!" ); + + // Set default return value. (empty sequence) + Sequence< css::uno::Reference< XFrame > > seqFrames; + + // Do the follow only, if owner instance valid. + // Lock owner for follow operations - make a "hard reference"! + css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY ); + if ( xOwner.is() ) + { + // Work only, if search was not started here ...! + if( !m_bRecursiveSearchProtection ) + { + // This class is a helper for services, which must implement XFrames. + // His parent and children are MY parent and children to. + // All searchflags are supported by this implementation! + // If some flags should not be supported - don't call me with this flags!!! + + // Search with AUTO-flag is not supported yet! + // We think about right implementation. + SAL_WARN_IF( (nSearchFlags & FrameSearchFlag::AUTO), "fwk", "OFrames::queryFrames(): Search with AUTO-flag is not supported yet!" ); + + // Search for ALL and GLOBAL is superfluous! + // We support all necessary flags, from which these two flags are derived. + // ALL = PARENT + SELF + CHILDREN + SIBLINGS + // GLOBAL = ALL + TASKS + + // Add parent to list ... if any exist! + if( nSearchFlags & FrameSearchFlag::PARENT ) + { + css::uno::Reference< XFrame > xParent = xOwner->getCreator(); + if( xParent.is() ) + { + impl_appendSequence( seqFrames, { xParent } ); + } + } + + // Add owner to list if SELF is searched. + if( nSearchFlags & FrameSearchFlag::SELF ) + { + impl_appendSequence( seqFrames, { xOwner } ); + } + + // Add SIBLINGS to list. + if( nSearchFlags & FrameSearchFlag::SIBLINGS ) + { + // Else; start a new search. + // Protect this instance against recursive calls from parents. + m_bRecursiveSearchProtection = true; + // Ask parent of my owner for frames and append results to return list. + css::uno::Reference< XFramesSupplier > xParent = xOwner->getCreator(); + // If a parent exist ... + if ( xParent.is() ) + { + // ... ask him for right frames. + impl_appendSequence( seqFrames, xParent->getFrames()->queryFrames( nSearchFlags ) ); + } + // We have all searched information. + // Reset protection-mode. + m_bRecursiveSearchProtection = false; + } + + // If searched for children, step over all elements in container and collect the information. + if ( nSearchFlags & FrameSearchFlag::CHILDREN ) + { + // Don't search for parents, siblings and self at children! + // These things are supported by this instance himself. + sal_Int32 const nChildSearchFlags = FrameSearchFlag::SELF | FrameSearchFlag::CHILDREN; + // Step over all items of container and ask children for frames. + sal_uInt32 nCount = m_pFrameContainer->getCount(); + for ( sal_uInt32 nIndex=0; nIndex<nCount; ++nIndex ) + { + // We don't must control this conversion. + // We have done this at append()! + css::uno::Reference< XFramesSupplier > xItem( (*m_pFrameContainer)[nIndex], UNO_QUERY ); + impl_appendSequence( seqFrames, xItem->getFrames()->queryFrames( nChildSearchFlags ) ); + } + } + } + } + // Else; Do nothing! Our owner is dead. + SAL_WARN_IF( !xOwner.is(), "fwk", "OFrames::queryFrames(): Our owner is dead - you can't query for frames ...!" ); + + // Return result of this operation. + return seqFrames; +} + +// XIndexAccess +sal_Int32 SAL_CALL OFrames::getCount() +{ + SolarMutexGuard g; + + // Set default return value. + sal_Int32 nCount = 0; + + // Do the follow only, if owner instance valid. + // Lock owner for follow operations - make a "hard reference"! + css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY ); + if ( xOwner.is() ) + { + // Set CURRENT size of container for return. + nCount = m_pFrameContainer->getCount(); + } + + // Return result. + return nCount; +} + +// XIndexAccess + +Any SAL_CALL OFrames::getByIndex( sal_Int32 nIndex ) +{ + SolarMutexGuard g; + + sal_uInt32 nCount = m_pFrameContainer->getCount(); + if ( nIndex < 0 || ( sal::static_int_cast< sal_uInt32 >( nIndex ) >= nCount )) + throw IndexOutOfBoundsException("OFrames::getByIndex - Index out of bounds", + static_cast<OWeakObject *>(this) ); + + // Set default return value. + Any aReturnValue; + + // Do the follow only, if owner instance valid. + // Lock owner for follow operations - make a "hard reference"! + css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY ); + if ( xOwner.is() ) + { + // Get element form container. + // (If index not valid, FrameContainer return NULL!) + aReturnValue <<= (*m_pFrameContainer)[nIndex]; + } + + // Return result of this operation. + return aReturnValue; +} + +// XElementAccess +Type SAL_CALL OFrames::getElementType() +{ + // This "container" support XFrame-interfaces only! + return cppu::UnoType<XFrame>::get(); +} + +// XElementAccess +sal_Bool SAL_CALL OFrames::hasElements() +{ + SolarMutexGuard g; + + // Set default return value. + bool bHasElements = false; + // Do the follow only, if owner instance valid. + // Lock owner for follow operations - make a "hard reference"! + css::uno::Reference< XFrame > xOwner( m_xOwner.get(), UNO_QUERY ); + if ( xOwner.is() ) + { + // If some elements exist ... + if ( m_pFrameContainer->getCount() > 0 ) + { + // ... change this state value! + bHasElements = true; + } + } + // Return result of this operation. + return bHasElements; +} + +// protected method + +void OFrames::impl_resetObject() +{ + // Attention: + // Write this for multiple calls - NOT AT THE SAME TIME - but for more than one call again)! + // It exist two ways to call this method. From destructor and from disposing(). + // I can't say, which one is the first. Normally the disposing-call - but other way... + + // This instance can't work if the weakreference to owner is invalid! + // Destroy this to reset this object. + m_xOwner.clear(); + // Reset pointer to shared container to! + m_pFrameContainer = nullptr; +} + +void OFrames::impl_appendSequence( Sequence< css::uno::Reference< XFrame > >& seqDestination , + const Sequence< css::uno::Reference< XFrame > >& seqSource ) +{ + // Get some information about the sequences. + sal_Int32 nSourceCount = seqSource.getLength(); + sal_Int32 nDestinationCount = seqDestination.getLength(); + const css::uno::Reference< XFrame >* pSourceAccess = seqSource.getConstArray(); + css::uno::Reference< XFrame >* pDestinationAccess = seqDestination.getArray(); + + // Get memory for result list. + Sequence< css::uno::Reference< XFrame > > seqResult ( nSourceCount + nDestinationCount ); + css::uno::Reference< XFrame >* pResultAccess = seqResult.getArray(); + sal_Int32 nResultPosition = 0; + + // Copy all items from first sequence. + for ( sal_Int32 nSourcePosition=0; nSourcePosition<nSourceCount; ++nSourcePosition ) + { + pResultAccess[nResultPosition] = pSourceAccess[nSourcePosition]; + ++nResultPosition; + } + + // Don't manipulate nResultPosition between these two loops! + // It's the current position in the result list. + + // Copy all items from second sequence. + for ( sal_Int32 nDestinationPosition=0; nDestinationPosition<nDestinationCount; ++nDestinationPosition ) + { + pResultAccess[nResultPosition] = pDestinationAccess[nDestinationPosition]; + ++nResultPosition; + } + + // Return result of this operation. + seqDestination.realloc( 0 ); + seqDestination = seqResult; +} + +// debug methods + +/*----------------------------------------------------------------------------------------------------------------- + The follow methods checks the parameter for other functions. If a parameter or his value is non valid, + we return "sal_False". (else sal_True) This mechanism is used to throw an ASSERT! + + ATTENTION + + If you miss a test for one of this parameters, contact the author or add it himself !(?) + But ... look for right testing! See using of this methods! +-----------------------------------------------------------------------------------------------------------------*/ + +// A search for frames must initiate with right flags. +// Some one are superfluous and not supported yet. But here we control only the range of incoming parameter! +bool OFrames::impldbg_checkParameter_queryFrames( sal_Int32 nSearchFlags ) +{ + // Set default return value. + bool bOK = true; + // Check parameter. + if ( + ( nSearchFlags != FrameSearchFlag::AUTO ) && + ( !( nSearchFlags & FrameSearchFlag::PARENT ) ) && + ( !( nSearchFlags & FrameSearchFlag::SELF ) ) && + ( !( nSearchFlags & FrameSearchFlag::CHILDREN ) ) && + ( !( nSearchFlags & FrameSearchFlag::CREATE ) ) && + ( !( nSearchFlags & FrameSearchFlag::SIBLINGS ) ) && + ( !( nSearchFlags & FrameSearchFlag::TASKS ) ) && + ( !( nSearchFlags & FrameSearchFlag::ALL ) ) && + ( !( nSearchFlags & FrameSearchFlag::GLOBAL ) ) + ) + { + bOK = false; + } + // Return result of check. + return bOK; +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/persistentwindowstate.cxx b/framework/source/helper/persistentwindowstate.cxx new file mode 100644 index 000000000..2f7c99719 --- /dev/null +++ b/framework/source/helper/persistentwindowstate.cxx @@ -0,0 +1,267 @@ +/* -*- 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 <helper/persistentwindowstate.hxx> + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> + +#include <comphelper/lok.hxx> +#include <comphelper/configurationhelper.hxx> +#include <utility> +#include <vcl/window.hxx> +#include <vcl/syswin.hxx> + +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> + +namespace framework{ + +PersistentWindowState::PersistentWindowState(css::uno::Reference< css::uno::XComponentContext > xContext) + : m_xContext (std::move(xContext )) + , m_bWindowStateAlreadySet(false ) +{ +} + +PersistentWindowState::~PersistentWindowState() +{ +} + +void SAL_CALL PersistentWindowState::initialize(const css::uno::Sequence< css::uno::Any >& lArguments) +{ + // check arguments + css::uno::Reference< css::frame::XFrame > xFrame; + if (!lArguments.hasElements()) + throw css::lang::IllegalArgumentException( + "Empty argument list!", + static_cast< ::cppu::OWeakObject* >(this), + 1); + + lArguments[0] >>= xFrame; + if (!xFrame.is()) + throw css::lang::IllegalArgumentException( + "No valid frame specified!", + static_cast< ::cppu::OWeakObject* >(this), + 1); + + { + SolarMutexGuard g; + m_xFrame = xFrame; + } + + // start listening + xFrame->addFrameActionListener(this); +} + +void SAL_CALL PersistentWindowState::frameAction(const css::frame::FrameActionEvent& aEvent) +{ + // We don't want to do this stuff when being used through LibreOfficeKit + if( comphelper::LibreOfficeKit::isActive() ) + return; + + css::uno::Reference< css::uno::XComponentContext > xContext; + css::uno::Reference< css::frame::XFrame > xFrame; + bool bRestoreWindowState; + { + SolarMutexGuard g; + xContext = m_xContext; + xFrame.set(m_xFrame.get(), css::uno::UNO_QUERY); + bRestoreWindowState = !m_bWindowStateAlreadySet; + } + + // frame already gone ? We hold it weak only ... + if (!xFrame.is()) + return; + + // no window -> no position and size available + css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow(); + if (!xWindow.is()) + return; + + // unknown module -> no configuration available! + OUString sModuleName = PersistentWindowState::implst_identifyModule(xContext, xFrame); + if (sModuleName.isEmpty()) + return; + + switch(aEvent.Action) + { + case css::frame::FrameAction_COMPONENT_ATTACHED : + { + if (bRestoreWindowState) + { + OUString sWindowState = PersistentWindowState::implst_getWindowStateFromConfig(xContext, sModuleName); + PersistentWindowState::implst_setWindowStateOnWindow(xWindow,sWindowState); + SolarMutexGuard g; + m_bWindowStateAlreadySet = true; + } + } + break; + + case css::frame::FrameAction_COMPONENT_REATTACHED : + { + // nothing todo here, because it's not allowed to change position and size + // of an already existing frame! + } + break; + + case css::frame::FrameAction_COMPONENT_DETACHING : + { + OUString sWindowState = PersistentWindowState::implst_getWindowStateFromWindow(xWindow); + PersistentWindowState::implst_setWindowStateOnConfig(xContext, sModuleName, sWindowState); + } + break; + default: + break; + } +} + +void SAL_CALL PersistentWindowState::disposing(const css::lang::EventObject&) +{ + css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY); + if (xFrame.is()) + xFrame->removeFrameActionListener(this); + + // nothing todo here - because we hold the frame as weak reference only +} + +OUString PersistentWindowState::implst_identifyModule(const css::uno::Reference< css::uno::XComponentContext >& rxContext, + const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + OUString sModuleName; + + css::uno::Reference< css::frame::XModuleManager2 > xModuleManager = + css::frame::ModuleManager::create( rxContext ); + + try + { + sModuleName = xModuleManager->identify(xFrame); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { sModuleName.clear(); } + + return sModuleName; +} + +OUString PersistentWindowState::implst_getWindowStateFromConfig( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + std::u16string_view sModuleName) +{ + OUString sWindowState; + try + { + ::comphelper::ConfigurationHelper::readDirectKey(rxContext, + "org.openoffice.Setup/", + OUString::Concat("Office/Factories/*[\"") + sModuleName + "\"]", + "ooSetupFactoryWindowAttributes", + ::comphelper::EConfigurationModes::ReadOnly) >>= sWindowState; + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + { sWindowState.clear(); } + + return sWindowState; +} + +void PersistentWindowState::implst_setWindowStateOnConfig( + const css::uno::Reference< css::uno::XComponentContext >& rxContext, + std::u16string_view sModuleName, const OUString& sWindowState) +{ + try + { + ::comphelper::ConfigurationHelper::writeDirectKey(rxContext, + "org.openoffice.Setup/", + OUString::Concat("Office/Factories/*[\"") + sModuleName + "\"]", + "ooSetupFactoryWindowAttributes", + css::uno::Any(sWindowState), + ::comphelper::EConfigurationModes::Standard); + } + catch(const css::uno::RuntimeException&) + { throw; } + catch(const css::uno::Exception&) + {} +} + +OUString PersistentWindowState::implst_getWindowStateFromWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) +{ + OUString sWindowState; + + if (xWindow.is()) + { + // SOLAR SAFE -> ------------------------ + SolarMutexGuard aSolarGuard; + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow); + // check for system window is necessary to guarantee correct pointer cast! + if ( pWindow && pWindow->IsSystemWindow() ) + { + WindowStateMask const nMask = WindowStateMask::All & ~WindowStateMask::Minimized; + sWindowState = OStringToOUString( + static_cast<SystemWindow*>(pWindow.get())->GetWindowState(nMask), + RTL_TEXTENCODING_UTF8); + } + // <- SOLAR SAFE ------------------------ + } + + return sWindowState; +} + +void PersistentWindowState::implst_setWindowStateOnWindow(const css::uno::Reference< css::awt::XWindow >& xWindow , + std::u16string_view sWindowState) +{ + if ( + (!xWindow.is() ) || + ( sWindowState.empty() ) + ) + return; + + // SOLAR SAFE -> ------------------------ + SolarMutexGuard aSolarGuard; + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow); + if (!pWindow) + return; + + // check for system and work window - it's necessary to guarantee correct pointer cast! + bool bSystemWindow = pWindow->IsSystemWindow(); + bool bWorkWindow = (pWindow->GetType() == WindowType::WORKWINDOW); + + if (!bSystemWindow && !bWorkWindow) + return; + + SystemWindow* pSystemWindow = static_cast<SystemWindow*>(pWindow.get()); + WorkWindow* pWorkWindow = static_cast<WorkWindow* >(pWindow.get()); + + // don't save this special state! + if (pWorkWindow->IsMinimized()) + return; + + OUString sOldWindowState = OStringToOUString( pSystemWindow->GetWindowState(), RTL_TEXTENCODING_ASCII_US ); + if ( sOldWindowState != sWindowState ) + pSystemWindow->SetWindowState(OUStringToOString(sWindowState,RTL_TEXTENCODING_UTF8)); + // <- SOLAR SAFE ------------------------ +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/statusindicator.cxx b/framework/source/helper/statusindicator.cxx new file mode 100644 index 000000000..2deb4a0ae --- /dev/null +++ b/framework/source/helper/statusindicator.cxx @@ -0,0 +1,128 @@ +/* -*- 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 <comphelper/lok.hxx> +#include <helper/statusindicator.hxx> + +namespace framework +{ +StatusIndicator::StatusIndicator(StatusIndicatorFactory* pFactory) + : m_xFactory(pFactory) + , m_nRange(100) + , m_nLastCallbackPercent(-1) +{ +} + +StatusIndicator::~StatusIndicator() {} + +void SAL_CALL StatusIndicator::start(const OUString& sText, sal_Int32 nRange) +{ + if (comphelper::LibreOfficeKit::isActive()) + { + m_nRange = nRange; + m_nLastCallbackPercent = -1; + + comphelper::LibreOfficeKit::statusIndicatorStart(sText); + } +#if !defined(IOS) && !defined(ANDROID) + css::uno::Reference<css::task::XStatusIndicatorFactory> xFactory(m_xFactory); + if (xFactory.is()) + { + StatusIndicatorFactory* pFactory = static_cast<StatusIndicatorFactory*>(xFactory.get()); + pFactory->start(this, sText, nRange); + } +#else + (void)sText; +#endif +} + +void SAL_CALL StatusIndicator::end() +{ + if (comphelper::LibreOfficeKit::isActive()) + { + comphelper::LibreOfficeKit::statusIndicatorFinish(); + } +#if !defined(IOS) && !defined(ANDROID) + css::uno::Reference<css::task::XStatusIndicatorFactory> xFactory(m_xFactory); + if (xFactory.is()) + { + StatusIndicatorFactory* pFactory = static_cast<StatusIndicatorFactory*>(xFactory.get()); + pFactory->end(this); + } +#endif +} + +void SAL_CALL StatusIndicator::reset() +{ + if (comphelper::LibreOfficeKit::isActive()) + return; +#if !defined(IOS) && !defined(ANDROID) + css::uno::Reference<css::task::XStatusIndicatorFactory> xFactory(m_xFactory); + if (xFactory.is()) + { + StatusIndicatorFactory* pFactory = static_cast<StatusIndicatorFactory*>(xFactory.get()); + pFactory->reset(this); + } +#endif +} + +void SAL_CALL StatusIndicator::setText(const OUString& sText) +{ + if (comphelper::LibreOfficeKit::isActive()) + return; +#if !defined(IOS) && !defined(ANDROID) + css::uno::Reference<css::task::XStatusIndicatorFactory> xFactory(m_xFactory); + if (xFactory.is()) + { + StatusIndicatorFactory* pFactory = static_cast<StatusIndicatorFactory*>(xFactory.get()); + pFactory->setText(this, sText); + } +#else + (void)sText; +#endif +} + +void SAL_CALL StatusIndicator::setValue(sal_Int32 nValue) +{ + if (comphelper::LibreOfficeKit::isActive()) + { + if (m_nRange > 0) + { + int nPercent = (100 * nValue) / m_nRange; + if (nPercent >= m_nLastCallbackPercent) + { + comphelper::LibreOfficeKit::statusIndicatorSetValue(nPercent); + m_nLastCallbackPercent = nPercent; + } + } + return; + } +#if !defined(IOS) && !defined(ANDROID) + css::uno::Reference<css::task::XStatusIndicatorFactory> xFactory(m_xFactory); + if (xFactory.is()) + { + StatusIndicatorFactory* pFactory = static_cast<StatusIndicatorFactory*>(xFactory.get()); + pFactory->setValue(this, nValue); + } +#endif +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/statusindicatorfactory.cxx b/framework/source/helper/statusindicatorfactory.cxx new file mode 100644 index 000000000..e9e54df6b --- /dev/null +++ b/framework/source/helper/statusindicatorfactory.cxx @@ -0,0 +1,577 @@ +/* -*- 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 <algorithm> +#include <utility> +#include <helper/statusindicatorfactory.hxx> +#include <helper/statusindicator.hxx> +#include <helper/vclstatusindicator.hxx> +#include <properties.h> + +#include <com/sun/star/awt/XWindow2.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XLayoutManager2.hpp> + +#include <toolkit/helper/vclunohelper.hxx> + +#include <comphelper/sequenceashashmap.hxx> +#include <unotools/mediadescriptor.hxx> +#include <vcl/svapp.hxx> +#include <mutex> +#include <rtl/ref.hxx> + +#include <officecfg/Office/Common.hxx> + +namespace framework{ + +sal_Int32 StatusIndicatorFactory::m_nInReschedule = 0; ///< static counter for rescheduling + +constexpr OUStringLiteral PROGRESS_RESOURCE = u"private:resource/progressbar/progressbar"; + +StatusIndicatorFactory::StatusIndicatorFactory(css::uno::Reference< css::uno::XComponentContext > xContext) + : m_xContext (std::move(xContext )) + , m_bAllowReschedule (false) + , m_bAllowParentShow (false) + , m_bDisableReschedule(false) +{ +} + +StatusIndicatorFactory::~StatusIndicatorFactory() +{ + impl_stopWakeUpThread(); +} + +void SAL_CALL StatusIndicatorFactory::initialize(const css::uno::Sequence< css::uno::Any >& lArguments) +{ + if (lArguments.hasElements()) { + std::scoped_lock g(m_mutex); + + css::uno::Reference< css::frame::XFrame > xTmpFrame; + css::uno::Reference< css::awt::XWindow > xTmpWindow; + bool b1 = lArguments[0] >>= xTmpFrame; + bool b2 = lArguments[0] >>= xTmpWindow; + if (lArguments.getLength() == 3 && b1) { + // it's the first service constructor "createWithFrame" + m_xFrame = xTmpFrame; + lArguments[1] >>= m_bDisableReschedule; + lArguments[2] >>= m_bAllowParentShow; + } else if (lArguments.getLength() == 3 && b2) { + // it's the second service constructor "createWithWindow" + m_xPluggWindow = xTmpWindow; + lArguments[1] >>= m_bDisableReschedule; + lArguments[2] >>= m_bAllowParentShow; + } else { + // it's an old-style initialisation using properties + ::comphelper::SequenceAsHashMap lArgs(lArguments); + + m_xFrame = lArgs.getUnpackedValueOrDefault("Frame" , css::uno::Reference< css::frame::XFrame >()); + m_xPluggWindow = lArgs.getUnpackedValueOrDefault("Window" , css::uno::Reference< css::awt::XWindow >() ); + m_bAllowParentShow = lArgs.getUnpackedValueOrDefault("AllowParentShow" , false ); + m_bDisableReschedule = lArgs.getUnpackedValueOrDefault("DisableReschedule", false ); + } + } + +#ifdef EMSCRIPTEN + m_bDisableReschedule = true; +#endif + impl_createProgress(); +} + +css::uno::Reference< css::task::XStatusIndicator > SAL_CALL StatusIndicatorFactory::createStatusIndicator() +{ + return new StatusIndicator(this); +} + +void SAL_CALL StatusIndicatorFactory::update() +{ + std::scoped_lock g(m_mutex); + m_bAllowReschedule = true; +} + +void StatusIndicatorFactory::start(const css::uno::Reference< css::task::XStatusIndicator >& xChild, + const OUString& sText , + sal_Int32 nRange) +{ + css::uno::Reference< css::task::XStatusIndicator > xProgress; + // SAFE -> ---------------------------------- + { + std::scoped_lock aWriteLock(m_mutex); + + // create new info structure for this child or move it to the front of our stack + IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild); + if (pItem != m_aStack.end()) + m_aStack.erase(pItem); + IndicatorInfo aInfo(xChild, sText); + m_aStack.push_back (aInfo ); + + m_xActiveChild = xChild; + xProgress = m_xProgress; + } + // <- SAFE ---------------------------------- + + implts_makeParentVisibleIfAllowed(); + + if (xProgress.is()) + xProgress->start(sText, nRange); + + impl_startWakeUpThread(); + impl_reschedule(true); +} + +void StatusIndicatorFactory::reset(const css::uno::Reference< css::task::XStatusIndicator >& xChild) +{ + css::uno::Reference< css::task::XStatusIndicator > xActive; + css::uno::Reference< css::task::XStatusIndicator > xProgress; + // SAFE -> ---------------------------------- + { + std::scoped_lock aReadLock(m_mutex); + + // reset the internal info structure related to this child + IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild); + if (pItem != m_aStack.end()) + { + pItem->m_nValue = 0; + pItem->m_sText.clear(); + } + + xActive = m_xActiveChild; + xProgress = m_xProgress; + } + // <- SAFE ---------------------------------- + + // not the top most child => don't change UI + // But don't forget Reschedule! + if ( + (xChild == xActive) && + (xProgress.is() ) + ) + xProgress->reset(); + + impl_reschedule(true); +} + +void StatusIndicatorFactory::end(const css::uno::Reference< css::task::XStatusIndicator >& xChild) +{ + css::uno::Reference< css::task::XStatusIndicator > xActive; + css::uno::Reference< css::task::XStatusIndicator > xProgress; + OUString sText; + sal_Int32 nValue = 0; + // SAFE -> ---------------------------------- + { + std::scoped_lock aWriteLock(m_mutex); + + // remove this child from our stack + IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild); + if (pItem != m_aStack.end()) + m_aStack.erase(pItem); + + // activate next child ... or finish the progress if there is no further one. + m_xActiveChild.clear(); + IndicatorStack::reverse_iterator pNext = m_aStack.rbegin(); + if (pNext != m_aStack.rend()) + { + m_xActiveChild = pNext->m_xIndicator; + sText = pNext->m_sText; + nValue = pNext->m_nValue; + } + + xActive = m_xActiveChild; + xProgress = m_xProgress; + } + // <- SAFE ---------------------------------- + + if (xActive.is()) + { + // There is at least one further child indicator. + // Actualize our progress, so it shows these values from now. + if (xProgress.is()) + { + xProgress->setText (sText ); + xProgress->setValue(nValue); + } + } + else + { + // Our stack is empty. No further child exists. + // Se we must "end" our progress really + if (xProgress.is()) + xProgress->end(); + // Now hide the progress bar again. + impl_hideProgress(); + + impl_stopWakeUpThread(); + } + + impl_reschedule(true); +} + +void StatusIndicatorFactory::setText(const css::uno::Reference< css::task::XStatusIndicator >& xChild, + const OUString& sText ) +{ + css::uno::Reference< css::task::XStatusIndicator > xActive; + css::uno::Reference< css::task::XStatusIndicator > xProgress; + // SAFE -> ---------------------------------- + { + std::scoped_lock aWriteLock(m_mutex); + + IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild); + if (pItem != m_aStack.end()) + pItem->m_sText = sText; + + xActive = m_xActiveChild; + xProgress = m_xProgress; + } + // SAFE -> ---------------------------------- + + // paint only the top most indicator + // but don't forget to Reschedule! + if ( + (xChild == xActive) && + (xProgress.is() ) + ) + { + xProgress->setText(sText); + } + + impl_reschedule(true); +} + +void StatusIndicatorFactory::setValue( const css::uno::Reference< css::task::XStatusIndicator >& xChild , + sal_Int32 nValue ) +{ + sal_Int32 nOldValue = 0; + css::uno::Reference< css::task::XStatusIndicator > xActive; + css::uno::Reference< css::task::XStatusIndicator > xProgress; + // SAFE -> ---------------------------------- + { + std::scoped_lock aWriteLock(m_mutex); + + IndicatorStack::iterator pItem = ::std::find(m_aStack.begin(), m_aStack.end(), xChild); + if (pItem != m_aStack.end()) + { + nOldValue = pItem->m_nValue; + pItem->m_nValue = nValue; + } + + xActive = m_xActiveChild; + xProgress = m_xProgress; + } + // SAFE -> ---------------------------------- + + if ( + (xChild == xActive) && + (nOldValue != nValue ) && + (xProgress.is() ) + ) + { + xProgress->setValue(nValue); + } + + impl_reschedule(false); +} + +void StatusIndicatorFactory::implts_makeParentVisibleIfAllowed() +{ + css::uno::Reference< css::frame::XFrame > xFrame; + css::uno::Reference< css::awt::XWindow > xPluggWindow; + css::uno::Reference< css::uno::XComponentContext > xContext; + // SAFE -> ---------------------------------- + { + std::scoped_lock aReadLock(m_mutex); + + if (!m_bAllowParentShow) + return; + + xFrame = m_xFrame; + xPluggWindow = m_xPluggWindow; + xContext = m_xContext; + } + // <- SAFE ---------------------------------- + + css::uno::Reference< css::awt::XWindow > xParentWindow; + if (xFrame.is()) + xParentWindow = xFrame->getContainerWindow(); + else + xParentWindow = xPluggWindow; + + // don't disturb user in case he put the loading document into the background! + // Suppress any setVisible() or toFront() call in case the initial show was + // already made. + css::uno::Reference< css::awt::XWindow2 > xVisibleCheck(xParentWindow, css::uno::UNO_QUERY); + bool bIsVisible = false; + if (xVisibleCheck.is()) + bIsVisible = xVisibleCheck->isVisible(); + + if (bIsVisible) + { + impl_showProgress(); + return; + } + + // Check if the layout manager has been set to invisible state. It this case we are also + // not allowed to set the frame visible! + css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY); + if (xPropSet.is()) + { + css::uno::Reference< css::frame::XLayoutManager2 > xLayoutManager; + xPropSet->getPropertyValue(FRAME_PROPNAME_ASCII_LAYOUTMANAGER) >>= xLayoutManager; + if (xLayoutManager.is()) + { + if ( !xLayoutManager->isVisible() ) + return; + } + } + + // Ok the window should be made visible... because it is not currently visible. + // BUT..! + // We need a Hack for our applications: They get her progress from the frame directly + // on saving documents. Because there is no progress set on the MediaDescriptor. + // But that's wrong. In case the document was opened hidden, they should not use any progress .-( + // They only possible workaround: don't show the parent window here, if the document was opened hidden. + bool bHiddenDoc = false; + if (xFrame.is()) + { + css::uno::Reference< css::frame::XController > xController; + css::uno::Reference< css::frame::XModel > xModel; + xController = xFrame->getController(); + if (xController.is()) + xModel = xController->getModel(); + if (xModel.is()) + { + utl::MediaDescriptor lDocArgs(xModel->getArgs()); + bHiddenDoc = lDocArgs.getUnpackedValueOrDefault( + utl::MediaDescriptor::PROP_HIDDEN, + false); + } + } + + if (bHiddenDoc) + return; + + // OK: The document was not opened in hidden mode ... + // and the window isn't already visible. + // Show it and bring it to front. + // But before we have to be sure, that our internal used helper progress + // is visible too. + impl_showProgress(); + + SolarMutexGuard aSolarGuard; + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xParentWindow); + if ( pWindow ) + { + bool bForceFrontAndFocus(officecfg::Office::Common::View::NewDocumentHandling::ForceFocusAndToFront::get()); + pWindow->Show(true, bForceFrontAndFocus ? ShowFlags::ForegroundTask : ShowFlags::NONE ); + } + +} + +void StatusIndicatorFactory::impl_createProgress() +{ + css::uno::Reference< css::frame::XFrame > xFrame; + css::uno::Reference< css::awt::XWindow > xWindow; + // SAFE -> ---------------------------------- + { + std::scoped_lock aReadLock(m_mutex); + + xFrame = m_xFrame; + xWindow = m_xPluggWindow; + } + // <- SAFE ---------------------------------- + + css::uno::Reference< css::task::XStatusIndicator > xProgress; + + if (xWindow.is()) + { + // use vcl based progress implementation in plugged mode + xProgress = new VCLStatusIndicator(xWindow); + } + else if (xFrame.is()) + { + // use frame layouted progress implementation + css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY); + if (xPropSet.is()) + { + css::uno::Reference< css::frame::XLayoutManager2 > xLayoutManager; + xPropSet->getPropertyValue(FRAME_PROPNAME_ASCII_LAYOUTMANAGER) >>= xLayoutManager; + if (xLayoutManager.is()) + { + xLayoutManager->lock(); + OUString sPROGRESS_RESOURCE(PROGRESS_RESOURCE); + xLayoutManager->createElement( sPROGRESS_RESOURCE ); + xLayoutManager->hideElement( sPROGRESS_RESOURCE ); + + css::uno::Reference< css::ui::XUIElement > xProgressBar = xLayoutManager->getElement(sPROGRESS_RESOURCE); + if (xProgressBar.is()) + xProgress.set(xProgressBar->getRealInterface(), css::uno::UNO_QUERY); + xLayoutManager->unlock(); + } + } + } + + std::scoped_lock g(m_mutex); + m_xProgress = xProgress; +} + +void StatusIndicatorFactory::impl_showProgress() +{ + css::uno::Reference< css::frame::XFrame > xFrame; + // SAFE -> ---------------------------------- + { + std::scoped_lock aReadLock(m_mutex); + + xFrame = m_xFrame; + } + // <- SAFE ---------------------------------- + + css::uno::Reference< css::task::XStatusIndicator > xProgress; + + if (!xFrame.is()) + return; + + // use frame layouted progress implementation + css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY); + if (xPropSet.is()) + { + css::uno::Reference< css::frame::XLayoutManager2 > xLayoutManager; + xPropSet->getPropertyValue(FRAME_PROPNAME_ASCII_LAYOUTMANAGER) >>= xLayoutManager; + if (xLayoutManager.is()) + { + // Be sure that we have always a progress. It can be that our frame + // was recycled and therefore the progress was destroyed! + // CreateElement does nothing if there is already a valid progress. + OUString sPROGRESS_RESOURCE(PROGRESS_RESOURCE); + xLayoutManager->createElement( sPROGRESS_RESOURCE ); + xLayoutManager->showElement( sPROGRESS_RESOURCE ); + + css::uno::Reference< css::ui::XUIElement > xProgressBar = xLayoutManager->getElement(sPROGRESS_RESOURCE); + if (xProgressBar.is()) + xProgress.set(xProgressBar->getRealInterface(), css::uno::UNO_QUERY); + } + } + + std::scoped_lock g(m_mutex); + m_xProgress = xProgress; +} + +void StatusIndicatorFactory::impl_hideProgress() +{ + css::uno::Reference< css::frame::XFrame > xFrame; + // SAFE -> ---------------------------------- + { + std::scoped_lock aReadLock(m_mutex); + + xFrame = m_xFrame; + } + // <- SAFE ---------------------------------- + + if (xFrame.is()) + { + // use frame layouted progress implementation + css::uno::Reference< css::beans::XPropertySet > xPropSet(xFrame, css::uno::UNO_QUERY); + if (xPropSet.is()) + { + css::uno::Reference< css::frame::XLayoutManager2 > xLayoutManager; + xPropSet->getPropertyValue(FRAME_PROPNAME_ASCII_LAYOUTMANAGER) >>= xLayoutManager; + if (xLayoutManager.is()) + xLayoutManager->hideElement( PROGRESS_RESOURCE ); + } + } +} + +void StatusIndicatorFactory::impl_reschedule(bool bForce) +{ + // SAFE -> + { + std::scoped_lock aReadLock(m_mutex); + if (m_bDisableReschedule) + return; + } + // <- SAFE + + bool bReschedule = bForce; + if (!bReschedule) + { + std::scoped_lock g(m_mutex); + bReschedule = m_bAllowReschedule; + m_bAllowReschedule = false; + } + + if (!bReschedule) + return; + + static std::mutex rescheduleLock; + // SAFE -> + std::unique_lock aRescheduleGuard(rescheduleLock); + + if (m_nInReschedule != 0) + return; + + // coverity[missing_lock: FALSE] - coverity fails to see the aRescheduleGuard ctor as taking a lock + ++m_nInReschedule; + aRescheduleGuard.unlock(); + // <- SAFE + + { + SolarMutexGuard g; + Application::Reschedule(true); + } + + // SAFE -> + aRescheduleGuard.lock(); + --m_nInReschedule; +} + +void StatusIndicatorFactory::impl_startWakeUpThread() +{ + std::scoped_lock g(m_mutex); + + if (m_bDisableReschedule) + return; + + if (!m_pWakeUp.is()) + { + m_pWakeUp = new WakeUpThread(this); + m_pWakeUp->launch(); + } +} + +void StatusIndicatorFactory::impl_stopWakeUpThread() +{ + rtl::Reference<WakeUpThread> wakeUp; + { + std::scoped_lock g(m_mutex); + std::swap(wakeUp, m_pWakeUp); + } + if (wakeUp.is()) + { + wakeUp->stop(); + } +} + +} // namespace framework + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * +com_sun_star_comp_framework_StatusIndicatorFactory_get_implementation( + css::uno::XComponentContext *context, + css::uno::Sequence<css::uno::Any> const &) +{ + return cppu::acquire(new framework::StatusIndicatorFactory(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/tagwindowasmodified.cxx b/framework/source/helper/tagwindowasmodified.cxx new file mode 100644 index 000000000..b113c4b96 --- /dev/null +++ b/framework/source/helper/tagwindowasmodified.cxx @@ -0,0 +1,146 @@ +/* -*- 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 <helper/tagwindowasmodified.hxx> + +#include <com/sun/star/awt/XWindow.hpp> + +#include <com/sun/star/frame/FrameAction.hpp> + +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> +#include <tools/wintypes.hxx> + +namespace framework{ + +TagWindowAsModified::TagWindowAsModified() +{ +} + +TagWindowAsModified::~TagWindowAsModified() +{ +} + +void SAL_CALL TagWindowAsModified::initialize(const css::uno::Sequence< css::uno::Any >& lArguments) +{ + css::uno::Reference< css::frame::XFrame > xFrame; + + if (lArguments.hasElements()) + lArguments[0] >>= xFrame; + + if (!xFrame) + return; + + m_xFrame = xFrame; + xFrame->addFrameActionListener(this); + impl_update (xFrame); +} + +void SAL_CALL TagWindowAsModified::modified(const css::lang::EventObject& aEvent) +{ + if (!m_xModel || !m_xWindow || aEvent.Source != m_xModel) + return; + + bool bModified = m_xModel->isModified (); + + // SYNCHRONIZED -> + SolarMutexGuard aSolarGuard; + + if (m_xWindow->isDisposed()) + return; + + if (bModified) + m_xWindow->SetExtendedStyle(WindowExtendedStyle::DocModified); + else + m_xWindow->SetExtendedStyle(WindowExtendedStyle::NONE); + // <- SYNCHRONIZED +} + +void SAL_CALL TagWindowAsModified::frameAction(const css::frame::FrameActionEvent& aEvent) +{ + if ( + (aEvent.Action != css::frame::FrameAction_COMPONENT_REATTACHED) && + (aEvent.Action != css::frame::FrameAction_COMPONENT_ATTACHED ) + ) + return; + + if ( aEvent.Source != m_xFrame ) + return; + + impl_update (m_xFrame); +} + +void SAL_CALL TagWindowAsModified::disposing(const css::lang::EventObject& aEvent) +{ + SolarMutexGuard g; + + if (m_xFrame && aEvent.Source == m_xFrame) + { + m_xFrame->removeFrameActionListener(this); + m_xFrame.clear(); + return; + } + + if (m_xModel && aEvent.Source == m_xModel) + { + m_xModel->removeModifyListener(this); + m_xModel.clear(); + return; + } +} + +void TagWindowAsModified::impl_update (const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + if (!xFrame) + return; + + css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow (); + css::uno::Reference< css::frame::XController > xController = xFrame->getController (); + css::uno::Reference< css::util::XModifiable > xModel; + if (xController.is ()) + xModel = css::uno::Reference< css::util::XModifiable >(xController->getModel(), css::uno::UNO_QUERY); + + if (!xWindow || !xModel) + return; + + { + SolarMutexGuard g; + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow(xWindow); + bool bSystemWindow = pWindow->IsSystemWindow(); + bool bWorkWindow = (pWindow->GetType() == WindowType::WORKWINDOW); + if (!bSystemWindow && !bWorkWindow) + return; + + if (m_xModel) + m_xModel->removeModifyListener (this); + + // Note: frame was set as member outside ! we have to refresh connections + // regarding window and model only here. + m_xWindow = pWindow; + m_xModel = xModel; + } + + m_xModel->addModifyListener (this); +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/titlebarupdate.cxx b/framework/source/helper/titlebarupdate.cxx new file mode 100644 index 000000000..a9f27bd4a --- /dev/null +++ b/framework/source/helper/titlebarupdate.cxx @@ -0,0 +1,316 @@ +/* -*- 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 <helper/titlebarupdate.hxx> + +#include <properties.h> + +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <com/sun/star/frame/ModuleManager.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/frame/XTitle.hpp> +#include <com/sun/star/frame/XTitleChangeBroadcaster.hpp> + +#include <comphelper/sequenceashashmap.hxx> +#include <unotools/configmgr.hxx> +#include <utility> +#include <vcl/window.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> +#include <tools/diagnose_ex.h> + +namespace framework{ + +const ::sal_Int32 INVALID_ICON_ID = -1; +const ::sal_Int32 DEFAULT_ICON_ID = 0; + +TitleBarUpdate::TitleBarUpdate(css::uno::Reference< css::uno::XComponentContext > xContext) + : m_xContext (std::move(xContext )) +{ +} + +TitleBarUpdate::~TitleBarUpdate() +{ +} + +void SAL_CALL TitleBarUpdate::initialize(const css::uno::Sequence< css::uno::Any >& lArguments) +{ + // check arguments + css::uno::Reference< css::frame::XFrame > xFrame; + if (!lArguments.hasElements()) + throw css::lang::IllegalArgumentException( + "Empty argument list!", + static_cast< ::cppu::OWeakObject* >(this), + 1); + + lArguments[0] >>= xFrame; + if (!xFrame.is()) + throw css::lang::IllegalArgumentException( + "No valid frame specified!", + static_cast< ::cppu::OWeakObject* >(this), + 1); + + { + SolarMutexGuard g; + // hold the frame as weak reference(!) so it can die everytimes :-) + m_xFrame = xFrame; + } + + // start listening + xFrame->addFrameActionListener(this); + + css::uno::Reference< css::frame::XTitleChangeBroadcaster > xBroadcaster(xFrame, css::uno::UNO_QUERY); + if (xBroadcaster.is ()) + xBroadcaster->addTitleChangeListener (this); +} + +void SAL_CALL TitleBarUpdate::frameAction(const css::frame::FrameActionEvent& aEvent) +{ + // we are interested on events only, which must trigger a title bar update + // because component was changed. + if ( + (aEvent.Action == css::frame::FrameAction_COMPONENT_ATTACHED ) || + (aEvent.Action == css::frame::FrameAction_COMPONENT_REATTACHED) || + (aEvent.Action == css::frame::FrameAction_COMPONENT_DETACHING ) + ) + { + impl_forceUpdate (); + } +} + +void SAL_CALL TitleBarUpdate::titleChanged(const css::frame::TitleChangedEvent& /* aEvent */) +{ + impl_forceUpdate (); +} + +void SAL_CALL TitleBarUpdate::disposing(const css::lang::EventObject&) +{ + css::uno::Reference< css::frame::XFrame > xFrame(m_xFrame.get(), css::uno::UNO_QUERY); + if (xFrame.is()) + xFrame->removeFrameActionListener(this); + + // nothing todo here - because we hold the frame as weak reference only +} + +//http://live.gnome.org/GnomeShell/ApplicationBased +//http://msdn.microsoft.com/en-us/library/dd378459(v=VS.85).aspx +void TitleBarUpdate::impl_updateApplicationID(const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow (); + if ( ! xWindow.is() ) + return; + +#if !defined(MACOSX) + OUString sApplicationID; + try + { + css::uno::Reference< css::frame::XModuleManager2 > xModuleManager = + css::frame::ModuleManager::create( m_xContext ); + + OUString sDesktopName; + OUString aModuleId = xModuleManager->identify(xFrame); + if ( aModuleId.startsWith("com.sun.star.text.") || aModuleId.startsWith("com.sun.star.xforms.") ) + sDesktopName = "Writer"; + else if ( aModuleId.startsWith("com.sun.star.sheet.") ) + sDesktopName = "Calc"; + else if ( aModuleId.startsWith("com.sun.star.presentation.") ) + sDesktopName = "Impress"; + else if ( aModuleId.startsWith("com.sun.star.drawing." ) ) + sDesktopName = "Draw"; + else if ( aModuleId.startsWith("com.sun.star.formula." ) ) + sDesktopName = "Math"; + else if ( aModuleId.startsWith("com.sun.star.sdb.") ) + sDesktopName = "Base"; + else + sDesktopName = "Startcenter"; +#if defined(_WIN32) + // We use a hardcoded product name matching the registry keys so applications can be associated with file types + sApplicationID = "TheDocumentFoundation.LibreOffice." + sDesktopName; +#else + sApplicationID = utl::ConfigManager::getProductName().toAsciiLowerCase() + "-" + sDesktopName.toAsciiLowerCase(); +#endif + } + catch(const css::uno::Exception&) + { + } +#else + OUString const sApplicationID; +#endif + + // VCL SYNCHRONIZED -> + SolarMutexGuard aSolarGuard; + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow && pWindow->GetType() == WindowType::WORKWINDOW ) + { + WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get()); + pWorkWindow->SetApplicationID( sApplicationID ); + } + // <- VCL SYNCHRONIZED +} + +bool TitleBarUpdate::implst_getModuleInfo(const css::uno::Reference< css::frame::XFrame >& xFrame, + TModuleInfo& rInfo ) +{ + if ( ! xFrame.is ()) + return false; + + try + { + css::uno::Reference< css::frame::XModuleManager2 > xModuleManager = + css::frame::ModuleManager::create( m_xContext ); + + rInfo.sID = xModuleManager->identify(xFrame); + ::comphelper::SequenceAsHashMap lProps = xModuleManager->getByName (rInfo.sID); + + rInfo.nIcon = lProps.getUnpackedValueOrDefault (OFFICEFACTORY_PROPNAME_ASCII_ICON , INVALID_ICON_ID ); + + // Note: If we could retrieve a module id ... everything is OK. + // UIName and Icon ID are optional values ! + bool bSuccess = !rInfo.sID.isEmpty(); + return bSuccess; + } + catch(const css::uno::Exception&) + {} + + return false; +} + +void TitleBarUpdate::impl_forceUpdate() +{ + css::uno::Reference< css::frame::XFrame > xFrame; + { + SolarMutexGuard g; + xFrame.set(m_xFrame.get(), css::uno::UNO_QUERY); + } + + // frame already gone ? We hold it weak only ... + if ( ! xFrame.is()) + return; + + // no window -> no chance to set/update title and icon + css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow(); + if ( ! xWindow.is()) + return; + + impl_updateIcon (xFrame); + impl_updateTitle (xFrame); +#if !defined(MACOSX) + impl_updateApplicationID (xFrame); +#endif +} + +void TitleBarUpdate::impl_updateIcon(const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + css::uno::Reference< css::frame::XController > xController = xFrame->getController (); + css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow (); + + if ( + ( ! xController.is() ) || + ( ! xWindow.is() ) + ) + return; + + // a) set default value to an invalid one. So we can start further searches for right icon id, if + // first steps failed! + sal_Int32 nIcon = INVALID_ICON_ID; + + // b) try to find information on controller property set directly + // Don't forget to catch possible exceptions - because these property is an optional one! + css::uno::Reference< css::beans::XPropertySet > xSet( xController, css::uno::UNO_QUERY ); + if ( xSet.is() ) + { + try + { + css::uno::Reference< css::beans::XPropertySetInfo > const xPSI( xSet->getPropertySetInfo(), css::uno::UNO_SET_THROW ); + if ( xPSI->hasPropertyByName( "IconId" ) ) + xSet->getPropertyValue( "IconId" ) >>= nIcon; + } + catch(const css::uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("fwk"); + } + } + + // c) if b) failed ... identify the used module and retrieve set icon from module config. + // Tirck :-) Module was already specified outside and aInfo contains all needed information. + if ( nIcon == INVALID_ICON_ID ) + { + TModuleInfo aInfo; + if (implst_getModuleInfo(xFrame, aInfo)) + nIcon = aInfo.nIcon; + } + + // d) if all steps failed - use fallback :-) + // ... means using the global staroffice icon + if( nIcon == INVALID_ICON_ID ) + nIcon = DEFAULT_ICON_ID; + + // e) set icon on container window now + // Don't forget SolarMutex! We use vcl directly :-( + // Check window pointer for right WorkWindow class too!!! + + // VCL SYNCHRONIZED -> + SolarMutexGuard aSolarGuard; + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow && ( pWindow->GetType() == WindowType::WORKWINDOW ) ) + { + WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get()); + pWorkWindow->SetIcon( static_cast<sal_uInt16>(nIcon) ); + + css::uno::Reference< css::frame::XModel > xModel = xController->getModel(); + OUString aURL; + if( xModel.is() ) + aURL = xModel->getURL(); + pWorkWindow->SetRepresentedURL( aURL ); + } + // <- VCL SYNCHRONIZED +} + +void TitleBarUpdate::impl_updateTitle(const css::uno::Reference< css::frame::XFrame >& xFrame) +{ + // no window ... no chance to set any title -> return + css::uno::Reference< css::awt::XWindow > xWindow = xFrame->getContainerWindow (); + if ( ! xWindow.is() ) + return; + + css::uno::Reference< css::frame::XTitle > xTitle(xFrame, css::uno::UNO_QUERY); + if ( ! xTitle.is() ) + return; + + const OUString sTitle = xTitle->getTitle (); + + // VCL SYNCHRONIZED -> + SolarMutexGuard aSolarGuard; + + VclPtr<vcl::Window> pWindow = VCLUnoHelper::GetWindow( xWindow ); + if ( pWindow && ( pWindow->GetType() == WindowType::WORKWINDOW ) ) + { + WorkWindow* pWorkWindow = static_cast<WorkWindow*>(pWindow.get()); + pWorkWindow->SetText( sTitle ); + } + // <- VCL SYNCHRONIZED +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/uiconfigelementwrapperbase.cxx b/framework/source/helper/uiconfigelementwrapperbase.cxx new file mode 100644 index 000000000..95d5b4c65 --- /dev/null +++ b/framework/source/helper/uiconfigelementwrapperbase.cxx @@ -0,0 +1,481 @@ +/* -*- 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 <helper/uiconfigelementwrapperbase.hxx> +#include <properties.h> +#include <uielement/constitemcontainer.hxx> +#include <uielement/rootitemcontainer.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/ui/XUIConfiguration.hpp> + +#include <vcl/svapp.hxx> +#include <comphelper/sequence.hxx> + +const int UIELEMENT_PROPHANDLE_CONFIGSOURCE = 1; +const int UIELEMENT_PROPHANDLE_FRAME = 2; +const int UIELEMENT_PROPHANDLE_PERSISTENT = 3; +const int UIELEMENT_PROPHANDLE_RESOURCEURL = 4; +const int UIELEMENT_PROPHANDLE_TYPE = 5; +const int UIELEMENT_PROPHANDLE_XMENUBAR = 6; +const int UIELEMENT_PROPHANDLE_CONFIGLISTENER = 7; +const int UIELEMENT_PROPHANDLE_NOCLOSE = 8; +constexpr OUStringLiteral UIELEMENT_PROPNAME_CONFIGLISTENER = u"ConfigListener"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_CONFIGSOURCE = u"ConfigurationSource"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_FRAME = u"Frame"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_PERSISTENT = u"Persistent"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_RESOURCEURL = u"ResourceURL"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_TYPE = u"Type"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_XMENUBAR = u"XMenuBar"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_NOCLOSE = u"NoClose"; +using namespace com::sun::star::beans; +using namespace com::sun::star::uno; +using namespace com::sun::star::frame; +using namespace com::sun::star::lang; +using namespace com::sun::star::container; +using namespace ::com::sun::star::ui; + +namespace framework +{ + +UIConfigElementWrapperBase::UIConfigElementWrapperBase( sal_Int16 nType ) + : ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aMutex ) + , ::cppu::OPropertySetHelper ( *static_cast< ::cppu::OBroadcastHelper* >(this) ) + , m_nType ( nType ) + , m_bPersistent ( true ) + , m_bInitialized ( false ) + , m_bConfigListener ( false ) + , m_bConfigListening ( false ) + , m_bDisposed ( false ) + , m_bNoClose ( false ) + , m_aListenerContainer ( m_aMutex ) +{ +} + +UIConfigElementWrapperBase::~UIConfigElementWrapperBase() +{ +} + +Any SAL_CALL UIConfigElementWrapperBase::queryInterface( const Type& _rType ) +{ + Any aRet = UIConfigElementWrapperBase_BASE::queryInterface( _rType ); + if ( !aRet.hasValue() ) + aRet = OPropertySetHelper::queryInterface( _rType ); + return aRet; +} + +Sequence< Type > SAL_CALL UIConfigElementWrapperBase::getTypes( ) +{ + return comphelper::concatSequences( + UIConfigElementWrapperBase_BASE::getTypes(), + ::cppu::OPropertySetHelper::getTypes() + ); +} + +// XComponent +void SAL_CALL UIConfigElementWrapperBase::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) +{ + m_aListenerContainer.addInterface( cppu::UnoType<css::lang::XEventListener>::get(), xListener ); +} + +void SAL_CALL UIConfigElementWrapperBase::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& aListener ) +{ + m_aListenerContainer.removeInterface( cppu::UnoType<css::lang::XEventListener>::get(), aListener ); +} + +// XEventListener +void SAL_CALL UIConfigElementWrapperBase::disposing( const EventObject& ) +{ + SolarMutexGuard g; + m_xConfigSource.clear(); +} + +void SAL_CALL UIConfigElementWrapperBase::initialize( const Sequence< Any >& aArguments ) +{ + SolarMutexGuard g; + + if ( m_bInitialized ) + return; + + for ( const Any& rArg : aArguments ) + { + PropertyValue aPropValue; + if ( rArg >>= aPropValue ) + { + if ( aPropValue.Name == UIELEMENT_PROPNAME_CONFIGSOURCE ) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_CONFIGSOURCE, aPropValue.Value ); + else if ( aPropValue.Name == UIELEMENT_PROPNAME_FRAME ) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_FRAME, aPropValue.Value ); + else if ( aPropValue.Name == UIELEMENT_PROPNAME_PERSISTENT ) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_PERSISTENT, aPropValue.Value ); + else if ( aPropValue.Name == UIELEMENT_PROPNAME_RESOURCEURL ) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_RESOURCEURL, aPropValue.Value ); + else if ( aPropValue.Name == UIELEMENT_PROPNAME_TYPE ) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_TYPE, aPropValue.Value ); + else if ( aPropValue.Name == UIELEMENT_PROPNAME_CONFIGLISTENER ) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_CONFIGLISTENER, aPropValue.Value ); + else if ( aPropValue.Name == UIELEMENT_PROPNAME_NOCLOSE ) + setFastPropertyValue_NoBroadcast( UIELEMENT_PROPHANDLE_NOCLOSE, aPropValue.Value ); + } + } + + m_bInitialized = true; +} + +// XUpdatable +void SAL_CALL UIConfigElementWrapperBase::update() +{ + // can be implemented by derived class +} + +void SAL_CALL UIConfigElementWrapperBase::elementInserted( const css::ui::ConfigurationEvent& ) +{ + // can be implemented by derived class +} + +void SAL_CALL UIConfigElementWrapperBase::elementRemoved( const css::ui::ConfigurationEvent& ) +{ + // can be implemented by derived class +} + +void SAL_CALL UIConfigElementWrapperBase::elementReplaced( const css::ui::ConfigurationEvent& ) +{ + // can be implemented by derived class +} + +// XPropertySet helper +sal_Bool SAL_CALL UIConfigElementWrapperBase::convertFastPropertyValue( Any& aConvertedValue , + Any& aOldValue , + sal_Int32 nHandle , + const Any& aValue ) +{ + // Initialize state with sal_False !!! + // (Handle can be invalid) + bool bReturn = false; + + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_CONFIGLISTENER: + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_bConfigListener), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_CONFIGSOURCE: + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_xConfigSource), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_FRAME: + { + Reference< XFrame > xFrame( m_xWeakFrame ); + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(xFrame), + aValue, + aOldValue, + aConvertedValue); + } + break; + + case UIELEMENT_PROPHANDLE_PERSISTENT: + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_bPersistent), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_RESOURCEURL: + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_aResourceURL), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_TYPE : + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_nType), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_XMENUBAR : + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_xMenuBar), + aValue, + aOldValue, + aConvertedValue); + break; + + case UIELEMENT_PROPHANDLE_NOCLOSE: + bReturn = PropHelper::willPropertyBeChanged( + css::uno::Any(m_bNoClose), + aValue, + aOldValue, + aConvertedValue); + break; + } + + // Return state of operation. + return bReturn; +} + +void SAL_CALL UIConfigElementWrapperBase::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle , + const css::uno::Any& aValue ) +{ + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_CONFIGLISTENER: + { + bool bBool( m_bConfigListener ); + aValue >>= bBool; + if ( m_bConfigListener != bBool ) + { + if ( m_bConfigListening ) + { + if ( m_xConfigSource.is() && !bBool ) + { + try + { + Reference< XUIConfiguration > xUIConfig( m_xConfigSource, UNO_QUERY ); + if ( xUIConfig.is() ) + { + xUIConfig->removeConfigurationListener( Reference< XUIConfigurationListener >(this) ); + m_bConfigListening = false; + } + } + catch ( const Exception& ) + { + } + } + } + else + { + if ( m_xConfigSource.is() && bBool ) + { + try + { + Reference< XUIConfiguration > xUIConfig( m_xConfigSource, UNO_QUERY ); + if ( xUIConfig.is() ) + { + xUIConfig->addConfigurationListener( Reference< XUIConfigurationListener >(this) ); + m_bConfigListening = true; + } + } + catch ( const Exception& ) + { + } + } + } + + m_bConfigListener = bBool; + } + } + break; + case UIELEMENT_PROPHANDLE_CONFIGSOURCE: + aValue >>= m_xConfigSource; + break; + case UIELEMENT_PROPHANDLE_FRAME: + { + Reference< XFrame > xFrame; + + aValue >>= xFrame; + m_xWeakFrame = xFrame; + break; + } + case UIELEMENT_PROPHANDLE_PERSISTENT: + { + bool bBool( m_bPersistent ); + aValue >>= bBool; + m_bPersistent = bBool; + break; + } + case UIELEMENT_PROPHANDLE_RESOURCEURL: + aValue >>= m_aResourceURL; + break; + case UIELEMENT_PROPHANDLE_TYPE: + aValue >>= m_nType; + break; + case UIELEMENT_PROPHANDLE_XMENUBAR: + aValue >>= m_xMenuBar; + break; + case UIELEMENT_PROPHANDLE_NOCLOSE: + { + bool bBool( m_bNoClose ); + aValue >>= bBool; + m_bNoClose = bBool; + break; + } + } +} + +void SAL_CALL UIConfigElementWrapperBase::getFastPropertyValue( css::uno::Any& aValue , + sal_Int32 nHandle ) const +{ + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_CONFIGLISTENER: + aValue <<= m_bConfigListener; + break; + case UIELEMENT_PROPHANDLE_CONFIGSOURCE: + aValue <<= m_xConfigSource; + break; + case UIELEMENT_PROPHANDLE_FRAME: + { + Reference< XFrame > xFrame( m_xWeakFrame ); + aValue <<= xFrame; + break; + } + case UIELEMENT_PROPHANDLE_PERSISTENT: + aValue <<= m_bPersistent; + break; + case UIELEMENT_PROPHANDLE_RESOURCEURL: + aValue <<= m_aResourceURL; + break; + case UIELEMENT_PROPHANDLE_TYPE: + aValue <<= m_nType; + break; + case UIELEMENT_PROPHANDLE_XMENUBAR: + aValue <<= m_xMenuBar; + break; + case UIELEMENT_PROPHANDLE_NOCLOSE: + aValue <<= m_bNoClose; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL UIConfigElementWrapperBase::getInfoHelper() +{ + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static function, who will define a static propertytable. + // "true" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper ourInfoHelper( impl_getStaticPropertyDescriptor(), true ); + + return ourInfoHelper; +} + +css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL UIConfigElementWrapperBase::getPropertySetInfo() +{ + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + + return xInfo; +} + +css::uno::Sequence< css::beans::Property > UIConfigElementWrapperBase::impl_getStaticPropertyDescriptor() +{ + // Create property array to initialize sequence! + // Table of all predefined properties of this class. It's used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + return + { + css::beans::Property( UIELEMENT_PROPNAME_CONFIGLISTENER, UIELEMENT_PROPHANDLE_CONFIGLISTENER , cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::TRANSIENT ), + css::beans::Property( UIELEMENT_PROPNAME_CONFIGSOURCE, UIELEMENT_PROPHANDLE_CONFIGSOURCE , cppu::UnoType<css::ui::XUIConfigurationManager>::get(), css::beans::PropertyAttribute::TRANSIENT ), + css::beans::Property( UIELEMENT_PROPNAME_FRAME, UIELEMENT_PROPHANDLE_FRAME , cppu::UnoType<css::frame::XFrame>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), + css::beans::Property( UIELEMENT_PROPNAME_NOCLOSE, UIELEMENT_PROPHANDLE_NOCLOSE , cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::TRANSIENT ), + css::beans::Property( UIELEMENT_PROPNAME_PERSISTENT, UIELEMENT_PROPHANDLE_PERSISTENT , cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::TRANSIENT ), + css::beans::Property( UIELEMENT_PROPNAME_RESOURCEURL, UIELEMENT_PROPHANDLE_RESOURCEURL , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), + css::beans::Property( UIELEMENT_PROPNAME_TYPE, UIELEMENT_PROPHANDLE_TYPE , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), + css::beans::Property( UIELEMENT_PROPNAME_XMENUBAR, UIELEMENT_PROPHANDLE_XMENUBAR , cppu::UnoType<css::awt::XMenuBar>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ) + }; +} + +void SAL_CALL UIConfigElementWrapperBase::setSettings( const Reference< XIndexAccess >& xSettings ) +{ + SolarMutexClearableGuard aLock; + + if ( !xSettings.is() ) + return; + + // Create a copy of the data if the container is not const + Reference< XIndexReplace > xReplace( xSettings, UNO_QUERY ); + if ( xReplace.is() ) + m_xConfigData = new ConstItemContainer( xSettings ); + else + m_xConfigData = xSettings; + + if ( m_xConfigSource.is() && m_bPersistent ) + { + OUString aResourceURL( m_aResourceURL ); + Reference< XUIConfigurationManager > xUICfgMgr( m_xConfigSource ); + + aLock.clear(); + + try + { + xUICfgMgr->replaceSettings( aResourceURL, m_xConfigData ); + } + catch( const NoSuchElementException& ) + { + } + } + else if ( !m_bPersistent ) + { + // Transient menubar => Fill menubar with new data + impl_fillNewData(); + } +} +void UIConfigElementWrapperBase::impl_fillNewData() +{ +} +Reference< XIndexAccess > SAL_CALL UIConfigElementWrapperBase::getSettings( sal_Bool bWriteable ) +{ + SolarMutexGuard g; + + if ( bWriteable ) + return Reference< XIndexAccess >( new RootItemContainer( m_xConfigData ) ); + + return m_xConfigData; +} + +Reference< XFrame > SAL_CALL UIConfigElementWrapperBase::getFrame() +{ + SolarMutexGuard g; + Reference< XFrame > xFrame( m_xWeakFrame ); + return xFrame; +} + +OUString SAL_CALL UIConfigElementWrapperBase::getResourceURL() +{ + SolarMutexGuard g; + return m_aResourceURL; +} + +::sal_Int16 SAL_CALL UIConfigElementWrapperBase::getType() +{ + SolarMutexGuard g; + return m_nType; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/uielementwrapperbase.cxx b/framework/source/helper/uielementwrapperbase.cxx new file mode 100644 index 000000000..829e4f952 --- /dev/null +++ b/framework/source/helper/uielementwrapperbase.cxx @@ -0,0 +1,203 @@ +/* -*- 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 <helper/uielementwrapperbase.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> + +#include <vcl/svapp.hxx> +#include <comphelper/sequence.hxx> + +const int UIELEMENT_PROPHANDLE_RESOURCEURL = 1; +const int UIELEMENT_PROPHANDLE_TYPE = 2; +const int UIELEMENT_PROPHANDLE_FRAME = 3; +constexpr OUStringLiteral UIELEMENT_PROPNAME_RESOURCEURL = u"ResourceURL"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_TYPE = u"Type"; +constexpr OUStringLiteral UIELEMENT_PROPNAME_FRAME = u"Frame"; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; + +namespace framework +{ + +UIElementWrapperBase::UIElementWrapperBase( sal_Int16 nType ) + : ::cppu::OBroadcastHelperVar< ::cppu::OMultiTypeInterfaceContainerHelper, ::cppu::OMultiTypeInterfaceContainerHelper::keyType >( m_aMutex ) + , ::cppu::OPropertySetHelper ( *static_cast< ::cppu::OBroadcastHelper* >(this) ) + , m_aListenerContainer ( m_aMutex ) + , m_nType ( nType ) + , m_bInitialized ( false ) + , m_bDisposed ( false ) +{ +} + +UIElementWrapperBase::~UIElementWrapperBase() +{ +} + +Any SAL_CALL UIElementWrapperBase::queryInterface( const Type& _rType ) +{ + Any aRet = UIElementWrapperBase_BASE::queryInterface( _rType ); + if ( !aRet.hasValue() ) + aRet = OPropertySetHelper::queryInterface( _rType ); + return aRet; +} + +Sequence< Type > SAL_CALL UIElementWrapperBase::getTypes( ) +{ + return comphelper::concatSequences( + UIElementWrapperBase_BASE::getTypes(), + ::cppu::OPropertySetHelper::getTypes() + ); +} + +void SAL_CALL UIElementWrapperBase::addEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) +{ + m_aListenerContainer.addInterface( cppu::UnoType<css::lang::XEventListener>::get(), xListener ); +} + +void SAL_CALL UIElementWrapperBase::removeEventListener( const css::uno::Reference< css::lang::XEventListener >& xListener ) +{ + m_aListenerContainer.removeInterface( cppu::UnoType<css::lang::XEventListener>::get(), xListener ); +} + +void SAL_CALL UIElementWrapperBase::initialize( const Sequence< Any >& aArguments ) +{ + SolarMutexGuard g; + + if ( m_bInitialized ) + return; + + for ( const Any& rArg : aArguments ) + { + PropertyValue aPropValue; + if ( rArg >>= aPropValue ) + { + if ( aPropValue.Name == "ResourceURL" ) + aPropValue.Value >>= m_aResourceURL; + else if ( aPropValue.Name == "Frame" ) + { + Reference< XFrame > xFrame; + aPropValue.Value >>= xFrame; + m_xWeakFrame = xFrame; + } + } + } + + m_bInitialized = true; +} + +// XUIElement +css::uno::Reference< css::frame::XFrame > SAL_CALL UIElementWrapperBase::getFrame() +{ + css::uno::Reference< css::frame::XFrame > xFrame( m_xWeakFrame ); + return xFrame; +} + +OUString SAL_CALL UIElementWrapperBase::getResourceURL() +{ + return m_aResourceURL; +} + +::sal_Int16 SAL_CALL UIElementWrapperBase::getType() +{ + return m_nType; +} + +// XUpdatable +void SAL_CALL UIElementWrapperBase::update() +{ + // can be implemented by derived class +} + +// XPropertySet helper +sal_Bool SAL_CALL UIElementWrapperBase::convertFastPropertyValue( Any& /*aConvertedValue*/ , + Any& /*aOldValue*/ , + sal_Int32 /*nHandle*/ , + const Any& /*aValue*/ ) +{ + // Initialize state with sal_False !!! + // (Handle can be invalid) + return false; +} + +void SAL_CALL UIElementWrapperBase::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/ , + const css::uno::Any& /*aValue*/ ) +{ +} + +void SAL_CALL UIElementWrapperBase::getFastPropertyValue( css::uno::Any& aValue , + sal_Int32 nHandle ) const +{ + switch( nHandle ) + { + case UIELEMENT_PROPHANDLE_RESOURCEURL: + aValue <<= m_aResourceURL; + break; + case UIELEMENT_PROPHANDLE_TYPE: + aValue <<= m_nType; + break; + case UIELEMENT_PROPHANDLE_FRAME: + Reference< XFrame > xFrame( m_xWeakFrame ); + aValue <<= xFrame; + break; + } +} + +::cppu::IPropertyArrayHelper& SAL_CALL UIElementWrapperBase::getInfoHelper() +{ + // Define static member to give structure of properties to baseclass "OPropertySetHelper". + // "impl_getStaticPropertyDescriptor" is a non exported and static function, who will define a static propertytable. + // "true" say: Table is sorted by name. + static ::cppu::OPropertyArrayHelper ourInfoHelper( impl_getStaticPropertyDescriptor(), true ); + + return ourInfoHelper; +} + +css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL UIElementWrapperBase::getPropertySetInfo() +{ + // Create structure of propertysetinfo for baseclass "OPropertySetHelper". + // (Use method "getInfoHelper()".) + static css::uno::Reference< css::beans::XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); + + return xInfo; +} + +css::uno::Sequence< css::beans::Property > UIElementWrapperBase::impl_getStaticPropertyDescriptor() +{ + // Create a property array to initialize sequence! + // Table of all predefined properties of this class. It's used from OPropertySetHelper-class! + // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! + // It's necessary for methods of OPropertySetHelper. + // ATTENTION: + // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! + + return + { + css::beans::Property( UIELEMENT_PROPNAME_FRAME, UIELEMENT_PROPHANDLE_FRAME , cppu::UnoType<XFrame>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), + css::beans::Property( UIELEMENT_PROPNAME_RESOURCEURL, UIELEMENT_PROPHANDLE_RESOURCEURL , cppu::UnoType<sal_Int16>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ), + css::beans::Property( UIELEMENT_PROPNAME_TYPE, UIELEMENT_PROPHANDLE_TYPE , cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::TRANSIENT | css::beans::PropertyAttribute::READONLY ) + }; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/vclstatusindicator.cxx b/framework/source/helper/vclstatusindicator.cxx new file mode 100644 index 000000000..b493eacc7 --- /dev/null +++ b/framework/source/helper/vclstatusindicator.cxx @@ -0,0 +1,140 @@ +/* -*- 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 <helper/vclstatusindicator.hxx> + +#include <toolkit/helper/vclunohelper.hxx> +#include <utility> +#include <vcl/svapp.hxx> + +namespace framework { + +VCLStatusIndicator::VCLStatusIndicator(css::uno::Reference< css::awt::XWindow > xParentWindow) + : m_xParentWindow (std::move(xParentWindow )) + , m_pStatusBar (nullptr ) + , m_nRange (0 ) + , m_nValue (0 ) +{ + if (!m_xParentWindow.is()) + throw css::uno::RuntimeException( + "Can't work without a parent window!", + static_cast< css::task::XStatusIndicator* >(this)); +} + +VCLStatusIndicator::~VCLStatusIndicator() +{ +} + +void SAL_CALL VCLStatusIndicator::start(const OUString& sText , + sal_Int32 nRange) +{ + SolarMutexGuard aSolarGuard; + + VclPtr<vcl::Window> pParentWindow = VCLUnoHelper::GetWindow(m_xParentWindow); + if (!m_pStatusBar) + m_pStatusBar = VclPtr<StatusBar>::Create(pParentWindow, WB_3DLOOK|WB_BORDER); + + VCLStatusIndicator::impl_recalcLayout(m_pStatusBar, pParentWindow); + + m_pStatusBar->Show(); + m_pStatusBar->StartProgressMode(sText); + m_pStatusBar->SetProgressValue(0); + + // force repaint! + pParentWindow->Show(); + pParentWindow->Invalidate(InvalidateFlags::Children); + pParentWindow->GetOutDev()->Flush(); + + m_nRange = nRange; + m_nValue = 0; +} + +void SAL_CALL VCLStatusIndicator::reset() +{ + SolarMutexGuard aSolarGuard; + if (m_pStatusBar) + { + m_pStatusBar->SetProgressValue(0); + m_pStatusBar->SetText(OUString()); + } +} + +void SAL_CALL VCLStatusIndicator::end() +{ + SolarMutexGuard aSolarGuard; + + m_nRange = 0; + m_nValue = 0; + + if (m_pStatusBar) + { + m_pStatusBar->EndProgressMode(); + m_pStatusBar->Show(false); + + m_pStatusBar.disposeAndClear(); + } +} + +void SAL_CALL VCLStatusIndicator::setText(const OUString& sText) +{ + SolarMutexGuard aSolarGuard; + if (m_pStatusBar) + m_pStatusBar->SetText(sText); +} + +void SAL_CALL VCLStatusIndicator::setValue(sal_Int32 nValue) +{ + SolarMutexGuard aSolarGuard; + + if (nValue <= m_nRange) + m_nValue = nValue; + else + m_nValue = m_nRange; + + sal_Int32 nRange = m_nRange; + nValue = m_nValue; + + // normalize value to fit the range of 0-100% + sal_uInt16 nPercent = sal::static_int_cast< sal_uInt16 >( + ::std::min( + ((nValue*100) / ::std::max(nRange,sal_Int32(1))), sal_Int32(100))); + + if (m_pStatusBar) + m_pStatusBar->SetProgressValue(nPercent); +} + +void VCLStatusIndicator::impl_recalcLayout(vcl::Window* pStatusBar , + vcl::Window const * pParentWindow) +{ + if ( + (!pStatusBar ) || + (!pParentWindow) + ) + return; + + Size aParentSize = pParentWindow->GetSizePixel(); + pStatusBar->setPosSizePixel(0, + 0, + aParentSize.Width(), + aParentSize.Height()); +} + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/helper/wakeupthread.cxx b/framework/source/helper/wakeupthread.cxx new file mode 100644 index 000000000..40487c83b --- /dev/null +++ b/framework/source/helper/wakeupthread.cxx @@ -0,0 +1,60 @@ +/* -*- 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 <sal/config.h> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/util/XUpdatable.hpp> + +#include <helper/wakeupthread.hxx> +#include <chrono> + +using namespace std::chrono_literals; + +void framework::WakeUpThread::execute() { + for (;;) { + { + std::unique_lock g(mutex_); + condition_.wait_for(g, 25ms, [this] { return terminate_; }); + if (terminate_) { + break; + } + } + css::uno::Reference<css::util::XUpdatable> up(updatable_); + if (up.is()) { + up->update(); + } + } +} + +framework::WakeUpThread::WakeUpThread( + css::uno::Reference<css::util::XUpdatable> const & updatable): + Thread("WakeUpThread"), updatable_(updatable), terminate_(false) +{} + +void framework::WakeUpThread::stop() { + { + std::unique_lock g(mutex_); + terminate_ = true; + } + condition_.notify_one(); + join(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |