1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <loadenv/actionlockguard.hxx>
23 #include <com/sun/star/frame/XComponentLoader.hpp>
24 #include <com/sun/star/frame/XFrame.hpp>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 #include <com/sun/star/util/URL.hpp>
27 #include <rtl/ref.hxx>
28 #include <unotools/mediadescriptor.hxx>
29 #include <o3tl/typed_flags_set.hxx>
32 /** @short enable/disable special features
35 @desrc Such features must outcome without
36 any special parameters.
37 To make enabling/disabling of
38 features very easy (e.g. at the ctor of
39 this class) these values must be combinable
40 as flags. That means: its values must be in
43 enum class LoadEnvFeatures
45 /// we should be informed, if no feature is enabled :-)
47 /// enable using of UI elements during loading (means progress, interaction handler etcpp.)
49 /// enable loading of resources, which are not related to a target frame! (see concept of ContentHandler)
50 AllowContentHandler
= 2
53 template<> struct typed_flags
<LoadEnvFeatures
> : is_typed_flags
<LoadEnvFeatures
, 0x3> {};
59 class QuietInteraction
;
61 /** @short implements general mechanism for loading documents.
63 @descr An instance of this class can be used inside the API calls
64 XComponentLoader::loadComponentFromURL() and
65 XDispatch::dispatch().
70 /** @short classify a content.
72 @descr The load environment must know, if a content
73 is related to a target frame or not. Only "visible"
74 components, which fulfill the requirements of the
75 model-controller-view paradigm can be loaded into a frame.
76 Such contents are classified as E_CAN_BE_LOADED.
78 But e.g. for the dispatch framework exists special ContentHandler
79 objects, which can load a content in "non visible" mode ...
80 and do not need a target frame for its operation. Such
81 ContentHandler e.g. plays sounds.
82 Such contents are classified as E_CAN_BE_HANDLED.
84 And last but not least a content can be "not valid" in general.
88 /// identifies a content, which seems to be invalid in general
89 E_UNSUPPORTED_CONTENT
,
90 /// identifies a content, which can be used with a ContentHandler and is not related to a target frame
92 /// identifies a content, which can be loaded into a target frame
94 /// special mode for non real loading, In such case the model is given directly!
99 mutable osl::Mutex m_mutex
;
101 /** @short reference to a uno service manager, which must be used
102 to created on needed services on demand.
104 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
106 /** @short points to the frame, which uses this LoadEnv object
107 and must be used to start target search there.
109 css::uno::Reference
< css::frame::XFrame
> m_xBaseFrame
;
111 /** @short points to the frame, into which the new component was loaded.
113 @descr Note: This reference will be empty if loading failed
114 or a non visible content was loaded!
115 It can be the same frame as m_xBaseFrame it describe, in case
116 the target "_self", "" or the search flag "SELF" was used.
117 Otherwise it's the new created or recycled frame, which was
118 used for loading and contains further the new component.
120 Please use method getTarget() or getTargetComponent()
121 to return the frame/controller or model to any interested
122 user of the results of this load request.
124 css::uno::Reference
< css::frame::XFrame
> m_xTargetFrame
;
126 /** @short contains the name of the target, in which the specified resource
127 of this instance must be loaded.
131 /** @short if m_sTarget is not a special one, this flags regulate searching
134 sal_Int32 m_nSearchFlags
;
136 /** @short contains all needed information about the resource,
137 which should be loaded.
139 @descr Inside this struct e.g. the URL, its type and filter name,
140 the stream or a model directly are saved.
142 utl::MediaDescriptor m_lMediaDescriptor
;
144 /** @short because the mediadescriptor contains the complete URL ... but
145 some functionality need the structured version, we hold it twice :-(.
147 css::util::URL m_aURL
;
149 /** @short enable/disable special features of a load request. */
150 LoadEnvFeatures m_eFeature
;
152 /** @short classify the content, which should be loaded by this instance. */
153 EContentType m_eContentType
;
155 /** @short it indicates, that the member m_xTargetFrame was new created for this
156 load request and must be closed in case loading (not handling!)
157 operation failed. The default value is sal_False!
159 bool m_bCloseFrameOnError
;
161 /** @short it indicates, that the old document (which was located inside m_xBaseFrame
162 in combination with the m_sTarget value "_self") was suspended.
163 Normally it will be replaced by the new loaded document. But in case
164 loading (not handling!) failed, it must be reactivated.
165 The default value is sal_False!
167 bool m_bReactivateControllerOnError
;
169 /** @short it holds one (!) asynchronous used contenthandler or frameloader
170 alive, till the asynchronous operation will be finished.
172 css::uno::Reference
< css::uno::XInterface
> m_xAsynchronousJob
;
174 /** @short holds the information about the finished load process.
176 @descr The content of m_xTargetFrame can't be used as valid indicator,
177 (in case the existing old document was reactivated)
178 we must hold the result of the load process explicitly.
182 /** @short If we already brought it to front; do not do that again
183 (the user could switch elsewhere after the first activation,
184 and we shouldn't nag them again).
186 bool m_bFocusedAndToFront
= false;
188 /** @short holds an XActionLock on the internal used task member.
190 @seealso m_xTargetFrame
192 ActionLockGuard m_aTargetLock
;
194 rtl::Reference
<QuietInteraction
> m_pQuietInteraction
;
198 /** @short initialize a new instance of this load environment.
201 reference to a uno service manager, which can be used internally
202 to create on needed services on demand.
204 @throw Currently there is no reason to throw such exception!
206 @throw A RuntimeException in case any internal process indicates, that
207 the whole runtime can't be used any longer.
209 LoadEnv(css::uno::Reference
< css::uno::XComponentContext
> xContext
);
211 /** @short deinitialize an instance of this class in the right way.
215 /// @throws css::lang::IllegalArgumentException
216 /// @throws css::io::IOException
217 /// @throws css::uno::RuntimeException
218 static css::uno::Reference
< css::lang::XComponent
> loadComponentFromURL(const css::uno::Reference
< css::frame::XComponentLoader
>& xLoader
,
219 const css::uno::Reference
< css::uno::XComponentContext
>& xContext
,
220 const OUString
& sURL
,
221 const OUString
& sTarget
,
223 const css::uno::Sequence
< css::beans::PropertyValue
>& lArgs
);
225 /** @short start loading of a resource
227 @descr The parameter for targeting, the content description, and
228 some environment specifier (UI, dispatch functionality)
229 can be set here. Of course a still running load request
230 will be detected here and a suitable exception will be thrown.
231 Such constellation can be detected outside by using provided
232 synchronisation methods or callbacks.
234 There is no direct return value possible here. Because it depends
235 from the usage of this instance! E.g. for loading a "visible component"
236 a frame with a controller/model inside can be possible. For loading
237 of a "non visible component" only an information about a successfully start
239 Further it can't be guaranteed, that the internal process runs synchronous.
240 that's why we prefer using of specialized methods afterwards e.g. to:
241 - wait till the internal job will be finished
243 - or to let it run without any further control from outside.
246 points to the resource, which should be loaded.
248 @param lMediaDescriptor
249 contains additional information for the following load request.
252 points to the frame which must be used as start point for target search.
255 regulate searching/creating of frames, which should contain the
256 new loaded component afterwards.
259 regulate searching of targets, if sTarget is not a special one.
262 flag field, which enable/disable special features of this
263 new instance for following load call.
265 @throw A LoadEnvException e.g. if another load operation is till in progress
266 or initialization of a new one fail by other reasons.
267 The real reason, a suitable message and ID will be given here immediately.
269 @throw A RuntimeException in case any internal process indicates, that
270 the whole runtime can't be used any longer.
272 void startLoading(const OUString
& sURL
,
273 const css::uno::Sequence
< css::beans::PropertyValue
>& lMediaDescriptor
,
274 const css::uno::Reference
< css::frame::XFrame
>& xBaseFrame
,
275 const OUString
& sTarget
,
276 sal_Int32 nSearchFlags
,
277 LoadEnvFeatures eFeature
= LoadEnvFeatures::NONE
);
279 /** @short wait for an already running load request (started by calling
280 startLoading() before).
282 @descr The timeout parameter can be used to wait some times only
283 or forever. The return value indicates if the load request
284 was finished during the specified timeout period.
285 But it indicates not, if the load request was successful or not!
288 specify a timeout in [ms].
289 A value 0 let it wait forever!
291 @return sal_True if the started load process could be finished in time;
292 sal_False if the specified time was over.
294 @throw ... currently not used :-)
296 @throw A RuntimeException in case any internal process indicates, that
297 the whole runtime can't be used any longer.
299 bool waitWhileLoading(sal_uInt32 nTimeout
= 0);
301 /** TODO document me ... */
302 css::uno::Reference
< css::lang::XComponent
> getTargetComponent() const;
306 /** @short checks if the specified content can be handled by a
307 ContentHandler only and is not related to a target frame,
308 or if it can be loaded by a FrameLoader into a target frame
309 as "visible" component.
312 switch(classifyContent(...))
314 case E_CAN_BE_HANDLED :
318 case E_CAN_BE_LOADED :
319 xFrame = locateTargetFrame();
323 case E_NOT_A_CONTENT :
328 describe the content.
330 @param lMediaDescriptor
331 describe the content more detailed!
333 @return A suitable enum value, which classify the specified content.
335 static EContentType
classifyContent(const OUString
& sURL
,
336 const css::uno::Sequence
< css::beans::PropertyValue
>& lMediaDescriptor
);
338 /** TODO document me ... */
339 static void initializeUIDefaults(
340 const css::uno::Reference
< css::uno::XComponentContext
>& i_rxContext
,
341 utl::MediaDescriptor
& io_lMediaDescriptor
,
343 rtl::Reference
<QuietInteraction
>* o_ppQuiteInteraction
346 /** TODO document me ... */
347 void impl_setResult(bool bResult
);
349 /** TODO document me ... */
350 css::uno::Reference
< css::uno::XInterface
> impl_searchLoader();
352 /** @short it means; show the frame, bring it to front,
353 might set the right icon etcpp. in case loading was
354 successfully or reactivate a might existing old document or
355 close the frame if it was created before in case loading failed.
357 @throw A LoadEnvException only in cases, where an internal error indicates,
358 that the complete load environment seems to be not usable in general.
359 In such cases a RuntimeException would be to hard for the outside code :-)
361 @throw A RuntimeException in case any internal process indicates, that
362 the whole runtime can't be used any longer.
364 void impl_reactForLoadingState();
369 /** @short tries to detect the type and the filter of the specified content.
371 @descr This method update the available media descriptor of this instance,
372 so it contains the right type, a corresponding filter, may a
373 valid frame loader etc. In case detection failed, this descriptor
374 is corrected first, before a suitable exception will be thrown.
375 (Excepting a RuntimeException occurrence!)
377 @attention Not all types we know, are supported by filters. So it does not
378 indicates an error, if no suitable filter(loader etcpp will be found
379 for a type. But a type must be detected for the specified content.
380 Otherwise it's an error and loading can't be finished successfully.
382 @throw A LoadEnvException if detection failed.
384 @throw A RuntimeException in case any internal process indicates, that
385 the whole runtime can't be used any longer.
387 void impl_detectTypeAndFilter();
389 /** @short tries to use ContentHandler objects for loading.
391 @descr It searches for a suitable content handler object, registered
392 for the detected content type (must be done before by calling
393 impl_detectTypeAndFilter()). Because such handler does not depend
394 from a real target frame, location of such frame will be
396 In case handle failed all new created resources will be
397 removed before a suitable exception is thrown.
398 (Excepting a RuntimeException occurrence!)
402 @throw A LoadEnvException if handling failed.
404 @throw A RuntimeException in case any internal process indicates, that
405 the whole runtime can't be used any longer.
407 bool impl_handleContent();
409 /** @short tries to use FrameLoader objects for loading.
411 @descr First the target frame will be located. If it could be found
412 or new created a filter/frame loader will be instantiated and
413 used to load the content into this frame.
414 In case loading failed all new created resources will be
415 removed before a suitable exception is thrown.
416 (Excepting a RuntimeException occurrence!)
420 @throw A LoadEnvException if loading failed.
422 @throw A RuntimeException in case any internal process indicates, that
423 the whole runtime can't be used any longer.
425 bool impl_loadContent();
427 /** @short checks if the specified content is already loaded.
429 @descr It depends from the set target information, if such
430 search is allowed or not! So this method checks first,
431 if the target is the special one "_default".
432 If not it returns with an empty result immediately!
433 In case search is allowed, an existing document with the
434 same URL is searched. If it could be found, the corresponding
435 view will get the focus and this method return the corresponding frame.
436 Optional jumpmarks will be accepted here too. So the
437 view of the document will be updated to show the position
438 inside the document, which is related to the jumpmark.
440 @return A valid reference to the target frame, which contains the already loaded content
441 and could be activated successfully. An empty reference otherwise.
443 @throw A LoadEnvException only in cases, where an internal error indicates,
444 that the complete load environment seems to be not usable in general.
445 In such cases a RuntimeException would be to hard for the outside code :-)
447 @throw A RuntimeException in case any internal process indicates, that
448 the whole runtime can't be used any longer.
450 css::uno::Reference
< css::frame::XFrame
> impl_searchAlreadyLoaded();
452 /** @short search for any target frame, which seems to be usable
453 for this load request.
455 @descr Because this special feature is bound to the target specifier "_default"
456 its checked inside first. If it's not set => this method return an empty
457 reference. Otherwise any currently existing frame will be analyzed, if
458 it can be used here. The following rules exists:
461 <li>The frame must be empty ...</li>
462 <li>or contains an empty document of the same application module
463 which the new document will have (Note: the filter of the new content
464 must be well known here!)</li>
465 <li>and(!) this target must not be already used by any other load request.</li>
468 If a suitable target is located it will be locked. That's why the last rule
469 exists! If this method returns a valid frame reference, it was locked to be usable
470 for this load request only. (Don't forget to reset this state later!)
471 Concurrent LoadEnv instances can synchronize her work be using such locks :-) HOPEFULLY
473 @throw A LoadEnvException only in cases, where an internal error indicates,
474 that the complete load environment seems to be not usable in general.
475 In such cases a RuntimeException would be to hard for the outside code :-)
477 @throw A RuntimeException in case any internal process indicates, that
478 the whole runtime can't be used any longer.
480 css::uno::Reference
< css::frame::XFrame
> impl_searchRecycleTarget();
482 /** @short because showing of a frame is needed more than once...
483 it's implemented as a separate method .-)
485 @descr Note: Showing of a frame is bound to a special feature...
486 a) If we recycle any existing frame, we must bring it to front.
487 Showing of such frame is not needed really... because we recycle
489 b) If the document was already shown (e.g. by our progress implementation)
490 we do nothing here. The reason behind: The document was already shown...
491 and it was already make a top window...
492 If the user activated another frame inbetween (because loading needed some time)
493 it's not allowed to disturb the user again. Then the frame must resists in the background.
494 c) If the frame was not shown before... but loading of a visible document into this frame
495 was finished... we need both actions: setVisible() and toFront().
498 points to the container window of a frame.
501 if it's set to sal_False... showing of the window is done more intelligent.
502 setVisible() is called only if the window was not shown before.
503 This mode is needed by b) and c)
504 If it's set to sal_True... both actions has to be done: setVisible(), toFront()!
505 This mode is needed by a)
507 static void impl_makeFrameWindowVisible(const css::uno::Reference
< css::awt::XWindow
>& xWindow
,
510 /** @short checks whether a frame is already used for another load request or not.
512 @descr Such frames can't be used for our "recycle feature"!
515 the frame, which should be checked.
518 sal_True if this frame is already used for loading,
521 static bool impl_isFrameAlreadyUsedForLoading(const css::uno::Reference
< css::frame::XFrame
>& xFrame
);
523 /** @short try to determine the used application module
524 of this load request and apply right position and size
525 for this document window... hopefully before we show it .-)
527 void impl_applyPersistentWindowState(const css::uno::Reference
< css::awt::XWindow
>& xWindow
);
529 /** @short determine if it's allowed to open new document frames.
531 bool impl_furtherDocsAllowed();
533 /** @short jumps to the requested bookmark inside a given document.
535 void impl_jumpToMark(const css::uno::Reference
< css::frame::XFrame
>& xFrame
,
536 const css::util::URL
& aURL
);
538 /** @short determine if this loader has an interactive dialog shown before
539 loading the document.
541 bool impl_filterHasInteractiveDialog() const;
543 /** @short checks if this should bring to front and get focus on load,
544 according to user settings and to the load flags.
546 bool shouldFocusAndToFront() const;
549 } // namespace framework
551 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */