1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/EmbedStates.hpp>
21 #include <com/sun/star/embed/XVisualObject.hpp>
22 #include <com/sun/star/embed/XEmbeddedClient.hpp>
23 #include <com/sun/star/embed/XInplaceClient.hpp>
24 #include <com/sun/star/embed/XInplaceObject.hpp>
25 #include <com/sun/star/embed/XComponentSupplier.hpp>
26 #include <com/sun/star/embed/XWindowSupplier.hpp>
27 #include <com/sun/star/embed/XEmbedPersist.hpp>
28 #include <com/sun/star/embed/EmbedVerbs.hpp>
29 #include <com/sun/star/embed/XEmbeddedOleObject.hpp>
30 #include <com/sun/star/container/XChild.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/embed/XStateChangeListener.hpp>
34 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
35 #include <com/sun/star/embed/XLinkageSupport.hpp>
36 #include <com/sun/star/lang/XInitialization.hpp>
37 #include <com/sun/star/task/ErrorCodeIOException.hpp>
38 #include <com/sun/star/task/StatusIndicatorFactory.hpp>
39 #include <com/sun/star/task/XStatusIndicator.hpp>
41 #include <com/sun/star/embed/EmbedMisc.hpp>
42 #include <svtools/embedhlp.hxx>
43 #include <vcl/svapp.hxx>
45 #include <sfx2/ipclient.hxx>
46 #include <sfx2/viewsh.hxx>
47 #include <sfx2/viewfrm.hxx>
48 #include <sfx2/objsh.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include "workwin.hxx"
51 #include "guisaveas.hxx"
52 #include <cppuhelper/implbase.hxx>
53 #include <svtools/ehdl.hxx>
55 #include <vcl/timer.hxx>
56 #include <vcl/window.hxx>
57 #include <toolkit/awt/vclxwindow.hxx>
58 #include <toolkit/helper/vclunohelper.hxx>
59 #include <toolkit/helper/convert.hxx>
60 #include <tools/fract.hxx>
61 #include <tools/gen.hxx>
62 #include <svl/rectitem.hxx>
63 #include <svtools/soerr.hxx>
64 #include <comphelper/processfactory.hxx>
66 #define SFX_CLIENTACTIVATE_TIMEOUT 100
68 using namespace com::sun::star
;
71 // SfxEmbedResizeGuard
72 class SfxBooleanFlagGuard
77 explicit SfxBooleanFlagGuard(bool& bFlag
)
79 , m_bLifeValue( true )
81 m_rFlag
= m_bLifeValue
;
84 ~SfxBooleanFlagGuard()
86 m_rFlag
= !m_bLifeValue
;
91 // SfxInPlaceClient_Impl
94 class SfxInPlaceClient_Impl
: public ::cppu::WeakImplHelper
< embed::XEmbeddedClient
,
95 embed::XInplaceClient
,
96 document::XEventListener
,
97 embed::XStateChangeListener
,
98 embed::XWindowSupplier
>
101 Timer m_aTimer
; // activation timeout, starts after object connection
102 Rectangle m_aObjArea
; // area of object in coordinate system of the container (without scaling)
103 Fraction m_aScaleWidth
; // scaling that was applied to the object when it was not active
104 Fraction m_aScaleHeight
;
105 SfxInPlaceClient
* m_pClient
;
106 sal_Int64 m_nAspect
; // ViewAspect that is assigned from the container
108 bool m_bUIActive
; // set and cleared when notification for UI (de)activation is sent
109 bool m_bResizeNoScale
;
111 uno::Reference
< embed::XEmbeddedObject
> m_xObject
;
112 uno::Reference
< embed::XEmbeddedClient
> m_xClient
;
115 SfxInPlaceClient_Impl()
116 : m_pClient( nullptr )
118 , m_bStoreObject( true )
119 , m_bUIActive( false )
120 , m_bResizeNoScale( false )
123 virtual ~SfxInPlaceClient_Impl() override
;
125 void SizeHasChanged();
126 DECL_LINK(TimerHdl
, Timer
*, void);
127 uno::Reference
< frame::XFrame
> GetFrame() const;
130 virtual void SAL_CALL
saveObject() throw ( embed::ObjectSaveVetoException
, uno::Exception
, uno::RuntimeException
, std::exception
) override
;
131 virtual void SAL_CALL
visibilityChanged( sal_Bool bVisible
) throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
134 virtual sal_Bool SAL_CALL
canInplaceActivate() throw ( uno::RuntimeException
, std::exception
) override
;
135 virtual void SAL_CALL
activatingInplace() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
136 virtual void SAL_CALL
activatingUI() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
137 virtual void SAL_CALL
deactivatedInplace() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
138 virtual void SAL_CALL
deactivatedUI() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
139 virtual uno::Reference
< css::frame::XLayoutManager
> SAL_CALL
getLayoutManager() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
140 virtual uno::Reference
< frame::XDispatchProvider
> SAL_CALL
getInplaceDispatchProvider() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
141 virtual awt::Rectangle SAL_CALL
getPlacement() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
142 virtual awt::Rectangle SAL_CALL
getClipRectangle() throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
143 virtual void SAL_CALL
translateAccelerators( const uno::Sequence
< awt::KeyEvent
>& aKeys
) throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
144 virtual void SAL_CALL
scrollObject( const awt::Size
& aOffset
) throw ( embed::WrongStateException
, uno::RuntimeException
, std::exception
) override
;
145 virtual void SAL_CALL
changedPlacement( const awt::Rectangle
& aPosRect
) throw ( embed::WrongStateException
, uno::Exception
, uno::RuntimeException
, std::exception
) override
;
147 // XComponentSupplier
148 virtual uno::Reference
< util::XCloseable
> SAL_CALL
getComponent() throw ( uno::RuntimeException
, std::exception
) override
;
151 virtual uno::Reference
< awt::XWindow
> SAL_CALL
getWindow() throw ( uno::RuntimeException
, std::exception
) override
;
153 // document::XEventListener
154 virtual void SAL_CALL
notifyEvent( const document::EventObject
& aEvent
) throw( uno::RuntimeException
, std::exception
) override
;
156 // XStateChangeListener
157 virtual void SAL_CALL
changingState( const css::lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (css::embed::WrongStateException
, css::uno::RuntimeException
, std::exception
) override
;
158 virtual void SAL_CALL
stateChanged( const css::lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (css::uno::RuntimeException
, std::exception
) override
;
159 virtual void SAL_CALL
disposing( const css::lang::EventObject
& aEvent
) throw (css::uno::RuntimeException
, std::exception
) override
;
162 SfxInPlaceClient_Impl::~SfxInPlaceClient_Impl()
166 void SAL_CALL
SfxInPlaceClient_Impl::changingState(
167 const css::lang::EventObject
& /*aEvent*/,
168 ::sal_Int32
/*nOldState*/,
169 ::sal_Int32
/*nNewState*/ )
170 throw (css::embed::WrongStateException
, css::uno::RuntimeException
, std::exception
)
174 void SAL_CALL
SfxInPlaceClient_Impl::stateChanged(
175 const css::lang::EventObject
& /*aEvent*/,
176 ::sal_Int32 nOldState
,
177 ::sal_Int32 nNewState
)
178 throw (css::uno::RuntimeException
, std::exception
)
180 if ( m_pClient
&& nOldState
!= embed::EmbedStates::LOADED
&& nNewState
== embed::EmbedStates::RUNNING
)
182 // deactivation of object
183 uno::Reference
< frame::XModel
> xDocument
;
184 if ( m_pClient
->GetViewShell()->GetObjectShell() )
185 xDocument
= m_pClient
->GetViewShell()->GetObjectShell()->GetModel();
186 SfxObjectShell::SetCurrentComponent( xDocument
);
190 void SAL_CALL
SfxInPlaceClient_Impl::notifyEvent( const document::EventObject
& aEvent
) throw( uno::RuntimeException
, std::exception
)
192 SolarMutexGuard aGuard
;
194 if ( m_pClient
&& aEvent
.EventName
== "OnVisAreaChanged" && m_nAspect
!= embed::Aspects::MSOLE_ICON
)
196 m_pClient
->FormatChanged(); // for Writer when format of the object is changed with the area
197 m_pClient
->ViewChanged();
198 m_pClient
->Invalidate();
202 void SAL_CALL
SfxInPlaceClient_Impl::disposing( const css::lang::EventObject
& /*aEvent*/ )
203 throw (css::uno::RuntimeException
, std::exception
)
205 DELETEZ( m_pClient
);
210 uno::Reference
< frame::XFrame
> SfxInPlaceClient_Impl::GetFrame() const
213 throw uno::RuntimeException();
214 return m_pClient
->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
217 void SAL_CALL
SfxInPlaceClient_Impl::saveObject()
218 throw ( embed::ObjectSaveVetoException
,
220 uno::RuntimeException
, std::exception
)
222 if ( !m_bStoreObject
)
223 // client wants to discard the object (usually it means the container document is closed while an object is active
224 // and the user didn't request saving the changes
227 // the common persistence is supported by objects and links
228 uno::Reference
< embed::XCommonEmbedPersist
> xPersist( m_xObject
, uno::UNO_QUERY
);
229 if ( !xPersist
.is() )
230 throw uno::RuntimeException();
232 uno::Reference
< frame::XFrame
> xFrame
;
233 uno::Reference
< task::XStatusIndicator
> xStatusIndicator
;
234 uno::Reference
< frame::XModel
> xModel( m_xObject
->getComponent(), uno::UNO_QUERY
);
235 uno::Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
239 uno::Reference
< frame::XController
> xController
= xModel
->getCurrentController();
240 if ( xController
.is() )
241 xFrame
= xController
->getFrame();
246 // set non-reschedule progress to prevent problems when asynchronous calls are made
247 // during storing of the embedded object
248 uno::Reference
< task::XStatusIndicatorFactory
> xStatusIndicatorFactory
=
249 task::StatusIndicatorFactory::createWithFrame( xContext
, xFrame
, true/*DisableReschedule*/, false/*AllowParentShow*/ );
251 uno::Reference
< beans::XPropertySet
> xPropSet( xFrame
, uno::UNO_QUERY
);
256 xStatusIndicator
= xStatusIndicatorFactory
->createStatusIndicator();
257 xPropSet
->setPropertyValue( "IndicatorInterception" , uno::makeAny( xStatusIndicator
));
259 catch ( const uno::RuntimeException
& )
263 catch ( uno::Exception
& )
271 xPersist
->storeOwn();
274 catch ( uno::Exception
& )
276 //TODO/LATER: what should happen if object can't be saved?!
279 // reset status indicator interception after storing
282 uno::Reference
< beans::XPropertySet
> xPropSet( xFrame
, uno::UNO_QUERY
);
285 xStatusIndicator
.clear();
286 xPropSet
->setPropertyValue( "IndicatorInterception" , uno::makeAny( xStatusIndicator
));
289 catch ( const uno::RuntimeException
& )
293 catch ( uno::Exception
& )
297 // the client can exist only in case there is a view shell
298 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
299 throw uno::RuntimeException();
301 SfxObjectShell
* pDocShell
= m_pClient
->GetViewShell()->GetObjectShell();
303 throw uno::RuntimeException();
305 pDocShell
->SetModified();
307 //TODO/LATER: invalidation might be necessary when object was modified, but is not
308 //saved through this method
309 // m_pClient->Invalidate();
313 void SAL_CALL
SfxInPlaceClient_Impl::visibilityChanged( sal_Bool bVisible
)
314 throw ( embed::WrongStateException
,
315 uno::RuntimeException
, std::exception
)
317 SolarMutexGuard aGuard
;
319 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
320 throw uno::RuntimeException();
322 m_pClient
->GetViewShell()->OutplaceActivated( bVisible
, m_pClient
);
323 m_pClient
->Invalidate();
329 sal_Bool SAL_CALL
SfxInPlaceClient_Impl::canInplaceActivate()
330 throw ( uno::RuntimeException
, std::exception
)
332 if ( !m_xObject
.is() )
333 throw uno::RuntimeException();
335 // we don't want to switch directly from outplace to inplace mode
336 if ( m_xObject
->getCurrentState() == embed::EmbedStates::ACTIVE
|| m_nAspect
== embed::Aspects::MSOLE_ICON
)
343 void SAL_CALL
SfxInPlaceClient_Impl::activatingInplace()
344 throw ( embed::WrongStateException
,
345 uno::RuntimeException
, std::exception
)
347 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
348 throw uno::RuntimeException();
352 void SAL_CALL
SfxInPlaceClient_Impl::activatingUI()
353 throw ( embed::WrongStateException
,
354 uno::RuntimeException
, std::exception
)
356 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
357 throw uno::RuntimeException();
359 m_pClient
->GetViewShell()->ResetAllClients_Impl(m_pClient
);
361 m_pClient
->GetViewShell()->UIActivating( m_pClient
);
365 void SAL_CALL
SfxInPlaceClient_Impl::deactivatedInplace()
366 throw ( embed::WrongStateException
,
367 uno::RuntimeException
, std::exception
)
369 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
370 throw uno::RuntimeException();
374 void SAL_CALL
SfxInPlaceClient_Impl::deactivatedUI()
375 throw ( embed::WrongStateException
,
376 uno::RuntimeException
, std::exception
)
378 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
379 throw uno::RuntimeException();
381 m_pClient
->GetViewShell()->UIDeactivated( m_pClient
);
386 uno::Reference
< css::frame::XLayoutManager
> SAL_CALL
SfxInPlaceClient_Impl::getLayoutManager()
387 throw ( embed::WrongStateException
,
388 uno::RuntimeException
, std::exception
)
390 uno::Reference
< beans::XPropertySet
> xFrame( GetFrame(), uno::UNO_QUERY
);
392 throw uno::RuntimeException();
394 uno::Reference
< css::frame::XLayoutManager
> xMan
;
397 uno::Any aAny
= xFrame
->getPropertyValue( "LayoutManager" );
400 catch ( uno::Exception
& )
402 throw uno::RuntimeException();
409 uno::Reference
< frame::XDispatchProvider
> SAL_CALL
SfxInPlaceClient_Impl::getInplaceDispatchProvider()
410 throw ( embed::WrongStateException
,
411 uno::RuntimeException
, std::exception
)
413 return uno::Reference
< frame::XDispatchProvider
>( GetFrame(), uno::UNO_QUERY_THROW
);
417 awt::Rectangle SAL_CALL
SfxInPlaceClient_Impl::getPlacement()
418 throw ( embed::WrongStateException
,
419 uno::RuntimeException
, std::exception
)
421 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
422 throw uno::RuntimeException();
424 // apply scaling to object area and convert to pixels
425 Rectangle
aRealObjArea( m_aObjArea
);
426 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_aScaleWidth
,
427 Fraction( aRealObjArea
.GetHeight() ) * m_aScaleHeight
) );
429 aRealObjArea
= m_pClient
->GetEditWin()->LogicToPixel( aRealObjArea
);
430 return AWTRectangle( aRealObjArea
);
434 awt::Rectangle SAL_CALL
SfxInPlaceClient_Impl::getClipRectangle()
435 throw ( embed::WrongStateException
,
436 uno::RuntimeException
, std::exception
)
438 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
439 throw uno::RuntimeException();
441 // currently(?) same as placement
442 Rectangle
aRealObjArea( m_aObjArea
);
443 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_aScaleWidth
,
444 Fraction( aRealObjArea
.GetHeight() ) * m_aScaleHeight
) );
446 aRealObjArea
= m_pClient
->GetEditWin()->LogicToPixel( aRealObjArea
);
447 return AWTRectangle( aRealObjArea
);
451 void SAL_CALL
SfxInPlaceClient_Impl::translateAccelerators( const uno::Sequence
< awt::KeyEvent
>& /*aKeys*/ )
452 throw ( embed::WrongStateException
,
453 uno::RuntimeException
, std::exception
)
455 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
456 throw uno::RuntimeException();
458 // TODO/MBA: keyboard accelerators
462 void SAL_CALL
SfxInPlaceClient_Impl::scrollObject( const awt::Size
& /*aOffset*/ )
463 throw ( embed::WrongStateException
,
464 uno::RuntimeException
, std::exception
)
466 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
467 throw uno::RuntimeException();
471 void SAL_CALL
SfxInPlaceClient_Impl::changedPlacement( const awt::Rectangle
& aPosRect
)
472 throw ( embed::WrongStateException
,
474 uno::RuntimeException
, std::exception
)
476 uno::Reference
< embed::XInplaceObject
> xInplace( m_xObject
, uno::UNO_QUERY
);
477 if ( !xInplace
.is() || !m_pClient
|| !m_pClient
->GetEditWin() || !m_pClient
->GetViewShell() )
478 throw uno::RuntimeException();
480 // check if the change is at least one pixel in size
481 awt::Rectangle aOldRect
= getPlacement();
482 Rectangle aNewPixelRect
= VCLRectangle( aPosRect
);
483 Rectangle aOldPixelRect
= VCLRectangle( aOldRect
);
484 if ( aOldPixelRect
== aNewPixelRect
)
485 // nothing has changed
488 // new scaled object area
489 Rectangle aNewLogicRect
= m_pClient
->GetEditWin()->PixelToLogic( aNewPixelRect
);
491 // all the size changes in this method should happen without scaling
492 // SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True );
494 // allow container to apply restrictions on the requested new area;
495 // the container might change the object view during size calculation;
496 // currently only writer does it
497 m_pClient
->RequestNewObjectArea( aNewLogicRect
);
499 if ( aNewLogicRect
!= m_pClient
->GetScaledObjArea() )
501 // the calculation of the object area has not changed the object size
502 // it should be done here then
503 SfxBooleanFlagGuard
aGuard( m_bResizeNoScale
);
505 // new size of the object area without scaling
506 Size
aNewObjSize( Fraction( aNewLogicRect
.GetWidth() ) / m_aScaleWidth
,
507 Fraction( aNewLogicRect
.GetHeight() ) / m_aScaleHeight
);
509 // now remove scaling from new placement and keep this a the new object area
510 aNewLogicRect
.SetSize( aNewObjSize
);
511 m_aObjArea
= aNewLogicRect
;
513 // let the window size be recalculated
517 // notify container view about changes
518 m_pClient
->ObjectAreaChanged();
521 // XComponentSupplier
523 uno::Reference
< util::XCloseable
> SAL_CALL
SfxInPlaceClient_Impl::getComponent()
524 throw ( uno::RuntimeException
, std::exception
)
526 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
527 throw uno::RuntimeException();
529 SfxObjectShell
* pDocShell
= m_pClient
->GetViewShell()->GetObjectShell();
531 throw uno::RuntimeException();
533 // all the components must implement XCloseable
534 uno::Reference
< util::XCloseable
> xComp( pDocShell
->GetModel(), uno::UNO_QUERY
);
536 throw uno::RuntimeException();
544 uno::Reference
< awt::XWindow
> SAL_CALL
SfxInPlaceClient_Impl::getWindow()
545 throw ( uno::RuntimeException
, std::exception
)
547 if ( !m_pClient
|| !m_pClient
->GetEditWin() )
548 throw uno::RuntimeException();
550 uno::Reference
< awt::XWindow
> xWin( m_pClient
->GetEditWin()->GetComponentInterface(), uno::UNO_QUERY
);
555 // notification to the client implementation that either the object area or the scaling has been changed
556 // as a result the logical size of the window has changed also
557 void SfxInPlaceClient_Impl::SizeHasChanged()
559 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
560 throw uno::RuntimeException();
564 && ( m_xObject
->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
565 || m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
) )
567 // only possible in active states
568 uno::Reference
< embed::XInplaceObject
> xInplace( m_xObject
, uno::UNO_QUERY
);
569 if ( !xInplace
.is() )
570 throw uno::RuntimeException();
572 if ( m_bResizeNoScale
)
574 // the resizing should be done without scaling
575 // set the correct size to the object to avoid the scaling
576 MapMode
aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_xObject
->getMapUnit( m_nAspect
) ) );
577 MapMode
aClientMap( m_pClient
->GetEditWin()->GetMapMode().GetMapUnit() );
579 // convert to logical coordinates of the embedded object
580 Size aNewSize
= m_pClient
->GetEditWin()->LogicToLogic( m_aObjArea
.GetSize(), &aClientMap
, &aObjectMap
);
581 m_xObject
->setVisualAreaSize( m_nAspect
, awt::Size( aNewSize
.Width(), aNewSize
.Height() ) );
584 xInplace
->setObjectRectangles( getPlacement(), getClipRectangle() );
587 catch( uno::Exception
& )
589 // TODO/LATER: handle error
594 IMPL_LINK_NOARG(SfxInPlaceClient_Impl
, TimerHdl
, Timer
*, void)
596 if ( m_pClient
&& m_xObject
.is() )
598 m_pClient
->GetViewShell()->CheckIPClient_Impl(m_pClient
,
599 m_pClient
->GetViewShell()->GetObjectShell()->GetVisArea());
607 SfxInPlaceClient::SfxInPlaceClient( SfxViewShell
* pViewShell
, vcl::Window
*pDraw
, sal_Int64 nAspect
) :
608 m_pImp( new SfxInPlaceClient_Impl
),
609 m_pViewSh( pViewShell
),
613 m_pImp
->m_pClient
= this;
614 m_pImp
->m_nAspect
= nAspect
;
615 m_pImp
->m_aScaleWidth
= m_pImp
->m_aScaleHeight
= Fraction(1,1);
616 m_pImp
->m_xClient
= static_cast< embed::XEmbeddedClient
* >( m_pImp
);
617 pViewShell
->NewIPClient_Impl(this);
618 m_pImp
->m_aTimer
.SetTimeout( SFX_CLIENTACTIVATE_TIMEOUT
);
619 m_pImp
->m_aTimer
.SetTimeoutHdl( LINK( m_pImp
, SfxInPlaceClient_Impl
, TimerHdl
) );
623 SfxInPlaceClient::~SfxInPlaceClient()
625 m_pViewSh
->IPClientGone_Impl(this);
627 // deleting the client before storing the object means discarding all changes
628 m_pImp
->m_bStoreObject
= false;
631 m_pImp
->m_pClient
= nullptr;
633 // the next call will destroy m_pImp if no other reference to it exists
634 m_pImp
->m_xClient
.clear();
638 // the class is not intended to be used in multithreaded environment;
639 // if it will this disconnection and all the parts that use the m_pClient
640 // must be guarded with mutex
644 void SfxInPlaceClient::SetObjectState( sal_Int32 nState
)
646 if ( GetObject().is() )
648 if ( m_pImp
->m_nAspect
== embed::Aspects::MSOLE_ICON
649 && ( nState
== embed::EmbedStates::UI_ACTIVE
|| nState
== embed::EmbedStates::INPLACE_ACTIVE
) )
651 OSL_FAIL( "Iconified object should not be activated inplace!\n" );
657 GetObject()->changeState( nState
);
659 catch ( uno::Exception
& )
665 sal_Int64
SfxInPlaceClient::GetObjectMiscStatus() const
667 if ( GetObject().is() )
668 return GetObject()->getStatus( m_pImp
->m_nAspect
);
673 const uno::Reference
< embed::XEmbeddedObject
>& SfxInPlaceClient::GetObject() const
675 return m_pImp
->m_xObject
;
679 void SfxInPlaceClient::SetObject( const uno::Reference
< embed::XEmbeddedObject
>& rObject
)
681 if ( m_pImp
->m_xObject
.is() && rObject
!= m_pImp
->m_xObject
)
683 DBG_ASSERT( GetObject()->getClientSite() == m_pImp
->m_xClient
, "Wrong ClientSite!" );
684 if ( GetObject()->getClientSite() == m_pImp
->m_xClient
)
686 if ( GetObject()->getCurrentState() != embed::EmbedStates::LOADED
)
687 SetObjectState( embed::EmbedStates::RUNNING
);
688 m_pImp
->m_xObject
->removeEventListener( uno::Reference
< document::XEventListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
689 m_pImp
->m_xObject
->removeStateChangeListener( uno::Reference
< embed::XStateChangeListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
692 m_pImp
->m_xObject
->setClientSite( nullptr );
694 catch( uno::Exception
& )
696 OSL_FAIL( "Can not clean the client site!\n" );
701 if ( m_pViewSh
->GetViewFrame()->GetFrame().IsClosing_Impl() )
702 // sometimes applications reconnect clients on shutting down because it happens in their Paint methods
705 m_pImp
->m_xObject
= rObject
;
709 // as soon as an object was connected to a client it has to be checked whether the object wants
711 rObject
->addStateChangeListener( uno::Reference
< embed::XStateChangeListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
712 rObject
->addEventListener( uno::Reference
< document::XEventListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
716 rObject
->setClientSite( m_pImp
->m_xClient
);
718 catch( uno::Exception
& )
720 OSL_FAIL( "Can not set the client site!\n" );
723 m_pImp
->m_aTimer
.Start();
726 m_pImp
->m_aTimer
.Stop();
730 bool SfxInPlaceClient::SetObjArea( const Rectangle
& rArea
)
732 if( rArea
!= m_pImp
->m_aObjArea
)
734 m_pImp
->m_aObjArea
= rArea
;
735 m_pImp
->SizeHasChanged();
745 const Rectangle
& SfxInPlaceClient::GetObjArea() const
747 return m_pImp
->m_aObjArea
;
750 Rectangle
SfxInPlaceClient::GetScaledObjArea() const
752 Rectangle
aRealObjArea( m_pImp
->m_aObjArea
);
753 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_pImp
->m_aScaleWidth
,
754 Fraction( aRealObjArea
.GetHeight() ) * m_pImp
->m_aScaleHeight
) );
759 void SfxInPlaceClient::SetSizeScale( const Fraction
& rScaleWidth
, const Fraction
& rScaleHeight
)
761 if ( m_pImp
->m_aScaleWidth
!= rScaleWidth
|| m_pImp
->m_aScaleHeight
!= rScaleHeight
)
763 m_pImp
->m_aScaleWidth
= rScaleWidth
;
764 m_pImp
->m_aScaleHeight
= rScaleHeight
;
766 m_pImp
->SizeHasChanged();
768 // TODO/LATER: Invalidate seems to trigger (wrong) recalculations of the ObjArea, so it's better
769 // not to call it here, but maybe it sounds reasonable to do so.
775 void SfxInPlaceClient::SetObjAreaAndScale( const Rectangle
& rArea
, const Fraction
& rScaleWidth
, const Fraction
& rScaleHeight
)
777 if( rArea
!= m_pImp
->m_aObjArea
|| m_pImp
->m_aScaleWidth
!= rScaleWidth
|| m_pImp
->m_aScaleHeight
!= rScaleHeight
)
779 m_pImp
->m_aObjArea
= rArea
;
780 m_pImp
->m_aScaleWidth
= rScaleWidth
;
781 m_pImp
->m_aScaleHeight
= rScaleHeight
;
783 m_pImp
->SizeHasChanged();
790 const Fraction
& SfxInPlaceClient::GetScaleWidth() const
792 return m_pImp
->m_aScaleWidth
;
796 const Fraction
& SfxInPlaceClient::GetScaleHeight() const
798 return m_pImp
->m_aScaleHeight
;
802 void SfxInPlaceClient::Invalidate()
804 // TODO/LATER: do we need both?
806 // the object area is provided in logical coordinates of the window but without scaling applied
807 Rectangle
aRealObjArea( m_pImp
->m_aObjArea
);
808 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_pImp
->m_aScaleWidth
,
809 Fraction( aRealObjArea
.GetHeight() ) * m_pImp
->m_aScaleHeight
) );
810 m_pEditWin
->Invalidate( aRealObjArea
);
816 bool SfxInPlaceClient::IsObjectUIActive() const
819 return ( m_pImp
->m_xObject
.is() && ( m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
) );
821 catch( uno::Exception
& )
828 bool SfxInPlaceClient::IsObjectInPlaceActive() const
833 m_pImp
->m_xObject
.is() &&
834 (m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
)
837 m_pImp
->m_xObject
.is() &&
838 (m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
)
842 catch( uno::Exception
& )
849 SfxInPlaceClient
* SfxInPlaceClient::GetClient( SfxObjectShell
* pDoc
, const css::uno::Reference
< css::embed::XEmbeddedObject
>& xObject
)
851 for ( SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst(pDoc
); pFrame
; pFrame
=SfxViewFrame::GetNext(*pFrame
,pDoc
) )
853 if( pFrame
->GetViewShell() )
855 SfxInPlaceClient
* pClient
= pFrame
->GetViewShell()->FindIPClient( xObject
, nullptr );
864 sal_Int64
SfxInPlaceClient::GetAspect() const
866 return m_pImp
->m_nAspect
;
869 ErrCode
SfxInPlaceClient::DoVerb( long nVerb
)
871 SfxErrorContext
aEc( ERRCTX_SO_DOVERB
, m_pViewSh
->GetWindow(), RID_SO_ERRCTX
);
872 ErrCode nError
= ERRCODE_NONE
;
874 if ( m_pImp
->m_xObject
.is() )
876 bool bSaveCopyAs
= false;
877 if ( nVerb
== -8 ) // "Save Copy as..."
879 svt::EmbeddedObjectRef::TryRunningState( m_pImp
->m_xObject
);
880 // TODO/LATER: this special verb should disappear when outplace activation is completely available
881 uno::Reference
< frame::XModel
> xEmbModel( m_pImp
->m_xObject
->getComponent(), uno::UNO_QUERY
);
882 if ( xEmbModel
.is() )
888 SfxStoringHelper aHelper
;
889 uno::Sequence
< beans::PropertyValue
> aDispatchArgs( 1 );
890 aDispatchArgs
[0].Name
= "SaveTo";
891 aDispatchArgs
[0].Value
<<= true;
893 aHelper
.GUIStoreModel( xEmbModel
,
898 SignatureState::NOSIGNATURES
);
900 catch( const task::ErrorCodeIOException
& aErrorEx
)
902 nError
= (sal_uInt32
)aErrorEx
.ErrCode
;
904 catch( uno::Exception
& )
906 nError
= ERRCODE_IO_GENERAL
;
907 // TODO/LATER: better error handling
914 if ( m_pImp
->m_nAspect
== embed::Aspects::MSOLE_ICON
)
916 // the common persistence is supported by objects and links
918 uno::Reference
< embed::XEmbeddedOleObject
> xEmbeddedOleObject( m_pImp
->m_xObject
, uno::UNO_QUERY
);
920 if ( xEmbeddedOleObject
.is() && (nVerb
== embed::EmbedVerbs::MS_OLEVERB_PRIMARY
|| nVerb
== embed::EmbedVerbs::MS_OLEVERB_OPEN
|| nVerb
== embed::EmbedVerbs::MS_OLEVERB_SHOW
))
921 nVerb
= embed::EmbedVerbs::MS_OLEVERB_SHOW
;
922 else if ( nVerb
== embed::EmbedVerbs::MS_OLEVERB_PRIMARY
|| nVerb
== embed::EmbedVerbs::MS_OLEVERB_SHOW
)
923 nVerb
= embed::EmbedVerbs::MS_OLEVERB_OPEN
; // outplace activation
924 else if ( nVerb
== embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE
925 || nVerb
== embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE
)
926 nError
= ERRCODE_SO_GENERALERROR
;
932 m_pViewSh
->GetViewFrame()->GetFrame().LockResize_Impl(true);
935 m_pImp
->m_xObject
->setClientSite( m_pImp
->m_xClient
);
937 m_pImp
->m_xObject
->doVerb( nVerb
);
939 catch ( embed::UnreachableStateException
& )
941 if (nVerb
== embed::EmbedVerbs::MS_OLEVERB_PRIMARY
|| nVerb
== embed::EmbedVerbs::MS_OLEVERB_OPEN
|| nVerb
== embed::EmbedVerbs::MS_OLEVERB_SHOW
)
943 // a workaround for the default verb, usually makes sense for alien objects
946 m_pImp
->m_xObject
->doVerb( -9 ); // open own view, a workaround verb that is not visible
948 if ( m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
)
950 // the object was converted to OOo object
951 awt::Size aSize
= m_pImp
->m_xObject
->getVisualAreaSize( m_pImp
->m_nAspect
);
952 MapMode
aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_pImp
->m_xObject
->getMapUnit( m_pImp
->m_nAspect
) ) );
953 MapMode
aClientMap( GetEditWin()->GetMapMode().GetMapUnit() );
954 Size aNewSize
= GetEditWin()->LogicToLogic( Size( aSize
.Width
, aSize
.Height
), &aObjectMap
, &aClientMap
);
956 Rectangle aScaledArea
= GetScaledObjArea();
957 m_pImp
->m_aObjArea
.SetSize( aNewSize
);
958 m_pImp
->m_aScaleWidth
= Fraction( aScaledArea
.GetWidth(), aNewSize
.Width() );
959 m_pImp
->m_aScaleHeight
= Fraction( aScaledArea
.GetHeight(), aNewSize
.Height() );
962 catch (uno::Exception
const& e
)
964 SAL_WARN("embeddedobj", "SfxInPlaceClient::DoVerb:"
965 " -9 fallback path: exception caught: "
967 nError
= ERRCODE_SO_GENERALERROR
;
971 catch ( embed::StateChangeInProgressException
& )
973 // TODO/LATER: it would be nice to be able to provide the current target state outside
974 nError
= ERRCODE_SO_CANNOT_DOVERB_NOW
;
976 catch (uno::Exception
const& e
)
978 SAL_WARN("embeddedobj", "SfxInPlaceClient::DoVerb:"
979 " exception caught: " << e
.Message
);
980 nError
= ERRCODE_SO_GENERALERROR
;
981 //TODO/LATER: better error handling
984 SfxViewFrame
* pFrame
= m_pViewSh
->GetViewFrame();
985 pFrame
->GetFrame().LockResize_Impl(false);
986 pFrame
->GetFrame().Resize();
992 ErrorHandler::HandleError( nError
);
997 void SfxInPlaceClient::VisAreaChanged()
999 uno::Reference
< embed::XInplaceObject
> xObj( m_pImp
->m_xObject
, uno::UNO_QUERY
);
1000 uno::Reference
< embed::XInplaceClient
> xClient( m_pImp
->m_xClient
, uno::UNO_QUERY
);
1001 if ( xObj
.is() && xClient
.is() )
1002 m_pImp
->SizeHasChanged();
1005 void SfxInPlaceClient::ObjectAreaChanged()
1007 // dummy implementation
1010 void SfxInPlaceClient::RequestNewObjectArea( Rectangle
& )
1012 // dummy implementation
1015 void SfxInPlaceClient::ViewChanged()
1017 // dummy implementation
1020 void SfxInPlaceClient::FormatChanged()
1022 // dummy implementation
1025 void SfxInPlaceClient::DeactivateObject()
1027 if ( GetObject().is() )
1031 m_pImp
->m_bUIActive
= false;
1032 bool bHasFocus
= false;
1033 uno::Reference
< frame::XModel
> xModel( m_pImp
->m_xObject
->getComponent(), uno::UNO_QUERY
);
1036 uno::Reference
< frame::XController
> xController
= xModel
->getCurrentController();
1037 if ( xController
.is() )
1039 VclPtr
<vcl::Window
> pWindow
= VCLUnoHelper::GetWindow( xController
->getFrame()->getContainerWindow() );
1040 bHasFocus
= pWindow
->HasChildPathFocus( true );
1044 m_pViewSh
->GetViewFrame()->GetFrame().LockResize_Impl(true);
1046 if ( (m_pImp
->m_xObject
->getStatus( m_pImp
->m_nAspect
) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
) ||
1047 svt::EmbeddedObjectRef::IsGLChart(m_pImp
->m_xObject
) )
1049 m_pImp
->m_xObject
->changeState( embed::EmbedStates::INPLACE_ACTIVE
);
1051 m_pViewSh
->GetWindow()->GrabFocus();
1055 // the links should not stay in running state for long time because of locking
1056 uno::Reference
< embed::XLinkageSupport
> xLink( m_pImp
->m_xObject
, uno::UNO_QUERY
);
1057 if ( xLink
.is() && xLink
->isLink() )
1058 m_pImp
->m_xObject
->changeState( embed::EmbedStates::LOADED
);
1060 m_pImp
->m_xObject
->changeState( embed::EmbedStates::RUNNING
);
1063 SfxViewFrame
* pFrame
= m_pViewSh
->GetViewFrame();
1064 SfxViewFrame::SetViewFrame( pFrame
);
1065 pFrame
->GetFrame().LockResize_Impl(false);
1066 pFrame
->GetFrame().Resize();
1068 catch (css::uno::Exception
& )
1073 void SfxInPlaceClient::ResetObject()
1075 if ( GetObject().is() )
1079 m_pImp
->m_bUIActive
= false;
1080 if ( (m_pImp
->m_xObject
->getStatus( m_pImp
->m_nAspect
) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
) ||
1081 svt::EmbeddedObjectRef::IsGLChart(m_pImp
->m_xObject
) )
1082 m_pImp
->m_xObject
->changeState( embed::EmbedStates::INPLACE_ACTIVE
);
1085 // the links should not stay in running state for long time because of locking
1086 uno::Reference
< embed::XLinkageSupport
> xLink( m_pImp
->m_xObject
, uno::UNO_QUERY
);
1087 if ( xLink
.is() && xLink
->isLink() )
1088 m_pImp
->m_xObject
->changeState( embed::EmbedStates::LOADED
);
1090 m_pImp
->m_xObject
->changeState( embed::EmbedStates::RUNNING
);
1093 catch (css::uno::Exception
& )
1098 bool SfxInPlaceClient::IsUIActive()
1100 return m_pImp
->m_bUIActive
;
1103 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */