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/XSingleServiceFactory.hpp>
27 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
28 #include <com/sun/star/util/CloseVetoException.hpp>
29 #include <com/sun/star/util/XCloseBroadcaster.hpp>
30 #include <com/sun/star/util/XCloseable.hpp>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <com/sun/star/beans/XPropertySet.hpp>
33 #include <com/sun/star/beans/NamedValue.hpp>
34 #include <com/sun/star/frame/XModel.hpp>
35 #include <com/sun/star/frame/Desktop.hpp>
36 #include <com/sun/star/frame/XFramesSupplier.hpp>
37 #include <com/sun/star/frame/XControllerBorder.hpp>
38 #include <com/sun/star/util/XModifyBroadcaster.hpp>
39 #include <com/sun/star/frame/XDispatchProviderInterception.hpp>
40 #include <com/sun/star/awt/Toolkit.hpp>
41 #include <com/sun/star/awt/XTopWindow.hpp>
42 #include <com/sun/star/awt/PosSize.hpp>
43 #include <com/sun/star/awt/WindowAttribute.hpp>
44 #include <com/sun/star/awt/VclWindowPeerAttribute.hpp>
45 #include <com/sun/star/embed/XHatchWindow.hpp>
46 #include <com/sun/star/embed/HatchWindowFactory.hpp>
47 #include <com/sun/star/frame/XLayoutManager.hpp>
48 #include <com/sun/star/frame/XMenuBarMergingAcceptor.hpp>
49 #include <com/sun/star/frame/ModuleManager.hpp>
50 #include <com/sun/star/ui/XDockingAreaAcceptor.hpp>
51 #include <com/sun/star/ui/XUIElementSettings.hpp>
52 #include <com/sun/star/ui/XUIConfigurationManager.hpp>
53 #include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
54 #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
55 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
57 #include <com/sun/star/embed/EmbedMisc.hpp>
58 #include <com/sun/star/embed/EmbedStates.hpp>
59 #include <osl/diagnose.h>
61 #include <vcl/svapp.hxx>
62 #include <unotools/resmgr.hxx>
63 #include <sfx2/strings.hrc>
65 #include <comphelper/processfactory.hxx>
66 #include <comphelper/namedvaluecollection.hxx>
68 #include <docholder.hxx>
69 #include <commonembobj.hxx>
70 #include <intercept.hxx>
72 #define HATCH_BORDER_WIDTH (((m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) && \
73 m_pEmbedObj->getCurrentState()!=embed::EmbedStates::UI_ACTIVE) ? 0 : 4 )
75 using namespace ::com::sun::star
;
83 explicit IntCounterGuard(sal_Int32
& rFlag
)
98 static void InsertMenu_Impl( const uno::Reference
< container::XIndexContainer
>& xTargetMenu
,
99 sal_Int32 nTargetIndex
,
100 const uno::Reference
< container::XIndexAccess
>& xSourceMenu
,
101 sal_Int32 nSourceIndex
,
102 const OUString
& aContModuleName
,
103 const uno::Reference
< frame::XDispatchProvider
>& xSourceDisp
)
106 OUString
aModuleIdentPropName( u
"ModuleIdentifier"_ustr
);
107 OUString
aDispProvPropName( u
"DispatchProvider"_ustr
);
108 bool bModuleNameSet
= false;
109 bool bDispProvSet
= false;
111 uno::Sequence
< beans::PropertyValue
> aSourceProps
;
112 xSourceMenu
->getByIndex( nSourceIndex
) >>= aSourceProps
;
113 uno::Sequence
< beans::PropertyValue
> aTargetProps( aSourceProps
.getLength() );
114 auto aTargetPropsRange
= asNonConstRange(aTargetProps
);
115 for ( nInd
= 0; nInd
< aSourceProps
.getLength(); nInd
++ )
117 aTargetPropsRange
[nInd
].Name
= aSourceProps
[nInd
].Name
;
118 if ( !aContModuleName
.isEmpty() && aTargetProps
[nInd
].Name
== aModuleIdentPropName
)
120 aTargetPropsRange
[nInd
].Value
<<= aContModuleName
;
121 bModuleNameSet
= true;
123 else if ( aTargetProps
[nInd
].Name
== aDispProvPropName
)
125 aTargetPropsRange
[nInd
].Value
<<= xSourceDisp
;
129 aTargetPropsRange
[nInd
].Value
= aSourceProps
[nInd
].Value
;
132 if ( !bModuleNameSet
&& !aContModuleName
.isEmpty() )
134 aTargetProps
.realloc( ++nInd
);
135 auto pTargetProps
= aTargetProps
.getArray();
136 pTargetProps
[nInd
-1].Name
= aModuleIdentPropName
;
137 pTargetProps
[nInd
-1].Value
<<= aContModuleName
;
140 if ( !bDispProvSet
&& xSourceDisp
.is() )
142 aTargetProps
.realloc( ++nInd
);
143 auto pTargetProps
= aTargetProps
.getArray();
144 pTargetProps
[nInd
-1].Name
= aDispProvPropName
;
145 pTargetProps
[nInd
-1].Value
<<= xSourceDisp
;
148 xTargetMenu
->insertByIndex( nTargetIndex
, uno::Any( aTargetProps
) );
151 namespace embeddedobj
154 DocumentHolder::DocumentHolder( uno::Reference
< uno::XComponentContext
> xContext
,
155 OCommonEmbeddedObject
* pEmbObj
)
156 : m_pEmbedObj( pEmbObj
),
157 m_xContext(std::move( xContext
)),
158 m_bReadOnly( false ),
159 m_bWaitForClose( false ),
160 m_bAllowClosing( false ),
161 m_bDesktopTerminated( false ),
162 m_nNoBorderResizeReact( 0 ),
163 m_nNoResizeReact( 0 )
165 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( m_xContext
);
166 osl_atomic_increment(&m_refCount
);
169 xDesktop
->addTerminateListener( this );
171 catch ( const uno::Exception
& )
174 osl_atomic_decrement(&m_refCount
);
176 m_aOutplaceFrameProps
= { uno::Any(beans::NamedValue
{ u
"TopWindow"_ustr
, uno::Any(true) }),
177 uno::Any(beans::NamedValue
{ u
"MakeVisible"_ustr
, uno::Any(false) }),
178 //TODO/LATER: should use parent document frame
179 uno::Any(beans::NamedValue
{ u
"ParentFrame"_ustr
, uno::Any(xDesktop
) }) };
183 DocumentHolder::~DocumentHolder()
185 osl_atomic_increment(&m_refCount
); // to allow deregistration as a listener
190 if ( m_xComponent
.is() )
193 CloseDocument( true, false );
194 } catch( const uno::Exception
& ) {}
197 if ( m_xInterceptor
.is() )
199 m_xInterceptor
->DisconnectDocHolder();
200 m_xInterceptor
.clear();
203 if ( !m_bDesktopTerminated
)
208 void DocumentHolder::CloseFrame()
210 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xFrame
, uno::UNO_QUERY
);
211 if ( xCloseBroadcaster
.is() )
212 xCloseBroadcaster
->removeCloseListener( static_cast<util::XCloseListener
*>(this) );
214 uno::Reference
<util::XCloseable
> xCloseable(
215 m_xFrame
,uno::UNO_QUERY
);
216 if( xCloseable
.is() )
218 xCloseable
->close( true );
220 catch( const uno::Exception
& ) {
227 if ( m_xHatchWindow
.is() )
228 m_xHatchWindow
->dispose();
230 m_xHatchWindow
.clear();
231 m_xOwnWindow
.clear();
236 void DocumentHolder::FreeOffice()
239 uno::Reference
< frame::XDesktop2
> xDesktop
= frame::Desktop::create( m_xContext
);
240 xDesktop
->removeTerminateListener( this );
241 } catch (const css::uno::DeploymentException
&) {
242 // if this happens, the desktop is already gone
245 // the following code is commented out since for now there is still no completely correct way to detect
246 // whether the office can be terminated, so it is better to have unnecessary process running than
249 // uno::Reference< frame::XFramesSupplier > xFramesSupplier( xDesktop, uno::UNO_QUERY );
250 // if ( xFramesSupplier.is() )
252 // uno::Reference< frame::XFrames > xFrames = xFramesSupplier->getFrames();
253 // if ( xFrames.is() && !xFrames->hasElements() )
257 // xDesktop->terminate();
259 // catch( uno::Exception & )
266 void DocumentHolder::CloseDocument( bool bDeliverOwnership
, bool bWaitForClose
)
268 if ( m_xComponent
.is() )
270 uno::Reference
< document::XEventBroadcaster
> xEventBroadcaster( m_xComponent
, uno::UNO_QUERY
);
271 if ( xEventBroadcaster
.is() )
272 xEventBroadcaster
->removeEventListener( static_cast<document::XEventListener
*>(this) );
275 // the object does not support document::XEventBroadcaster interface
276 // use the workaround, register for modified events
277 uno::Reference
< util::XModifyBroadcaster
> xModifyBroadcaster( m_xComponent
, uno::UNO_QUERY
);
278 if ( xModifyBroadcaster
.is() )
279 xModifyBroadcaster
->removeModifyListener( static_cast<util::XModifyListener
*>(this) );
282 m_bAllowClosing
= true;
283 m_bWaitForClose
= bWaitForClose
;
284 m_xComponent
->close( bDeliverOwnership
);
287 m_xComponent
= nullptr;
291 void DocumentHolder::PlaceFrame( const awt::Rectangle
& aNewRect
)
293 OSL_ENSURE( m_xFrame
.is() && m_xOwnWindow
.is(),
294 "The object does not have windows required for inplace mode!" );
296 //TODO: may need mutex locking???
297 if ( !(m_xFrame
.is() && m_xOwnWindow
.is()) )
300 // the frame can be replaced only in inplace mode
301 frame::BorderWidths aOldWidths
;
302 IntCounterGuard
aGuard( m_nNoBorderResizeReact
);
306 aOldWidths
= m_aBorderWidths
;
308 awt::Rectangle aHatchRect
= AddBorderToArea( aNewRect
);
310 ResizeWindows_Impl( aHatchRect
);
312 } while ( aOldWidths
.Left
!= m_aBorderWidths
.Left
313 || aOldWidths
.Top
!= m_aBorderWidths
.Top
314 || aOldWidths
.Right
!= m_aBorderWidths
.Right
315 || aOldWidths
.Bottom
!= m_aBorderWidths
.Bottom
);
317 m_aObjRect
= aNewRect
;
321 void DocumentHolder::ResizeWindows_Impl( const awt::Rectangle
& aHatchRect
)
323 OSL_ENSURE( m_xFrame
.is() && m_xOwnWindow
.is() /*&& m_xHatchWindow.is()*/,
324 "The object does not have windows required for inplace mode!" );
325 if ( m_xHatchWindow
.is() )
327 m_xOwnWindow
->setPosSize( HATCH_BORDER_WIDTH
,
329 aHatchRect
.Width
- 2*HATCH_BORDER_WIDTH
,
330 aHatchRect
.Height
- 2*HATCH_BORDER_WIDTH
,
331 awt::PosSize::POSSIZE
);
334 m_xHatchWindow
->setPosSize( aHatchRect
.X
,
338 awt::PosSize::POSSIZE
);
341 m_xOwnWindow
->setPosSize( aHatchRect
.X
+ HATCH_BORDER_WIDTH
,
342 aHatchRect
.Y
+ HATCH_BORDER_WIDTH
,
343 aHatchRect
.Width
- 2*HATCH_BORDER_WIDTH
,
344 aHatchRect
.Height
- 2*HATCH_BORDER_WIDTH
,
345 awt::PosSize::POSSIZE
);
349 bool DocumentHolder::SetFrameLMVisibility( const uno::Reference
< frame::XFrame
>& xFrame
, bool bVisible
)
351 bool bResult
= false;
355 uno::Reference
< css::frame::XLayoutManager
> xLayoutManager
;
356 uno::Reference
< beans::XPropertySet
> xPropSet( xFrame
, uno::UNO_QUERY_THROW
);
357 xPropSet
->getPropertyValue(u
"LayoutManager"_ustr
) >>= xLayoutManager
;
358 if ( xLayoutManager
.is() )
360 xLayoutManager
->setVisible( bVisible
);
362 // MBA: locking is done only on the container LM, because it is not about hiding windows, it's about
363 // giving up control over the component window (and stopping to listen for resize events of the container window)
365 xLayoutManager
->unlock();
367 xLayoutManager
->lock();
372 catch( const uno::Exception
& )
379 bool DocumentHolder::ShowInplace( const uno::Reference
< awt::XWindowPeer
>& xParent
,
380 const awt::Rectangle
& aRectangleToShow
,
381 const uno::Reference
< frame::XDispatchProvider
>& xContDisp
)
383 OSL_ENSURE( !m_xFrame
.is(), "A frame exists already!" );
385 if ( !m_xFrame
.is() )
387 uno::Reference
< frame::XModel
> xModel( GetComponent(), uno::UNO_QUERY
);
388 awt::Rectangle aHatchRectangle
= AddBorderToArea( aRectangleToShow
);
390 awt::Rectangle
aOwnRectangle( HATCH_BORDER_WIDTH
,
392 aHatchRectangle
.Width
- 2*HATCH_BORDER_WIDTH
,
393 aHatchRectangle
.Height
- 2*HATCH_BORDER_WIDTH
);
394 uno::Reference
< awt::XWindow
> xHWindow
;
395 uno::Reference
< awt::XWindowPeer
> xMyParent( xParent
);
400 uno::Reference
< embed::XHatchWindowFactory
> xHatchFactory
=
401 embed::HatchWindowFactory::create(m_xContext
);
403 uno::Reference
< embed::XHatchWindow
> xHatchWindow
=
404 xHatchFactory
->createHatchWindowInstance( xParent
,
406 awt::Size( HATCH_BORDER_WIDTH
, HATCH_BORDER_WIDTH
) );
408 uno::Reference
< awt::XWindowPeer
> xHatchWinPeer( xHatchWindow
, uno::UNO_QUERY
);
409 xHWindow
.set( xHatchWinPeer
, uno::UNO_QUERY_THROW
);
411 xHatchWindow
->setController( uno::Reference
< embed::XHatchWindowController
>(
412 static_cast< embed::XHatchWindowController
* >( this ) ) );
414 xMyParent
= std::move(xHatchWinPeer
);
418 aOwnRectangle
.X
+= aHatchRectangle
.X
;
419 aOwnRectangle
.Y
+= aHatchRectangle
.Y
;
422 awt::WindowDescriptor
aOwnWinDescriptor( awt::WindowClass_TOP
,
423 u
"dockingwindow"_ustr
,
426 awt::Rectangle(),//aOwnRectangle,
427 awt::WindowAttribute::SHOW
| awt::VclWindowPeerAttribute::CLIPCHILDREN
);
429 uno::Reference
< awt::XToolkit2
> xToolkit
= awt::Toolkit::create(m_xContext
);
431 uno::Reference
< awt::XWindowPeer
> xNewWinPeer
= xToolkit
->createWindow( aOwnWinDescriptor
);
432 uno::Reference
< awt::XWindow
> xOwnWindow( xNewWinPeer
, uno::UNO_QUERY_THROW
);
433 uno::Reference
< frame::XFrame
> xContFrame( xContDisp
, uno::UNO_QUERY
);
435 // create a frame based on the specified window
436 uno::Reference
< lang::XSingleServiceFactory
> xFrameFact
= frame::TaskCreator::create(m_xContext
);
438 uno::Sequence
< uno::Any
> aArgs( xContFrame
.is() ? 2 : 1 );
439 auto pArgs
= aArgs
.getArray();
440 beans::NamedValue aArg
;
442 aArg
.Name
= "ContainerWindow";
443 aArg
.Value
<<= xOwnWindow
;
446 if ( xContFrame
.is() )
448 aArg
.Name
= "ParentFrame";
449 aArg
.Value
<<= xContFrame
;
453 // the call will create, initialize the frame, and register it in the parent
454 m_xFrame
.set( xFrameFact
->createInstanceWithArguments( aArgs
), uno::UNO_QUERY_THROW
);
456 m_xHatchWindow
= std::move(xHWindow
);
457 m_xOwnWindow
= std::move(xOwnWindow
);
459 if ( !SetFrameLMVisibility( m_xFrame
, false ) )
461 OSL_FAIL( "Can't deactivate LayoutManager!" );
462 // TODO/LATER: error handling?
465 // m_bIsInplace = sal_True; TODO: ?
467 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xFrame
, uno::UNO_QUERY
);
468 if ( xCloseBroadcaster
.is() )
469 xCloseBroadcaster
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
471 // TODO: some listeners to the frame and the window ( resize for example )
477 if ( !LoadDocToFrame( true ) )
483 uno::Reference
< frame::XControllerBorder
> xControllerBorder( m_xFrame
->getController(), uno::UNO_QUERY
);
484 if ( xControllerBorder
.is() )
486 m_aBorderWidths
= xControllerBorder
->getBorder();
487 xControllerBorder
->addBorderResizeListener( static_cast<frame::XBorderResizeListener
*>(this) );
490 PlaceFrame( aRectangleToShow
);
492 if ( m_xHatchWindow
.is() )
493 m_xHatchWindow
->setVisible( true );
499 uno::Reference
< container::XIndexAccess
> DocumentHolder::RetrieveOwnMenu_Impl()
501 uno::Reference
< container::XIndexAccess
> xResult
;
503 uno::Reference
< css::ui::XUIConfigurationManagerSupplier
> xUIConfSupplier(
506 uno::Reference
< css::ui::XUIConfigurationManager
> xUIConfigManager
;
507 if( xUIConfSupplier
.is())
509 xUIConfigManager
.set(
510 xUIConfSupplier
->getUIConfigurationManager(),
511 uno::UNO_SET_THROW
);
516 if( xUIConfigManager
.is())
518 xResult
= xUIConfigManager
->getSettings(
519 u
"private:resource/menubar/menubar"_ustr
,
523 catch( const uno::Exception
& )
528 // no internal document configuration, use the one from the module
529 uno::Reference
< frame::XModuleManager2
> xModuleMan
= frame::ModuleManager::create(m_xContext
);
530 OUString aModuleIdent
=
531 xModuleMan
->identify( uno::Reference
< uno::XInterface
>( m_xComponent
, uno::UNO_QUERY
) );
533 if ( !aModuleIdent
.isEmpty() )
535 uno::Reference
< ui::XModuleUIConfigurationManagerSupplier
> xModConfSupplier
=
536 ui::theModuleUIConfigurationManagerSupplier::get(m_xContext
);
537 uno::Reference
< css::ui::XUIConfigurationManager
> xModUIConfMan(
538 xModConfSupplier
->getUIConfigurationManager( aModuleIdent
),
539 uno::UNO_SET_THROW
);
540 xResult
= xModUIConfMan
->getSettings(
541 u
"private:resource/menubar/menubar"_ustr
,
547 throw uno::RuntimeException(u
"Unable to retrieve the UI configuration menu."_ustr
, getXWeak());
553 void DocumentHolder::FindConnectPoints(
554 const uno::Reference
< container::XIndexAccess
>& xMenu
,
555 sal_Int32 nConnectPoints
[2] )
557 nConnectPoints
[0] = -1;
558 nConnectPoints
[1] = -1;
559 for ( sal_Int32 nInd
= 0; nInd
< xMenu
->getCount(); nInd
++ )
561 uno::Sequence
< beans::PropertyValue
> aProps
;
562 xMenu
->getByIndex( nInd
) >>= aProps
;
564 for (beans::PropertyValue
const& prop
: aProps
)
565 if ( prop
.Name
== "CommandURL" )
567 prop
.Value
>>= aCommand
;
571 if ( aCommand
.isEmpty() )
572 throw uno::RuntimeException("CommandURL is empty at index: " + OUString::number(nInd
), xMenu
);
574 if ( aCommand
== ".uno:PickList" )
575 nConnectPoints
[0] = nInd
;
576 else if ( aCommand
== ".uno:WindowList" )
577 nConnectPoints
[1] = nInd
;
582 uno::Reference
< container::XIndexAccess
> DocumentHolder::MergeMenusForInplace(
583 const uno::Reference
< container::XIndexAccess
>& xContMenu
,
584 const uno::Reference
< frame::XDispatchProvider
>& xContDisp
,
585 const OUString
& aContModuleName
,
586 const uno::Reference
< container::XIndexAccess
>& xOwnMenu
,
587 const uno::Reference
< frame::XDispatchProvider
>& xOwnDisp
)
589 // TODO/LATER: use dispatch providers on merge
591 sal_Int32 nContPoints
[2];
592 sal_Int32 nOwnPoints
[2];
594 uno::Reference
< lang::XSingleComponentFactory
> xIndAccessFact( xContMenu
, uno::UNO_QUERY_THROW
);
596 uno::Reference
< container::XIndexContainer
> xMergedMenu(
597 xIndAccessFact
->createInstanceWithContext(
598 comphelper::getProcessComponentContext() ),
599 uno::UNO_QUERY_THROW
);
601 FindConnectPoints( xContMenu
, nContPoints
);
602 FindConnectPoints( xOwnMenu
, nOwnPoints
);
604 for ( sal_Int32 nInd
= 0; nInd
< xOwnMenu
->getCount(); nInd
++ )
606 if ( nOwnPoints
[0] == nInd
)
608 if ( nContPoints
[0] >= 0 && nContPoints
[0] < xContMenu
->getCount() )
610 InsertMenu_Impl( xMergedMenu
, nInd
, xContMenu
, nContPoints
[0], aContModuleName
, xContDisp
);
613 else if ( nOwnPoints
[1] == nInd
)
615 if ( nContPoints
[1] >= 0 && nContPoints
[1] < xContMenu
->getCount() )
617 InsertMenu_Impl( xMergedMenu
, nInd
, xContMenu
, nContPoints
[1], aContModuleName
, xContDisp
);
621 InsertMenu_Impl( xMergedMenu
, nInd
, xOwnMenu
, nInd
, OUString(), xOwnDisp
);
624 return uno::Reference
< container::XIndexAccess
>( xMergedMenu
, uno::UNO_QUERY_THROW
);
628 bool DocumentHolder::MergeMenus_Impl( const uno::Reference
< css::frame::XLayoutManager
>& xOwnLM
,
629 const uno::Reference
< css::frame::XLayoutManager
>& xContLM
,
630 const uno::Reference
< frame::XDispatchProvider
>& xContDisp
,
631 const OUString
& aContModuleName
)
633 bool bMenuMerged
= false;
636 uno::Reference
< css::ui::XUIElementSettings
> xUISettings(
637 xContLM
->getElement( u
"private:resource/menubar/menubar"_ustr
),
638 uno::UNO_QUERY_THROW
);
639 uno::Reference
< container::XIndexAccess
> xContMenu
= xUISettings
->getSettings( true );
640 if ( !xContMenu
.is() )
641 throw uno::RuntimeException(u
"Unable to merge the menu"_ustr
, getXWeak());
643 uno::Reference
< container::XIndexAccess
> xOwnMenu
= RetrieveOwnMenu_Impl();
644 uno::Reference
< frame::XDispatchProvider
> xOwnDisp( m_xFrame
, uno::UNO_QUERY_THROW
);
646 uno::Reference
< container::XIndexAccess
> xMergedMenu
= MergeMenusForInplace( xContMenu
, xContDisp
, aContModuleName
, xOwnMenu
, xOwnDisp
);
647 uno::Reference
< css::frame::XMenuBarMergingAcceptor
> xMerge( xOwnLM
,
648 uno::UNO_QUERY_THROW
);
649 bMenuMerged
= xMerge
->setMergedMenuBar( xMergedMenu
);
651 catch( const uno::Exception
& )
657 bool DocumentHolder::ShowUI( const uno::Reference
< css::frame::XLayoutManager
>& xContainerLM
,
658 const uno::Reference
< frame::XDispatchProvider
>& xContainerDP
,
659 const OUString
& aContModuleName
)
661 bool bResult
= false;
662 if ( xContainerLM
.is() )
664 // the LM of the embedded frame and its current DockingAreaAcceptor
665 uno::Reference
< css::frame::XLayoutManager
> xOwnLM
;
666 uno::Reference
< css::ui::XDockingAreaAcceptor
> xDocAreaAcc
;
670 uno::Reference
< beans::XPropertySet
> xPropSet( m_xFrame
, uno::UNO_QUERY_THROW
);
671 xPropSet
->getPropertyValue(u
"LayoutManager"_ustr
) >>= xOwnLM
;
672 xDocAreaAcc
= xContainerLM
->getDockingAreaAcceptor();
674 catch( const uno::Exception
& ){}
676 if ( xOwnLM
.is() && xDocAreaAcc
.is() )
678 // make sure that lock state of LM is correct even if an exception is thrown in between
679 bool bUnlockContainerLM
= false;
680 bool bLockOwnLM
= false;
683 // take over the control over the containers window
684 // as long as the LM is invisible and locked an empty tool space will be used on resizing
685 xOwnLM
->setDockingAreaAcceptor( xDocAreaAcc
);
687 // try to merge menus; don't do anything else if it fails
688 if ( MergeMenus_Impl( xOwnLM
, xContainerLM
, xContainerDP
, aContModuleName
) )
690 // make sure that the container LM does not control the size of the containers window anymore
691 // this must be done after merging menus as we won't get the container menu otherwise
692 xContainerLM
->setDockingAreaAcceptor( uno::Reference
< ui::XDockingAreaAcceptor
>() );
694 uno::Reference
< lang::XServiceInfo
> xServiceInfo(m_xComponent
, uno::UNO_QUERY
);
695 if (!xServiceInfo
.is() || !xServiceInfo
->supportsService(u
"com.sun.star.chart2.ChartDocument"_ustr
))
697 // prevent further changes at this LM
698 xContainerLM
->setVisible(false);
699 xContainerLM
->lock();
700 bUnlockContainerLM
= true;
703 // by unlocking the LM each layout change will now resize the containers window; pending layouts will be processed now
704 xOwnLM
->setVisible( true );
706 uno::Reference
< frame::XFramesSupplier
> xSupp
= m_xFrame
->getCreator();
708 xSupp
->setActiveFrame( m_xFrame
);
714 // TODO/LATER: The following action should be done only if the window is not hidden
715 // otherwise the activation must fail, unfortunately currently it is not possible
716 // to detect whether the window is hidden using UNO API
717 m_xOwnWindow
->setFocus();
720 catch( const uno::Exception
& )
722 // activation failed; reestablish old state
725 uno::Reference
< frame::XFramesSupplier
> xSupp
= m_xFrame
->getCreator();
727 xSupp
->setActiveFrame( nullptr );
729 // remove control about containers window from own LM
732 xOwnLM
->setVisible( false );
733 xOwnLM
->setDockingAreaAcceptor( uno::Reference
< css::ui::XDockingAreaAcceptor
>() );
736 uno::Reference
< css::frame::XMenuBarMergingAcceptor
> xMerge( xOwnLM
, uno::UNO_QUERY_THROW
);
737 xMerge
->removeMergedMenuBar();
739 catch( const uno::Exception
& ) {}
743 // reestablish control of containers window
744 xContainerLM
->setDockingAreaAcceptor( xDocAreaAcc
);
745 xContainerLM
->setVisible( true );
746 if (bUnlockContainerLM
)
747 xContainerLM
->unlock();
749 catch( const uno::Exception
& ) {}
758 bool DocumentHolder::HideUI( const uno::Reference
< css::frame::XLayoutManager
>& xContainerLM
)
760 bool bResult
= false;
762 if ( xContainerLM
.is() )
764 uno::Reference
< css::frame::XLayoutManager
> xOwnLM
;
767 uno::Reference
< beans::XPropertySet
> xPropSet( m_xFrame
, uno::UNO_QUERY_THROW
);
768 xPropSet
->getPropertyValue(u
"LayoutManager"_ustr
) >>= xOwnLM
;
769 } catch( const uno::Exception
& )
775 uno::Reference
< frame::XFramesSupplier
> xSupp
= m_xFrame
->getCreator();
777 xSupp
->setActiveFrame( nullptr );
779 uno::Reference
< css::ui::XDockingAreaAcceptor
> xDocAreaAcc
= xOwnLM
->getDockingAreaAcceptor();
781 xOwnLM
->setDockingAreaAcceptor( uno::Reference
< ui::XDockingAreaAcceptor
>() );
783 xOwnLM
->setVisible( false );
785 uno::Reference
< css::frame::XMenuBarMergingAcceptor
> xMerge( xOwnLM
, uno::UNO_QUERY_THROW
);
786 xMerge
->removeMergedMenuBar();
788 xContainerLM
->setDockingAreaAcceptor( xDocAreaAcc
);
789 uno::Reference
< lang::XServiceInfo
> xServiceInfo(m_xComponent
, uno::UNO_QUERY
);
790 if (!xServiceInfo
.is() || !xServiceInfo
->supportsService(u
"com.sun.star.chart2.ChartDocument"_ustr
))
792 xContainerLM
->setVisible(true);
793 xContainerLM
->unlock();
796 xContainerLM
->doLayout();
799 catch( const uno::Exception
& )
801 SetFrameLMVisibility( m_xFrame
, true );
810 uno::Reference
< frame::XFrame
> const & DocumentHolder::GetDocFrame()
812 // the frame for outplace activation
813 if ( !m_xFrame
.is() )
815 uno::Reference
< lang::XSingleServiceFactory
> xFrameFact
= frame::TaskCreator::create(m_xContext
);
817 m_xFrame
.set(xFrameFact
->createInstanceWithArguments( m_aOutplaceFrameProps
), uno::UNO_QUERY_THROW
);
819 uno::Reference
< frame::XDispatchProviderInterception
> xInterception( m_xFrame
, uno::UNO_QUERY
);
820 if ( xInterception
.is() )
822 if ( m_xInterceptor
.is() )
824 m_xInterceptor
->DisconnectDocHolder();
825 m_xInterceptor
.clear();
828 m_xInterceptor
= new Interceptor( this );
830 xInterception
->registerDispatchProviderInterceptor( m_xInterceptor
);
832 // register interceptor from outside
833 if ( m_xOutplaceInterceptor
.is() )
834 xInterception
->registerDispatchProviderInterceptor( m_xOutplaceInterceptor
);
837 uno::Reference
< util::XCloseBroadcaster
> xCloseBroadcaster( m_xFrame
, uno::UNO_QUERY
);
838 if ( xCloseBroadcaster
.is() )
839 xCloseBroadcaster
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
842 if ( m_xComponent
.is() )
844 uno::Reference
< css::frame::XLayoutManager
> xOwnLM
;
846 uno::Reference
< beans::XPropertySet
> xPropSet( m_xFrame
, uno::UNO_QUERY_THROW
);
847 xPropSet
->getPropertyValue(u
"LayoutManager"_ustr
) >>= xOwnLM
;
848 } catch( const uno::Exception
& )
854 // TODO/LATER: get it for the real aspect
856 LoadDocToFrame(false);
864 GetExtent(embed::Aspects::MSOLE_CONTENT
, &aSize
);
865 SetExtent(embed::Aspects::MSOLE_CONTENT
, aSize
);
873 uno::Reference
< awt::XWindow
> xHWindow
= m_xFrame
->getContainerWindow();
877 sal_Int32 nDisplay
= Application::GetDisplayBuiltInScreen();
879 AbsoluteScreenPixelRectangle aWorkRect
= Application::GetScreenPosSizePixel( nDisplay
);
880 awt::Rectangle aWindowRect
= xHWindow
->getPosSize();
882 if (( aWindowRect
.Width
< aWorkRect
.GetWidth()) && ( aWindowRect
.Height
< aWorkRect
.GetHeight() ))
884 int OffsetX
= ( aWorkRect
.GetWidth() - aWindowRect
.Width
) / 2 + aWorkRect
.Left();
885 int OffsetY
= ( aWorkRect
.GetHeight() - aWindowRect
.Height
) /2 + aWorkRect
.Top();
886 xHWindow
->setPosSize( OffsetX
, OffsetY
, aWindowRect
.Width
, aWindowRect
.Height
, awt::PosSize::POS
);
890 xHWindow
->setPosSize( aWorkRect
.Left(), aWorkRect
.Top(), aWorkRect
.GetWidth(), aWorkRect
.GetHeight(), awt::PosSize::POSSIZE
);
893 xHWindow
->setVisible( true );
896 catch ( const uno::Exception
& )
904 void DocumentHolder::SetComponent( const uno::Reference
< util::XCloseable
>& xDoc
, bool bReadOnly
)
906 if ( m_xComponent
.is() )
908 // May be should be improved
910 CloseDocument( true, false );
911 } catch( const uno::Exception
& )
917 m_bReadOnly
= bReadOnly
;
918 m_bAllowClosing
= false;
920 if ( m_xComponent
.is() )
921 m_xComponent
->addCloseListener( static_cast<util::XCloseListener
*>(this) );
923 uno::Reference
< document::XEventBroadcaster
> xEventBroadcaster( m_xComponent
, uno::UNO_QUERY
);
924 if ( xEventBroadcaster
.is() )
925 xEventBroadcaster
->addEventListener( static_cast<document::XEventListener
*>(this) );
928 // the object does not support document::XEventBroadcaster interface
929 // use the workaround, register for modified events
930 uno::Reference
< util::XModifyBroadcaster
> xModifyBroadcaster( m_xComponent
, uno::UNO_QUERY
);
931 if ( xModifyBroadcaster
.is() )
932 xModifyBroadcaster
->addModifyListener( static_cast<util::XModifyListener
*>(this) );
936 LoadDocToFrame(false);
940 bool DocumentHolder::LoadDocToFrame( bool bInPlace
)
942 if ( !m_xFrame
|| !m_xComponent
)
945 uno::Reference
< frame::XModel
> xDoc( m_xComponent
, uno::UNO_QUERY
);
948 // load new document into the frame
949 uno::Reference
< frame::XComponentLoader
> xComponentLoader( m_xFrame
, uno::UNO_QUERY_THROW
);
951 ::comphelper::NamedValueCollection aArgs
;
952 aArgs
.put( u
"Model"_ustr
, m_xComponent
);
953 aArgs
.put( u
"ReadOnly"_ustr
, m_bReadOnly
);
955 // set document title to show in the title bar
956 css::uno::Reference
< css::frame::XTitle
> xModelTitle( xDoc
, css::uno::UNO_QUERY
);
957 if( xModelTitle
.is() && m_pEmbedObj
&& !m_pEmbedObj
->getContainerName().isEmpty() )
959 std::locale aResLoc
= Translate::Create("sfx");
960 OUString sEmbedded
= Translate::get(STR_EMBEDDED_TITLE
, aResLoc
);
961 xModelTitle
->setTitle( m_pEmbedObj
->getContainerName() + sEmbedded
);
962 m_aContainerName
= m_pEmbedObj
->getContainerName();
963 // TODO: get real m_aDocumentNamePart
964 m_aDocumentNamePart
= sEmbedded
;
968 aArgs
.put( u
"PluginMode"_ustr
, sal_Int16(1) );
970 uno::Reference
< lang::XServiceInfo
> xServiceInfo(xDoc
,uno::UNO_QUERY
);
971 if ( xServiceInfo
.is()
972 && xServiceInfo
->supportsService(u
"com.sun.star.report.ReportDefinition"_ustr
) )
974 sUrl
= ".component:DB/ReportDesign";
976 else if( xServiceInfo
.is()
977 && xServiceInfo
->supportsService(u
"com.sun.star.chart2.ChartDocument"_ustr
))
978 sUrl
= "private:factory/schart";
980 sUrl
= "private:object";
982 xComponentLoader
->loadComponentFromURL( sUrl
,
985 aArgs
.getPropertyValues() );
991 uno::Reference
< frame::XSynchronousFrameLoader
> xLoader( m_xComponent
, uno::UNO_QUERY
);
993 return xLoader
->load( uno::Sequence
< beans::PropertyValue
>(), m_xFrame
);
1002 void DocumentHolder::Show()
1006 m_xFrame
->activate();
1007 uno::Reference
<awt::XTopWindow
> xTopWindow( m_xFrame
->getContainerWindow(), uno::UNO_QUERY
);
1008 if( xTopWindow
.is() )
1009 xTopWindow
->toFront();
1016 bool DocumentHolder::SetExtent( sal_Int64 nAspect
, const awt::Size
& aSize
)
1018 uno::Reference
< embed::XVisualObject
> xDocVis( m_xComponent
, uno::UNO_QUERY
);
1023 xDocVis
->setVisualAreaSize( nAspect
, aSize
);
1026 catch( const uno::Exception
& )
1028 // TODO: Error handling
1036 bool DocumentHolder::GetExtent( sal_Int64 nAspect
, awt::Size
*pSize
)
1038 uno::Reference
< embed::XVisualObject
> xDocVis( m_xComponent
, uno::UNO_QUERY
);
1039 if ( pSize
&& xDocVis
.is() )
1043 *pSize
= xDocVis
->getVisualAreaSize( nAspect
);
1046 catch( const uno::Exception
& )
1048 // TODO: Error handling
1056 sal_Int32
DocumentHolder::GetMapUnit( sal_Int64 nAspect
)
1058 uno::Reference
< embed::XVisualObject
> xDocVis( m_xComponent
, uno::UNO_QUERY
);
1063 return xDocVis
->getMapUnit( nAspect
);
1065 catch( const uno::Exception
& )
1067 // TODO: Error handling
1075 awt::Rectangle
DocumentHolder::CalculateBorderedArea( const awt::Rectangle
& aRect
)
1077 return awt::Rectangle( aRect
.X
+ m_aBorderWidths
.Left
+ HATCH_BORDER_WIDTH
,
1078 aRect
.Y
+ m_aBorderWidths
.Top
+ HATCH_BORDER_WIDTH
,
1079 aRect
.Width
- m_aBorderWidths
.Left
- m_aBorderWidths
.Right
- 2*HATCH_BORDER_WIDTH
,
1080 aRect
.Height
- m_aBorderWidths
.Top
- m_aBorderWidths
.Bottom
- 2*HATCH_BORDER_WIDTH
);
1084 awt::Rectangle
DocumentHolder::AddBorderToArea( const awt::Rectangle
& aRect
)
1086 return awt::Rectangle( aRect
.X
- m_aBorderWidths
.Left
- HATCH_BORDER_WIDTH
,
1087 aRect
.Y
- m_aBorderWidths
.Top
- HATCH_BORDER_WIDTH
,
1088 aRect
.Width
+ m_aBorderWidths
.Left
+ m_aBorderWidths
.Right
+ 2*HATCH_BORDER_WIDTH
,
1089 aRect
.Height
+ m_aBorderWidths
.Top
+ m_aBorderWidths
.Bottom
+ 2*HATCH_BORDER_WIDTH
);
1093 void SAL_CALL
DocumentHolder::disposing( const css::lang::EventObject
& aSource
)
1095 if ( m_xComponent
.is() && m_xComponent
== aSource
.Source
)
1097 m_xComponent
= nullptr;
1098 if ( m_bWaitForClose
)
1100 m_bWaitForClose
= false;
1105 if( m_xFrame
.is() && m_xFrame
== aSource
.Source
)
1107 m_xHatchWindow
.clear();
1108 m_xOwnWindow
.clear();
1114 void SAL_CALL
DocumentHolder::queryClosing( const lang::EventObject
& aSource
, sal_Bool
/*bGetsOwnership*/ )
1116 if ( m_xComponent
.is() && m_xComponent
== aSource
.Source
&& !m_bAllowClosing
)
1117 throw util::CloseVetoException(u
"To close an embedded document, close the document holder (document definition), not the document itself."_ustr
, static_cast< ::cppu::OWeakObject
*>(this));
1121 void SAL_CALL
DocumentHolder::notifyClosing( const lang::EventObject
& aSource
)
1123 if ( m_xComponent
.is() && m_xComponent
== aSource
.Source
)
1125 m_xComponent
= nullptr;
1126 if ( m_bWaitForClose
)
1128 m_bWaitForClose
= false;
1133 if( m_xFrame
.is() && m_xFrame
== aSource
.Source
)
1135 m_xHatchWindow
.clear();
1136 m_xOwnWindow
.clear();
1142 void SAL_CALL
DocumentHolder::queryTermination( const lang::EventObject
& )
1144 if ( m_bWaitForClose
)
1145 throw frame::TerminationVetoException();
1149 void SAL_CALL
DocumentHolder::notifyTermination( const lang::EventObject
& aSource
)
1151 OSL_ENSURE( !m_xComponent
.is(), "Just a disaster..." );
1153 uno::Reference
< frame::XDesktop
> xDesktop( aSource
.Source
, uno::UNO_QUERY
);
1154 m_bDesktopTerminated
= true;
1155 if ( xDesktop
.is() )
1156 xDesktop
->removeTerminateListener( static_cast<frame::XTerminateListener
*>(this) );
1160 void SAL_CALL
DocumentHolder::modified( const lang::EventObject
& aEvent
)
1162 // if the component does not support document::XEventBroadcaster
1163 // the modify notifications are used as workaround, but only for running state
1164 if( aEvent
.Source
== m_xComponent
&& m_pEmbedObj
&& m_pEmbedObj
->getCurrentState() == embed::EmbedStates::RUNNING
)
1165 m_pEmbedObj
->PostEvent_Impl( u
"OnVisAreaChanged"_ustr
);
1169 void SAL_CALL
DocumentHolder::notifyEvent( const document::EventObject
& Event
)
1171 if( m_pEmbedObj
&& Event
.Source
== m_xComponent
)
1173 // for now the ignored events are not forwarded, but sent by the object itself
1174 if ( !Event
.EventName
.startsWith( "OnSave" )
1175 && !Event
.EventName
.startsWith( "OnSaveDone" )
1176 && !Event
.EventName
.startsWith( "OnSaveAs" )
1177 && !Event
.EventName
.startsWith( "OnSaveAsDone" )
1178 && !( Event
.EventName
.startsWith( "OnVisAreaChanged" ) && m_nNoResizeReact
) )
1179 m_pEmbedObj
->PostEvent_Impl( Event
.EventName
);
1184 void SAL_CALL
DocumentHolder::borderWidthsChanged( const uno::Reference
< uno::XInterface
>& aObject
,
1185 const frame::BorderWidths
& aNewSize
)
1187 // TODO: may require mutex introduction ???
1188 if ( m_pEmbedObj
&& m_xFrame
.is() && aObject
== m_xFrame
->getController() )
1190 if ( m_aBorderWidths
.Left
!= aNewSize
.Left
1191 || m_aBorderWidths
.Right
!= aNewSize
.Right
1192 || m_aBorderWidths
.Top
!= aNewSize
.Top
1193 || m_aBorderWidths
.Bottom
!= aNewSize
.Bottom
)
1195 m_aBorderWidths
= aNewSize
;
1196 if ( !m_nNoBorderResizeReact
)
1197 PlaceFrame( m_aObjRect
);
1203 void SAL_CALL
DocumentHolder::requestPositioning( const awt::Rectangle
& aRect
)
1205 // TODO: may require mutex introduction ???
1208 // borders should not be counted
1209 awt::Rectangle aObjRect
= CalculateBorderedArea( aRect
);
1210 IntCounterGuard
aGuard( m_nNoResizeReact
);
1211 m_pEmbedObj
->requestPositioning( aObjRect
);
1216 awt::Rectangle SAL_CALL
DocumentHolder::calcAdjustedRectangle( const awt::Rectangle
& aRect
)
1218 // Solar mutex should be locked already since this is a call from HatchWindow with focus
1219 awt::Rectangle
aResult( aRect
);
1221 if ( m_xFrame
.is() )
1223 // borders should not be counted
1224 uno::Reference
< frame::XControllerBorder
> xControllerBorder( m_xFrame
->getController(), uno::UNO_QUERY
);
1225 if ( xControllerBorder
.is() )
1227 awt::Rectangle aObjRect
= CalculateBorderedArea( aRect
);
1228 aObjRect
= xControllerBorder
->queryBorderedArea( aObjRect
);
1229 aResult
= AddBorderToArea( aObjRect
);
1233 awt::Rectangle aMinRectangle
= AddBorderToArea( awt::Rectangle() );
1234 if ( aResult
.Width
< aMinRectangle
.Width
+ 2 )
1235 aResult
.Width
= aMinRectangle
.Width
+ 2;
1236 if ( aResult
.Height
< aMinRectangle
.Height
+ 2 )
1237 aResult
.Height
= aMinRectangle
.Height
+ 2;
1242 void SAL_CALL
DocumentHolder::activated( )
1244 if ( !(m_pEmbedObj
->getStatus(embed::Aspects::MSOLE_CONTENT
)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
) )
1247 if ( m_pEmbedObj
->getCurrentState() != embed::EmbedStates::UI_ACTIVE
&&
1248 !(m_pEmbedObj
->getStatus(embed::Aspects::MSOLE_CONTENT
)&embed::EmbedMisc::MS_EMBED_NOUIACTIVATE
) )
1252 m_pEmbedObj
->changeState( embed::EmbedStates::UI_ACTIVE
);
1254 catch ( const css::embed::StateChangeInProgressException
& )
1256 // must catch this exception because focus is grabbed while UI activation in doVerb()
1258 catch ( const css::uno::Exception
& )
1260 // no outgoing exceptions specified here
1265 uno::Reference
< frame::XFramesSupplier
> xSupp
= m_xFrame
->getCreator();
1267 xSupp
->setActiveFrame( m_xFrame
);
1271 void DocumentHolder::ResizeHatchWindow()
1273 awt::Rectangle aHatchRect
= AddBorderToArea( m_aObjRect
);
1274 ResizeWindows_Impl( aHatchRect
);
1275 uno::Reference
< embed::XHatchWindow
> xHatchWindow( m_xHatchWindow
, uno::UNO_QUERY
);
1276 xHatchWindow
->setHatchBorderSize( awt::Size( HATCH_BORDER_WIDTH
, HATCH_BORDER_WIDTH
) );
1279 void SAL_CALL
DocumentHolder::deactivated( )
1281 // deactivation is too unspecific to be useful; usually we only trigger code from activation
1282 // so UIDeactivation is actively triggered by the container
1285 } // namespace embeddedobj
1287 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */