diff options
Diffstat (limited to 'framework/source/inc/loadenv/loadenv.hxx')
-rw-r--r-- | framework/source/inc/loadenv/loadenv.hxx | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/framework/source/inc/loadenv/loadenv.hxx b/framework/source/inc/loadenv/loadenv.hxx new file mode 100644 index 000000000..351d39b94 --- /dev/null +++ b/framework/source/inc/loadenv/loadenv.hxx @@ -0,0 +1,540 @@ +/* -*- 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 . + */ +#pragma once + +#include <loadenv/actionlockguard.hxx> + +#include <com/sun/star/frame/XComponentLoader.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/util/URL.hpp> +#include <rtl/ref.hxx> +#include <unotools/mediadescriptor.hxx> +#include <o3tl/typed_flags_set.hxx> + + +/** @short enable/disable special features + of a load request. + + @desrc Such features must outcome without + any special parameters. + To make enabling/disabling of + features very easy (e.g. at the ctor of + this class) these values must be combinable + as flags. That means: its values must be in + range of [2^n]! + */ +enum class LoadEnvFeatures +{ + /// we should be informed, if no feature is enabled :-) + NONE = 0, + /// enable using of UI elements during loading (means progress, interaction handler etcpp.) + WorkWithUI = 1, + /// enable loading of resources, which are not related to a target frame! (see concept of ContentHandler) + AllowContentHandler = 2 +}; +namespace o3tl { + template<> struct typed_flags<LoadEnvFeatures> : is_typed_flags<LoadEnvFeatures, 0x3> {}; +} + + +namespace framework { + +class QuietInteraction; + +/** @short implements general mechanism for loading documents. + + @descr An instance of this class can be used inside the API calls + XComponentLoader::loadComponentFromURL() and + XDispatch::dispatch(). + */ +class LoadEnv +{ +public: + /** @short classify a content. + + @descr The load environment must know, if a content + is related to a target frame or not. Only "visible" + components, which fulfill the requirements of the + model-controller-view paradigm can be loaded into a frame. + Such contents are classified as E_CAN_BE_LOADED. + + But e.g. for the dispatch framework exists special ContentHandler + objects, which can load a content in "non visible" mode ... + and do not need a target frame for its operation. Such + ContentHandler e.g. plays sounds. + Such contents are classified as E_CAN_BE_HANDLED. + + And last but not least a content can be "not valid" in general. + */ + enum EContentType + { + /// identifies a content, which seems to be invalid in general + E_UNSUPPORTED_CONTENT, + /// identifies a content, which can be used with a ContentHandler and is not related to a target frame + E_CAN_BE_HANDLED, + /// identifies a content, which can be loaded into a target frame + E_CAN_BE_LOADED, + /// special mode for non real loading, In such case the model is given directly! + E_CAN_BE_SET + }; + +private: + mutable osl::Mutex m_mutex; + + /** @short reference to a uno service manager, which must be used + to created on needed services on demand. + */ + css::uno::Reference< css::uno::XComponentContext > m_xContext; + + /** @short points to the frame, which uses this LoadEnv object + and must be used to start target search there. + */ + css::uno::Reference< css::frame::XFrame > m_xBaseFrame; + + /** @short points to the frame, into which the new component was loaded. + + @descr Note: This reference will be empty if loading failed + or a non visible content was loaded! + It can be the same frame as m_xBaseFrame it describe, in case + the target "_self", "" or the search flag "SELF" was used. + Otherwise it's the new created or recycled frame, which was + used for loading and contains further the new component. + + Please use method getTarget() or getTargetComponent() + to return the frame/controller or model to any interested + user of the results of this load request. + */ + css::uno::Reference< css::frame::XFrame > m_xTargetFrame; + + /** @short contains the name of the target, in which the specified resource + of this instance must be loaded. + */ + OUString m_sTarget; + + /** @short if m_sTarget is not a special one, this flags regulate searching + of a suitable one. + */ + sal_Int32 m_nSearchFlags; + + /** @short contains all needed information about the resource, + which should be loaded. + + @descr Inside this struct e.g. the URL, its type and filter name, + the stream or a model directly are saved. + */ + utl::MediaDescriptor m_lMediaDescriptor; + + /** @short because the mediadescriptor contains the complete URL ... but + some functionality need the structured version, we hold it twice :-(. + */ + css::util::URL m_aURL; + + /** @short enable/disable special features of a load request. */ + LoadEnvFeatures m_eFeature; + + /** @short classify the content, which should be loaded by this instance. */ + EContentType m_eContentType; + + /** @short it indicates, that the member m_xTargetFrame was new created for this + load request and must be closed in case loading (not handling!) + operation failed. The default value is sal_False! + */ + bool m_bCloseFrameOnError; + + /** @short it indicates, that the old document (which was located inside m_xBaseFrame + in combination with the m_sTarget value "_self") was suspended. + Normally it will be replaced by the new loaded document. But in case + loading (not handling!) failed, it must be reactivated. + The default value is sal_False! + */ + bool m_bReactivateControllerOnError; + + /** @short it holds one (!) asynchronous used contenthandler or frameloader + alive, till the asynchronous operation will be finished. + */ + css::uno::Reference< css::uno::XInterface > m_xAsynchronousJob; + + /** @short holds the information about the finished load process. + + @descr The content of m_xTargetFrame can't be used as valid indicator, + (in case the existing old document was reactivated) + we must hold the result of the load process explicitly. + */ + bool m_bLoaded; + + /** @short holds an XActionLock on the internal used task member. + + @seealso m_xTargetFrame + */ + ActionLockGuard m_aTargetLock; + + rtl::Reference<QuietInteraction> m_pQuietInteraction; + +public: + + /** @short initialize a new instance of this load environment. + + @param xContext + reference to a uno service manager, which can be used internally + to create on needed services on demand. + + @throw Currently there is no reason to throw such exception! + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + LoadEnv(css::uno::Reference< css::uno::XComponentContext > xContext); + + /** @short deinitialize an instance of this class in the right way. + */ + ~LoadEnv(); + + /// @throws css::lang::IllegalArgumentException + /// @throws css::io::IOException + /// @throws css::uno::RuntimeException + static css::uno::Reference< css::lang::XComponent > loadComponentFromURL(const css::uno::Reference< css::frame::XComponentLoader >& xLoader, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const OUString& sURL , + const OUString& sTarget, + sal_Int32 nFlags , + const css::uno::Sequence< css::beans::PropertyValue >& lArgs ); + + /** @short start loading of a resource + + @descr The parameter for targeting, the content description, and + some environment specifier (UI, dispatch functionality) + can be set here. Of course a still running load request + will be detected here and a suitable exception will be thrown. + Such constellation can be detected outside by using provided + synchronisation methods or callbacks. + + There is no direct return value possible here. Because it depends + from the usage of this instance! E.g. for loading a "visible component" + a frame with a controller/model inside can be possible. For loading + of a "non visible component" only an information about a successfully start + can be provided. + Further it can't be guaranteed, that the internal process runs synchronous. + that's why we prefer using of specialized methods afterwards e.g. to: + - wait till the internal job will be finished + and get the results + - or to let it run without any further control from outside. + + @param sURL + points to the resource, which should be loaded. + + @param lMediaDescriptor + contains additional information for the following load request. + + @param xBaseFrame + points to the frame which must be used as start point for target search. + + @param sTarget + regulate searching/creating of frames, which should contain the + new loaded component afterwards. + + @param nSearchFlags + regulate searching of targets, if sTarget is not a special one. + + @param eFeature + flag field, which enable/disable special features of this + new instance for following load call. + + @throw A LoadEnvException e.g. if another load operation is till in progress + or initialization of a new one fail by other reasons. + The real reason, a suitable message and ID will be given here immediately. + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + void startLoading(const OUString& sURL , + const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor, + const css::uno::Reference< css::frame::XFrame >& xBaseFrame , + const OUString& sTarget , + sal_Int32 nSearchFlags , + LoadEnvFeatures eFeature = LoadEnvFeatures::NONE); + + /** @short wait for an already running load request (started by calling + startLoading() before). + + @descr The timeout parameter can be used to wait some times only + or forever. The return value indicates if the load request + was finished during the specified timeout period. + But it indicates not, if the load request was successful or not! + + @param nTimeout + specify a timeout in [ms]. + A value 0 let it wait forever! + + @return sal_True if the started load process could be finished in time; + sal_False if the specified time was over. + + @throw ... currently not used :-) + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + bool waitWhileLoading(sal_uInt32 nTimeout = 0); + + /** TODO document me ... */ + css::uno::Reference< css::lang::XComponent > getTargetComponent() const; + +public: + + /** @short checks if the specified content can be handled by a + ContentHandler only and is not related to a target frame, + or if it can be loaded by a FrameLoader into a target frame + as "visible" component. + + @descr using: + switch(classifyContent(...)) + { + case E_CAN_BE_HANDLED : + handleIt(...); + break; + + case E_CAN_BE_LOADED : + xFrame = locateTargetFrame(); + loadIt(xFrame); + break; + + case E_NOT_A_CONTENT : + default : throw ...; + } + + @param sURL + describe the content. + + @param lMediaDescriptor + describe the content more detailed! + + @return A suitable enum value, which classify the specified content. + */ + static EContentType classifyContent(const OUString& sURL , + const css::uno::Sequence< css::beans::PropertyValue >& lMediaDescriptor); + + /** TODO document me ... */ + static void initializeUIDefaults( + const css::uno::Reference< css::uno::XComponentContext >& i_rxContext, + utl::MediaDescriptor& io_lMediaDescriptor, + const bool _bUIMode, + rtl::Reference<QuietInteraction>* o_ppQuiteInteraction + ); + + /** TODO document me ... */ + void impl_setResult(bool bResult); + + /** TODO document me ... */ + css::uno::Reference< css::uno::XInterface > impl_searchLoader(); + + /** @short it means; show the frame, bring it to front, + might set the right icon etcpp. in case loading was + successfully or reactivate a might existing old document or + close the frame if it was created before in case loading failed. + + @throw A LoadEnvException only in cases, where an internal error indicates, + that the complete load environment seems to be not usable in general. + In such cases a RuntimeException would be to hard for the outside code :-) + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + void impl_reactForLoadingState(); + +private: + void start(); + + /** @short tries to detect the type and the filter of the specified content. + + @descr This method update the available media descriptor of this instance, + so it contains the right type, a corresponding filter, may a + valid frame loader etc. In case detection failed, this descriptor + is corrected first, before a suitable exception will be thrown. + (Excepting a RuntimeException occurrence!) + + @attention Not all types we know, are supported by filters. So it does not + indicates an error, if no suitable filter(loader etcpp will be found + for a type. But a type must be detected for the specified content. + Otherwise it's an error and loading can't be finished successfully. + + @throw A LoadEnvException if detection failed. + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + void impl_detectTypeAndFilter(); + + /** @short tries to use ContentHandler objects for loading. + + @descr It searches for a suitable content handler object, registered + for the detected content type (must be done before by calling + impl_detectTypeAndFilter()). Because such handler does not depend + from a real target frame, location of such frame will be + suppressed here. + In case handle failed all new created resources will be + removed before a suitable exception is thrown. + (Excepting a RuntimeException occurrence!) + + @return TODO + + @throw A LoadEnvException if handling failed. + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + bool impl_handleContent(); + + /** @short tries to use FrameLoader objects for loading. + + @descr First the target frame will be located. If it could be found + or new created a filter/frame loader will be instantiated and + used to load the content into this frame. + In case loading failed all new created resources will be + removed before a suitable exception is thrown. + (Excepting a RuntimeException occurrence!) + + @return TODO + + @throw A LoadEnvException if loading failed. + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + bool impl_loadContent(); + + /** @short checks if the specified content is already loaded. + + @descr It depends from the set target information, if such + search is allowed or not! So this method checks first, + if the target is the special one "_default". + If not it returns with an empty result immediately! + In case search is allowed, an existing document with the + same URL is searched. If it could be found, the corresponding + view will get the focus and this method return the corresponding frame. + Optional jumpmarks will be accepted here too. So the + view of the document will be updated to show the position + inside the document, which is related to the jumpmark. + + @return A valid reference to the target frame, which contains the already loaded content + and could be activated successfully. An empty reference otherwise. + + @throw A LoadEnvException only in cases, where an internal error indicates, + that the complete load environment seems to be not usable in general. + In such cases a RuntimeException would be to hard for the outside code :-) + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + css::uno::Reference< css::frame::XFrame > impl_searchAlreadyLoaded(); + + /** @short search for any target frame, which seems to be usable + for this load request. + + @descr Because this special feature is bound to the target specifier "_default" + its checked inside first. If it's not set => this method return an empty + reference. Otherwise any currently existing frame will be analyzed, if + it can be used here. The following rules exists: + + <ul> + <li>The frame must be empty ...</li> + <li>or contains an empty document of the same application module + which the new document will have (Note: the filter of the new content + must be well known here!)</li> + <li>and(!) this target must not be already used by any other load request.</li> + </ul> + + If a suitable target is located it will be locked. That's why the last rule + exists! If this method returns a valid frame reference, it was locked to be usable + for this load request only. (Don't forget to reset this state later!) + Concurrent LoadEnv instances can synchronize her work be using such locks :-) HOPEFULLY + + @throw A LoadEnvException only in cases, where an internal error indicates, + that the complete load environment seems to be not usable in general. + In such cases a RuntimeException would be to hard for the outside code :-) + + @throw A RuntimeException in case any internal process indicates, that + the whole runtime can't be used any longer. + */ + css::uno::Reference< css::frame::XFrame > impl_searchRecycleTarget(); + + /** @short because showing of a frame is needed more than once... + it's implemented as a separate method .-) + + @descr Note: Showing of a frame is bound to a special feature... + a) If we recycle any existing frame, we must bring it to front. + Showing of such frame is not needed really... because we recycle + visible frames only! + b) If the document was already shown (e.g. by our progress implementation) + we do nothing here. The reason behind: The document was already shown... + and it was already make a top window... + If the user activated another frame inbetween (because loading needed some time) + it's not allowed to disturb the user again. Then the frame must resists in the background. + c) If the frame was not shown before... but loading of a visible document into this frame + was finished... we need both actions: setVisible() and toFront(). + + @param xWindow + points to the container window of a frame. + + @param bForceToFront + if it's set to sal_False... showing of the window is done more intelligent. + setVisible() is called only if the window was not shown before. + This mode is needed by b) and c) + If it's set to sal_True... both actions has to be done: setVisible(), toFront()! + This mode is needed by a) + */ + void impl_makeFrameWindowVisible(const css::uno::Reference< css::awt::XWindow >& xWindow , + bool bForceToFront); + + /** @short checks whether a frame is already used for another load request or not. + + @descr Such frames can't be used for our "recycle feature"! + + @param xFrame + the frame, which should be checked. + + @return [sal_Bool] + sal_True if this frame is already used for loading, + sal_False otherwise. + */ + bool impl_isFrameAlreadyUsedForLoading(const css::uno::Reference< css::frame::XFrame >& xFrame) const; + + /** @short try to determine the used application module + of this load request and apply right position and size + for this document window... hopefully before we show it .-) + */ + void impl_applyPersistentWindowState(const css::uno::Reference< css::awt::XWindow >& xWindow); + + /** @short determine if it's allowed to open new document frames. + */ + bool impl_furtherDocsAllowed(); + + /** @short jumps to the requested bookmark inside a given document. + */ + void impl_jumpToMark(const css::uno::Reference< css::frame::XFrame >& xFrame, + const css::util::URL& aURL ); + + /** @short determine if this loader has an interactive dialog shown before + loading the document. + */ + bool impl_filterHasInteractiveDialog() const; +}; + +} // namespace framework + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |