1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ipclient.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sfx2.hxx"
33 #include <com/sun/star/embed/EmbedStates.hpp>
34 #include <com/sun/star/embed/XVisualObject.hpp>
35 #include <com/sun/star/embed/XEmbeddedClient.hpp>
36 #include <com/sun/star/embed/XInplaceClient.hpp>
37 #include <com/sun/star/embed/XInplaceObject.hpp>
38 #include <com/sun/star/embed/XComponentSupplier.hpp>
39 #include <com/sun/star/embed/XWindowSupplier.hpp>
40 #include <com/sun/star/embed/XEmbedPersist.hpp>
41 #include <com/sun/star/embed/EmbedVerbs.hpp>
42 #include <com/sun/star/container/XChild.hpp>
43 #include <com/sun/star/beans/XPropertySet.hpp>
44 #include <com/sun/star/beans/PropertyValue.hpp>
45 #include <com/sun/star/embed/XStateChangeListener.hpp>
46 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
47 #include <com/sun/star/embed/XLinkageSupport.hpp>
48 #include <com/sun/star/lang/XInitialization.hpp>
49 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
50 #include <com/sun/star/task/XStatusIndicator.hpp>
52 #include <com/sun/star/embed/EmbedMisc.hpp>
53 #include <svtools/embedhlp.hxx>
54 #include <vcl/svapp.hxx>
56 #include <sfx2/ipclient.hxx>
57 #include <sfx2/viewsh.hxx>
58 #include <sfx2/viewfrm.hxx>
59 #include <sfx2/objsh.hxx>
60 #include <sfx2/dispatch.hxx>
61 #include "workwin.hxx"
62 #include "guisaveas.hxx"
63 #include <sfx2/topfrm.hxx>
64 #include <cppuhelper/implbase5.hxx>
65 #include <vcl/salbtype.hxx>
66 #include <svtools/ehdl.hxx>
68 #include <vcl/timer.hxx>
69 #include <vcl/window.hxx>
70 #include <toolkit/awt/vclxwindow.hxx>
71 #include <toolkit/helper/vclunohelper.hxx>
72 #include <toolkit/helper/convert.hxx>
73 #include <tools/fract.hxx>
74 #include <tools/gen.hxx>
75 #include <svtools/rectitem.hxx>
76 #include <svtools/soerr.hxx>
77 #include <comphelper/processfactory.hxx>
79 #define SFX_CLIENTACTIVATE_TIMEOUT 100
81 using namespace com::sun::star
;
83 //====================================================================
84 // SfxEmbedResizeGuard
85 class SfxBooleanFlagGuard
88 sal_Bool m_bLifeValue
;
90 SfxBooleanFlagGuard( sal_Bool
& bFlag
, sal_Bool bLifeValue
)
92 , m_bLifeValue( bLifeValue
)
94 m_rFlag
= m_bLifeValue
;
97 ~SfxBooleanFlagGuard()
99 m_rFlag
= !m_bLifeValue
;
103 //====================================================================
104 // SfxInPlaceClient_Impl
106 //--------------------------------------------------------------------
107 class SfxInPlaceClient_Impl
: public ::cppu::WeakImplHelper5
< embed::XEmbeddedClient
,
108 embed::XInplaceClient
,
109 document::XEventListener
,
110 embed::XStateChangeListener
,
111 embed::XWindowSupplier
>
114 Timer m_aTimer
; // activation timeout, starts after object connection
115 Rectangle m_aObjArea
; // area of object in coordinate system of the container (without scaling)
116 Fraction m_aScaleWidth
; // scaling that was applied to the object when it was not active
117 Fraction m_aScaleHeight
;
118 SfxInPlaceClient
* m_pClient
;
119 sal_Int64 m_nAspect
; // ViewAspect that is assigned from the container
120 Rectangle m_aLastObjAreaPixel
; // area of object in coordinate system of the container (without scaling)
121 sal_Bool m_bStoreObject
;
122 sal_Bool m_bUIActive
; // set and cleared when notification for UI (de)activation is sent
123 sal_Bool m_bResizeNoScale
;
125 uno::Reference
< embed::XEmbeddedObject
> m_xObject
;
126 uno::Reference
< embed::XEmbeddedClient
> m_xClient
;
129 SfxInPlaceClient_Impl()
132 , m_bStoreObject( sal_True
)
133 , m_bUIActive( sal_False
)
134 , m_bResizeNoScale( sal_False
)
137 void SizeHasChanged();
138 DECL_LINK (TimerHdl
, Timer
*);
139 uno::Reference
< frame::XFrame
> GetFrame() const;
142 virtual void SAL_CALL
saveObject() throw ( embed::ObjectSaveVetoException
, uno::Exception
, uno::RuntimeException
);
143 virtual void SAL_CALL
visibilityChanged( sal_Bool bVisible
) throw ( embed::WrongStateException
, uno::RuntimeException
);
146 virtual sal_Bool SAL_CALL
canInplaceActivate() throw ( uno::RuntimeException
);
147 virtual void SAL_CALL
activatingInplace() throw ( embed::WrongStateException
, uno::RuntimeException
);
148 virtual void SAL_CALL
activatingUI() throw ( embed::WrongStateException
, uno::RuntimeException
);
149 virtual void SAL_CALL
deactivatedInplace() throw ( embed::WrongStateException
, uno::RuntimeException
);
150 virtual void SAL_CALL
deactivatedUI() throw ( embed::WrongStateException
, uno::RuntimeException
);
151 virtual uno::Reference
< ::com::sun::star::frame::XLayoutManager
> SAL_CALL
getLayoutManager() throw ( embed::WrongStateException
, uno::RuntimeException
);
152 virtual uno::Reference
< frame::XDispatchProvider
> SAL_CALL
getInplaceDispatchProvider() throw ( embed::WrongStateException
, uno::RuntimeException
);
153 virtual awt::Rectangle SAL_CALL
getPlacement() throw ( embed::WrongStateException
, uno::RuntimeException
);
154 virtual awt::Rectangle SAL_CALL
getClipRectangle() throw ( embed::WrongStateException
, uno::RuntimeException
);
155 virtual void SAL_CALL
translateAccelerators( const uno::Sequence
< awt::KeyEvent
>& aKeys
) throw ( embed::WrongStateException
, uno::RuntimeException
);
156 virtual void SAL_CALL
scrollObject( const awt::Size
& aOffset
) throw ( embed::WrongStateException
, uno::RuntimeException
);
157 virtual void SAL_CALL
changedPlacement( const awt::Rectangle
& aPosRect
) throw ( embed::WrongStateException
, uno::Exception
, uno::RuntimeException
);
159 // XComponentSupplier
160 virtual uno::Reference
< util::XCloseable
> SAL_CALL
getComponent() throw ( uno::RuntimeException
);
163 virtual uno::Reference
< awt::XWindow
> SAL_CALL
getWindow() throw ( uno::RuntimeException
);
165 // document::XEventListener
166 virtual void SAL_CALL
notifyEvent( const document::EventObject
& aEvent
) throw( uno::RuntimeException
);
168 // XStateChangeListener
169 virtual void SAL_CALL
changingState( const ::com::sun::star::lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (::com::sun::star::embed::WrongStateException
, ::com::sun::star::uno::RuntimeException
);
170 virtual void SAL_CALL
stateChanged( const ::com::sun::star::lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (::com::sun::star::uno::RuntimeException
);
171 virtual void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& aEvent
) throw (::com::sun::star::uno::RuntimeException
);
174 void SAL_CALL
SfxInPlaceClient_Impl::changingState(
175 const ::com::sun::star::lang::EventObject
& /*aEvent*/,
176 ::sal_Int32
/*nOldState*/,
177 ::sal_Int32
/*nNewState*/ )
178 throw (::com::sun::star::embed::WrongStateException
, ::com::sun::star::uno::RuntimeException
)
182 void SAL_CALL
SfxInPlaceClient_Impl::stateChanged(
183 const ::com::sun::star::lang::EventObject
& /*aEvent*/,
184 ::sal_Int32 nOldState
,
185 ::sal_Int32 nNewState
)
186 throw (::com::sun::star::uno::RuntimeException
)
188 if ( m_pClient
&& nOldState
!= embed::EmbedStates::LOADED
&& nNewState
== embed::EmbedStates::RUNNING
)
190 // deactivation of object
191 uno::Reference
< frame::XModel
> xDocument
;
192 if ( m_pClient
->GetViewShell()->GetObjectShell() )
193 xDocument
= m_pClient
->GetViewShell()->GetObjectShell()->GetModel();
194 SfxObjectShell::SetCurrentComponent( xDocument
);
196 else if ( m_pClient
&& nNewState
== embed::EmbedStates::UI_ACTIVE
)
199 uno::Reference < lang::XUnoTunnel > xObj( m_xObject->getComponent(), uno::UNO_QUERY );
200 uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
201 sal_Int64 nHandle = xObj.is() ? xObj->getSomething( aSeq ) : 0;
204 // currently needs SFX code
205 SfxObjectShell* pDoc = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
206 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDoc );
207 SfxWorkWindow *pWorkWin = pFrame->GetFrame()->GetWorkWindow_Impl();
208 pWorkWin->UpdateObjectBars_Impl();
214 void SAL_CALL
SfxInPlaceClient_Impl::notifyEvent( const document::EventObject
& aEvent
) throw( uno::RuntimeException
)
216 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
218 if ( m_pClient
&& aEvent
.EventName
.equalsAscii("OnVisAreaChanged") && m_nAspect
!= embed::Aspects::MSOLE_ICON
)
220 m_pClient
->ViewChanged();
221 m_pClient
->Invalidate();
225 void SAL_CALL
SfxInPlaceClient_Impl::disposing( const ::com::sun::star::lang::EventObject
& /*aEvent*/ )
226 throw (::com::sun::star::uno::RuntimeException
)
228 DELETEZ( m_pClient
);
232 //--------------------------------------------------------------------
233 uno::Reference
< frame::XFrame
> SfxInPlaceClient_Impl::GetFrame() const
236 throw uno::RuntimeException();
237 return m_pClient
->GetViewShell()->GetViewFrame()->GetFrame()->GetFrameInterface();
240 void SAL_CALL
SfxInPlaceClient_Impl::saveObject()
241 throw ( embed::ObjectSaveVetoException
,
243 uno::RuntimeException
)
245 if ( !m_bStoreObject
)
246 // client wants to discard the object (usually it means the container document is closed while an object is active
247 // and the user didn't request saving the changes
250 // the common persistance is supported by objects and links
251 uno::Reference
< embed::XCommonEmbedPersist
> xPersist( m_xObject
, uno::UNO_QUERY
);
252 if ( !xPersist
.is() )
253 throw uno::RuntimeException();
255 uno::Reference
< frame::XFrame
> xFrame
;
256 uno::Reference
< task::XStatusIndicator
> xStatusIndicator
;
257 uno::Reference
< frame::XModel
> xModel( m_xObject
->getComponent(), uno::UNO_QUERY
);
258 uno::Reference
< lang::XMultiServiceFactory
> xSrvMgr( ::comphelper::getProcessServiceFactory() );
262 uno::Reference
< frame::XController
> xController
= xModel
->getCurrentController();
263 if ( xController
.is() )
264 xFrame
= xController
->getFrame();
267 if ( xSrvMgr
.is() && xFrame
.is() )
269 // set non-reschedule progress to prevent problems when asynchronous calls are made
270 // during storing of the embedded object
271 uno::Reference
< lang::XInitialization
> xInit(
272 xSrvMgr
->createInstance(
273 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.framework.StatusIndicatorFactory" ))),
274 uno::UNO_QUERY_THROW
);
275 beans::PropertyValue aProperty
;
276 uno::Sequence
< uno::Any
> aArgs( 2 );
277 aProperty
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableReschedule" ));
278 aProperty
.Value
= uno::makeAny( sal_True
);
279 aArgs
[0] = uno::makeAny( aProperty
);
280 aProperty
.Name
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
281 aProperty
.Value
= uno::makeAny( xFrame
);
282 aArgs
[1] = uno::makeAny( aProperty
);
284 xInit
->initialize( aArgs
);
286 uno::Reference
< beans::XPropertySet
> xPropSet( xFrame
, uno::UNO_QUERY
);
291 uno::Reference
< task::XStatusIndicatorFactory
> xStatusIndicatorFactory( xInit
, uno::UNO_QUERY_THROW
);
292 xStatusIndicator
= xStatusIndicatorFactory
->createStatusIndicator();
293 xPropSet
->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IndicatorInterception" )), uno::makeAny( xStatusIndicator
));
295 catch ( uno::RuntimeException
& e
)
299 catch ( uno::Exception
& )
307 xPersist
->storeOwn();
310 catch ( uno::Exception
& )
312 //TODO/LATER: what should happen if object can't be saved?!
315 // reset status indicator interception after storing
318 uno::Reference
< beans::XPropertySet
> xPropSet( xFrame
, uno::UNO_QUERY
);
321 xStatusIndicator
.clear();
322 xPropSet
->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IndicatorInterception" )), uno::makeAny( xStatusIndicator
));
325 catch ( uno::RuntimeException
& e
)
329 catch ( uno::Exception
& )
333 // the client can exist only in case there is a view shell
334 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
335 throw uno::RuntimeException();
337 SfxObjectShell
* pDocShell
= m_pClient
->GetViewShell()->GetObjectShell();
339 throw uno::RuntimeException();
341 pDocShell
->SetModified( sal_True
);
343 //TODO/LATER: invalidation might be necessary when object was modified, but is not
344 //saved through this method
345 // m_pClient->Invalidate();
348 //--------------------------------------------------------------------
349 void SAL_CALL
SfxInPlaceClient_Impl::visibilityChanged( sal_Bool bVisible
)
350 throw ( embed::WrongStateException
,
351 uno::RuntimeException
)
353 ::vos::OGuard
aGuard( Application::GetSolarMutex() );
355 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
356 throw uno::RuntimeException();
358 m_pClient
->GetViewShell()->OutplaceActivated( bVisible
, m_pClient
);
359 m_pClient
->Invalidate();
364 //--------------------------------------------------------------------
365 sal_Bool SAL_CALL
SfxInPlaceClient_Impl::canInplaceActivate()
366 throw ( uno::RuntimeException
)
368 if ( !m_xObject
.is() )
369 throw uno::RuntimeException();
371 // we don't want to switch directly from outplace to inplace mode
372 if ( m_xObject
->getCurrentState() == embed::EmbedStates::ACTIVE
|| m_nAspect
== embed::Aspects::MSOLE_ICON
)
378 //--------------------------------------------------------------------
379 void SAL_CALL
SfxInPlaceClient_Impl::activatingInplace()
380 throw ( embed::WrongStateException
,
381 uno::RuntimeException
)
383 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
384 throw uno::RuntimeException();
386 m_pClient
->GetViewShell()->InplaceActivating( m_pClient
);
389 //--------------------------------------------------------------------
390 void SAL_CALL
SfxInPlaceClient_Impl::activatingUI()
391 throw ( embed::WrongStateException
,
392 uno::RuntimeException
)
394 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
395 throw uno::RuntimeException();
397 m_pClient
->GetViewShell()->ResetAllClients_Impl(m_pClient
);
399 m_pClient
->GetViewShell()->UIActivating( m_pClient
);
402 //--------------------------------------------------------------------
403 void SAL_CALL
SfxInPlaceClient_Impl::deactivatedInplace()
404 throw ( embed::WrongStateException
,
405 uno::RuntimeException
)
407 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
408 throw uno::RuntimeException();
410 m_pClient
->GetViewShell()->InplaceDeactivated( m_pClient
);
413 //--------------------------------------------------------------------
414 void SAL_CALL
SfxInPlaceClient_Impl::deactivatedUI()
415 throw ( embed::WrongStateException
,
416 uno::RuntimeException
)
418 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
419 throw uno::RuntimeException();
421 m_pClient
->GetViewShell()->UIDeactivated( m_pClient
);
425 //--------------------------------------------------------------------
426 uno::Reference
< ::com::sun::star::frame::XLayoutManager
> SAL_CALL
SfxInPlaceClient_Impl::getLayoutManager()
427 throw ( embed::WrongStateException
,
428 uno::RuntimeException
)
430 uno::Reference
< beans::XPropertySet
> xFrame( GetFrame(), uno::UNO_QUERY
);
432 throw uno::RuntimeException();
434 uno::Reference
< ::com::sun::star::frame::XLayoutManager
> xMan
;
437 uno::Any aAny
= xFrame
->getPropertyValue( ::rtl::OUString::createFromAscii("LayoutManager") );
440 catch ( uno::Exception
& )
442 throw uno::RuntimeException();
448 //--------------------------------------------------------------------
449 uno::Reference
< frame::XDispatchProvider
> SAL_CALL
SfxInPlaceClient_Impl::getInplaceDispatchProvider()
450 throw ( embed::WrongStateException
,
451 uno::RuntimeException
)
453 return uno::Reference
< frame::XDispatchProvider
>( GetFrame(), uno::UNO_QUERY_THROW
);
456 //--------------------------------------------------------------------
457 awt::Rectangle SAL_CALL
SfxInPlaceClient_Impl::getPlacement()
458 throw ( embed::WrongStateException
,
459 uno::RuntimeException
)
461 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
462 throw uno::RuntimeException();
464 // apply scaling to object area and convert to pixels
465 Rectangle
aRealObjArea( m_aObjArea
);
466 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_aScaleWidth
,
467 Fraction( aRealObjArea
.GetHeight() ) * m_aScaleHeight
) );
469 aRealObjArea
= m_pClient
->GetEditWin()->LogicToPixel( aRealObjArea
);
470 return AWTRectangle( aRealObjArea
);
473 //--------------------------------------------------------------------
474 awt::Rectangle SAL_CALL
SfxInPlaceClient_Impl::getClipRectangle()
475 throw ( embed::WrongStateException
,
476 uno::RuntimeException
)
478 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
479 throw uno::RuntimeException();
481 // currently(?) same as placement
482 Rectangle
aRealObjArea( m_aObjArea
);
483 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_aScaleWidth
,
484 Fraction( aRealObjArea
.GetHeight() ) * m_aScaleHeight
) );
486 aRealObjArea
= m_pClient
->GetEditWin()->LogicToPixel( aRealObjArea
);
487 return AWTRectangle( aRealObjArea
);
490 //--------------------------------------------------------------------
491 void SAL_CALL
SfxInPlaceClient_Impl::translateAccelerators( const uno::Sequence
< awt::KeyEvent
>& /*aKeys*/ )
492 throw ( embed::WrongStateException
,
493 uno::RuntimeException
)
495 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
496 throw uno::RuntimeException();
498 // TODO/MBA: keyboard accelerators
501 //--------------------------------------------------------------------
502 void SAL_CALL
SfxInPlaceClient_Impl::scrollObject( const awt::Size
& /*aOffset*/ )
503 throw ( embed::WrongStateException
,
504 uno::RuntimeException
)
506 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
507 throw uno::RuntimeException();
510 //--------------------------------------------------------------------
511 void SAL_CALL
SfxInPlaceClient_Impl::changedPlacement( const awt::Rectangle
& aPosRect
)
512 throw ( embed::WrongStateException
,
514 uno::RuntimeException
)
516 uno::Reference
< embed::XInplaceObject
> xInplace( m_xObject
, uno::UNO_QUERY
);
517 if ( !xInplace
.is() || !m_pClient
|| !m_pClient
->GetEditWin() || !m_pClient
->GetViewShell() )
518 throw uno::RuntimeException();
520 // check if the change is at least one pixel in size
521 awt::Rectangle aOldRect
= getPlacement();
522 Rectangle aNewPixelRect
= VCLRectangle( aPosRect
);
523 Rectangle aOldPixelRect
= VCLRectangle( aOldRect
);
524 if ( aOldPixelRect
== aNewPixelRect
)
525 // nothing has changed
528 // new scaled object area
529 Rectangle aNewLogicRect
= m_pClient
->GetEditWin()->PixelToLogic( aNewPixelRect
);
531 // all the size changes in this method should happen without scaling
532 // SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True );
534 // allow container to apply restrictions on the requested new area;
535 // the container might change the object view during size calculation;
536 // currently only writer does it
537 m_pClient
->RequestNewObjectArea( aNewLogicRect
);
539 if ( aNewLogicRect
!= m_pClient
->GetScaledObjArea() )
541 // the calculation of the object area has not changed the object size
542 // it should be done here then
543 SfxBooleanFlagGuard
aGuard( m_bResizeNoScale
, sal_True
);
545 // new size of the object area without scaling
546 Size
aNewObjSize( Fraction( aNewLogicRect
.GetWidth() ) / m_aScaleWidth
,
547 Fraction( aNewLogicRect
.GetHeight() ) / m_aScaleHeight
);
549 // now remove scaling from new placement and keep this a the new object area
550 aNewLogicRect
.SetSize( aNewObjSize
);
551 m_aObjArea
= aNewLogicRect
;
553 // let the window size be recalculated
557 // notify container view about changes
558 m_pClient
->ObjectAreaChanged();
561 // XComponentSupplier
562 //--------------------------------------------------------------------
563 uno::Reference
< util::XCloseable
> SAL_CALL
SfxInPlaceClient_Impl::getComponent()
564 throw ( uno::RuntimeException
)
566 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
567 throw uno::RuntimeException();
569 SfxObjectShell
* pDocShell
= m_pClient
->GetViewShell()->GetObjectShell();
571 throw uno::RuntimeException();
573 // all the components must implement XCloseable
574 uno::Reference
< util::XCloseable
> xComp( pDocShell
->GetModel(), uno::UNO_QUERY
);
576 throw uno::RuntimeException();
583 //--------------------------------------------------------------------
584 uno::Reference
< awt::XWindow
> SAL_CALL
SfxInPlaceClient_Impl::getWindow()
585 throw ( uno::RuntimeException
)
587 if ( !m_pClient
|| !m_pClient
->GetEditWin() )
588 throw uno::RuntimeException();
590 uno::Reference
< awt::XWindow
> xWin( m_pClient
->GetEditWin()->GetComponentInterface(), uno::UNO_QUERY
);
594 //--------------------------------------------------------------------
595 // notification to the client implementation that either the object area or the scaling has been changed
596 // as a result the logical size of the window has changed also
597 void SfxInPlaceClient_Impl::SizeHasChanged()
599 if ( !m_pClient
|| !m_pClient
->GetViewShell() )
600 throw uno::RuntimeException();
604 && ( m_xObject
->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
605 || m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
) )
607 // only possible in active states
608 uno::Reference
< embed::XInplaceObject
> xInplace( m_xObject
, uno::UNO_QUERY
);
609 if ( !xInplace
.is() )
610 throw uno::RuntimeException();
612 if ( m_bResizeNoScale
)
614 // the resizing should be done without scaling
615 // set the correct size to the object to avoid the scaling
616 MapMode
aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_xObject
->getMapUnit( m_nAspect
) ) );
617 MapMode
aClientMap( m_pClient
->GetEditWin()->GetMapMode().GetMapUnit() );
619 // convert to logical coordinates of the embedded object
620 Size aNewSize
= m_pClient
->GetEditWin()->LogicToLogic( m_aObjArea
.GetSize(), &aClientMap
, &aObjectMap
);
621 m_xObject
->setVisualAreaSize( m_nAspect
, awt::Size( aNewSize
.Width(), aNewSize
.Height() ) );
624 xInplace
->setObjectRectangles( getPlacement(), getClipRectangle() );
627 catch( uno::Exception
& )
629 // TODO/LATER: handle error
633 //--------------------------------------------------------------------
634 IMPL_LINK( SfxInPlaceClient_Impl
, TimerHdl
, Timer
*, EMPTYARG
)
636 if ( m_pClient
&& m_xObject
.is() )
637 m_pClient
->GetViewShell()->CheckIPClient_Impl( m_pClient
, m_pClient
->GetViewShell()->GetObjectShell()->GetVisArea() );
642 //====================================================================
645 //--------------------------------------------------------------------
646 SfxInPlaceClient::SfxInPlaceClient( SfxViewShell
* pViewShell
, Window
*pDraw
, sal_Int64 nAspect
) :
647 m_pImp( new SfxInPlaceClient_Impl
),
648 m_pViewSh( pViewShell
),
651 m_pImp
->m_pClient
= this;
652 m_pImp
->m_nAspect
= nAspect
;
653 m_pImp
->m_aScaleWidth
= m_pImp
->m_aScaleHeight
= Fraction(1,1);
654 m_pImp
->m_xClient
= static_cast< embed::XEmbeddedClient
* >( m_pImp
);
655 pViewShell
->NewIPClient_Impl(this);
656 m_pImp
->m_aTimer
.SetTimeout( SFX_CLIENTACTIVATE_TIMEOUT
);
657 m_pImp
->m_aTimer
.SetTimeoutHdl( LINK( m_pImp
, SfxInPlaceClient_Impl
, TimerHdl
) );
660 //--------------------------------------------------------------------
662 SfxInPlaceClient::~SfxInPlaceClient()
664 m_pViewSh
->IPClientGone_Impl(this);
666 // deleting the client before storing the object means discarding all changes
667 m_pImp
->m_bStoreObject
= sal_False
;
670 m_pImp
->m_pClient
= NULL
;
672 // the next call will destroy m_pImp if no other reference to it exists
673 m_pImp
->m_xClient
= uno::Reference
< embed::XEmbeddedClient
>();
676 // the class is not intended to be used in multithreaded environment;
677 // if it will this disconnection and all the parts that use the m_pClient
678 // must be guarded with mutex
681 //--------------------------------------------------------------------
682 void SfxInPlaceClient::SetObjectState( sal_Int32 nState
)
684 if ( GetObject().is() )
686 if ( m_pImp
->m_nAspect
== embed::Aspects::MSOLE_ICON
687 && ( nState
== embed::EmbedStates::UI_ACTIVE
|| nState
== embed::EmbedStates::INPLACE_ACTIVE
) )
689 OSL_ENSURE( sal_False
, "Iconified object should not be activated inplace!\n" );
695 GetObject()->changeState( nState
);
697 catch ( uno::Exception
& )
702 //--------------------------------------------------------------------
703 sal_Int64
SfxInPlaceClient::GetObjectMiscStatus() const
705 if ( GetObject().is() )
706 return GetObject()->getStatus( m_pImp
->m_nAspect
);
710 //--------------------------------------------------------------------
711 uno::Reference
< embed::XEmbeddedObject
> SfxInPlaceClient::GetObject() const
713 return m_pImp
->m_xObject
;
716 //--------------------------------------------------------------------
717 void SfxInPlaceClient::SetObject( const uno::Reference
< embed::XEmbeddedObject
>& rObject
)
719 if ( m_pImp
->m_xObject
.is() && rObject
!= m_pImp
->m_xObject
)
721 DBG_ASSERT( GetObject()->getClientSite() == m_pImp
->m_xClient
, "Wrong ClientSite!" );
722 if ( GetObject()->getClientSite() == m_pImp
->m_xClient
)
724 if ( GetObject()->getCurrentState() != embed::EmbedStates::LOADED
)
725 SetObjectState( embed::EmbedStates::RUNNING
);
726 m_pImp
->m_xObject
->removeEventListener( uno::Reference
< document::XEventListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
727 m_pImp
->m_xObject
->removeStateChangeListener( uno::Reference
< embed::XStateChangeListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
730 m_pImp
->m_xObject
->setClientSite( 0 );
732 catch( uno::Exception
& )
734 OSL_ENSURE( sal_False
, "Can not clean the client site!\n" );
739 if ( !m_pViewSh
|| m_pViewSh
->GetViewFrame()->GetFrame()->IsClosing_Impl() )
740 // sometimes applications reconnect clients on shutting down because it happens in their Paint methods
743 m_pImp
->m_xObject
= rObject
;
747 // as soon as an object was connected to a client it has to be checked wether the object wants
749 rObject
->addStateChangeListener( uno::Reference
< embed::XStateChangeListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
750 rObject
->addEventListener( uno::Reference
< document::XEventListener
>( m_pImp
->m_xClient
, uno::UNO_QUERY
) );
754 rObject
->setClientSite( m_pImp
->m_xClient
);
756 catch( uno::Exception
& )
758 OSL_ENSURE( sal_False
, "Can not set the client site!\n" );
761 m_pImp
->m_aTimer
.Start();
764 m_pImp
->m_aTimer
.Stop();
767 //--------------------------------------------------------------------
768 BOOL
SfxInPlaceClient::SetObjArea( const Rectangle
& rArea
)
770 if( rArea
!= m_pImp
->m_aObjArea
)
772 m_pImp
->m_aObjArea
= rArea
;
773 m_pImp
->SizeHasChanged();
782 //--------------------------------------------------------------------
783 Rectangle
SfxInPlaceClient::GetObjArea() const
785 return m_pImp
->m_aObjArea
;
788 Rectangle
SfxInPlaceClient::GetScaledObjArea() const
790 Rectangle
aRealObjArea( m_pImp
->m_aObjArea
);
791 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_pImp
->m_aScaleWidth
,
792 Fraction( aRealObjArea
.GetHeight() ) * m_pImp
->m_aScaleHeight
) );
796 //--------------------------------------------------------------------
797 void SfxInPlaceClient::SetSizeScale( const Fraction
& rScaleWidth
, const Fraction
& rScaleHeight
)
799 if ( m_pImp
->m_aScaleWidth
!= rScaleWidth
|| m_pImp
->m_aScaleHeight
!= rScaleHeight
)
801 m_pImp
->m_aScaleWidth
= rScaleWidth
;
802 m_pImp
->m_aScaleHeight
= rScaleHeight
;
804 m_pImp
->SizeHasChanged();
806 // TODO/LATER: Invalidate seems to trigger (wrong) recalculations of the ObjArea, so it's better
807 // not to call it here, but maybe it sounds reasonable to do so.
812 //--------------------------------------------------------------------
813 sal_Bool
SfxInPlaceClient::SetObjAreaAndScale( const Rectangle
& rArea
, const Fraction
& rScaleWidth
, const Fraction
& rScaleHeight
)
815 if( rArea
!= m_pImp
->m_aObjArea
|| m_pImp
->m_aScaleWidth
!= rScaleWidth
|| m_pImp
->m_aScaleHeight
!= rScaleHeight
)
817 m_pImp
->m_aObjArea
= rArea
;
818 m_pImp
->m_aScaleWidth
= rScaleWidth
;
819 m_pImp
->m_aScaleHeight
= rScaleHeight
;
821 m_pImp
->SizeHasChanged();
830 //--------------------------------------------------------------------
831 const Fraction
& SfxInPlaceClient::GetScaleWidth() const
833 return m_pImp
->m_aScaleWidth
;
836 //--------------------------------------------------------------------
837 const Fraction
& SfxInPlaceClient::GetScaleHeight() const
839 return m_pImp
->m_aScaleHeight
;
842 //--------------------------------------------------------------------
843 void SfxInPlaceClient::Invalidate()
845 // TODO/LATER: do we need both?
847 // the object area is provided in logical coordinates of the window but without scaling applied
848 Rectangle
aRealObjArea( m_pImp
->m_aObjArea
);
849 aRealObjArea
.SetSize( Size( Fraction( aRealObjArea
.GetWidth() ) * m_pImp
->m_aScaleWidth
,
850 Fraction( aRealObjArea
.GetHeight() ) * m_pImp
->m_aScaleHeight
) );
851 m_pEditWin
->Invalidate( aRealObjArea
);
856 //--------------------------------------------------------------------
857 sal_Bool
SfxInPlaceClient::IsObjectUIActive() const
860 return ( m_pImp
->m_xObject
.is() && ( m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
) );
862 catch( uno::Exception
& )
868 //--------------------------------------------------------------------
869 sal_Bool
SfxInPlaceClient::IsObjectInPlaceActive() const
874 m_pImp
->m_xObject
.is() &&
875 (m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
)
878 m_pImp
->m_xObject
.is() &&
879 (m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
)
883 catch( uno::Exception
& )
889 //--------------------------------------------------------------------
890 sal_Bool
SfxInPlaceClient::IsObjectActive() const
893 return ( m_pImp
->m_xObject
.is() && ( m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::ACTIVE
) );
895 catch( uno::Exception
& )
901 //--------------------------------------------------------------------
902 Window
* SfxInPlaceClient::GetActiveWindow( SfxObjectShell
* pDoc
, const com::sun::star::uno::Reference
< com::sun::star::embed::XEmbeddedObject
>& xObject
)
904 SfxInPlaceClient
* pClient
= GetClient( pDoc
, xObject
);
906 return pClient
->GetEditWin();
910 //--------------------------------------------------------------------
911 SfxInPlaceClient
* SfxInPlaceClient::GetClient( SfxObjectShell
* pDoc
, const com::sun::star::uno::Reference
< com::sun::star::embed::XEmbeddedObject
>& xObject
)
913 for ( SfxViewFrame
* pFrame
= SfxViewFrame::GetFirst(pDoc
); pFrame
; pFrame
=SfxViewFrame::GetNext(*pFrame
,pDoc
) )
915 if( pFrame
->GetViewShell() )
917 SfxInPlaceClient
* pClient
= pFrame
->GetViewShell()->FindIPClient( xObject
, NULL
);
926 sal_Int64
SfxInPlaceClient::GetAspect() const
928 return m_pImp
->m_nAspect
;
931 ErrCode
SfxInPlaceClient::DoVerb( long nVerb
)
933 SfxErrorContext
aEc( ERRCTX_SO_DOVERB
, m_pViewSh
->GetWindow(), RID_SO_ERRCTX
);
934 ErrCode nError
= ERRCODE_NONE
;
936 if ( m_pImp
->m_xObject
.is() )
938 sal_Bool bSaveCopyAs
= sal_False
;
939 if ( nVerb
== -8 ) // "Save Copy as..."
941 svt::EmbeddedObjectRef::TryRunningState( m_pImp
->m_xObject
);
942 // TODO/LATER: this special verb should disappear when outplace activation is completely available
943 uno::Reference
< frame::XModel
> xEmbModel( m_pImp
->m_xObject
->getComponent(), uno::UNO_QUERY
);
944 if ( xEmbModel
.is() )
946 bSaveCopyAs
= sal_True
;
950 uno::Reference
< lang::XMultiServiceFactory
> xEmptyFactory
;
951 SfxStoringHelper
aHelper( xEmptyFactory
);
952 uno::Sequence
< beans::PropertyValue
> aDispatchArgs( 1 );
953 aDispatchArgs
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SaveTo" ) );
954 aDispatchArgs
[0].Value
<<= (sal_Bool
)sal_True
;
956 aHelper
.GUIStoreModel( xEmbModel
,
957 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SaveAs" ) ),
962 catch( task::ErrorCodeIOException
& aErrorEx
)
964 nError
= (sal_uInt32
)aErrorEx
.ErrCode
;
966 catch( uno::Exception
& )
968 nError
= ERRCODE_IO_GENERAL
;
969 // TODO/LATER: better error handling
976 if ( m_pImp
->m_nAspect
== embed::Aspects::MSOLE_ICON
)
978 if ( nVerb
== embed::EmbedVerbs::MS_OLEVERB_PRIMARY
|| nVerb
== embed::EmbedVerbs::MS_OLEVERB_SHOW
)
979 nVerb
= embed::EmbedVerbs::MS_OLEVERB_OPEN
; // outplace activation
980 else if ( nVerb
== embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE
981 || nVerb
== embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE
)
982 nError
= ERRCODE_SO_GENERALERROR
;
989 ((SfxTopFrame
*)m_pViewSh
->GetViewFrame()->GetTopFrame())->LockResize_Impl(TRUE
);
992 m_pImp
->m_xObject
->setClientSite( m_pImp
->m_xClient
);
994 m_pImp
->m_xObject
->doVerb( nVerb
);
996 catch ( embed::UnreachableStateException
& )
998 if ( nVerb
== 0 || nVerb
== embed::EmbedVerbs::MS_OLEVERB_OPEN
)
1000 // a workaround for the default verb, usually makes sence for alien objects
1003 m_pImp
->m_xObject
->doVerb( -9 ); // open own view, a workaround verb that is not visible
1005 if ( m_pImp
->m_xObject
->getCurrentState() == embed::EmbedStates::UI_ACTIVE
)
1007 // the object was converted to OOo object
1008 awt::Size aSize
= m_pImp
->m_xObject
->getVisualAreaSize( m_pImp
->m_nAspect
);
1009 MapMode
aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_pImp
->m_xObject
->getMapUnit( m_pImp
->m_nAspect
) ) );
1010 MapMode
aClientMap( GetEditWin()->GetMapMode().GetMapUnit() );
1011 Size aNewSize
= GetEditWin()->LogicToLogic( Size( aSize
.Width
, aSize
.Height
), &aObjectMap
, &aClientMap
);
1013 Rectangle aScaledArea
= GetScaledObjArea();
1014 m_pImp
->m_aObjArea
.SetSize( aNewSize
);
1015 m_pImp
->m_aScaleWidth
= Fraction( aScaledArea
.GetWidth(), aNewSize
.Width() );
1016 m_pImp
->m_aScaleHeight
= Fraction( aScaledArea
.GetHeight(), aNewSize
.Height() );
1019 catch ( uno::Exception
& )
1021 nError
= ERRCODE_SO_GENERALERROR
;
1025 catch ( embed::StateChangeInProgressException
& )
1027 // TODO/LATER: it would be nice to be able to provide the current target state outside
1028 nError
= ERRCODE_SO_CANNOT_DOVERB_NOW
;
1030 catch ( uno::Exception
& )
1032 nError
= ERRCODE_SO_GENERALERROR
;
1033 //TODO/LATER: better error handling
1038 SfxViewFrame
* pFrame
= m_pViewSh
->GetViewFrame();
1039 ((SfxTopFrame
*)pFrame
->GetTopFrame())->LockResize_Impl(FALSE
);
1040 pFrame
->GetTopFrame()->Resize();
1047 ErrorHandler::HandleError( nError
);
1052 void SfxInPlaceClient::VisAreaChanged()
1054 uno::Reference
< embed::XInplaceObject
> xObj( m_pImp
->m_xObject
, uno::UNO_QUERY
);
1055 uno::Reference
< embed::XInplaceClient
> xClient( m_pImp
->m_xClient
, uno::UNO_QUERY
);
1056 if ( xObj
.is() && xClient
.is() )
1057 m_pImp
->SizeHasChanged();
1060 void SfxInPlaceClient::ObjectAreaChanged()
1062 // dummy implementation
1065 void SfxInPlaceClient::RequestNewObjectArea( Rectangle
& )
1067 // dummy implementation
1070 void SfxInPlaceClient::ViewChanged()
1072 // dummy implementation
1075 void SfxInPlaceClient::MakeVisible()
1077 // dummy implementation
1080 void SfxInPlaceClient::DeactivateObject()
1082 if ( GetObject().is() )
1086 m_pImp
->m_bUIActive
= FALSE
;
1087 BOOL bHasFocus
= FALSE
;
1088 uno::Reference
< frame::XModel
> xModel( m_pImp
->m_xObject
->getComponent(), uno::UNO_QUERY
);
1091 uno::Reference
< frame::XController
> xController
= xModel
->getCurrentController();
1092 if ( xController
.is() )
1094 Window
* pWindow
= VCLUnoHelper::GetWindow( xController
->getFrame()->getContainerWindow() );
1095 bHasFocus
= pWindow
->HasChildPathFocus( TRUE
);
1100 ((SfxTopFrame
*)m_pViewSh
->GetViewFrame()->GetTopFrame())->LockResize_Impl(TRUE
);
1102 if ( m_pImp
->m_xObject
->getStatus( m_pImp
->m_nAspect
) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
)
1104 m_pImp
->m_xObject
->changeState( embed::EmbedStates::INPLACE_ACTIVE
);
1105 if ( bHasFocus
&& m_pViewSh
)
1106 m_pViewSh
->GetWindow()->GrabFocus();
1110 // the links should not stay in running state for long time because of locking
1111 uno::Reference
< embed::XLinkageSupport
> xLink( m_pImp
->m_xObject
, uno::UNO_QUERY
);
1112 if ( xLink
.is() && xLink
->isLink() )
1113 m_pImp
->m_xObject
->changeState( embed::EmbedStates::LOADED
);
1115 m_pImp
->m_xObject
->changeState( embed::EmbedStates::RUNNING
);
1120 SfxViewFrame
* pFrame
= m_pViewSh
->GetViewFrame();
1121 SfxViewFrame::SetViewFrame( pFrame
);
1122 ((SfxTopFrame
*)pFrame
->GetTopFrame())->LockResize_Impl(FALSE
);
1123 pFrame
->GetTopFrame()->Resize();
1126 catch (com::sun::star::uno::Exception
& )
1131 void SfxInPlaceClient::ResetObject()
1133 if ( GetObject().is() )
1137 m_pImp
->m_bUIActive
= FALSE
;
1138 if ( m_pImp
->m_xObject
->getStatus( m_pImp
->m_nAspect
) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE
)
1139 m_pImp
->m_xObject
->changeState( embed::EmbedStates::INPLACE_ACTIVE
);
1142 // the links should not stay in running state for long time because of locking
1143 uno::Reference
< embed::XLinkageSupport
> xLink( m_pImp
->m_xObject
, uno::UNO_QUERY
);
1144 if ( xLink
.is() && xLink
->isLink() )
1145 m_pImp
->m_xObject
->changeState( embed::EmbedStates::LOADED
);
1147 m_pImp
->m_xObject
->changeState( embed::EmbedStates::RUNNING
);
1150 catch (com::sun::star::uno::Exception
& )
1155 BOOL
SfxInPlaceClient::IsUIActive()
1157 return m_pImp
->m_bUIActive
;