nss: upgrade to release 3.73
[LibreOffice.git] / embeddedobj / source / general / docholder.cxx
blob90a04d85e125a55fff67a577d2a41a76f0793101
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 <vcl/svapp.hxx>
61 #include <unotools/resmgr.hxx>
62 #include <sfx2/strings.hrc>
64 #include <comphelper/processfactory.hxx>
65 #include <comphelper/namedvaluecollection.hxx>
67 #include <docholder.hxx>
68 #include <commonembobj.hxx>
69 #include <intercept.hxx>
71 #define HATCH_BORDER_WIDTH (((m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) && \
72 m_pEmbedObj->getCurrentState()!=embed::EmbedStates::UI_ACTIVE) ? 0 : 4 )
74 using namespace ::com::sun::star;
76 namespace {
78 class IntCounterGuard
80 sal_Int32& m_rFlag;
81 public:
82 explicit IntCounterGuard(sal_Int32& rFlag)
83 : m_rFlag(rFlag)
85 ++m_rFlag;
88 ~IntCounterGuard()
90 if (m_rFlag)
91 --m_rFlag;
97 static void InsertMenu_Impl( const uno::Reference< container::XIndexContainer >& xTargetMenu,
98 sal_Int32 nTargetIndex,
99 const uno::Reference< container::XIndexAccess >& xSourceMenu,
100 sal_Int32 nSourceIndex,
101 const OUString& aContModuleName,
102 const uno::Reference< frame::XDispatchProvider >& xSourceDisp )
104 sal_Int32 nInd = 0;
105 OUString aModuleIdentPropName( "ModuleIdentifier" );
106 OUString aDispProvPropName( "DispatchProvider" );
107 bool bModuleNameSet = false;
108 bool bDispProvSet = false;
110 uno::Sequence< beans::PropertyValue > aSourceProps;
111 xSourceMenu->getByIndex( nSourceIndex ) >>= aSourceProps;
112 uno::Sequence< beans::PropertyValue > aTargetProps( aSourceProps.getLength() );
113 for ( nInd = 0; nInd < aSourceProps.getLength(); nInd++ )
115 aTargetProps[nInd].Name = aSourceProps[nInd].Name;
116 if ( !aContModuleName.isEmpty() && aTargetProps[nInd].Name == aModuleIdentPropName )
118 aTargetProps[nInd].Value <<= aContModuleName;
119 bModuleNameSet = true;
121 else if ( aTargetProps[nInd].Name == aDispProvPropName )
123 aTargetProps[nInd].Value <<= xSourceDisp;
124 bDispProvSet = true;
126 else
127 aTargetProps[nInd].Value = aSourceProps[nInd].Value;
130 if ( !bModuleNameSet && !aContModuleName.isEmpty() )
132 aTargetProps.realloc( ++nInd );
133 aTargetProps[nInd-1].Name = aModuleIdentPropName;
134 aTargetProps[nInd-1].Value <<= aContModuleName;
137 if ( !bDispProvSet && xSourceDisp.is() )
139 aTargetProps.realloc( ++nInd );
140 aTargetProps[nInd-1].Name = aDispProvPropName;
141 aTargetProps[nInd-1].Value <<= xSourceDisp;
144 xTargetMenu->insertByIndex( nTargetIndex, uno::makeAny( aTargetProps ) );
148 DocumentHolder::DocumentHolder( const uno::Reference< uno::XComponentContext >& xContext,
149 OCommonEmbeddedObject* pEmbObj )
150 : m_pEmbedObj( pEmbObj ),
151 m_xContext( xContext ),
152 m_bReadOnly( false ),
153 m_bWaitForClose( false ),
154 m_bAllowClosing( false ),
155 m_bDesktopTerminated( false ),
156 m_nNoBorderResizeReact( 0 ),
157 m_nNoResizeReact( 0 )
159 m_aOutplaceFrameProps.realloc( 3 );
160 beans::NamedValue aArg;
162 aArg.Name = "TopWindow";
163 aArg.Value <<= true;
164 m_aOutplaceFrameProps[0] <<= aArg;
166 aArg.Name = "MakeVisible";
167 aArg.Value <<= false;
168 m_aOutplaceFrameProps[1] <<= aArg;
170 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext );
171 osl_atomic_increment(&m_refCount);
174 xDesktop->addTerminateListener( this );
176 catch ( const uno::Exception& )
179 osl_atomic_decrement(&m_refCount);
181 aArg.Name = "ParentFrame";
182 aArg.Value <<= xDesktop; //TODO/LATER: should use parent document frame
183 m_aOutplaceFrameProps[2] <<= aArg;
187 DocumentHolder::~DocumentHolder()
189 osl_atomic_increment(&m_refCount); // to allow deregistration as a listener
191 if( m_xFrame.is() )
192 CloseFrame();
194 if ( m_xComponent.is() )
196 try {
197 CloseDocument( true, false );
198 } catch( const uno::Exception& ) {}
201 if ( m_xInterceptor.is() )
203 m_xInterceptor->DisconnectDocHolder();
204 m_xInterceptor.clear();
207 if ( !m_bDesktopTerminated )
208 FreeOffice();
212 void DocumentHolder::CloseFrame()
214 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
215 if ( xCloseBroadcaster.is() )
216 xCloseBroadcaster->removeCloseListener( static_cast<util::XCloseListener*>(this) );
218 uno::Reference<util::XCloseable> xCloseable(
219 m_xFrame,uno::UNO_QUERY );
220 if( xCloseable.is() )
221 try {
222 xCloseable->close( true );
224 catch( const uno::Exception& ) {
226 else {
227 if( m_xFrame.is() )
228 m_xFrame->dispose();
231 if ( m_xHatchWindow.is() )
232 m_xHatchWindow->dispose();
234 m_xHatchWindow.clear();
235 m_xOwnWindow.clear();
236 m_xFrame.clear();
240 void DocumentHolder::FreeOffice()
242 uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create( m_xContext );
243 xDesktop->removeTerminateListener( this );
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
247 // to lose any data
249 // uno::Reference< frame::XFramesSupplier > xFramesSupplier( xDesktop, uno::UNO_QUERY );
250 // if ( xFramesSupplier.is() )
251 // {
252 // uno::Reference< frame::XFrames > xFrames = xFramesSupplier->getFrames();
253 // if ( xFrames.is() && !xFrames->hasElements() )
254 // {
255 // try
256 // {
257 // xDesktop->terminate();
258 // }
259 // catch( uno::Exception & )
260 // {}
261 // }
262 // }
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) );
273 else
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()) )
298 return;
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,
328 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,
335 aHatchRect.Y,
336 aHatchRect.Width,
337 aHatchRect.Height,
338 awt::PosSize::POSSIZE );
340 else
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("LayoutManager") >>= 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)
364 if ( bVisible )
365 xLayoutManager->unlock();
366 else
367 xLayoutManager->lock();
369 bResult = true;
372 catch( const uno::Exception& )
375 return bResult;
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,
391 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 );
397 if ( xModel.is() )
400 uno::Reference< embed::XHatchWindowFactory > xHatchFactory =
401 embed::HatchWindowFactory::create(m_xContext);
403 uno::Reference< embed::XHatchWindow > xHatchWindow =
404 xHatchFactory->createHatchWindowInstance( xParent,
405 aHatchRectangle,
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 = xHatchWinPeer;
416 else
418 aOwnRectangle.X += aHatchRectangle.X;
419 aOwnRectangle.Y += aHatchRectangle.Y;
422 awt::WindowDescriptor aOwnWinDescriptor( awt::WindowClass_TOP,
423 "dockingwindow",
424 xMyParent,
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 );
434 // create a frame based on the specified window
435 uno::Reference< lang::XSingleServiceFactory > xFrameFact = frame::TaskCreator::create(m_xContext);
437 uno::Sequence< uno::Any > aArgs( 2 );
438 beans::NamedValue aArg;
440 aArg.Name = "ContainerWindow";
441 aArg.Value <<= xOwnWindow;
442 aArgs[0] <<= aArg;
444 uno::Reference< frame::XFrame > xContFrame( xContDisp, uno::UNO_QUERY );
445 if ( xContFrame.is() )
447 aArg.Name = "ParentFrame";
448 aArg.Value <<= xContFrame;
449 aArgs[1] <<= aArg;
451 else
452 aArgs.realloc( 1 );
454 // the call will create, initialize the frame, and register it in the parent
455 m_xFrame.set( xFrameFact->createInstanceWithArguments( aArgs ), uno::UNO_QUERY_THROW );
457 m_xHatchWindow = xHWindow;
458 m_xOwnWindow = xOwnWindow;
460 if ( !SetFrameLMVisibility( m_xFrame, false ) )
462 OSL_FAIL( "Can't deactivate LayoutManager!" );
463 // TODO/LATER: error handling?
466 // m_bIsInplace = sal_True; TODO: ?
468 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
469 if ( xCloseBroadcaster.is() )
470 xCloseBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
472 // TODO: some listeners to the frame and the window ( resize for example )
475 if ( m_xComponent.is() )
477 if ( !LoadDocToFrame( true ) )
479 CloseFrame();
480 return false;
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 );
495 return true;
498 return false;
502 uno::Reference< container::XIndexAccess > DocumentHolder::RetrieveOwnMenu_Impl()
504 uno::Reference< container::XIndexAccess > xResult;
506 uno::Reference< css::ui::XUIConfigurationManagerSupplier > xUIConfSupplier(
507 m_xComponent,
508 uno::UNO_QUERY );
509 uno::Reference< css::ui::XUIConfigurationManager > xUIConfigManager;
510 if( xUIConfSupplier.is())
512 xUIConfigManager.set(
513 xUIConfSupplier->getUIConfigurationManager(),
514 uno::UNO_SET_THROW );
519 if( xUIConfigManager.is())
521 xResult = xUIConfigManager->getSettings(
522 "private:resource/menubar/menubar",
523 false );
526 catch( const uno::Exception& )
529 if ( !xResult.is() )
531 // no internal document configuration, use the one from the module
532 uno::Reference< frame::XModuleManager2 > xModuleMan = frame::ModuleManager::create(m_xContext);
533 OUString aModuleIdent =
534 xModuleMan->identify( uno::Reference< uno::XInterface >( m_xComponent, uno::UNO_QUERY ) );
536 if ( !aModuleIdent.isEmpty() )
538 uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xModConfSupplier =
539 ui::theModuleUIConfigurationManagerSupplier::get(m_xContext);
540 uno::Reference< css::ui::XUIConfigurationManager > xModUIConfMan(
541 xModConfSupplier->getUIConfigurationManager( aModuleIdent ),
542 uno::UNO_SET_THROW );
543 xResult = xModUIConfMan->getSettings(
544 "private:resource/menubar/menubar",
545 false );
549 if ( !xResult.is() )
550 throw uno::RuntimeException();
552 return xResult;
556 void DocumentHolder::FindConnectPoints(
557 const uno::Reference< container::XIndexAccess >& xMenu,
558 sal_Int32 nConnectPoints[2] )
560 nConnectPoints[0] = -1;
561 nConnectPoints[1] = -1;
562 for ( sal_Int32 nInd = 0; nInd < xMenu->getCount(); nInd++ )
564 uno::Sequence< beans::PropertyValue > aProps;
565 xMenu->getByIndex( nInd ) >>= aProps;
566 OUString aCommand;
567 for ( beans::PropertyValue const & prop : std::as_const(aProps) )
568 if ( prop.Name == "CommandURL" )
570 prop.Value >>= aCommand;
571 break;
574 if ( aCommand.isEmpty() )
575 throw uno::RuntimeException();
577 if ( aCommand == ".uno:PickList" )
578 nConnectPoints[0] = nInd;
579 else if ( aCommand == ".uno:WindowList" )
580 nConnectPoints[1] = nInd;
585 uno::Reference< container::XIndexAccess > DocumentHolder::MergeMenusForInplace(
586 const uno::Reference< container::XIndexAccess >& xContMenu,
587 const uno::Reference< frame::XDispatchProvider >& xContDisp,
588 const OUString& aContModuleName,
589 const uno::Reference< container::XIndexAccess >& xOwnMenu,
590 const uno::Reference< frame::XDispatchProvider >& xOwnDisp )
592 // TODO/LATER: use dispatch providers on merge
594 sal_Int32 nContPoints[2];
595 sal_Int32 nOwnPoints[2];
597 uno::Reference< lang::XSingleComponentFactory > xIndAccessFact( xContMenu, uno::UNO_QUERY_THROW );
599 uno::Reference< container::XIndexContainer > xMergedMenu(
600 xIndAccessFact->createInstanceWithContext(
601 comphelper::getProcessComponentContext() ),
602 uno::UNO_QUERY_THROW );
604 FindConnectPoints( xContMenu, nContPoints );
605 FindConnectPoints( xOwnMenu, nOwnPoints );
607 for ( sal_Int32 nInd = 0; nInd < xOwnMenu->getCount(); nInd++ )
609 if ( nOwnPoints[0] == nInd )
611 if ( nContPoints[0] >= 0 && nContPoints[0] < xContMenu->getCount() )
613 InsertMenu_Impl( xMergedMenu, nInd, xContMenu, nContPoints[0], aContModuleName, xContDisp );
616 else if ( nOwnPoints[1] == nInd )
618 if ( nContPoints[1] >= 0 && nContPoints[1] < xContMenu->getCount() )
620 InsertMenu_Impl( xMergedMenu, nInd, xContMenu, nContPoints[1], aContModuleName, xContDisp );
623 else
624 InsertMenu_Impl( xMergedMenu, nInd, xOwnMenu, nInd, OUString(), xOwnDisp );
627 return uno::Reference< container::XIndexAccess >( xMergedMenu, uno::UNO_QUERY_THROW );
631 bool DocumentHolder::MergeMenus_Impl( const uno::Reference< css::frame::XLayoutManager >& xOwnLM,
632 const uno::Reference< css::frame::XLayoutManager >& xContLM,
633 const uno::Reference< frame::XDispatchProvider >& xContDisp,
634 const OUString& aContModuleName )
636 bool bMenuMerged = false;
639 uno::Reference< css::ui::XUIElementSettings > xUISettings(
640 xContLM->getElement( "private:resource/menubar/menubar" ),
641 uno::UNO_QUERY_THROW );
642 uno::Reference< container::XIndexAccess > xContMenu = xUISettings->getSettings( true );
643 if ( !xContMenu.is() )
644 throw uno::RuntimeException();
646 uno::Reference< container::XIndexAccess > xOwnMenu = RetrieveOwnMenu_Impl();
647 uno::Reference< frame::XDispatchProvider > xOwnDisp( m_xFrame, uno::UNO_QUERY_THROW );
649 uno::Reference< container::XIndexAccess > xMergedMenu = MergeMenusForInplace( xContMenu, xContDisp, aContModuleName, xOwnMenu, xOwnDisp );
650 uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM,
651 uno::UNO_QUERY_THROW );
652 bMenuMerged = xMerge->setMergedMenuBar( xMergedMenu );
654 catch( const uno::Exception& )
657 return bMenuMerged;
660 bool DocumentHolder::ShowUI( const uno::Reference< css::frame::XLayoutManager >& xContainerLM,
661 const uno::Reference< frame::XDispatchProvider >& xContainerDP,
662 const OUString& aContModuleName )
664 bool bResult = false;
665 if ( xContainerLM.is() )
667 // the LM of the embedded frame and its current DockingAreaAcceptor
668 uno::Reference< css::frame::XLayoutManager > xOwnLM;
669 uno::Reference< css::ui::XDockingAreaAcceptor > xDocAreaAcc;
673 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
674 xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
675 xDocAreaAcc = xContainerLM->getDockingAreaAcceptor();
677 catch( const uno::Exception& ){}
679 if ( xOwnLM.is() && xDocAreaAcc.is() )
681 // make sure that lock state of LM is correct even if an exception is thrown in between
682 bool bUnlockContainerLM = false;
683 bool bLockOwnLM = false;
686 // take over the control over the containers window
687 // as long as the LM is invisible and locked an empty tool space will be used on resizing
688 xOwnLM->setDockingAreaAcceptor( xDocAreaAcc );
690 // try to merge menus; don't do anything else if it fails
691 if ( MergeMenus_Impl( xOwnLM, xContainerLM, xContainerDP, aContModuleName ) )
693 // make sure that the container LM does not control the size of the containers window anymore
694 // this must be done after merging menus as we won't get the container menu otherwise
695 xContainerLM->setDockingAreaAcceptor( uno::Reference < ui::XDockingAreaAcceptor >() );
697 uno::Reference< lang::XServiceInfo> xServiceInfo(m_xComponent, uno::UNO_QUERY);
698 if (!xServiceInfo.is() || !xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
700 // prevent further changes at this LM
701 xContainerLM->setVisible(false);
702 xContainerLM->lock();
703 bUnlockContainerLM = true;
706 // by unlocking the LM each layout change will now resize the containers window; pending layouts will be processed now
707 xOwnLM->setVisible( true );
709 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
710 if ( xSupp.is() )
711 xSupp->setActiveFrame( m_xFrame );
713 xOwnLM->unlock();
714 bLockOwnLM = true;
715 bResult = true;
717 // TODO/LATER: The following action should be done only if the window is not hidden
718 // otherwise the activation must fail, unfortunately currently it is not possible
719 // to detect whether the window is hidden using UNO API
720 m_xOwnWindow->setFocus();
723 catch( const uno::Exception& )
725 // activation failed; reestablish old state
728 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
729 if ( xSupp.is() )
730 xSupp->setActiveFrame( nullptr );
732 // remove control about containers window from own LM
733 if (bLockOwnLM)
734 xOwnLM->lock();
735 xOwnLM->setVisible( false );
736 xOwnLM->setDockingAreaAcceptor( uno::Reference< css::ui::XDockingAreaAcceptor >() );
738 // unmerge menu
739 uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM, uno::UNO_QUERY_THROW );
740 xMerge->removeMergedMenuBar();
742 catch( const uno::Exception& ) {}
746 // reestablish control of containers window
747 xContainerLM->setDockingAreaAcceptor( xDocAreaAcc );
748 xContainerLM->setVisible( true );
749 if (bUnlockContainerLM)
750 xContainerLM->unlock();
752 catch( const uno::Exception& ) {}
757 return bResult;
761 bool DocumentHolder::HideUI( const uno::Reference< css::frame::XLayoutManager >& xContainerLM )
763 bool bResult = false;
765 if ( xContainerLM.is() )
767 uno::Reference< css::frame::XLayoutManager > xOwnLM;
769 try {
770 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
771 xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
772 } catch( const uno::Exception& )
775 if ( xOwnLM.is() )
777 try {
778 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
779 if ( xSupp.is() )
780 xSupp->setActiveFrame( nullptr );
782 uno::Reference< css::ui::XDockingAreaAcceptor > xDocAreaAcc = xOwnLM->getDockingAreaAcceptor();
784 xOwnLM->setDockingAreaAcceptor( uno::Reference < ui::XDockingAreaAcceptor >() );
785 xOwnLM->lock();
786 xOwnLM->setVisible( false );
788 uno::Reference< css::frame::XMenuBarMergingAcceptor > xMerge( xOwnLM, uno::UNO_QUERY_THROW );
789 xMerge->removeMergedMenuBar();
791 xContainerLM->setDockingAreaAcceptor( xDocAreaAcc );
792 uno::Reference< lang::XServiceInfo> xServiceInfo(m_xComponent, uno::UNO_QUERY);
793 if (!xServiceInfo.is() || !xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
795 xContainerLM->setVisible(true);
796 xContainerLM->unlock();
799 xContainerLM->doLayout();
800 bResult = true;
802 catch( const uno::Exception& )
804 SetFrameLMVisibility( m_xFrame, true );
809 return bResult;
813 uno::Reference< frame::XFrame > const & DocumentHolder::GetDocFrame()
815 // the frame for outplace activation
816 if ( !m_xFrame.is() )
818 uno::Reference< lang::XSingleServiceFactory > xFrameFact = frame::TaskCreator::create(m_xContext);
820 m_xFrame.set(xFrameFact->createInstanceWithArguments( m_aOutplaceFrameProps ), uno::UNO_QUERY_THROW);
822 uno::Reference< frame::XDispatchProviderInterception > xInterception( m_xFrame, uno::UNO_QUERY );
823 if ( xInterception.is() )
825 if ( m_xInterceptor.is() )
827 m_xInterceptor->DisconnectDocHolder();
828 m_xInterceptor.clear();
831 m_xInterceptor = new Interceptor( this );
833 xInterception->registerDispatchProviderInterceptor( m_xInterceptor.get() );
835 // register interceptor from outside
836 if ( m_xOutplaceInterceptor.is() )
837 xInterception->registerDispatchProviderInterceptor( m_xOutplaceInterceptor );
840 uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( m_xFrame, uno::UNO_QUERY );
841 if ( xCloseBroadcaster.is() )
842 xCloseBroadcaster->addCloseListener( static_cast<util::XCloseListener*>(this) );
845 if ( m_xComponent.is() )
847 uno::Reference< css::frame::XLayoutManager > xOwnLM;
848 try {
849 uno::Reference< beans::XPropertySet > xPropSet( m_xFrame, uno::UNO_QUERY_THROW );
850 xPropSet->getPropertyValue("LayoutManager") >>= xOwnLM;
851 } catch( const uno::Exception& )
854 if ( xOwnLM.is() )
855 xOwnLM->lock();
857 // TODO/LATER: get it for the real aspect
858 awt::Size aSize;
859 LoadDocToFrame(false);
861 if ( xOwnLM.is() )
863 xOwnLM->unlock();
864 xOwnLM->lock();
867 GetExtent(embed::Aspects::MSOLE_CONTENT, &aSize);
868 SetExtent(embed::Aspects::MSOLE_CONTENT, aSize);
870 if ( xOwnLM.is() )
871 xOwnLM->unlock();
876 uno::Reference< awt::XWindow > xHWindow = m_xFrame->getContainerWindow();
878 if( xHWindow.is() )
880 sal_Int32 nDisplay = Application::GetDisplayBuiltInScreen();
882 tools::Rectangle aWorkRect = Application::GetScreenPosSizePixel( nDisplay );
883 awt::Rectangle aWindowRect = xHWindow->getPosSize();
885 if (( aWindowRect.Width < aWorkRect.GetWidth()) && ( aWindowRect.Height < aWorkRect.GetHeight() ))
887 int OffsetX = ( aWorkRect.GetWidth() - aWindowRect.Width ) / 2 + aWorkRect.Left();
888 int OffsetY = ( aWorkRect.GetHeight() - aWindowRect.Height ) /2 + aWorkRect.Top();
889 xHWindow->setPosSize( OffsetX, OffsetY, aWindowRect.Width, aWindowRect.Height, awt::PosSize::POS );
891 else
893 xHWindow->setPosSize( aWorkRect.Left(), aWorkRect.Top(), aWorkRect.GetWidth(), aWorkRect.GetHeight(), awt::PosSize::POSSIZE );
896 xHWindow->setVisible( true );
899 catch ( const uno::Exception& )
903 return m_xFrame;
907 void DocumentHolder::SetComponent( const uno::Reference< util::XCloseable >& xDoc, bool bReadOnly )
909 if ( m_xComponent.is() )
911 // May be should be improved
912 try {
913 CloseDocument( true, false );
914 } catch( const uno::Exception& )
918 m_xComponent = xDoc;
920 m_bReadOnly = bReadOnly;
921 m_bAllowClosing = false;
923 if ( m_xComponent.is() )
924 m_xComponent->addCloseListener( static_cast<util::XCloseListener*>(this) );
926 uno::Reference< document::XEventBroadcaster > xEventBroadcaster( m_xComponent, uno::UNO_QUERY );
927 if ( xEventBroadcaster.is() )
928 xEventBroadcaster->addEventListener( static_cast<document::XEventListener*>(this) );
929 else
931 // the object does not support document::XEventBroadcaster interface
932 // use the workaround, register for modified events
933 uno::Reference< util::XModifyBroadcaster > xModifyBroadcaster( m_xComponent, uno::UNO_QUERY );
934 if ( xModifyBroadcaster.is() )
935 xModifyBroadcaster->addModifyListener( static_cast<util::XModifyListener*>(this) );
938 if ( m_xFrame.is() )
939 LoadDocToFrame(false);
943 bool DocumentHolder::LoadDocToFrame( bool bInPlace )
945 if ( m_xFrame.is() && m_xComponent.is() )
947 uno::Reference < frame::XModel > xDoc( m_xComponent, uno::UNO_QUERY );
948 if ( xDoc.is() )
950 // load new document into the frame
951 uno::Reference< frame::XComponentLoader > xComponentLoader( m_xFrame, uno::UNO_QUERY_THROW );
953 ::comphelper::NamedValueCollection aArgs;
954 aArgs.put( "Model", m_xComponent );
955 aArgs.put( "ReadOnly", m_bReadOnly );
957 // set document title to show in the title bar
958 css::uno::Reference< css::frame::XTitle > xModelTitle( xDoc, css::uno::UNO_QUERY );
959 if( xModelTitle.is() && m_pEmbedObj && !m_pEmbedObj->getContainerName().isEmpty() )
961 std::locale aResLoc = Translate::Create("sfx");
962 OUString sEmbedded = Translate::get(STR_EMBEDDED_TITLE, aResLoc);
963 xModelTitle->setTitle( m_pEmbedObj->getContainerName() + sEmbedded );
964 m_aContainerName = m_pEmbedObj->getContainerName();
965 // TODO: get real m_aDocumentNamePart
966 m_aDocumentNamePart = sEmbedded;
969 if ( bInPlace )
970 aArgs.put( "PluginMode", sal_Int16(1) );
971 OUString sUrl;
972 uno::Reference< lang::XServiceInfo> xServiceInfo(xDoc,uno::UNO_QUERY);
973 if ( xServiceInfo.is()
974 && xServiceInfo->supportsService("com.sun.star.report.ReportDefinition") )
976 sUrl = ".component:DB/ReportDesign";
978 else if( xServiceInfo.is()
979 && xServiceInfo->supportsService("com.sun.star.chart2.ChartDocument"))
980 sUrl = "private:factory/schart";
981 else
982 sUrl = "private:object";
984 xComponentLoader->loadComponentFromURL( sUrl,
985 "_self",
987 aArgs.getPropertyValues() );
989 return true;
991 else
993 uno::Reference < frame::XSynchronousFrameLoader > xLoader( m_xComponent, uno::UNO_QUERY );
994 if ( xLoader.is() )
995 return xLoader->load( uno::Sequence < beans::PropertyValue >(), m_xFrame );
996 else
997 return false;
1001 return true;
1005 void DocumentHolder::Show()
1007 if( m_xFrame.is() )
1009 m_xFrame->activate();
1010 uno::Reference<awt::XTopWindow> xTopWindow( m_xFrame->getContainerWindow(), uno::UNO_QUERY );
1011 if( xTopWindow.is() )
1012 xTopWindow->toFront();
1014 else
1015 GetDocFrame();
1019 bool DocumentHolder::SetExtent( sal_Int64 nAspect, const awt::Size& aSize )
1021 uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
1022 if ( xDocVis.is() )
1026 xDocVis->setVisualAreaSize( nAspect, aSize );
1027 return true;
1029 catch( const uno::Exception& )
1031 // TODO: Error handling
1035 return false;
1039 bool DocumentHolder::GetExtent( sal_Int64 nAspect, awt::Size *pSize )
1041 uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
1042 if ( pSize && xDocVis.is() )
1046 *pSize = xDocVis->getVisualAreaSize( nAspect );
1047 return true;
1049 catch( const uno::Exception& )
1051 // TODO: Error handling
1055 return false;
1059 sal_Int32 DocumentHolder::GetMapUnit( sal_Int64 nAspect )
1061 uno::Reference< embed::XVisualObject > xDocVis( m_xComponent, uno::UNO_QUERY );
1062 if ( xDocVis.is() )
1066 return xDocVis->getMapUnit( nAspect );
1068 catch( const uno::Exception& )
1070 // TODO: Error handling
1074 return 0;
1078 awt::Rectangle DocumentHolder::CalculateBorderedArea( const awt::Rectangle& aRect )
1080 return awt::Rectangle( aRect.X + m_aBorderWidths.Left + HATCH_BORDER_WIDTH,
1081 aRect.Y + m_aBorderWidths.Top + HATCH_BORDER_WIDTH,
1082 aRect.Width - m_aBorderWidths.Left - m_aBorderWidths.Right - 2*HATCH_BORDER_WIDTH,
1083 aRect.Height - m_aBorderWidths.Top - m_aBorderWidths.Bottom - 2*HATCH_BORDER_WIDTH );
1087 awt::Rectangle DocumentHolder::AddBorderToArea( const awt::Rectangle& aRect )
1089 return awt::Rectangle( aRect.X - m_aBorderWidths.Left - HATCH_BORDER_WIDTH,
1090 aRect.Y - m_aBorderWidths.Top - HATCH_BORDER_WIDTH,
1091 aRect.Width + m_aBorderWidths.Left + m_aBorderWidths.Right + 2*HATCH_BORDER_WIDTH,
1092 aRect.Height + m_aBorderWidths.Top + m_aBorderWidths.Bottom + 2*HATCH_BORDER_WIDTH );
1096 void SAL_CALL DocumentHolder::disposing( const css::lang::EventObject& aSource )
1098 if ( m_xComponent.is() && m_xComponent == aSource.Source )
1100 m_xComponent = nullptr;
1101 if ( m_bWaitForClose )
1103 m_bWaitForClose = false;
1104 FreeOffice();
1108 if( m_xFrame.is() && m_xFrame == aSource.Source )
1110 m_xHatchWindow.clear();
1111 m_xOwnWindow.clear();
1112 m_xFrame.clear();
1117 void SAL_CALL DocumentHolder::queryClosing( const lang::EventObject& aSource, sal_Bool /*bGetsOwnership*/ )
1119 if ( m_xComponent.is() && m_xComponent == aSource.Source && !m_bAllowClosing )
1120 throw util::CloseVetoException("To close an embedded document, close the document holder (document definition), not the document itself.", static_cast< ::cppu::OWeakObject*>(this));
1124 void SAL_CALL DocumentHolder::notifyClosing( const lang::EventObject& aSource )
1126 if ( m_xComponent.is() && m_xComponent == aSource.Source )
1128 m_xComponent = nullptr;
1129 if ( m_bWaitForClose )
1131 m_bWaitForClose = false;
1132 FreeOffice();
1136 if( m_xFrame.is() && m_xFrame == aSource.Source )
1138 m_xHatchWindow.clear();
1139 m_xOwnWindow.clear();
1140 m_xFrame.clear();
1145 void SAL_CALL DocumentHolder::queryTermination( const lang::EventObject& )
1147 if ( m_bWaitForClose )
1148 throw frame::TerminationVetoException();
1152 void SAL_CALL DocumentHolder::notifyTermination( const lang::EventObject& aSource )
1154 OSL_ENSURE( !m_xComponent.is(), "Just a disaster..." );
1156 uno::Reference< frame::XDesktop > xDesktop( aSource.Source, uno::UNO_QUERY );
1157 m_bDesktopTerminated = true;
1158 if ( xDesktop.is() )
1159 xDesktop->removeTerminateListener( static_cast<frame::XTerminateListener*>(this) );
1163 void SAL_CALL DocumentHolder::modified( const lang::EventObject& aEvent )
1165 // if the component does not support document::XEventBroadcaster
1166 // the modify notifications are used as workaround, but only for running state
1167 if( aEvent.Source == m_xComponent && m_pEmbedObj && m_pEmbedObj->getCurrentState() == embed::EmbedStates::RUNNING )
1168 m_pEmbedObj->PostEvent_Impl( "OnVisAreaChanged" );
1172 void SAL_CALL DocumentHolder::notifyEvent( const document::EventObject& Event )
1174 if( m_pEmbedObj && Event.Source == m_xComponent )
1176 // for now the ignored events are not forwarded, but sent by the object itself
1177 if ( !Event.EventName.startsWith( "OnSave" )
1178 && !Event.EventName.startsWith( "OnSaveDone" )
1179 && !Event.EventName.startsWith( "OnSaveAs" )
1180 && !Event.EventName.startsWith( "OnSaveAsDone" )
1181 && !( Event.EventName.startsWith( "OnVisAreaChanged" ) && m_nNoResizeReact ) )
1182 m_pEmbedObj->PostEvent_Impl( Event.EventName );
1187 void SAL_CALL DocumentHolder::borderWidthsChanged( const uno::Reference< uno::XInterface >& aObject,
1188 const frame::BorderWidths& aNewSize )
1190 // TODO: may require mutex introduction ???
1191 if ( m_pEmbedObj && m_xFrame.is() && aObject == m_xFrame->getController() )
1193 if ( m_aBorderWidths.Left != aNewSize.Left
1194 || m_aBorderWidths.Right != aNewSize.Right
1195 || m_aBorderWidths.Top != aNewSize.Top
1196 || m_aBorderWidths.Bottom != aNewSize.Bottom )
1198 m_aBorderWidths = aNewSize;
1199 if ( !m_nNoBorderResizeReact )
1200 PlaceFrame( m_aObjRect );
1206 void SAL_CALL DocumentHolder::requestPositioning( const awt::Rectangle& aRect )
1208 // TODO: may require mutex introduction ???
1209 if ( m_pEmbedObj )
1211 // borders should not be counted
1212 awt::Rectangle aObjRect = CalculateBorderedArea( aRect );
1213 IntCounterGuard aGuard( m_nNoResizeReact );
1214 m_pEmbedObj->requestPositioning( aObjRect );
1219 awt::Rectangle SAL_CALL DocumentHolder::calcAdjustedRectangle( const awt::Rectangle& aRect )
1221 // Solar mutex should be locked already since this is a call from HatchWindow with focus
1222 awt::Rectangle aResult( aRect );
1224 if ( m_xFrame.is() )
1226 // borders should not be counted
1227 uno::Reference< frame::XControllerBorder > xControllerBorder( m_xFrame->getController(), uno::UNO_QUERY );
1228 if ( xControllerBorder.is() )
1230 awt::Rectangle aObjRect = CalculateBorderedArea( aRect );
1231 aObjRect = xControllerBorder->queryBorderedArea( aObjRect );
1232 aResult = AddBorderToArea( aObjRect );
1236 awt::Rectangle aMinRectangle = AddBorderToArea( awt::Rectangle() );
1237 if ( aResult.Width < aMinRectangle.Width + 2 )
1238 aResult.Width = aMinRectangle.Width + 2;
1239 if ( aResult.Height < aMinRectangle.Height + 2 )
1240 aResult.Height = aMinRectangle.Height + 2;
1242 return aResult;
1245 void SAL_CALL DocumentHolder::activated( )
1247 if ( !(m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) )
1248 return;
1250 if ( m_pEmbedObj->getCurrentState() != embed::EmbedStates::UI_ACTIVE &&
1251 !(m_pEmbedObj->getStatus(embed::Aspects::MSOLE_CONTENT)&embed::EmbedMisc::MS_EMBED_NOUIACTIVATE) )
1255 m_pEmbedObj->changeState( embed::EmbedStates::UI_ACTIVE );
1257 catch ( const css::embed::StateChangeInProgressException& )
1259 // must catch this exception because focus is grabbed while UI activation in doVerb()
1261 catch ( const css::uno::Exception& )
1263 // no outgoing exceptions specified here
1266 else
1268 uno::Reference< frame::XFramesSupplier > xSupp = m_xFrame->getCreator();
1269 if ( xSupp.is() )
1270 xSupp->setActiveFrame( m_xFrame );
1274 void DocumentHolder::ResizeHatchWindow()
1276 awt::Rectangle aHatchRect = AddBorderToArea( m_aObjRect );
1277 ResizeWindows_Impl( aHatchRect );
1278 uno::Reference< embed::XHatchWindow > xHatchWindow( m_xHatchWindow, uno::UNO_QUERY );
1279 xHatchWindow->setHatchBorderSize( awt::Size( HATCH_BORDER_WIDTH, HATCH_BORDER_WIDTH ) );
1282 void SAL_CALL DocumentHolder::deactivated( )
1284 // deactivation is too unspecific to be useful; usually we only trigger code from activation
1285 // so UIDeactivation is actively triggered by the container
1288 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */