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