merge the formfield patch from ooo-build
[ooovba.git] / sfx2 / source / view / ipclient.cxx
blob18fe96ebb040b6ae21949b9e41a7bc66d4606d4f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ipclient.cxx,v $
10 * $Revision: 1.34 $
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
87 sal_Bool& m_rFlag;
88 sal_Bool m_bLifeValue;
89 public:
90 SfxBooleanFlagGuard( sal_Bool& bFlag, sal_Bool bLifeValue )
91 : m_rFlag( bFlag )
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 >
113 public:
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()
130 : m_pClient( NULL )
131 , m_nAspect( 0 )
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;
141 // XEmbeddedClient
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 );
145 // XInplaceClient
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 );
162 // XWindowSupplier
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;
202 if ( nHandle )
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 );
231 // XEmbeddedClient
232 //--------------------------------------------------------------------
233 uno::Reference < frame::XFrame > SfxInPlaceClient_Impl::GetFrame() const
235 if ( !m_pClient )
236 throw uno::RuntimeException();
237 return m_pClient->GetViewShell()->GetViewFrame()->GetFrame()->GetFrameInterface();
240 void SAL_CALL SfxInPlaceClient_Impl::saveObject()
241 throw ( embed::ObjectSaveVetoException,
242 uno::Exception,
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
248 return;
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() );
260 if ( xModel.is() )
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 );
287 if ( xPropSet.is() )
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 )
297 throw e;
299 catch ( uno::Exception& )
307 xPersist->storeOwn();
308 m_xObject->update();
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 );
319 if ( xPropSet.is() )
321 xStatusIndicator.clear();
322 xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IndicatorInterception" )), uno::makeAny( xStatusIndicator ));
325 catch ( uno::RuntimeException& e )
327 throw 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();
338 if ( !pDocShell )
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();
363 // XInplaceClient
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 )
373 return sal_False;
375 return sal_True;
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);
398 m_bUIActive = TRUE;
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 );
422 m_bUIActive = FALSE;
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 );
431 if ( !xFrame.is() )
432 throw uno::RuntimeException();
434 uno::Reference< ::com::sun::star::frame::XLayoutManager > xMan;
437 uno::Any aAny = xFrame->getPropertyValue( ::rtl::OUString::createFromAscii("LayoutManager") );
438 aAny >>= xMan;
440 catch ( uno::Exception& )
442 throw uno::RuntimeException();
445 return xMan;
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,
513 uno::Exception,
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
526 return;
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
554 SizeHasChanged();
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();
570 if ( !pDocShell )
571 throw uno::RuntimeException();
573 // all the components must implement XCloseable
574 uno::Reference< util::XCloseable > xComp( pDocShell->GetModel(), uno::UNO_QUERY );
575 if ( !xComp.is() )
576 throw uno::RuntimeException();
578 return xComp;
582 // XWindowSupplier
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 );
591 return xWin;
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();
602 try {
603 if ( m_xObject.is()
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() );
638 return 0;
642 //====================================================================
643 // SfxInPlaceClient
645 //--------------------------------------------------------------------
646 SfxInPlaceClient::SfxInPlaceClient( SfxViewShell* pViewShell, Window *pDraw, sal_Int64 nAspect ) :
647 m_pImp( new SfxInPlaceClient_Impl ),
648 m_pViewSh( pViewShell ),
649 m_pEditWin( pDraw )
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;
668 SetObject(0);
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 >();
675 // TODO/LATER:
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" );
690 return;
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 );
707 return 0;
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
741 return;
743 m_pImp->m_xObject = rObject;
745 if ( rObject.is() )
747 // as soon as an object was connected to a client it has to be checked wether the object wants
748 // to be activated
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();
763 else
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();
775 Invalidate();
776 return TRUE;
779 return FALSE;
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 ) );
793 return aRealObjArea;
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.
808 //Invalidate();
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();
823 Invalidate();
824 return sal_True;
827 return sal_False;
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 );
853 ViewChanged();
856 //--------------------------------------------------------------------
857 sal_Bool SfxInPlaceClient::IsObjectUIActive() const
859 try {
860 return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) );
862 catch( uno::Exception& )
865 return sal_False;
868 //--------------------------------------------------------------------
869 sal_Bool SfxInPlaceClient::IsObjectInPlaceActive() const
871 try {
872 return(
874 m_pImp->m_xObject.is() &&
875 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE)
876 ) ||
878 m_pImp->m_xObject.is() &&
879 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE)
883 catch( uno::Exception& )
886 return sal_False;
889 //--------------------------------------------------------------------
890 sal_Bool SfxInPlaceClient::IsObjectActive() const
892 try {
893 return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::ACTIVE ) );
895 catch( uno::Exception& )
898 return sal_False;
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 );
905 if ( pClient )
906 return pClient->GetEditWin();
907 return NULL;
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 );
918 if ( pClient )
919 return pClient;
923 return 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" ) ),
958 aDispatchArgs,
959 sal_False,
960 ::rtl::OUString() );
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
974 if ( !bSaveCopyAs )
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;
985 if ( !nError )
988 if ( m_pViewSh )
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
1036 if ( m_pViewSh )
1038 SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
1039 ((SfxTopFrame*)pFrame->GetTopFrame())->LockResize_Impl(FALSE);
1040 pFrame->GetTopFrame()->Resize();
1046 if( nError )
1047 ErrorHandler::HandleError( nError );
1049 return 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 );
1089 if ( xModel.is() )
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 );
1099 if ( m_pViewSh )
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();
1108 else
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 );
1114 else
1115 m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING );
1118 if ( m_pViewSh )
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 );
1140 else
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 );
1146 else
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;