Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / embeddedobj / source / general / docholder.cxx
blobbcac2d08c9e54b524f1cdbb3bad7795d8d917594
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
60 #include <utility>
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;
77 namespace {
79 class IntCounterGuard
81 sal_Int32& m_rFlag;
82 public:
83 explicit IntCounterGuard(sal_Int32& rFlag)
84 : m_rFlag(rFlag)
86 ++m_rFlag;
89 ~IntCounterGuard()
91 if (m_rFlag)
92 --m_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 )
105 sal_Int32 nInd = 0;
106 OUString aModuleIdentPropName( "ModuleIdentifier" );
107 OUString aDispProvPropName( "DispatchProvider" );
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;
126 bDispProvSet = true;
128 else
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 ) );
152 DocumentHolder::DocumentHolder( uno::Reference< uno::XComponentContext > xContext,
153 OCommonEmbeddedObject* pEmbObj )
154 : m_pEmbedObj( pEmbObj ),
155 m_xContext(std::move( xContext )),
156 m_bReadOnly( false ),
157 m_bWaitForClose( false ),
158 m_bAllowClosing( false ),
159 m_bDesktopTerminated( false ),
160 m_nNoBorderResizeReact( 0 ),
161 m_nNoResizeReact( 0 )
163 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext );
164 osl_atomic_increment(&m_refCount);
167 xDesktop->addTerminateListener( this );
169 catch ( const uno::Exception& )
172 osl_atomic_decrement(&m_refCount);
174 m_aOutplaceFrameProps = { uno::Any(beans::NamedValue{ "TopWindow", uno::Any(true) }),
175 uno::Any(beans::NamedValue{ "MakeVisible", uno::Any(false) }),
176 //TODO/LATER: should use parent document frame
177 uno::Any(beans::NamedValue{ "ParentFrame", uno::Any(xDesktop) }) };
181 DocumentHolder::~DocumentHolder()
183 osl_atomic_increment(&m_refCount); // to allow deregistration as a listener
185 if( m_xFrame.is() )
186 CloseFrame();
188 if ( m_xComponent.is() )
190 try {
191 CloseDocument( true, false );
192 } catch( const uno::Exception& ) {}
195 if ( m_xInterceptor.is() )
197 m_xInterceptor->DisconnectDocHolder();
198 m_xInterceptor.clear();
201 if ( !m_bDesktopTerminated )
202 FreeOffice();
206 void DocumentHolder::CloseFrame()
208 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
209 if ( xCloseBroadcaster.is() )
210 xCloseBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
212 uno::Reference<util::XCloseable> xCloseable(
213 m_xFrame,uno::UNO_QUERY );
214 if( xCloseable.is() )
215 try {
216 xCloseable->close( true );
218 catch( const uno::Exception& ) {
220 else {
221 if( m_xFrame.is() )
222 m_xFrame->dispose();
225 if ( m_xHatchWindow.is() )
226 m_xHatchWindow->dispose();
228 m_xHatchWindow.clear();
229 m_xOwnWindow.clear();
230 m_xFrame.clear();
234 void DocumentHolder::FreeOffice()
236 try {
237 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext );
238 xDesktop->removeTerminateListener( this );
239 } catch (const css::uno::DeploymentException&) {
240 // if this happens, the desktop is already gone
243 // the following code is commented out since for now there is still no completely correct way to detect
244 // whether the office can be terminated, so it is better to have unnecessary process running than
245 // to lose any data
247 // uno::Reference< frame::XFramesSupplier > xFramesSupplier( xDesktop, uno::UNO_QUERY );
248 // if ( xFramesSupplier.is() )
249 // {
250 // uno::Reference< frame::XFrames > xFrames = xFramesSupplier->getFrames();
251 // if ( xFrames.is() && !xFrames->hasElements() )
252 // {
253 // try
254 // {
255 // xDesktop->terminate();
256 // }
257 // catch( uno::Exception & )
258 // {}
259 // }
260 // }
264 void DocumentHolder::CloseDocument( bool bDeliverOwnership, bool bWaitForClose )
266 if ( m_xComponent.is() )
268 uno::Reference< document::XEventBroadcaster > xEventBroadcaster( m_xComponent, uno::UNO_QUERY );
269 if ( xEventBroadcaster.is() )
270 xEventBroadcaster->removeEventListener( static_cast<document::XEventListener*>(this) );
271 else
273 // the object does not support document::XEventBroadcaster interface
274 // use the workaround, register for modified events
275 uno::Reference< util::XModifyBroadcaster > xModifyBroadcaster( m_xComponent, uno::UNO_QUERY );
276 if ( xModifyBroadcaster.is() )
277 xModifyBroadcaster->removeModifyListener( static_cast<util::XModifyListener*>(this) );
280 m_bAllowClosing = true;
281 m_bWaitForClose = bWaitForClose;
282 m_xComponent->close( bDeliverOwnership );
285 m_xComponent = nullptr;
289 void DocumentHolder::PlaceFrame( const awt::Rectangle& aNewRect )
291 OSL_ENSURE( m_xFrame.is() && m_xOwnWindow.is(),
292 "The object does not have windows required for inplace mode!" );
294 //TODO: may need mutex locking???
295 if ( !(m_xFrame.is() && m_xOwnWindow.is()) )
296 return;
298 // the frame can be replaced only in inplace mode
299 frame::BorderWidths aOldWidths;
300 IntCounterGuard aGuard( m_nNoBorderResizeReact );
304 aOldWidths = m_aBorderWidths;
306 awt::Rectangle aHatchRect = AddBorderToArea( aNewRect );
308 ResizeWindows_Impl( aHatchRect );
310 } while ( aOldWidths.Left != m_aBorderWidths.Left
311 || aOldWidths.Top != m_aBorderWidths.Top
312 || aOldWidths.Right != m_aBorderWidths.Right
313 || aOldWidths.Bottom != m_aBorderWidths.Bottom );
315 m_aObjRect = aNewRect;
319 void DocumentHolder::ResizeWindows_Impl( const awt::Rectangle& aHatchRect )
321 OSL_ENSURE( m_xFrame.is() && m_xOwnWindow.is() /*&& m_xHatchWindow.is()*/,
322 "The object does not have windows required for inplace mode!" );
323 if ( m_xHatchWindow.is() )
325 m_xOwnWindow->setPosSize( HATCH_BORDER_WIDTH,
326 HATCH_BORDER_WIDTH,
327 aHatchRect.Width - 2*HATCH_BORDER_WIDTH,
328 aHatchRect.Height - 2*HATCH_BORDER_WIDTH,
329 awt::PosSize::POSSIZE );
332 m_xHatchWindow->setPosSize( aHatchRect.X,
333 aHatchRect.Y,
334 aHatchRect.Width,
335 aHatchRect.Height,
336 awt::PosSize::POSSIZE );
338 else
339 m_xOwnWindow->setPosSize( aHatchRect.X + HATCH_BORDER_WIDTH,
340 aHatchRect.Y + HATCH_BORDER_WIDTH,
341 aHatchRect.Width - 2*HATCH_BORDER_WIDTH,
342 aHatchRect.Height - 2*HATCH_BORDER_WIDTH,
343 awt::PosSize::POSSIZE );
347 bool DocumentHolder::SetFrameLMVisibility( const uno::Reference< frame::XFrame >& xFrame, bool bVisible )
349 bool bResult = false;
353 uno::Reference< css::frame::XLayoutManager > xLayoutManager;
354 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY_THROW );
355 xPropSet->getPropertyValue("LayoutManager") >>= xLayoutManager;
356 if ( xLayoutManager.is() )
358 xLayoutManager->setVisible( bVisible );
360 // MBA: locking is done only on the container LM, because it is not about hiding windows, it's about
361 // giving up control over the component window (and stopping to listen for resize events of the container window)
362 if ( bVisible )
363 xLayoutManager->unlock();
364 else
365 xLayoutManager->lock();
367 bResult = true;
370 catch( const uno::Exception& )
373 return bResult;
377 bool DocumentHolder::ShowInplace( const uno::Reference< awt::XWindowPeer >& xParent,
378 const awt::Rectangle& aRectangleToShow,
379 const uno::Reference< frame::XDispatchProvider >& xContDisp )
381 OSL_ENSURE( !m_xFrame.is(), "A frame exists already!" );
383 if ( !m_xFrame.is() )
385 uno::Reference < frame::XModel > xModel( GetComponent(), uno::UNO_QUERY );
386 awt::Rectangle aHatchRectangle = AddBorderToArea( aRectangleToShow );
388 awt::Rectangle aOwnRectangle( HATCH_BORDER_WIDTH,
389 HATCH_BORDER_WIDTH,
390 aHatchRectangle.Width - 2*HATCH_BORDER_WIDTH,
391 aHatchRectangle.Height - 2*HATCH_BORDER_WIDTH );
392 uno::Reference< awt::XWindow > xHWindow;
393 uno::Reference< awt::XWindowPeer > xMyParent( xParent );
395 if ( xModel.is() )
398 uno::Reference< embed::XHatchWindowFactory > xHatchFactory =
399 embed::HatchWindowFactory::create(m_xContext);
401 uno::Reference< embed::XHatchWindow > xHatchWindow =
402 xHatchFactory->createHatchWindowInstance( xParent,
403 aHatchRectangle,
404 awt::Size( HATCH_BORDER_WIDTH, HATCH_BORDER_WIDTH ) );
406 uno::Reference< awt::XWindowPeer > xHatchWinPeer( xHatchWindow, uno::UNO_QUERY );
407 xHWindow.set( xHatchWinPeer, uno::UNO_QUERY_THROW );
409 xHatchWindow->setController( uno::Reference< embed::XHatchWindowController >(
410 static_cast< embed::XHatchWindowController* >( this ) ) );
412 xMyParent = xHatchWinPeer;
414 else
416 aOwnRectangle.X += aHatchRectangle.X;
417 aOwnRectangle.Y += aHatchRectangle.Y;
420 awt::WindowDescriptor aOwnWinDescriptor( awt::WindowClass_TOP,
421 "dockingwindow",
422 xMyParent,
424 awt::Rectangle(),//aOwnRectangle,
425 awt::WindowAttribute::SHOW | awt::VclWindowPeerAttribute::CLIPCHILDREN );
427 uno::Reference< awt::XToolkit2 > xToolkit = awt::Toolkit::create(m_xContext);
429 uno::Reference< awt::XWindowPeer > xNewWinPeer = xToolkit->createWindow( aOwnWinDescriptor );
430 uno::Reference< awt::XWindow > xOwnWindow( xNewWinPeer, uno::UNO_QUERY_THROW );
431 uno::Reference< frame::XFrame > xContFrame( xContDisp, uno::UNO_QUERY );
433 // create a frame based on the specified window
434 uno::Reference< lang::XSingleServiceFactory > xFrameFact = frame::TaskCreator::create(m_xContext);
436 uno::Sequence< uno::Any > aArgs( xContFrame.is() ? 2 : 1 );
437 auto pArgs = aArgs.getArray();
438 beans::NamedValue aArg;
440 aArg.Name = "ContainerWindow";
441 aArg.Value <<= xOwnWindow;
442 pArgs[0] <<= aArg;
444 if ( xContFrame.is() )
446 aArg.Name = "ParentFrame";
447 aArg.Value <<= xContFrame;
448 pArgs[1] <<= aArg;
451 // the call will create, initialize the frame, and register it in the parent
452 m_xFrame.set( xFrameFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW );
454 m_xHatchWindow = xHWindow;
455 m_xOwnWindow = xOwnWindow;
457 if ( !SetFrameLMVisibility( m_xFrame, false ) )
459 OSL_FAIL( "Can't deactivate LayoutManager!" );
460 // TODO/LATER: error handling?
463 // m_bIsInplace = sal_True; TODO: ?
465 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
466 if ( xCloseBroadcaster.is() )
467 xCloseBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
469 // TODO: some listeners to the frame and the window ( resize for example )
472 if ( !m_xComponent )
473 return false;
475 if ( !LoadDocToFrame( true ) )
477 CloseFrame();
478 return false;
481 uno::Reference< frame::XControllerBorder > xControllerBorder( m_xFrame->getController(), uno::UNO_QUERY );
482 if ( xControllerBorder.is() )
484 m_aBorderWidths = xControllerBorder->getBorder();
485 xControllerBorder->addBorderResizeListener( static_cast<frame::XBorderResizeListener*>(this) );
488 PlaceFrame( aRectangleToShow );
490 if ( m_xHatchWindow.is() )
491 m_xHatchWindow->setVisible( true );
493 return true;
497 uno::Reference< container::XIndexAccess > DocumentHolder::RetrieveOwnMenu_Impl()
499 uno::Reference< container::XIndexAccess > xResult;
501 uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUIConfSupplier(
502 m_xComponent,
503 uno::UNO_QUERY );
504 uno::Reference< css::ui::XUIConfigurationManager > xUIConfigManager;
505 if( xUIConfSupplier.is())
507 xUIConfigManager.set(
508 xUIConfSupplier->getUIConfigurationManager(),
509 uno::UNO_SET_THROW );
514 if( xUIConfigManager.is())
516 xResult = xUIConfigManager->getSettings(
517 "private:resource/menubar/menubar",
518 false );
521 catch( const uno::Exception& )
524 if ( !xResult.is() )
526 // no internal document configuration, use the one from the module
527 uno::Reference< frame::XModuleManager2 > xModuleMan = frame::ModuleManager::create(m_xContext);
528 OUString aModuleIdent =
529 xModuleMan->identify( uno::Reference< uno::XInterface >( m_xComponent, uno::UNO_QUERY ) );
531 if ( !aModuleIdent.isEmpty() )
533 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModConfSupplier =
534 ui::theModuleUIConfigurationManagerSupplier::get(m_xContext);
535 uno::Reference< css::ui::XUIConfigurationManager > xModUIConfMan(
536 xModConfSupplier->getUIConfigurationManager( aModuleIdent ),
537 uno::UNO_SET_THROW );
538 xResult = xModUIConfMan->getSettings(
539 "private:resource/menubar/menubar",
540 false );
544 if ( !xResult.is() )
545 throw uno::RuntimeException();
547 return xResult;
551 void DocumentHolder::FindConnectPoints(
552 const uno::Reference< container::XIndexAccess >& xMenu,
553 sal_Int32 nConnectPoints[2] )
555 nConnectPoints[0] = -1;
556 nConnectPoints[1] = -1;
557 for ( sal_Int32 nInd = 0; nInd < xMenu->getCount(); nInd++ )
559 uno::Sequence< beans::PropertyValue > aProps;
560 xMenu->getByIndex( nInd ) >>= aProps;
561 OUString aCommand;
562 for ( beans::PropertyValue const & prop : std::as_const(aProps) )
563 if ( prop.Name == "CommandURL" )
565 prop.Value >>= aCommand;
566 break;
569 if ( aCommand.isEmpty() )
570 throw uno::RuntimeException();
572 if ( aCommand == ".uno:PickList" )
573 nConnectPoints[0] = nInd;
574 else if ( aCommand == ".uno:WindowList" )
575 nConnectPoints[1] = nInd;
580 uno::Reference< container::XIndexAccess > DocumentHolder::MergeMenusForInplace(
581 const uno::Reference< container::XIndexAccess >& xContMenu,
582 const uno::Reference< frame::XDispatchProvider >& xContDisp,
583 const OUString& aContModuleName,
584 const uno::Reference< container::XIndexAccess >& xOwnMenu,
585 const uno::Reference< frame::XDispatchProvider >& xOwnDisp )
587 // TODO/LATER: use dispatch providers on merge
589 sal_Int32 nContPoints[2];
590 sal_Int32 nOwnPoints[2];
592 uno::Reference< lang::XSingleComponentFactory > xIndAccessFact( xContMenu, uno::UNO_QUERY_THROW );
594 uno::Reference< container::XIndexContainer > xMergedMenu(
595 xIndAccessFact->createInstanceWithContext(
596 comphelper::getProcessComponentContext() ),
597 uno::UNO_QUERY_THROW );
599 FindConnectPoints( xContMenu, nContPoints );
600 FindConnectPoints( xOwnMenu, nOwnPoints );
602 for ( sal_Int32 nInd = 0; nInd < xOwnMenu->getCount(); nInd++ )
604 if ( nOwnPoints[0] == nInd )
606 if ( nContPoints[0] >= 0 && nContPoints[0] < xContMenu->getCount() )
608 InsertMenu_Impl( xMergedMenu, nInd, xContMenu, nContPoints[0], aContModuleName, xContDisp );
611 else if ( nOwnPoints[1] == nInd )
613 if ( nContPoints[1] >= 0 && nContPoints[1] < xContMenu->getCount() )
615 InsertMenu_Impl( xMergedMenu, nInd, xContMenu, nContPoints[1], aContModuleName, xContDisp );
618 else
619 InsertMenu_Impl( xMergedMenu, nInd, xOwnMenu, nInd, OUString(), xOwnDisp );
622 return uno::Reference< container::XIndexAccess >( xMergedMenu, uno::UNO_QUERY_THROW );
626 bool DocumentHolder::MergeMenus_Impl( const uno::Reference< css::frame::XLayoutManager >& xOwnLM,
627 const uno::Reference< css::frame::XLayoutManager >& xContLM,
628 const uno::Reference< frame::XDispatchProvider >& xContDisp,
629 const OUString& aContModuleName )
631 bool bMenuMerged = false;
634 uno::Reference< css::ui::XUIElementSettings > xUISettings(
635 xContLM->getElement( "private:resource/menubar/menubar" ),
636 uno::UNO_QUERY_THROW );
637 uno::Reference< container::XIndexAccess > xContMenu = xUISettings->getSettings( true );
638 if ( !xContMenu.is() )
639 throw uno::RuntimeException();
641 uno::Reference< container::XIndexAccess > xOwnMenu = RetrieveOwnMenu_Impl();
642 uno::Reference< frame::XDispatchProvider > xOwnDisp( m_xFrame, uno::UNO_QUERY_THROW );
644 uno::Reference< container::XIndexAccess > xMergedMenu = MergeMenusForInplace( xContMenu, xContDisp, aContModuleName, xOwnMenu, xOwnDisp );
645 uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM,
646 uno::UNO_QUERY_THROW );
647 bMenuMerged = xMerge->setMergedMenuBar( xMergedMenu );
649 catch( const uno::Exception& )
652 return bMenuMerged;
655 bool DocumentHolder::ShowUI( const uno::Reference< css::frame::XLayoutManager >& xContainerLM,
656 const uno::Reference< frame::XDispatchProvider >& xContainerDP,
657 const OUString& aContModuleName )
659 bool bResult = false;
660 if ( xContainerLM.is() )
662 // the LM of the embedded frame and its current DockingAreaAcceptor
663 uno::Reference< css::frame::XLayoutManager > xOwnLM;
664 uno::Reference< css::ui::XDockingAreaAcceptor > xDocAreaAcc;
668 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
669 xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
670 xDocAreaAcc = xContainerLM->getDockingAreaAcceptor();
672 catch( const uno::Exception& ){}
674 if ( xOwnLM.is() && xDocAreaAcc.is() )
676 // make sure that lock state of LM is correct even if an exception is thrown in between
677 bool bUnlockContainerLM = false;
678 bool bLockOwnLM = false;
681 // take over the control over the containers window
682 // as long as the LM is invisible and locked an empty tool space will be used on resizing
683 xOwnLM->setDockingAreaAcceptor( xDocAreaAcc );
685 // try to merge menus; don't do anything else if it fails
686 if ( MergeMenus_Impl( xOwnLM, xContainerLM, xContainerDP, aContModuleName ) )
688 // make sure that the container LM does not control the size of the containers window anymore
689 // this must be done after merging menus as we won't get the container menu otherwise
690 xContainerLM->setDockingAreaAcceptor( uno::Reference < ui::XDockingAreaAcceptor >() );
692 uno::Reference< lang::XServiceInfo> xServiceInfo(m_xComponent, uno::UNO_QUERY);
693 if (!xServiceInfo.is() || !xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
695 // prevent further changes at this LM
696 xContainerLM->setVisible(false);
697 xContainerLM->lock();
698 bUnlockContainerLM = true;
701 // by unlocking the LM each layout change will now resize the containers window; pending layouts will be processed now
702 xOwnLM->setVisible( true );
704 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
705 if ( xSupp.is() )
706 xSupp->setActiveFrame( m_xFrame );
708 xOwnLM->unlock();
709 bLockOwnLM = true;
710 bResult = true;
712 // TODO/LATER: The following action should be done only if the window is not hidden
713 // otherwise the activation must fail, unfortunately currently it is not possible
714 // to detect whether the window is hidden using UNO API
715 m_xOwnWindow->setFocus();
718 catch( const uno::Exception& )
720 // activation failed; reestablish old state
723 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
724 if ( xSupp.is() )
725 xSupp->setActiveFrame( nullptr );
727 // remove control about containers window from own LM
728 if (bLockOwnLM)
729 xOwnLM->lock();
730 xOwnLM->setVisible( false );
731 xOwnLM->setDockingAreaAcceptor( uno::Reference< css::ui::XDockingAreaAcceptor >() );
733 // unmerge menu
734 uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM, uno::UNO_QUERY_THROW );
735 xMerge->removeMergedMenuBar();
737 catch( const uno::Exception& ) {}
741 // reestablish control of containers window
742 xContainerLM->setDockingAreaAcceptor( xDocAreaAcc );
743 xContainerLM->setVisible( true );
744 if (bUnlockContainerLM)
745 xContainerLM->unlock();
747 catch( const uno::Exception& ) {}
752 return bResult;
756 bool DocumentHolder::HideUI( const uno::Reference< css::frame::XLayoutManager >& xContainerLM )
758 bool bResult = false;
760 if ( xContainerLM.is() )
762 uno::Reference< css::frame::XLayoutManager > xOwnLM;
764 try {
765 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
766 xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
767 } catch( const uno::Exception& )
770 if ( xOwnLM.is() )
772 try {
773 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
774 if ( xSupp.is() )
775 xSupp->setActiveFrame( nullptr );
777 uno::Reference< css::ui::XDockingAreaAcceptor > xDocAreaAcc = xOwnLM->getDockingAreaAcceptor();
779 xOwnLM->setDockingAreaAcceptor( uno::Reference < ui::XDockingAreaAcceptor >() );
780 xOwnLM->lock();
781 xOwnLM->setVisible( false );
783 uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM, uno::UNO_QUERY_THROW );
784 xMerge->removeMergedMenuBar();
786 xContainerLM->setDockingAreaAcceptor( xDocAreaAcc );
787 uno::Reference< lang::XServiceInfo> xServiceInfo(m_xComponent, uno::UNO_QUERY);
788 if (!xServiceInfo.is() || !xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
790 xContainerLM->setVisible(true);
791 xContainerLM->unlock();
794 xContainerLM->doLayout();
795 bResult = true;
797 catch( const uno::Exception& )
799 SetFrameLMVisibility( m_xFrame, true );
804 return bResult;
808 uno::Reference< frame::XFrame > const & DocumentHolder::GetDocFrame()
810 // the frame for outplace activation
811 if ( !m_xFrame.is() )
813 uno::Reference< lang::XSingleServiceFactory > xFrameFact = frame::TaskCreator::create(m_xContext);
815 m_xFrame.set(xFrameFact->createInstanceWithArguments( m_aOutplaceFrameProps ), uno::UNO_QUERY_THROW);
817 uno::Reference< frame::XDispatchProviderInterception > xInterception( m_xFrame, uno::UNO_QUERY );
818 if ( xInterception.is() )
820 if ( m_xInterceptor.is() )
822 m_xInterceptor->DisconnectDocHolder();
823 m_xInterceptor.clear();
826 m_xInterceptor = new Interceptor( this );
828 xInterception->registerDispatchProviderInterceptor( m_xInterceptor );
830 // register interceptor from outside
831 if ( m_xOutplaceInterceptor.is() )
832 xInterception->registerDispatchProviderInterceptor( m_xOutplaceInterceptor );
835 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
836 if ( xCloseBroadcaster.is() )
837 xCloseBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
840 if ( m_xComponent.is() )
842 uno::Reference< css::frame::XLayoutManager > xOwnLM;
843 try {
844 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
845 xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
846 } catch( const uno::Exception& )
849 if ( xOwnLM.is() )
850 xOwnLM->lock();
852 // TODO/LATER: get it for the real aspect
853 awt::Size aSize;
854 LoadDocToFrame(false);
856 if ( xOwnLM.is() )
858 xOwnLM->unlock();
859 xOwnLM->lock();
862 GetExtent(embed::Aspects::MSOLE_CONTENT, &aSize);
863 SetExtent(embed::Aspects::MSOLE_CONTENT, aSize);
865 if ( xOwnLM.is() )
866 xOwnLM->unlock();
871 uno::Reference< awt::XWindow > xHWindow = m_xFrame->getContainerWindow();
873 if( xHWindow.is() )
875 sal_Int32 nDisplay = Application::GetDisplayBuiltInScreen();
877 tools::Rectangle aWorkRect = Application::GetScreenPosSizePixel( nDisplay );
878 awt::Rectangle aWindowRect = xHWindow->getPosSize();
880 if (( aWindowRect.Width < aWorkRect.GetWidth()) && ( aWindowRect.Height < aWorkRect.GetHeight() ))
882 int OffsetX = ( aWorkRect.GetWidth() - aWindowRect.Width ) / 2 + aWorkRect.Left();
883 int OffsetY = ( aWorkRect.GetHeight() - aWindowRect.Height ) /2 + aWorkRect.Top();
884 xHWindow->setPosSize( OffsetX, OffsetY, aWindowRect.Width, aWindowRect.Height, awt::PosSize::POS );
886 else
888 xHWindow->setPosSize( aWorkRect.Left(), aWorkRect.Top(), aWorkRect.GetWidth(), aWorkRect.GetHeight(), awt::PosSize::POSSIZE );
891 xHWindow->setVisible( true );
894 catch ( const uno::Exception& )
898 return m_xFrame;
902 void DocumentHolder::SetComponent( const uno::Reference< util::XCloseable >& xDoc, bool bReadOnly )
904 if ( m_xComponent.is() )
906 // May be should be improved
907 try {
908 CloseDocument( true, false );
909 } catch( const uno::Exception& )
913 m_xComponent = xDoc;
915 m_bReadOnly = bReadOnly;
916 m_bAllowClosing = false;
918 if ( m_xComponent.is() )
919 m_xComponent->addCloseListener( static_cast<util::XCloseListener*>(this) );
921 uno::Reference< document::XEventBroadcaster > xEventBroadcaster( m_xComponent, uno::UNO_QUERY );
922 if ( xEventBroadcaster.is() )
923 xEventBroadcaster->addEventListener( static_cast<document::XEventListener*>(this) );
924 else
926 // the object does not support document::XEventBroadcaster interface
927 // use the workaround, register for modified events
928 uno::Reference< util::XModifyBroadcaster > xModifyBroadcaster( m_xComponent, uno::UNO_QUERY );
929 if ( xModifyBroadcaster.is() )
930 xModifyBroadcaster->addModifyListener( static_cast<util::XModifyListener*>(this) );
933 if ( m_xFrame.is() )
934 LoadDocToFrame(false);
938 bool DocumentHolder::LoadDocToFrame( bool bInPlace )
940 if ( !m_xFrame || !m_xComponent )
941 return true;
943 uno::Reference < frame::XModel > xDoc( m_xComponent, uno::UNO_QUERY );
944 if ( xDoc.is() )
946 // load new document into the frame
947 uno::Reference< frame::XComponentLoader > xComponentLoader( m_xFrame, uno::UNO_QUERY_THROW );
949 ::comphelper::NamedValueCollection aArgs;
950 aArgs.put( "Model", m_xComponent );
951 aArgs.put( "ReadOnly", m_bReadOnly );
953 // set document title to show in the title bar
954 css::uno::Reference< css::frame::XTitle > xModelTitle( xDoc, css::uno::UNO_QUERY );
955 if( xModelTitle.is() && m_pEmbedObj && !m_pEmbedObj->getContainerName().isEmpty() )
957 std::locale aResLoc = Translate::Create("sfx");
958 OUString sEmbedded = Translate::get(STR_EMBEDDED_TITLE, aResLoc);
959 xModelTitle->setTitle( m_pEmbedObj->getContainerName() + sEmbedded );
960 m_aContainerName = m_pEmbedObj->getContainerName();
961 // TODO: get real m_aDocumentNamePart
962 m_aDocumentNamePart = sEmbedded;
965 if ( bInPlace )
966 aArgs.put( "PluginMode", sal_Int16(1) );
967 OUString sUrl;
968 uno::Reference< lang::XServiceInfo> xServiceInfo(xDoc,uno::UNO_QUERY);
969 if ( xServiceInfo.is()
970 && xServiceInfo->supportsService("com.sun.star.report.ReportDefinition") )
972 sUrl = ".component:DB/ReportDesign";
974 else if( xServiceInfo.is()
975 && xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
976 sUrl = "private:factory/schart";
977 else
978 sUrl = "private:object";
980 xComponentLoader->loadComponentFromURL( sUrl,
981 "_self",
983 aArgs.getPropertyValues() );
985 return true;
987 else
989 uno::Reference < frame::XSynchronousFrameLoader > xLoader( m_xComponent, uno::UNO_QUERY );
990 if ( xLoader.is() )
991 return xLoader->load( uno::Sequence < beans::PropertyValue >(), m_xFrame );
992 else
993 return false;
996 return true;
1000 void DocumentHolder::Show()
1002 if( m_xFrame.is() )
1004 m_xFrame->activate();
1005 uno::Reference<awt::XTopWindow> xTopWindow( m_xFrame->getContainerWindow(), uno::UNO_QUERY );
1006 if( xTopWindow.is() )
1007 xTopWindow->toFront();
1009 else
1010 GetDocFrame();
1014 bool DocumentHolder::SetExtent( sal_Int64 nAspect, const awt::Size& aSize )
1016 uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
1017 if ( xDocVis.is() )
1021 xDocVis->setVisualAreaSize( nAspect, aSize );
1022 return true;
1024 catch( const uno::Exception& )
1026 // TODO: Error handling
1030 return false;
1034 bool DocumentHolder::GetExtent( sal_Int64 nAspect, awt::Size *pSize )
1036 uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
1037 if ( pSize && xDocVis.is() )
1041 *pSize = xDocVis->getVisualAreaSize( nAspect );
1042 return true;
1044 catch( const uno::Exception& )
1046 // TODO: Error handling
1050 return false;
1054 sal_Int32 DocumentHolder::GetMapUnit( sal_Int64 nAspect )
1056 uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
1057 if ( xDocVis.is() )
1061 return xDocVis->getMapUnit( nAspect );
1063 catch( const uno::Exception& )
1065 // TODO: Error handling
1069 return 0;
1073 awt::Rectangle DocumentHolder::CalculateBorderedArea( const awt::Rectangle& aRect )
1075 return awt::Rectangle( aRect.X + m_aBorderWidths.Left + HATCH_BORDER_WIDTH,
1076 aRect.Y + m_aBorderWidths.Top + HATCH_BORDER_WIDTH,
1077 aRect.Width - m_aBorderWidths.Left - m_aBorderWidths.Right - 2*HATCH_BORDER_WIDTH,
1078 aRect.Height - m_aBorderWidths.Top - m_aBorderWidths.Bottom - 2*HATCH_BORDER_WIDTH );
1082 awt::Rectangle DocumentHolder::AddBorderToArea( const awt::Rectangle& aRect )
1084 return awt::Rectangle( aRect.X - m_aBorderWidths.Left - HATCH_BORDER_WIDTH,
1085 aRect.Y - m_aBorderWidths.Top - HATCH_BORDER_WIDTH,
1086 aRect.Width + m_aBorderWidths.Left + m_aBorderWidths.Right + 2*HATCH_BORDER_WIDTH,
1087 aRect.Height + m_aBorderWidths.Top + m_aBorderWidths.Bottom + 2*HATCH_BORDER_WIDTH );
1091 void SAL_CALL DocumentHolder::disposing( const css::lang::EventObject& aSource )
1093 if ( m_xComponent.is() && m_xComponent == aSource.Source )
1095 m_xComponent = nullptr;
1096 if ( m_bWaitForClose )
1098 m_bWaitForClose = false;
1099 FreeOffice();
1103 if( m_xFrame.is() && m_xFrame == aSource.Source )
1105 m_xHatchWindow.clear();
1106 m_xOwnWindow.clear();
1107 m_xFrame.clear();
1112 void SAL_CALL DocumentHolder::queryClosing( const lang::EventObject& aSource, sal_Bool /*bGetsOwnership*/ )
1114 if ( m_xComponent.is() && m_xComponent == aSource.Source && !m_bAllowClosing )
1115 throw util::CloseVetoException("To close an embedded document, close the document holder (document definition), not the document itself.", static_cast< ::cppu::OWeakObject*>(this));
1119 void SAL_CALL DocumentHolder::notifyClosing( const lang::EventObject& aSource )
1121 if ( m_xComponent.is() && m_xComponent == aSource.Source )
1123 m_xComponent = nullptr;
1124 if ( m_bWaitForClose )
1126 m_bWaitForClose = false;
1127 FreeOffice();
1131 if( m_xFrame.is() && m_xFrame == aSource.Source )
1133 m_xHatchWindow.clear();
1134 m_xOwnWindow.clear();
1135 m_xFrame.clear();
1140 void SAL_CALL DocumentHolder::queryTermination( const lang::EventObject& )
1142 if ( m_bWaitForClose )
1143 throw frame::TerminationVetoException();
1147 void SAL_CALL DocumentHolder::notifyTermination( const lang::EventObject& aSource )
1149 OSL_ENSURE( !m_xComponent.is(), "Just a disaster..." );
1151 uno::Reference< frame::XDesktop > xDesktop( aSource.Source, uno::UNO_QUERY );
1152 m_bDesktopTerminated = true;
1153 if ( xDesktop.is() )
1154 xDesktop->removeTerminateListener( static_cast<frame::XTerminateListener*>(this) );
1158 void SAL_CALL DocumentHolder::modified( const lang::EventObject& aEvent )
1160 // if the component does not support document::XEventBroadcaster
1161 // the modify notifications are used as workaround, but only for running state
1162 if( aEvent.Source == m_xComponent && m_pEmbedObj && m_pEmbedObj->getCurrentState() == embed::EmbedStates::RUNNING )
1163 m_pEmbedObj->PostEvent_Impl( "OnVisAreaChanged" );
1167 void SAL_CALL DocumentHolder::notifyEvent( const document::EventObject& Event )
1169 if( m_pEmbedObj && Event.Source == m_xComponent )
1171 // for now the ignored events are not forwarded, but sent by the object itself
1172 if ( !Event.EventName.startsWith( "OnSave" )
1173 && !Event.EventName.startsWith( "OnSaveDone" )
1174 && !Event.EventName.startsWith( "OnSaveAs" )
1175 && !Event.EventName.startsWith( "OnSaveAsDone" )
1176 && !( Event.EventName.startsWith( "OnVisAreaChanged" ) && m_nNoResizeReact ) )
1177 m_pEmbedObj->PostEvent_Impl( Event.EventName );
1182 void SAL_CALL DocumentHolder::borderWidthsChanged( const uno::Reference< uno::XInterface >& aObject,
1183 const frame::BorderWidths& aNewSize )
1185 // TODO: may require mutex introduction ???
1186 if ( m_pEmbedObj && m_xFrame.is() && aObject == m_xFrame->getController() )
1188 if ( m_aBorderWidths.Left != aNewSize.Left
1189 || m_aBorderWidths.Right != aNewSize.Right
1190 || m_aBorderWidths.Top != aNewSize.Top
1191 || m_aBorderWidths.Bottom != aNewSize.Bottom )
1193 m_aBorderWidths = aNewSize;
1194 if ( !m_nNoBorderResizeReact )
1195 PlaceFrame( m_aObjRect );
1201 void SAL_CALL DocumentHolder::requestPositioning( const awt::Rectangle& aRect )
1203 // TODO: may require mutex introduction ???
1204 if ( m_pEmbedObj )
1206 // borders should not be counted
1207 awt::Rectangle aObjRect = CalculateBorderedArea( aRect );
1208 IntCounterGuard aGuard( m_nNoResizeReact );
1209 m_pEmbedObj->requestPositioning( aObjRect );
1214 awt::Rectangle SAL_CALL DocumentHolder::calcAdjustedRectangle( const awt::Rectangle& aRect )
1216 // Solar mutex should be locked already since this is a call from HatchWindow with focus
1217 awt::Rectangle aResult( aRect );
1219 if ( m_xFrame.is() )
1221 // borders should not be counted
1222 uno::Reference< frame::XControllerBorder > xControllerBorder( m_xFrame->getController(), uno::UNO_QUERY );
1223 if ( xControllerBorder.is() )
1225 awt::Rectangle aObjRect = CalculateBorderedArea( aRect );
1226 aObjRect = xControllerBorder->queryBorderedArea( aObjRect );
1227 aResult = AddBorderToArea( aObjRect );
1231 awt::Rectangle aMinRectangle = AddBorderToArea( awt::Rectangle() );
1232 if ( aResult.Width < aMinRectangle.Width + 2 )
1233 aResult.Width = aMinRectangle.Width + 2;
1234 if ( aResult.Height < aMinRectangle.Height + 2 )
1235 aResult.Height = aMinRectangle.Height + 2;
1237 return aResult;
1240 void SAL_CALL DocumentHolder::activated( )
1242 if ( !(m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) )
1243 return;
1245 if ( m_pEmbedObj->getCurrentState() != embed::EmbedStates::UI_ACTIVE &&
1246 !(m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_NOUIACTIVATE) )
1250 m_pEmbedObj->changeState( embed::EmbedStates::UI_ACTIVE );
1252 catch ( const css::embed::StateChangeInProgressException& )
1254 // must catch this exception because focus is grabbed while UI activation in doVerb()
1256 catch ( const css::uno::Exception& )
1258 // no outgoing exceptions specified here
1261 else
1263 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
1264 if ( xSupp.is() )
1265 xSupp->setActiveFrame( m_xFrame );
1269 void DocumentHolder::ResizeHatchWindow()
1271 awt::Rectangle aHatchRect = AddBorderToArea( m_aObjRect );
1272 ResizeWindows_Impl( aHatchRect );
1273 uno::Reference< embed::XHatchWindow > xHatchWindow( m_xHatchWindow, uno::UNO_QUERY );
1274 xHatchWindow->setHatchBorderSize( awt::Size( HATCH_BORDER_WIDTH, HATCH_BORDER_WIDTH ) );
1277 void SAL_CALL DocumentHolder::deactivated( )
1279 // deactivation is too unspecific to be useful; usually we only trigger code from activation
1280 // so UIDeactivation is actively triggered by the container
1283 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */