diff options
Diffstat (limited to 'framework/source/services/taskcreatorsrv.cxx')
-rw-r--r-- | framework/source/services/taskcreatorsrv.cxx | 404 |
1 files changed, 404 insertions, 0 deletions
diff --git a/framework/source/services/taskcreatorsrv.cxx b/framework/source/services/taskcreatorsrv.cxx new file mode 100644 index 000000000000..90bcdb93efbf --- /dev/null +++ b/framework/source/services/taskcreatorsrv.cxx @@ -0,0 +1,404 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_framework.hxx" +#include "services/taskcreatorsrv.hxx" + +//_______________________________________________ +// own includes +#include <helper/persistentwindowstate.hxx> +#include <helper/tagwindowasmodified.hxx> +#include <helper/titlebarupdate.hxx> +#include <threadhelp/readguard.hxx> +#include <threadhelp/writeguard.hxx> +#include <loadenv/targethelper.hxx> +#include <services.h> + +//_______________________________________________ +// interface includes +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XController.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/awt/WindowDescriptor.hpp> +#include <com/sun/star/awt/WindowAttribute.hpp> +#include <com/sun/star/awt/VclWindowPeerAttribute.hpp> + +//_______________________________________________ +// other includes +#include <svtools/colorcfg.hxx> +#include <vcl/svapp.hxx> + +#ifndef _TOOLKIT_HELPER_VCLUNOHELPER_HXX_ +#include <toolkit/unohlp.hxx> +#endif +#include <vcl/window.hxx> + +//_______________________________________________ +// namespaces + +namespace framework +{ + +//----------------------------------------------- +const ::rtl::OUString TaskCreatorService::ARGUMENT_PARENTFRAME = ::rtl::OUString::createFromAscii("ParentFrame" ); // XFrame +const ::rtl::OUString TaskCreatorService::ARGUMENT_FRAMENAME = ::rtl::OUString::createFromAscii("FrameName" ); // OUString +const ::rtl::OUString TaskCreatorService::ARGUMENT_MAKEVISIBLE = ::rtl::OUString::createFromAscii("MakeVisible" ); // sal_Bool +const ::rtl::OUString TaskCreatorService::ARGUMENT_CREATETOPWINDOW = ::rtl::OUString::createFromAscii("CreateTopWindow" ); // sal_Bool +const ::rtl::OUString TaskCreatorService::ARGUMENT_POSSIZE = ::rtl::OUString::createFromAscii("PosSize" ); // Rectangle +const ::rtl::OUString TaskCreatorService::ARGUMENT_CONTAINERWINDOW = ::rtl::OUString::createFromAscii("ContainerWindow" ); // XWindow +const ::rtl::OUString TaskCreatorService::ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE = ::rtl::OUString::createFromAscii("SupportPersistentWindowState" ); // sal_Bool +const ::rtl::OUString TaskCreatorService::ARGUMENT_ENABLE_TITLEBARUPDATE = ::rtl::OUString::createFromAscii("EnableTitleBarUpdate" ); // sal_Bool + +//----------------------------------------------- +DEFINE_XINTERFACE_3(TaskCreatorService , + OWeakObject , + DIRECT_INTERFACE(css::lang::XTypeProvider ), + DIRECT_INTERFACE(css::lang::XServiceInfo ), + DIRECT_INTERFACE(css::lang::XSingleServiceFactory)) + +//----------------------------------------------- +DEFINE_XTYPEPROVIDER_3(TaskCreatorService , + css::lang::XTypeProvider , + css::lang::XServiceInfo , + css::lang::XSingleServiceFactory) + +//----------------------------------------------- +DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(TaskCreatorService , + ::cppu::OWeakObject , + SERVICENAME_TASKCREATOR , + IMPLEMENTATIONNAME_FWK_TASKCREATOR) + +//----------------------------------------------- +DEFINE_INIT_SERVICE( + TaskCreatorService, + { + /*Attention + I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance() + to create a new instance of this class by our own supported service factory. + see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations! + */ + } + ) + +//----------------------------------------------- +TaskCreatorService::TaskCreatorService(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) + : ThreadHelpBase (&Application::GetSolarMutex()) + , ::cppu::OWeakObject( ) + , m_xSMGR (xSMGR ) +{ +} + +//----------------------------------------------- +TaskCreatorService::~TaskCreatorService() +{ +} + +//----------------------------------------------- +css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstance() + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + return createInstanceWithArguments(css::uno::Sequence< css::uno::Any >()); +} + +//----------------------------------------------- +css::uno::Reference< css::uno::XInterface > SAL_CALL TaskCreatorService::createInstanceWithArguments(const css::uno::Sequence< css::uno::Any >& lArguments) + throw(css::uno::Exception , + css::uno::RuntimeException) +{ + static ::rtl::OUString DEFAULTVAL_FRAMENAME = ::rtl::OUString(); + static sal_Bool DEFAULTVAL_MAKEVISIBLE = sal_False; + static sal_Bool DEFAULTVAL_CREATETOPWINDOW = sal_True; + static css::awt::Rectangle DEFAULTVAL_POSSIZE = css::awt::Rectangle(0, 0, 0, 0); // only possize=[0,0,0,0] triggers default handling of vcl ! + static sal_Bool DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE = sal_False; + static sal_Bool DEFAULTVAL_ENABLE_TITLEBARUPDATE = sal_True; + + ::comphelper::SequenceAsHashMap lArgs(lArguments); + + css::uno::Reference< css::frame::XFrame > xParentFrame = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_PARENTFRAME , css::uno::Reference< css::frame::XFrame >()); + ::rtl::OUString sFrameName = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_FRAMENAME , DEFAULTVAL_FRAMENAME ); + sal_Bool bVisible = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_MAKEVISIBLE , DEFAULTVAL_MAKEVISIBLE ); + sal_Bool bCreateTopWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CREATETOPWINDOW , DEFAULTVAL_CREATETOPWINDOW ); + css::awt::Rectangle aPosSize = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_POSSIZE , DEFAULTVAL_POSSIZE ); + css::uno::Reference< css::awt::XWindow > xContainerWindow = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_CONTAINERWINDOW , css::uno::Reference< css::awt::XWindow >() ); + sal_Bool bSupportPersistentWindowState = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_SUPPORTPERSISTENTWINDOWSTATE , DEFAULTVAL_SUPPORTPERSSISTENTWINDOWSTATE ); + sal_Bool bEnableTitleBarUpdate = lArgs.getUnpackedValueOrDefault(TaskCreatorService::ARGUMENT_ENABLE_TITLEBARUPDATE , DEFAULTVAL_ENABLE_TITLEBARUPDATE ); + + /* SAFE { */ + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aReadLock.unlock(); + /* } SAFE */ + + // We use FrameName property to set it as API name of the new created frame later. + // But those frame names must be different from the set of special target names as e.g. _blank, _self etcpp ! + ::rtl::OUString sRightName = impl_filterNames(sFrameName); + + // if no external frame window was given ... create a new one. + if ( ! xContainerWindow.is()) + { + css::uno::Reference< css::awt::XWindow > xParentWindow; + if (xParentFrame.is()) + xParentWindow = xParentFrame->getContainerWindow(); + + // Parent has no own window ... + // So we have to create a top level window always ! + if ( ! xParentWindow.is()) + bCreateTopWindow = sal_True; + + xContainerWindow = implts_createContainerWindow(xParentWindow, aPosSize, bCreateTopWindow); + } + + //-------------------> + // HACK #125187# + #i53630# + // Mark all document windows as "special ones", so VCL can bind + // special features to it. Because VCL doesnt know anything about documents ... + // Note: Doing so it's no longer supported, that e.g. our wizards can use findFrame(_blank) + // to create it's previes frames. They must do it manually by using WindowDescriptor+Toolkit! + css::uno::Reference< css::frame::XDesktop > xDesktop(xParentFrame, css::uno::UNO_QUERY); + ::sal_Bool bTopLevelDocumentWindow = ( + (sRightName.getLength () < 1) && + ( + (! xParentFrame.is() ) || + ( xDesktop.is() ) + ) + ); + if (bTopLevelDocumentWindow) + implts_applyDocStyleToWindow(xContainerWindow); + //-------------------> + + // create the new frame + css::uno::Reference< css::frame::XFrame > xFrame = implts_createFrame(xParentFrame, xContainerWindow, sRightName); + + // special freature: + // A special listener will restore pos/size states in case + // a component was loaded into the frame first time. + if (bSupportPersistentWindowState) + implts_establishWindowStateListener(xFrame); + + // special feature: On Mac we need tagging the window in case + // the underlying model was modified. + // VCL will ignore our calls in case different platform then Mac + // is used ... + if (bTopLevelDocumentWindow) + implts_establishDocModifyListener (xFrame); + + // special freature: + // A special listener will update title bar (text and icon) + // if component of frame will be changed. + if (bEnableTitleBarUpdate) + implts_establishTitleBarUpdate(xFrame); + + // Make it visible directly here ... + // if its required from outside. + if (bVisible) + xContainerWindow->setVisible(bVisible); + + return css::uno::Reference< css::uno::XInterface >(xFrame, css::uno::UNO_QUERY_THROW); +} + +//----------------------------------------------- +void TaskCreatorService::implts_applyDocStyleToWindow(const css::uno::Reference< css::awt::XWindow >& xWindow) const +{ + // SYNCHRONIZED -> + ::vos::OClearableGuard aSolarGuard(Application::GetSolarMutex()); + Window* pVCLWindow = VCLUnoHelper::GetWindow(xWindow); + if (pVCLWindow) + pVCLWindow->SetExtendedStyle(WB_EXT_DOCUMENT); + aSolarGuard.clear(); + // <- SYNCHRONIZED +} + +//----------------------------------------------- +css::uno::Reference< css::awt::XWindow > TaskCreatorService::implts_createContainerWindow( const css::uno::Reference< css::awt::XWindow >& xParentWindow , + const css::awt::Rectangle& aPosSize , + sal_Bool bTopWindow ) +{ + // SAFE -> + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aReadLock.unlock(); + // <- SAFE + + // get toolkit to create task container window + css::uno::Reference< css::awt::XToolkit > xToolkit( xSMGR->createInstance( SERVICENAME_VCLTOOLKIT ), css::uno::UNO_QUERY_THROW); + + // Check if child frames can be created realy. We need at least a valid window at the parent frame ... + css::uno::Reference< css::awt::XWindowPeer > xParentWindowPeer; + if ( ! bTopWindow) + { + if ( ! xParentWindow.is()) + bTopWindow = sal_False; + else + xParentWindowPeer = css::uno::Reference< css::awt::XWindowPeer >(xParentWindow, css::uno::UNO_QUERY_THROW); + } + + // describe window properties. + css::awt::WindowDescriptor aDescriptor; + if (bTopWindow) + { + aDescriptor.Type = css::awt::WindowClass_TOP ; + aDescriptor.WindowServiceName = DECLARE_ASCII("window") ; + aDescriptor.ParentIndex = -1 ; + aDescriptor.Parent = css::uno::Reference< css::awt::XWindowPeer >() ; + aDescriptor.Bounds = aPosSize ; + aDescriptor.WindowAttributes = css::awt::WindowAttribute::BORDER | + css::awt::WindowAttribute::MOVEABLE | + css::awt::WindowAttribute::SIZEABLE | + css::awt::WindowAttribute::CLOSEABLE | + css::awt::VclWindowPeerAttribute::CLIPCHILDREN ; + } + else + { + aDescriptor.Type = css::awt::WindowClass_TOP ; + aDescriptor.WindowServiceName = DECLARE_ASCII("dockingwindow") ; + aDescriptor.ParentIndex = 1 ; + aDescriptor.Parent = xParentWindowPeer ; + aDescriptor.Bounds = aPosSize ; + aDescriptor.WindowAttributes = css::awt::VclWindowPeerAttribute::CLIPCHILDREN ; + } + + // create a new blank container window and get access to parent container to append new created task. + css::uno::Reference< css::awt::XWindowPeer > xPeer = xToolkit->createWindow( aDescriptor ); + css::uno::Reference< css::awt::XWindow > xWindow ( xPeer, css::uno::UNO_QUERY ); + if ( ! xWindow.is()) + throw css::uno::Exception(::rtl::OUString::createFromAscii("TaskCreator service was not able to create suitable frame window."), + static_cast< ::cppu::OWeakObject* >(this)); + if (bTopWindow) + xPeer->setBackground(::svtools::ColorConfig().GetColorValue(::svtools::APPBACKGROUND).nColor); + else + xPeer->setBackground(0xffffffff); + + return xWindow; +} + +//----------------------------------------------- +css::uno::Reference< css::frame::XFrame > TaskCreatorService::implts_createFrame( const css::uno::Reference< css::frame::XFrame >& xParentFrame , + const css::uno::Reference< css::awt::XWindow >& xContainerWindow, + const ::rtl::OUString& sName ) +{ + // SAFE -> + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aReadLock.unlock(); + // <- SAFE + + // create new frame. + css::uno::Reference< css::frame::XFrame > xNewFrame( xSMGR->createInstance( SERVICENAME_FRAME ), css::uno::UNO_QUERY_THROW ); + + // Set window on frame. + // Do it before calling any other interface methods ... + // The new created frame must be initialized before you can do anything else there. + xNewFrame->initialize( xContainerWindow ); + + // Put frame to the frame tree. + // Note: The property creator/parent will be set on the new putted frame automaticly ... by the parent container. + if (xParentFrame.is()) + { + css::uno::Reference< css::frame::XFramesSupplier > xSupplier (xParentFrame, css::uno::UNO_QUERY_THROW); + css::uno::Reference< css::frame::XFrames > xContainer = xSupplier->getFrames(); + xContainer->append( xNewFrame ); + } + + // Set it's API name (if there is one from outside) + if (sName.getLength()) + xNewFrame->setName( sName ); + + return xNewFrame; +} + +//----------------------------------------------- +void TaskCreatorService::implts_establishWindowStateListener( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + // SAFE -> + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aReadLock.unlock(); + // <- SAFE + + // Special feature: It's allowed for frames using a top level window only! + // We must create a special listener service and couple it with the new created task frame. + // He will restore or save the window state of it ... + // See used classes for further informations too. + PersistentWindowState* pPersistentStateHandler = new PersistentWindowState(xSMGR); + css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pPersistentStateHandler), css::uno::UNO_QUERY_THROW); + + css::uno::Sequence< css::uno::Any > lInitData(1); + lInitData[0] <<= xFrame; + xInit->initialize(lInitData); +} + +//----------------------------------------------- +void TaskCreatorService::implts_establishDocModifyListener( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + // SAFE -> + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aReadLock.unlock(); + // <- SAFE + + // Special feature: It's allowed for frames using a top level window only! + // We must create a special listener service and couple it with the new created task frame. + // It will tag the window as modified if the underlying model was modified ... + TagWindowAsModified* pTag = new TagWindowAsModified(xSMGR); + css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pTag), css::uno::UNO_QUERY_THROW); + + css::uno::Sequence< css::uno::Any > lInitData(1); + lInitData[0] <<= xFrame; + xInit->initialize(lInitData); +} + +//----------------------------------------------- +void TaskCreatorService::implts_establishTitleBarUpdate( const css::uno::Reference< css::frame::XFrame >& xFrame ) +{ + // SAFE -> + ReadGuard aReadLock( m_aLock ); + css::uno::Reference< css::lang::XMultiServiceFactory > xSMGR = m_xSMGR; + aReadLock.unlock(); + // <- SAFE + + TitleBarUpdate* pHelper = new TitleBarUpdate (xSMGR); + css::uno::Reference< css::lang::XInitialization > xInit(static_cast< ::cppu::OWeakObject* >(pHelper), css::uno::UNO_QUERY_THROW); + + css::uno::Sequence< css::uno::Any > lInitData(1); + lInitData[0] <<= xFrame; + xInit->initialize(lInitData); +} + +//----------------------------------------------- +::rtl::OUString TaskCreatorService::impl_filterNames( const ::rtl::OUString& sName ) +{ + ::rtl::OUString sFiltered; + if (TargetHelper::isValidNameForFrame(sName)) + sFiltered = sName; + return sFiltered; +} + +} // namespace framework |