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 .
20 #include <com/sun/star/embed/Aspects.hpp>
21 #include <com/sun/star/frame/TaskCreator.hpp>
22 #include <com/sun/star/frame/XTitle.hpp>
23 #include <com/sun/star/frame/TerminationVetoException.hpp>
24 #include <com/sun/star/frame/XComponentLoader.hpp>
25 #include <com/sun/star/frame/XSynchronousFrameLoader.hpp>
26 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
28 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
29 #include <com/sun/star/util/CloseVetoException.hpp>
30 #include <com/sun/star/util/XCloseBroadcaster.hpp>
31 #include <com/sun/star/util/XCloseable.hpp>
32 #include <com/sun/star/container/XNameAccess.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/NamedValue.hpp>
36 #include <com/sun/star/frame/XModel.hpp>
37 #include <com/sun/star/frame/Desktop.hpp>
38 #include <com/sun/star/frame/XFramesSupplier.hpp>
39 #include <com/sun/star/frame/XControllerBorder.hpp>
40 #include <com/sun/star/util/XModifyBroadcaster.hpp>
41 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
42 #include <com/sun/star/awt/Toolkit.hpp>
43 #include <com/sun/star/awt/XTopWindow.hpp>
44 #include <com/sun/star/awt/PosSize.hpp>
45 #include <com/sun/star/awt/XView.hpp>
46 #include <com/sun/star/awt/WindowAttribute.hpp>
47 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
48 #include <com/sun/star/bridge/XBridgeSupplier2.hpp>
49 #include <com/sun/star/bridge/ModelDependent.hpp>
50 #include <com/sun/star/embed/XHatchWindow.hpp>
51 #include <com/sun/star/embed/HatchWindowFactory.hpp>
52 #include <com/sun/star/embed/XInplaceClient.hpp>
53 #include <com/sun/star/frame/XLayoutManager.hpp>
54 #include <com/sun/star/frame/XMenuBarMergingAcceptor.hpp>
55 #include <com/sun/star/frame/ModuleManager.hpp>
56 #include <com/sun/star/ui/XDockingAreaAcceptor.hpp>
57 #include <com/sun/star/ui/XUIElementSettings.hpp>
58 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
59 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
60 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
61 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
63 #include <com/sun/star/embed/EmbedMisc.hpp>
64 #include <com/sun/star/embed/EmbedStates.hpp>
65 #include <osl/diagnose.h>
66 #include <rtl/process.h>
67 #include <vcl/svapp.hxx>
68 #include <svtools/embedhlp.hxx>
69 #include <unotools/resmgr.hxx>
70 #include <vcl/settings.hxx>
71 #include <sfx2/strings.hrc>
73 #include <comphelper/processfactory.hxx>
74 #include <comphelper/namedvaluecollection.hxx>
76 #include <docholder.hxx>
77 #include <commonembobj.hxx>
78 #include <intercept.hxx>
80 #define HATCH_BORDER_WIDTH (((m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) && \
81 m_pEmbedObj->getCurrentState()!=embed::EmbedStates::UI_ACTIVE) ? 0 : 4 )
83 using namespace ::com::sun::star
;
89 explicit IntCounterGuard(sal_Int32
& rFlag
)
102 static void InsertMenu_Impl( const uno::Reference
< container::XIndexContainer
>& xTargetMenu
,
103 sal_Int32 nTargetIndex
,
104 const uno::Reference
< container::XIndexAccess
>& xSourceMenu
,
105 sal_Int32 nSourceIndex
,
106 const OUString
& aContModuleName
,
107 const uno::Reference
< frame::XDispatchProvider
>& xSourceDisp
)
110 OUString
aModuleIdentPropName( "ModuleIdentifier" );
111 OUString
aDispProvPropName( "DispatchProvider" );
112 bool bModuleNameSet
= false;
113 bool bDispProvSet
= false;
115 uno::Sequence
< beans::PropertyValue
> aSourceProps
;
116 xSourceMenu
->getByIndex( nSourceIndex
) >>= aSourceProps
;
117 uno::Sequence
< beans::PropertyValue
> aTargetProps( aSourceProps
.getLength() );
118 for ( nInd
= 0; nInd
< aSourceProps
.getLength(); nInd
++ )
120 aTargetProps
[nInd
].Name
= aSourceProps
[nInd
].Name
;
121 if ( !aContModuleName
.isEmpty() && aTargetProps
[nInd
].Name
== aModuleIdentPropName
)
123 aTargetProps
[nInd
].Value
<<= aContModuleName
;
124 bModuleNameSet
= true;
126 else if ( aTargetProps
[nInd
].Name
== aDispProvPropName
)
128 aTargetProps
[nInd
].Value
<<= xSourceDisp
;
132 aTargetProps
[nInd
].Value
= aSourceProps
[nInd
].Value
;
135 if ( !bModuleNameSet
&& !aContModuleName
.isEmpty() )
137 aTargetProps
.realloc( ++nInd
);
138 aTargetProps
[nInd
-1].Name
= aModuleIdentPropName
;
139 aTargetProps
[nInd
-1].Value
<<= aContModuleName
;
142 if ( !bDispProvSet
&& xSourceDisp
.is() )
144 aTargetProps
.realloc( ++nInd
);
145 aTargetProps
[nInd
-1].Name
= aDispProvPropName
;
146 aTargetProps
[nInd
-1].Value
<<= xSourceDisp
;
149 xTargetMenu
->insertByIndex( nTargetIndex
, uno::makeAny( aTargetProps
) );
153 DocumentHolder::DocumentHolder( const uno::Reference
< uno::XComponentContext
>& xContext
,
154 OCommonEmbeddedObject
* pEmbObj
)
155 : m_pEmbedObj( pEmbObj
),
156 m_xContext( xContext
),
157 m_bReadOnly( false ),
158 m_bWaitForClose( false ),
159 m_bAllowClosing( false ),
160 m_bDesktopTerminated( false ),
161 m_nNoBorderResizeReact( 0 ),
162 m_nNoResizeReact( 0 )
164 m_aOutplaceFrameProps
.realloc( 3 );
165 beans::NamedValue aArg
;
167 aArg
.Name
= "TopWindow";
169 m_aOutplaceFrameProps
[0] <<= aArg
;
171 aArg
.Name
= "MakeVisible";
172 aArg
.Value
<<= false;
173 m_aOutplaceFrameProps
[1] <<= aArg
;
175 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( m_xContext
);
179 xDesktop
->addTerminateListener( this );
181 catch ( const uno::Exception
& )
186 aArg
.Name
= "ParentFrame";
187 aArg
.Value
<<= xDesktop
; //TODO/LATER: should use parent document frame
188 m_aOutplaceFrameProps
[2] <<= aArg
;
192 DocumentHolder::~DocumentHolder()
194 m_refCount
++; // to allow deregistration as a listener
199 if ( m_xComponent
.is() )
202 CloseDocument( true, false );
203 } catch( const uno::Exception
& ) {}
206 if ( m_xInterceptor
.is() )
208 m_xInterceptor
->DisconnectDocHolder();
209 m_xInterceptor
.clear();
212 if ( !m_bDesktopTerminated
)
217 void DocumentHolder::CloseFrame()
219 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xFrame
, uno::UNO_QUERY
);
220 if ( xCloseBroadcaster
.is() )
221 xCloseBroadcaster
->removeCloseListener( static_cast<util::XCloseListener
*>(this) );
223 uno::Reference
<util::XCloseable
> xCloseable(
224 m_xFrame
,uno::UNO_QUERY
);
225 if( xCloseable
.is() )
227 xCloseable
->close( true );
229 catch( const uno::Exception
& ) {
232 uno::Reference
<lang::XComponent
> xComp( m_xFrame
,uno::UNO_QUERY
);
237 uno::Reference
< lang::XComponent
> xComp( m_xHatchWindow
, uno::UNO_QUERY
);
241 m_xHatchWindow
.clear();
242 m_xOwnWindow
.clear();
247 void DocumentHolder::FreeOffice()
249 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( m_xContext
);
250 xDesktop
->removeTerminateListener( this );
252 // the following code is commented out since for now there is still no completely correct way to detect
253 // whether the office can be terminated, so it is better to have unnecessary process running than
256 // uno::Reference< frame::XFramesSupplier > xFramesSupplier( xDesktop, uno::UNO_QUERY );
257 // if ( xFramesSupplier.is() )
259 // uno::Reference< frame::XFrames > xFrames = xFramesSupplier->getFrames();
260 // if ( xFrames.is() && !xFrames->hasElements() )
264 // xDesktop->terminate();
266 // catch( uno::Exception & )
273 void DocumentHolder::CloseDocument( bool bDeliverOwnership
, bool bWaitForClose
)
275 uno::Reference
< util::XCloseBroadcaster
> xBroadcaster( m_xComponent
, uno::UNO_QUERY
);
276 if ( xBroadcaster
.is() )
278 uno::Reference
< document::XEventBroadcaster
> xEventBroadcaster( m_xComponent
, uno::UNO_QUERY
);
279 if ( xEventBroadcaster
.is() )
280 xEventBroadcaster
->removeEventListener( static_cast<document::XEventListener
*>(this) );
283 // the object does not support document::XEventBroadcaster interface
284 // use the workaround, register for modified events
285 uno::Reference
< util::XModifyBroadcaster
> xModifyBroadcaster( m_xComponent
, uno::UNO_QUERY
);
286 if ( xModifyBroadcaster
.is() )
287 xModifyBroadcaster
->removeModifyListener( static_cast<util::XModifyListener
*>(this) );
290 uno::Reference
< util::XCloseable
> xCloseable( xBroadcaster
, uno::UNO_QUERY
);
291 if ( xCloseable
.is() )
293 m_bAllowClosing
= true;
294 m_bWaitForClose
= bWaitForClose
;
295 xCloseable
->close( bDeliverOwnership
);
299 m_xComponent
= nullptr;
303 void DocumentHolder::PlaceFrame( const awt::Rectangle
& aNewRect
)
305 OSL_ENSURE( m_xFrame
.is() && m_xOwnWindow
.is(),
306 "The object does not have windows required for inplace mode!" );
308 //TODO: may need mutex locking???
309 if ( m_xFrame
.is() && m_xOwnWindow
.is() )
311 // the frame can be replaced only in inplace mode
312 frame::BorderWidths aOldWidths
;
313 IntCounterGuard
aGuard( m_nNoBorderResizeReact
);
317 aOldWidths
= m_aBorderWidths
;
319 awt::Rectangle aHatchRect
= AddBorderToArea( aNewRect
);
321 ResizeWindows_Impl( aHatchRect
);
323 } while ( aOldWidths
.Left
!= m_aBorderWidths
.Left
324 || aOldWidths
.Top
!= m_aBorderWidths
.Top
325 || aOldWidths
.Right
!= m_aBorderWidths
.Right
326 || aOldWidths
.Bottom
!= m_aBorderWidths
.Bottom
);
328 m_aObjRect
= aNewRect
;
333 void DocumentHolder::ResizeWindows_Impl( const awt::Rectangle
& aHatchRect
)
335 OSL_ENSURE( m_xFrame
.is() && m_xOwnWindow
.is() /*&& m_xHatchWindow.is()*/,
336 "The object does not have windows required for inplace mode!" );
337 if ( m_xHatchWindow
.is() )
339 m_xOwnWindow
->setPosSize( HATCH_BORDER_WIDTH
,
341 aHatchRect
.Width
- 2*HATCH_BORDER_WIDTH
,
342 aHatchRect
.Height
- 2*HATCH_BORDER_WIDTH
,
343 awt::PosSize::POSSIZE
);
346 m_xHatchWindow
->setPosSize( aHatchRect
.X
,
350 awt::PosSize::POSSIZE
);
353 m_xOwnWindow
->setPosSize( aHatchRect
.X
+ HATCH_BORDER_WIDTH
,
354 aHatchRect
.Y
+ HATCH_BORDER_WIDTH
,
355 aHatchRect
.Width
- 2*HATCH_BORDER_WIDTH
,
356 aHatchRect
.Height
- 2*HATCH_BORDER_WIDTH
,
357 awt::PosSize::POSSIZE
);
361 bool DocumentHolder::SetFrameLMVisibility( const uno::Reference
< frame::XFrame
>& xFrame
, bool bVisible
)
363 bool bResult
= false;
367 uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
368 uno::Reference
< beans::XPropertySet
> xPropSet( xFrame
, uno::UNO_QUERY_THROW
);
369 xPropSet
->getPropertyValue("LayoutManager") >>= xLayoutManager
;
370 if ( xLayoutManager
.is() )
372 xLayoutManager
->setVisible( bVisible
);
374 // MBA: locking is done only on the container LM, because it is not about hiding windows, it's about
375 // giving up control over the component window (and stopping to listen for resize events of the container window)
377 xLayoutManager
->unlock();
379 xLayoutManager
->lock();
384 catch( const uno::Exception
& )
391 bool DocumentHolder::ShowInplace( const uno::Reference
< awt::XWindowPeer
>& xParent
,
392 const awt::Rectangle
& aRectangleToShow
,
393 const uno::Reference
< frame::XDispatchProvider
>& xContDisp
)
395 OSL_ENSURE( !m_xFrame
.is(), "A frame exists already!" );
397 if ( !m_xFrame
.is() )
399 uno::Reference
< frame::XModel
> xModel( GetComponent(), uno::UNO_QUERY
);
400 awt::Rectangle aHatchRectangle
= AddBorderToArea( aRectangleToShow
);
402 awt::Rectangle
aOwnRectangle( HATCH_BORDER_WIDTH
,
404 aHatchRectangle
.Width
- 2*HATCH_BORDER_WIDTH
,
405 aHatchRectangle
.Height
- 2*HATCH_BORDER_WIDTH
);
406 uno::Reference
< awt::XWindow
> xHWindow
;
407 uno::Reference
< awt::XWindowPeer
> xMyParent( xParent
);
412 uno::Reference
< embed::XHatchWindowFactory
> xHatchFactory
=
413 embed::HatchWindowFactory::create(m_xContext
);
415 uno::Reference
< embed::XHatchWindow
> xHatchWindow
=
416 xHatchFactory
->createHatchWindowInstance( xParent
,
418 awt::Size( HATCH_BORDER_WIDTH
, HATCH_BORDER_WIDTH
) );
420 uno::Reference
< awt::XWindowPeer
> xHatchWinPeer( xHatchWindow
, uno::UNO_QUERY
);
421 xHWindow
.set( xHatchWinPeer
, uno::UNO_QUERY_THROW
);
423 xHatchWindow
->setController( uno::Reference
< embed::XHatchWindowController
>(
424 static_cast< embed::XHatchWindowController
* >( this ) ) );
426 xMyParent
= xHatchWinPeer
;
430 aOwnRectangle
.X
+= aHatchRectangle
.X
;
431 aOwnRectangle
.Y
+= aHatchRectangle
.Y
;
434 awt::WindowDescriptor
aOwnWinDescriptor( awt::WindowClass_TOP
,
438 awt::Rectangle(),//aOwnRectangle,
439 awt::WindowAttribute::SHOW
| awt::VclWindowPeerAttribute::CLIPCHILDREN
);
441 uno::Reference
< awt::XToolkit2
> xToolkit
= awt::Toolkit::create(m_xContext
);
443 uno::Reference
< awt::XWindowPeer
> xNewWinPeer
= xToolkit
->createWindow( aOwnWinDescriptor
);
444 uno::Reference
< awt::XWindow
> xOwnWindow( xNewWinPeer
, uno::UNO_QUERY_THROW
);
446 // create a frame based on the specified window
447 uno::Reference
< lang::XSingleServiceFactory
> xFrameFact
= frame::TaskCreator::create(m_xContext
);
449 uno::Sequence
< uno::Any
> aArgs( 2 );
450 beans::NamedValue aArg
;
452 aArg
.Name
= "ContainerWindow";
453 aArg
.Value
<<= xOwnWindow
;
456 uno::Reference
< frame::XFrame
> xContFrame( xContDisp
, uno::UNO_QUERY
);
457 if ( xContFrame
.is() )
459 aArg
.Name
= "ParentFrame";
460 aArg
.Value
<<= xContFrame
;
466 // the call will create, initialize the frame, and register it in the parent
467 m_xFrame
.set( xFrameFact
->createInstanceWithArguments( aArgs
), uno::UNO_QUERY_THROW
);
469 m_xHatchWindow
= xHWindow
;
470 m_xOwnWindow
= xOwnWindow
;
472 if ( !SetFrameLMVisibility( m_xFrame
, false ) )
474 OSL_FAIL( "Can't deactivate LayoutManager!" );
475 // TODO/LATER: error handling?
478 // m_bIsInplace = sal_True; TODO: ?
480 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xFrame
, uno::UNO_QUERY
);
481 if ( xCloseBroadcaster
.is() )
482 xCloseBroadcaster
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
484 // TODO: some listeners to the frame and the window ( resize for example )
487 if ( m_xComponent
.is() )
489 if ( !LoadDocToFrame( true ) )
495 uno::Reference
< frame::XControllerBorder
> xControllerBorder( m_xFrame
->getController(), uno::UNO_QUERY
);
496 if ( xControllerBorder
.is() )
498 m_aBorderWidths
= xControllerBorder
->getBorder();
499 xControllerBorder
->addBorderResizeListener( static_cast<frame::XBorderResizeListener
*>(this) );
502 PlaceFrame( aRectangleToShow
);
504 if ( m_xHatchWindow
.is() )
505 m_xHatchWindow
->setVisible( true );
514 uno::Reference
< container::XIndexAccess
> DocumentHolder::RetrieveOwnMenu_Impl()
516 uno::Reference
< container::XIndexAccess
> xResult
;
518 uno::Reference
< css::ui::XUIConfigurationManagerSupplier
> xUIConfSupplier(
521 uno::Reference
< css::ui::XUIConfigurationManager
> xUIConfigManager
;
522 if( xUIConfSupplier
.is())
524 xUIConfigManager
.set(
525 xUIConfSupplier
->getUIConfigurationManager(),
526 uno::UNO_QUERY_THROW
);
531 if( xUIConfigManager
.is())
533 xResult
= xUIConfigManager
->getSettings(
534 "private:resource/menubar/menubar",
538 catch( const uno::Exception
& )
543 // no internal document configuration, use the one from the module
544 uno::Reference
< frame::XModuleManager2
> xModuleMan
= frame::ModuleManager::create(m_xContext
);
545 OUString aModuleIdent
=
546 xModuleMan
->identify( uno::Reference
< uno::XInterface
>( m_xComponent
, uno::UNO_QUERY
) );
548 if ( !aModuleIdent
.isEmpty() )
550 uno::Reference
< ui::XModuleUIConfigurationManagerSupplier
> xModConfSupplier
=
551 ui::theModuleUIConfigurationManagerSupplier::get(m_xContext
);
552 uno::Reference
< css::ui::XUIConfigurationManager
> xModUIConfMan(
553 xModConfSupplier
->getUIConfigurationManager( aModuleIdent
),
554 uno::UNO_QUERY_THROW
);
555 xResult
= xModUIConfMan
->getSettings(
556 "private:resource/menubar/menubar",
562 throw uno::RuntimeException();
568 void DocumentHolder::FindConnectPoints(
569 const uno::Reference
< container::XIndexAccess
>& xMenu
,
570 sal_Int32 nConnectPoints
[2] )
572 nConnectPoints
[0] = -1;
573 nConnectPoints
[1] = -1;
574 for ( sal_Int32 nInd
= 0; nInd
< xMenu
->getCount(); nInd
++ )
576 uno::Sequence
< beans::PropertyValue
> aProps
;
577 xMenu
->getByIndex( nInd
) >>= aProps
;
579 for ( sal_Int32 nSeqInd
= 0; nSeqInd
< aProps
.getLength(); nSeqInd
++ )
580 if ( aProps
[nSeqInd
].Name
== "CommandURL" )
582 aProps
[nSeqInd
].Value
>>= aCommand
;
586 if ( aCommand
.isEmpty() )
587 throw uno::RuntimeException();
589 if ( aCommand
== ".uno:PickList" )
590 nConnectPoints
[0] = nInd
;
591 else if ( aCommand
== ".uno:WindowList" )
592 nConnectPoints
[1] = nInd
;
597 uno::Reference
< container::XIndexAccess
> DocumentHolder::MergeMenusForInplace(
598 const uno::Reference
< container::XIndexAccess
>& xContMenu
,
599 const uno::Reference
< frame::XDispatchProvider
>& xContDisp
,
600 const OUString
& aContModuleName
,
601 const uno::Reference
< container::XIndexAccess
>& xOwnMenu
,
602 const uno::Reference
< frame::XDispatchProvider
>& xOwnDisp
)
604 // TODO/LATER: use dispatch providers on merge
606 sal_Int32 nContPoints
[2];
607 sal_Int32 nOwnPoints
[2];
609 uno::Reference
< lang::XSingleComponentFactory
> xIndAccessFact( xContMenu
, uno::UNO_QUERY_THROW
);
611 uno::Reference
< container::XIndexContainer
> xMergedMenu(
612 xIndAccessFact
->createInstanceWithContext(
613 comphelper::getProcessComponentContext() ),
614 uno::UNO_QUERY_THROW
);
616 FindConnectPoints( xContMenu
, nContPoints
);
617 FindConnectPoints( xOwnMenu
, nOwnPoints
);
619 for ( sal_Int32 nInd
= 0; nInd
< xOwnMenu
->getCount(); nInd
++ )
621 if ( nOwnPoints
[0] == nInd
)
623 if ( nContPoints
[0] >= 0 && nContPoints
[0] < xContMenu
->getCount() )
625 InsertMenu_Impl( xMergedMenu
, nInd
, xContMenu
, nContPoints
[0], aContModuleName
, xContDisp
);
628 else if ( nOwnPoints
[1] == nInd
)
630 if ( nContPoints
[1] >= 0 && nContPoints
[1] < xContMenu
->getCount() )
632 InsertMenu_Impl( xMergedMenu
, nInd
, xContMenu
, nContPoints
[1], aContModuleName
, xContDisp
);
636 InsertMenu_Impl( xMergedMenu
, nInd
, xOwnMenu
, nInd
, OUString(), xOwnDisp
);
639 return uno::Reference
< container::XIndexAccess
>( xMergedMenu
, uno::UNO_QUERY_THROW
);
643 bool DocumentHolder::MergeMenus_Impl( const uno::Reference
< css::frame::XLayoutManager
>& xOwnLM
,
644 const uno::Reference
< css::frame::XLayoutManager
>& xContLM
,
645 const uno::Reference
< frame::XDispatchProvider
>& xContDisp
,
646 const OUString
& aContModuleName
)
648 bool bMenuMerged
= false;
651 uno::Reference
< css::ui::XUIElementSettings
> xUISettings(
652 xContLM
->getElement( "private:resource/menubar/menubar" ),
653 uno::UNO_QUERY_THROW
);
654 uno::Reference
< container::XIndexAccess
> xContMenu
= xUISettings
->getSettings( true );
655 if ( !xContMenu
.is() )
656 throw uno::RuntimeException();
658 uno::Reference
< container::XIndexAccess
> xOwnMenu
= RetrieveOwnMenu_Impl();
659 uno::Reference
< frame::XDispatchProvider
> xOwnDisp( m_xFrame
, uno::UNO_QUERY_THROW
);
661 uno::Reference
< container::XIndexAccess
> xMergedMenu
= MergeMenusForInplace( xContMenu
, xContDisp
, aContModuleName
, xOwnMenu
, xOwnDisp
);
662 uno::Reference
< css::frame::XMenuBarMergingAcceptor
> xMerge( xOwnLM
,
663 uno::UNO_QUERY_THROW
);
664 bMenuMerged
= xMerge
->setMergedMenuBar( xMergedMenu
);
666 catch( const uno::Exception
& )
672 bool DocumentHolder::ShowUI( const uno::Reference
< css::frame::XLayoutManager
>& xContainerLM
,
673 const uno::Reference
< frame::XDispatchProvider
>& xContainerDP
,
674 const OUString
& aContModuleName
)
676 bool bResult
= false;
677 if ( xContainerLM
.is() )
679 // the LM of the embedded frame and its current DockingAreaAcceptor
680 uno::Reference
< css::frame::XLayoutManager
> xOwnLM
;
681 uno::Reference
< css::ui::XDockingAreaAcceptor
> xDocAreaAcc
;
685 uno::Reference
< beans::XPropertySet
> xPropSet( m_xFrame
, uno::UNO_QUERY_THROW
);
686 xPropSet
->getPropertyValue("LayoutManager") >>= xOwnLM
;
687 xDocAreaAcc
= xContainerLM
->getDockingAreaAcceptor();
689 catch( const uno::Exception
& ){}
691 if ( xOwnLM
.is() && xDocAreaAcc
.is() )
693 // make sure that lock state of LM is correct even if an exception is thrown in between
694 bool bUnlock
= false;
698 // take over the control over the containers window
699 // as long as the LM is invisible and locked an empty tool space will be used on resizing
700 xOwnLM
->setDockingAreaAcceptor( xDocAreaAcc
);
702 // try to merge menus; don't do anything else if it fails
703 if ( MergeMenus_Impl( xOwnLM
, xContainerLM
, xContainerDP
, aContModuleName
) )
705 // make sure that the container LM does not control the size of the containers window anymore
706 // this must be done after merging menus as we won't get the container menu otherwise
707 xContainerLM
->setDockingAreaAcceptor( uno::Reference
< ui::XDockingAreaAcceptor
>() );
709 bool bIsChart
= false;
710 uno::Reference
< lang::XServiceInfo
> xServiceInfo(m_xComponent
, uno::UNO_QUERY
);
711 if (xServiceInfo
.is() && xServiceInfo
->supportsService("com.sun.star.chart2.ChartDocument"))
713 // prevent further changes at this LM
714 // TODO: moggi: why is this necessary?
717 xContainerLM
->setVisible( false );
718 xContainerLM
->lock();
722 // by unlocking the LM each layout change will now resize the containers window; pending layouts will be processed now
723 xOwnLM
->setVisible( true );
725 uno::Reference
< frame::XFramesSupplier
> xSupp( m_xFrame
->getCreator(), uno::UNO_QUERY
);
727 xSupp
->setActiveFrame( m_xFrame
);
733 // TODO/LATER: The following action should be done only if the window is not hidden
734 // otherwise the activation must fail, unfortunately currently it is not possible
735 // to detect whether the window is hidden using UNO API
736 m_xOwnWindow
->setFocus();
739 catch( const uno::Exception
& )
741 // activation failed; reestablish old state
744 uno::Reference
< frame::XFramesSupplier
> xSupp( m_xFrame
->getCreator(), uno::UNO_QUERY
);
746 xSupp
->setActiveFrame( nullptr );
748 // remove control about containers window from own LM
751 xOwnLM
->setVisible( false );
752 xOwnLM
->setDockingAreaAcceptor( uno::Reference
< css::ui::XDockingAreaAcceptor
>() );
755 uno::Reference
< css::frame::XMenuBarMergingAcceptor
> xMerge( xOwnLM
, uno::UNO_QUERY_THROW
);
756 xMerge
->removeMergedMenuBar();
758 catch( const uno::Exception
& ) {}
762 // reestablish control of containers window
763 xContainerLM
->setDockingAreaAcceptor( xDocAreaAcc
);
764 xContainerLM
->setVisible( true );
766 xContainerLM
->unlock();
768 catch( const uno::Exception
& ) {}
777 bool DocumentHolder::HideUI( const uno::Reference
< css::frame::XLayoutManager
>& xContainerLM
)
779 bool bResult
= false;
781 if ( xContainerLM
.is() )
783 uno::Reference
< css::frame::XLayoutManager
> xOwnLM
;
786 uno::Reference
< beans::XPropertySet
> xPropSet( m_xFrame
, uno::UNO_QUERY_THROW
);
787 xPropSet
->getPropertyValue("LayoutManager") >>= xOwnLM
;
788 } catch( const uno::Exception
& )
794 uno::Reference
< frame::XFramesSupplier
> xSupp( m_xFrame
->getCreator(), uno::UNO_QUERY
);
796 xSupp
->setActiveFrame( nullptr );
798 uno::Reference
< css::ui::XDockingAreaAcceptor
> xDocAreaAcc
= xOwnLM
->getDockingAreaAcceptor();
800 xOwnLM
->setDockingAreaAcceptor( uno::Reference
< ui::XDockingAreaAcceptor
>() );
802 xOwnLM
->setVisible( false );
804 uno::Reference
< css::frame::XMenuBarMergingAcceptor
> xMerge( xOwnLM
, uno::UNO_QUERY_THROW
);
805 xMerge
->removeMergedMenuBar();
807 xContainerLM
->setDockingAreaAcceptor( xDocAreaAcc
);
808 xContainerLM
->setVisible( true );
809 xContainerLM
->unlock();
811 xContainerLM
->doLayout();
814 catch( const uno::Exception
& )
816 SetFrameLMVisibility( m_xFrame
, true );
825 uno::Reference
< frame::XFrame
> const & DocumentHolder::GetDocFrame()
827 // the frame for outplace activation
828 if ( !m_xFrame
.is() )
830 uno::Reference
< lang::XSingleServiceFactory
> xFrameFact
= frame::TaskCreator::create(m_xContext
);
832 m_xFrame
.set(xFrameFact
->createInstanceWithArguments( m_aOutplaceFrameProps
), uno::UNO_QUERY_THROW
);
834 uno::Reference
< frame::XDispatchProviderInterception
> xInterception( m_xFrame
, uno::UNO_QUERY
);
835 if ( xInterception
.is() )
837 if ( m_xInterceptor
.is() )
839 m_xInterceptor
->DisconnectDocHolder();
840 m_xInterceptor
.clear();
843 m_xInterceptor
= new Interceptor( this );
845 xInterception
->registerDispatchProviderInterceptor( m_xInterceptor
.get() );
847 // register interceptor from outside
848 if ( m_xOutplaceInterceptor
.is() )
849 xInterception
->registerDispatchProviderInterceptor( m_xOutplaceInterceptor
);
852 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xFrame
, uno::UNO_QUERY
);
853 if ( xCloseBroadcaster
.is() )
854 xCloseBroadcaster
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
857 if ( m_xComponent
.is() )
859 uno::Reference
< css::frame::XLayoutManager
> xOwnLM
;
861 uno::Reference
< beans::XPropertySet
> xPropSet( m_xFrame
, uno::UNO_QUERY_THROW
);
862 xPropSet
->getPropertyValue("LayoutManager") >>= xOwnLM
;
863 } catch( const uno::Exception
& )
869 // TODO/LATER: get it for the real aspect
871 LoadDocToFrame(false);
879 GetExtent(embed::Aspects::MSOLE_CONTENT
, &aSize
);
880 SetExtent(embed::Aspects::MSOLE_CONTENT
, aSize
);
888 uno::Reference
< awt::XWindow
> xHWindow
= m_xFrame
->getContainerWindow();
892 sal_Int32 nDisplay
= Application::GetDisplayBuiltInScreen();
894 tools::Rectangle aWorkRect
= Application::GetScreenPosSizePixel( nDisplay
);
895 awt::Rectangle aWindowRect
= xHWindow
->getPosSize();
897 if (( aWindowRect
.Width
< aWorkRect
.GetWidth()) && ( aWindowRect
.Height
< aWorkRect
.GetHeight() ))
899 int OffsetX
= ( aWorkRect
.GetWidth() - aWindowRect
.Width
) / 2 + aWorkRect
.Left();
900 int OffsetY
= ( aWorkRect
.GetHeight() - aWindowRect
.Height
) /2 + aWorkRect
.Top();
901 xHWindow
->setPosSize( OffsetX
, OffsetY
, aWindowRect
.Width
, aWindowRect
.Height
, awt::PosSize::POS
);
905 xHWindow
->setPosSize( aWorkRect
.Left(), aWorkRect
.Top(), aWorkRect
.GetWidth(), aWorkRect
.GetHeight(), awt::PosSize::POSSIZE
);
908 xHWindow
->setVisible( true );
911 catch ( const uno::Exception
& )
919 void DocumentHolder::SetComponent( const uno::Reference
< util::XCloseable
>& xDoc
, bool bReadOnly
)
921 if ( m_xComponent
.is() )
923 // May be should be improved
925 CloseDocument( true, false );
926 } catch( const uno::Exception
& )
932 m_bReadOnly
= bReadOnly
;
933 m_bAllowClosing
= false;
935 uno::Reference
< util::XCloseBroadcaster
> xBroadcaster( m_xComponent
, uno::UNO_QUERY
);
936 if ( xBroadcaster
.is() )
937 xBroadcaster
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
939 uno::Reference
< document::XEventBroadcaster
> xEventBroadcaster( m_xComponent
, uno::UNO_QUERY
);
940 if ( xEventBroadcaster
.is() )
941 xEventBroadcaster
->addEventListener( static_cast<document::XEventListener
*>(this) );
944 // the object does not support document::XEventBroadcaster interface
945 // use the workaround, register for modified events
946 uno::Reference
< util::XModifyBroadcaster
> xModifyBroadcaster( m_xComponent
, uno::UNO_QUERY
);
947 if ( xModifyBroadcaster
.is() )
948 xModifyBroadcaster
->addModifyListener( static_cast<util::XModifyListener
*>(this) );
952 LoadDocToFrame(false);
956 bool DocumentHolder::LoadDocToFrame( bool bInPlace
)
958 if ( m_xFrame
.is() && m_xComponent
.is() )
960 uno::Reference
< frame::XModel
> xDoc( m_xComponent
, uno::UNO_QUERY
);
963 // load new document in to the frame
964 uno::Reference
< frame::XComponentLoader
> xComponentLoader( m_xFrame
, uno::UNO_QUERY_THROW
);
966 ::comphelper::NamedValueCollection aArgs
;
967 aArgs
.put( "Model", m_xComponent
);
968 aArgs
.put( "ReadOnly", m_bReadOnly
);
970 // set document title to show in the title bar
971 css::uno::Reference
< css::frame::XTitle
> xModelTitle( xDoc
, css::uno::UNO_QUERY
);
972 if( xModelTitle
.is() )
974 std::locale aResLoc
= Translate::Create("sfx");
975 OUString sEmbedded
= Translate::get(STR_EMBEDDED_TITLE
, aResLoc
);
976 xModelTitle
->setTitle( m_pEmbedObj
->getContainerName() + sEmbedded
);
977 m_aContainerName
= m_pEmbedObj
->getContainerName();
978 // TODO: get real m_aDocumentNamePart
979 m_aDocumentNamePart
= sEmbedded
;
983 aArgs
.put( "PluginMode", sal_Int16(1) );
985 uno::Reference
< lang::XServiceInfo
> xServiceInfo(xDoc
,uno::UNO_QUERY
);
986 if ( xServiceInfo
.is()
987 && xServiceInfo
->supportsService("com.sun.star.report.ReportDefinition") )
989 sUrl
= ".component:DB/ReportDesign";
991 else if( xServiceInfo
.is()
992 && xServiceInfo
->supportsService("com.sun.star.chart2.ChartDocument"))
993 sUrl
= "private:factory/schart";
995 sUrl
= "private:object";
997 xComponentLoader
->loadComponentFromURL( sUrl
,
1000 aArgs
.getPropertyValues() );
1006 uno::Reference
< frame::XSynchronousFrameLoader
> xLoader( m_xComponent
, uno::UNO_QUERY
);
1008 return xLoader
->load( uno::Sequence
< beans::PropertyValue
>(), m_xFrame
);
1018 void DocumentHolder::Show()
1022 m_xFrame
->activate();
1023 uno::Reference
<awt::XTopWindow
> xTopWindow( m_xFrame
->getContainerWindow(), uno::UNO_QUERY
);
1024 if( xTopWindow
.is() )
1025 xTopWindow
->toFront();
1032 bool DocumentHolder::SetExtent( sal_Int64 nAspect
, const awt::Size
& aSize
)
1034 uno::Reference
< embed::XVisualObject
> xDocVis( m_xComponent
, uno::UNO_QUERY
);
1039 xDocVis
->setVisualAreaSize( nAspect
, aSize
);
1042 catch( const uno::Exception
& )
1044 // TODO: Error handling
1052 bool DocumentHolder::GetExtent( sal_Int64 nAspect
, awt::Size
*pSize
)
1054 uno::Reference
< embed::XVisualObject
> xDocVis( m_xComponent
, uno::UNO_QUERY
);
1055 if ( pSize
&& xDocVis
.is() )
1059 *pSize
= xDocVis
->getVisualAreaSize( nAspect
);
1062 catch( const uno::Exception
& )
1064 // TODO: Error handling
1072 sal_Int32
DocumentHolder::GetMapUnit( sal_Int64 nAspect
)
1074 uno::Reference
< embed::XVisualObject
> xDocVis( m_xComponent
, uno::UNO_QUERY
);
1079 return xDocVis
->getMapUnit( nAspect
);
1081 catch( const uno::Exception
& )
1083 // TODO: Error handling
1091 awt::Rectangle
DocumentHolder::CalculateBorderedArea( const awt::Rectangle
& aRect
)
1093 return awt::Rectangle( aRect
.X
+ m_aBorderWidths
.Left
+ HATCH_BORDER_WIDTH
,
1094 aRect
.Y
+ m_aBorderWidths
.Top
+ HATCH_BORDER_WIDTH
,
1095 aRect
.Width
- m_aBorderWidths
.Left
- m_aBorderWidths
.Right
- 2*HATCH_BORDER_WIDTH
,
1096 aRect
.Height
- m_aBorderWidths
.Top
- m_aBorderWidths
.Bottom
- 2*HATCH_BORDER_WIDTH
);
1100 awt::Rectangle
DocumentHolder::AddBorderToArea( const awt::Rectangle
& aRect
)
1102 return awt::Rectangle( aRect
.X
- m_aBorderWidths
.Left
- HATCH_BORDER_WIDTH
,
1103 aRect
.Y
- m_aBorderWidths
.Top
- HATCH_BORDER_WIDTH
,
1104 aRect
.Width
+ m_aBorderWidths
.Left
+ m_aBorderWidths
.Right
+ 2*HATCH_BORDER_WIDTH
,
1105 aRect
.Height
+ m_aBorderWidths
.Top
+ m_aBorderWidths
.Bottom
+ 2*HATCH_BORDER_WIDTH
);
1109 void SAL_CALL
DocumentHolder::disposing( const css::lang::EventObject
& aSource
)
1111 if ( m_xComponent
.is() && m_xComponent
== aSource
.Source
)
1113 m_xComponent
= nullptr;
1114 if ( m_bWaitForClose
)
1116 m_bWaitForClose
= false;
1121 if( m_xFrame
.is() && m_xFrame
== aSource
.Source
)
1123 m_xHatchWindow
.clear();
1124 m_xOwnWindow
.clear();
1130 void SAL_CALL
DocumentHolder::queryClosing( const lang::EventObject
& aSource
, sal_Bool
/*bGetsOwnership*/ )
1132 if ( m_xComponent
.is() && m_xComponent
== aSource
.Source
&& !m_bAllowClosing
)
1133 throw util::CloseVetoException("To close an embedded document, close the document holder (document definition), not the document itself.", static_cast< ::cppu::OWeakObject
*>(this));
1137 void SAL_CALL
DocumentHolder::notifyClosing( const lang::EventObject
& aSource
)
1139 if ( m_xComponent
.is() && m_xComponent
== aSource
.Source
)
1141 m_xComponent
= nullptr;
1142 if ( m_bWaitForClose
)
1144 m_bWaitForClose
= false;
1149 if( m_xFrame
.is() && m_xFrame
== aSource
.Source
)
1151 m_xHatchWindow
.clear();
1152 m_xOwnWindow
.clear();
1158 void SAL_CALL
DocumentHolder::queryTermination( const lang::EventObject
& )
1160 if ( m_bWaitForClose
)
1161 throw frame::TerminationVetoException();
1165 void SAL_CALL
DocumentHolder::notifyTermination( const lang::EventObject
& aSource
)
1167 OSL_ENSURE( !m_xComponent
.is(), "Just a disaster..." );
1169 uno::Reference
< frame::XDesktop
> xDesktop( aSource
.Source
, uno::UNO_QUERY
);
1170 m_bDesktopTerminated
= true;
1171 if ( xDesktop
.is() )
1172 xDesktop
->removeTerminateListener( static_cast<frame::XTerminateListener
*>(this) );
1176 void SAL_CALL
DocumentHolder::modified( const lang::EventObject
& aEvent
)
1178 // if the component does not support document::XEventBroadcaster
1179 // the modify notifications are used as workaround, but only for running state
1180 if( aEvent
.Source
== m_xComponent
&& m_pEmbedObj
&& m_pEmbedObj
->getCurrentState() == embed::EmbedStates::RUNNING
)
1181 m_pEmbedObj
->PostEvent_Impl( "OnVisAreaChanged" );
1185 void SAL_CALL
DocumentHolder::notifyEvent( const document::EventObject
& Event
)
1187 if( m_pEmbedObj
&& Event
.Source
== m_xComponent
)
1189 // for now the ignored events are not forwarded, but sent by the object itself
1190 if ( !Event
.EventName
.startsWith( "OnSave" )
1191 && !Event
.EventName
.startsWith( "OnSaveDone" )
1192 && !Event
.EventName
.startsWith( "OnSaveAs" )
1193 && !Event
.EventName
.startsWith( "OnSaveAsDone" )
1194 && !( Event
.EventName
.startsWith( "OnVisAreaChanged" ) && m_nNoResizeReact
) )
1195 m_pEmbedObj
->PostEvent_Impl( Event
.EventName
);
1200 void SAL_CALL
DocumentHolder::borderWidthsChanged( const uno::Reference
< uno::XInterface
>& aObject
,
1201 const frame::BorderWidths
& aNewSize
)
1203 // TODO: may require mutex introduction ???
1204 if ( m_pEmbedObj
&& m_xFrame
.is() && aObject
== m_xFrame
->getController() )
1206 if ( m_aBorderWidths
.Left
!= aNewSize
.Left
1207 || m_aBorderWidths
.Right
!= aNewSize
.Right
1208 || m_aBorderWidths
.Top
!= aNewSize
.Top
1209 || m_aBorderWidths
.Bottom
!= aNewSize
.Bottom
)
1211 m_aBorderWidths
= aNewSize
;
1212 if ( !m_nNoBorderResizeReact
)
1213 PlaceFrame( m_aObjRect
);
1219 void SAL_CALL
DocumentHolder::requestPositioning( const awt::Rectangle
& aRect
)
1221 // TODO: may require mutex introduction ???
1224 // borders should not be counted
1225 awt::Rectangle aObjRect
= CalculateBorderedArea( aRect
);
1226 IntCounterGuard
aGuard( m_nNoResizeReact
);
1227 m_pEmbedObj
->requestPositioning( aObjRect
);
1232 awt::Rectangle SAL_CALL
DocumentHolder::calcAdjustedRectangle( const awt::Rectangle
& aRect
)
1234 // Solar mutex should be locked already since this is a call from HatchWindow with focus
1235 awt::Rectangle
aResult( aRect
);
1237 if ( m_xFrame
.is() )
1239 // borders should not be counted
1240 uno::Reference
< frame::XControllerBorder
> xControllerBorder( m_xFrame
->getController(), uno::UNO_QUERY
);
1241 if ( xControllerBorder
.is() )
1243 awt::Rectangle aObjRect
= CalculateBorderedArea( aRect
);
1244 aObjRect
= xControllerBorder
->queryBorderedArea( aObjRect
);
1245 aResult
= AddBorderToArea( aObjRect
);
1249 awt::Rectangle aMinRectangle
= AddBorderToArea( awt::Rectangle() );
1250 if ( aResult
.Width
< aMinRectangle
.Width
+ 2 )
1251 aResult
.Width
= aMinRectangle
.Width
+ 2;
1252 if ( aResult
.Height
< aMinRectangle
.Height
+ 2 )
1253 aResult
.Height
= aMinRectangle
.Height
+ 2;
1258 void SAL_CALL
DocumentHolder::activated( )
1260 if ( (m_pEmbedObj
->getStatus(embed::Aspects::MSOLE_CONTENT
)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
) ||
1261 svt::EmbeddedObjectRef::IsGLChart(m_pEmbedObj
) )
1263 if ( m_pEmbedObj
->getCurrentState() != embed::EmbedStates::UI_ACTIVE
&&
1264 !(m_pEmbedObj
->getStatus(embed::Aspects::MSOLE_CONTENT
)&embed::EmbedMisc::MS_EMBED_NOUIACTIVATE
) )
1268 m_pEmbedObj
->changeState( embed::EmbedStates::UI_ACTIVE
);
1270 catch ( const css::embed::StateChangeInProgressException
& )
1272 // must catch this exception because focus is grabbed while UI activation in doVerb()
1274 catch ( const css::uno::Exception
& )
1276 // no outgoing exceptions specified here
1281 uno::Reference
< frame::XFramesSupplier
> xSupp( m_xFrame
->getCreator(), uno::UNO_QUERY
);
1283 xSupp
->setActiveFrame( m_xFrame
);
1288 void DocumentHolder::ResizeHatchWindow()
1290 awt::Rectangle aHatchRect
= AddBorderToArea( m_aObjRect
);
1291 ResizeWindows_Impl( aHatchRect
);
1292 uno::Reference
< embed::XHatchWindow
> xHatchWindow( m_xHatchWindow
, uno::UNO_QUERY
);
1293 xHatchWindow
->setHatchBorderSize( awt::Size( HATCH_BORDER_WIDTH
, HATCH_BORDER_WIDTH
) );
1296 void SAL_CALL
DocumentHolder::deactivated( )
1298 // deactivation is too unspecific to be useful; usually we only trigger code from activation
1299 // so UIDeactivation is actively triggered by the container
1302 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */