Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / view / ipclient.cxx
blobd3c5989fac839633166b01aa4fd40da711180a7e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/embed/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/container/XChild.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/beans/PropertyValue.hpp>
32 #include <com/sun/star/embed/XStateChangeListener.hpp>
33 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
34 #include <com/sun/star/embed/XLinkageSupport.hpp>
35 #include <com/sun/star/lang/XInitialization.hpp>
36 #include <com/sun/star/task/StatusIndicatorFactory.hpp>
37 #include <com/sun/star/task/XStatusIndicator.hpp>
39 #include <com/sun/star/embed/EmbedMisc.hpp>
40 #include <svtools/embedhlp.hxx>
41 #include <vcl/svapp.hxx>
43 #include <sfx2/ipclient.hxx>
44 #include <sfx2/viewsh.hxx>
45 #include <sfx2/viewfrm.hxx>
46 #include <sfx2/objsh.hxx>
47 #include <sfx2/dispatch.hxx>
48 #include "workwin.hxx"
49 #include "guisaveas.hxx"
50 #include <cppuhelper/implbase5.hxx>
51 #include <svtools/ehdl.hxx>
53 #include <vcl/timer.hxx>
54 #include <vcl/window.hxx>
55 #include <toolkit/awt/vclxwindow.hxx>
56 #include <toolkit/helper/vclunohelper.hxx>
57 #include <toolkit/helper/convert.hxx>
58 #include <tools/fract.hxx>
59 #include <tools/gen.hxx>
60 #include <svl/rectitem.hxx>
61 #include <svtools/soerr.hxx>
62 #include <comphelper/processfactory.hxx>
64 #define SFX_CLIENTACTIVATE_TIMEOUT 100
66 using namespace com::sun::star;
68 //====================================================================
69 // SfxEmbedResizeGuard
70 class SfxBooleanFlagGuard
72 sal_Bool& m_rFlag;
73 sal_Bool m_bLifeValue;
74 public:
75 SfxBooleanFlagGuard( sal_Bool& bFlag, sal_Bool bLifeValue )
76 : m_rFlag( bFlag )
77 , m_bLifeValue( bLifeValue )
79 m_rFlag = m_bLifeValue;
82 ~SfxBooleanFlagGuard()
84 m_rFlag = !m_bLifeValue;
88 //====================================================================
89 // SfxInPlaceClient_Impl
91 //--------------------------------------------------------------------
92 class SfxInPlaceClient_Impl : public ::cppu::WeakImplHelper5< embed::XEmbeddedClient,
93 embed::XInplaceClient,
94 document::XEventListener,
95 embed::XStateChangeListener,
96 embed::XWindowSupplier >
98 public:
99 Timer m_aTimer; // activation timeout, starts after object connection
100 Rectangle m_aObjArea; // area of object in coordinate system of the container (without scaling)
101 Fraction m_aScaleWidth; // scaling that was applied to the object when it was not active
102 Fraction m_aScaleHeight;
103 SfxInPlaceClient* m_pClient;
104 sal_Int64 m_nAspect; // ViewAspect that is assigned from the container
105 Rectangle m_aLastObjAreaPixel; // area of object in coordinate system of the container (without scaling)
106 sal_Bool m_bStoreObject;
107 sal_Bool m_bUIActive; // set and cleared when notification for UI (de)activation is sent
108 sal_Bool m_bResizeNoScale;
110 uno::Reference < embed::XEmbeddedObject > m_xObject;
111 uno::Reference < embed::XEmbeddedClient > m_xClient;
114 SfxInPlaceClient_Impl()
115 : m_pClient( NULL )
116 , m_nAspect( 0 )
117 , m_bStoreObject( sal_True )
118 , m_bUIActive( sal_False )
119 , m_bResizeNoScale( sal_False )
122 ~SfxInPlaceClient_Impl();
124 void SizeHasChanged();
125 DECL_LINK(TimerHdl, void *);
126 uno::Reference < frame::XFrame > GetFrame() const;
128 // XEmbeddedClient
129 virtual void SAL_CALL saveObject() throw ( embed::ObjectSaveVetoException, uno::Exception, uno::RuntimeException );
130 virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) throw ( embed::WrongStateException, uno::RuntimeException );
132 // XInplaceClient
133 virtual sal_Bool SAL_CALL canInplaceActivate() throw ( uno::RuntimeException );
134 virtual void SAL_CALL activatingInplace() throw ( embed::WrongStateException, uno::RuntimeException );
135 virtual void SAL_CALL activatingUI() throw ( embed::WrongStateException, uno::RuntimeException );
136 virtual void SAL_CALL deactivatedInplace() throw ( embed::WrongStateException, uno::RuntimeException );
137 virtual void SAL_CALL deactivatedUI() throw ( embed::WrongStateException, uno::RuntimeException );
138 virtual uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL getLayoutManager() throw ( embed::WrongStateException, uno::RuntimeException );
139 virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider() throw ( embed::WrongStateException, uno::RuntimeException );
140 virtual awt::Rectangle SAL_CALL getPlacement() throw ( embed::WrongStateException, uno::RuntimeException );
141 virtual awt::Rectangle SAL_CALL getClipRectangle() throw ( embed::WrongStateException, uno::RuntimeException );
142 virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys ) throw ( embed::WrongStateException, uno::RuntimeException );
143 virtual void SAL_CALL scrollObject( const awt::Size& aOffset ) throw ( embed::WrongStateException, uno::RuntimeException );
144 virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect ) throw ( embed::WrongStateException, uno::Exception, uno::RuntimeException );
146 // XComponentSupplier
147 virtual uno::Reference< util::XCloseable > SAL_CALL getComponent() throw ( uno::RuntimeException );
149 // XWindowSupplier
150 virtual uno::Reference< awt::XWindow > SAL_CALL getWindow() throw ( uno::RuntimeException );
152 // document::XEventListener
153 virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException );
155 // XStateChangeListener
156 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);
157 virtual void SAL_CALL stateChanged( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::uno::RuntimeException);
158 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException);
161 SfxInPlaceClient_Impl::~SfxInPlaceClient_Impl()
165 void SAL_CALL SfxInPlaceClient_Impl::changingState(
166 const ::com::sun::star::lang::EventObject& /*aEvent*/,
167 ::sal_Int32 /*nOldState*/,
168 ::sal_Int32 /*nNewState*/ )
169 throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException)
173 void SAL_CALL SfxInPlaceClient_Impl::stateChanged(
174 const ::com::sun::star::lang::EventObject& /*aEvent*/,
175 ::sal_Int32 nOldState,
176 ::sal_Int32 nNewState )
177 throw (::com::sun::star::uno::RuntimeException)
179 if ( m_pClient && nOldState != embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING )
181 // deactivation of object
182 uno::Reference< frame::XModel > xDocument;
183 if ( m_pClient->GetViewShell()->GetObjectShell() )
184 xDocument = m_pClient->GetViewShell()->GetObjectShell()->GetModel();
185 SfxObjectShell::SetCurrentComponent( xDocument );
189 void SAL_CALL SfxInPlaceClient_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException )
191 SolarMutexGuard aGuard;
193 if ( m_pClient && aEvent.EventName == "OnVisAreaChanged" && m_nAspect != embed::Aspects::MSOLE_ICON )
195 m_pClient->FormatChanged(); // for Writer when format of the object is changed with the area
196 m_pClient->ViewChanged();
197 m_pClient->Invalidate();
201 void SAL_CALL SfxInPlaceClient_Impl::disposing( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
202 throw (::com::sun::star::uno::RuntimeException)
204 DELETEZ( m_pClient );
207 // XEmbeddedClient
208 //--------------------------------------------------------------------
209 uno::Reference < frame::XFrame > SfxInPlaceClient_Impl::GetFrame() const
211 if ( !m_pClient )
212 throw uno::RuntimeException();
213 return m_pClient->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
216 void SAL_CALL SfxInPlaceClient_Impl::saveObject()
217 throw ( embed::ObjectSaveVetoException,
218 uno::Exception,
219 uno::RuntimeException )
221 if ( !m_bStoreObject )
222 // client wants to discard the object (usually it means the container document is closed while an object is active
223 // and the user didn't request saving the changes
224 return;
226 // the common persistance is supported by objects and links
227 uno::Reference< embed::XCommonEmbedPersist > xPersist( m_xObject, uno::UNO_QUERY );
228 if ( !xPersist.is() )
229 throw uno::RuntimeException();
231 uno::Reference< frame::XFrame > xFrame;
232 uno::Reference< task::XStatusIndicator > xStatusIndicator;
233 uno::Reference< frame::XModel > xModel( m_xObject->getComponent(), uno::UNO_QUERY );
234 uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
236 if ( xModel.is() )
238 uno::Reference< frame::XController > xController = xModel->getCurrentController();
239 if ( xController.is() )
240 xFrame = xController->getFrame();
243 if ( xFrame.is() )
245 // set non-reschedule progress to prevent problems when asynchronous calls are made
246 // during storing of the embedded object
247 uno::Reference< task::XStatusIndicatorFactory > xStatusIndicatorFactory =
248 task::StatusIndicatorFactory::createWithFrame( xContext, xFrame, sal_True/*DisableReschedule*/, sal_False/*AllowParentShow*/ );
250 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
251 if ( xPropSet.is() )
255 xStatusIndicator = xStatusIndicatorFactory->createStatusIndicator();
256 xPropSet->setPropertyValue( "IndicatorInterception" , uno::makeAny( xStatusIndicator ));
258 catch ( const uno::RuntimeException& )
260 throw;
262 catch ( uno::Exception& )
270 xPersist->storeOwn();
271 m_xObject->update();
273 catch ( uno::Exception& )
275 //TODO/LATER: what should happen if object can't be saved?!
278 // reset status indicator interception after storing
281 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
282 if ( xPropSet.is() )
284 xStatusIndicator.clear();
285 xPropSet->setPropertyValue( "IndicatorInterception" , uno::makeAny( xStatusIndicator ));
288 catch ( const uno::RuntimeException& )
290 throw;
292 catch ( uno::Exception& )
296 // the client can exist only in case there is a view shell
297 if ( !m_pClient || !m_pClient->GetViewShell() )
298 throw uno::RuntimeException();
300 SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell();
301 if ( !pDocShell )
302 throw uno::RuntimeException();
304 pDocShell->SetModified( sal_True );
306 //TODO/LATER: invalidation might be necessary when object was modified, but is not
307 //saved through this method
308 // m_pClient->Invalidate();
311 //--------------------------------------------------------------------
312 void SAL_CALL SfxInPlaceClient_Impl::visibilityChanged( sal_Bool bVisible )
313 throw ( embed::WrongStateException,
314 uno::RuntimeException )
316 SolarMutexGuard aGuard;
318 if ( !m_pClient || !m_pClient->GetViewShell() )
319 throw uno::RuntimeException();
321 m_pClient->GetViewShell()->OutplaceActivated( bVisible, m_pClient );
322 m_pClient->Invalidate();
326 // XInplaceClient
327 //--------------------------------------------------------------------
328 sal_Bool SAL_CALL SfxInPlaceClient_Impl::canInplaceActivate()
329 throw ( uno::RuntimeException )
331 if ( !m_xObject.is() )
332 throw uno::RuntimeException();
334 // we don't want to switch directly from outplace to inplace mode
335 if ( m_xObject->getCurrentState() == embed::EmbedStates::ACTIVE || m_nAspect == embed::Aspects::MSOLE_ICON )
336 return sal_False;
338 return sal_True;
341 //--------------------------------------------------------------------
342 void SAL_CALL SfxInPlaceClient_Impl::activatingInplace()
343 throw ( embed::WrongStateException,
344 uno::RuntimeException )
346 if ( !m_pClient || !m_pClient->GetViewShell() )
347 throw uno::RuntimeException();
349 m_pClient->GetViewShell()->InplaceActivating( m_pClient );
352 //--------------------------------------------------------------------
353 void SAL_CALL SfxInPlaceClient_Impl::activatingUI()
354 throw ( embed::WrongStateException,
355 uno::RuntimeException )
357 if ( !m_pClient || !m_pClient->GetViewShell() )
358 throw uno::RuntimeException();
360 m_pClient->GetViewShell()->ResetAllClients_Impl(m_pClient);
361 m_bUIActive = sal_True;
362 m_pClient->GetViewShell()->UIActivating( m_pClient );
365 //--------------------------------------------------------------------
366 void SAL_CALL SfxInPlaceClient_Impl::deactivatedInplace()
367 throw ( embed::WrongStateException,
368 uno::RuntimeException )
370 if ( !m_pClient || !m_pClient->GetViewShell() )
371 throw uno::RuntimeException();
373 m_pClient->GetViewShell()->InplaceDeactivated( m_pClient );
376 //--------------------------------------------------------------------
377 void SAL_CALL SfxInPlaceClient_Impl::deactivatedUI()
378 throw ( embed::WrongStateException,
379 uno::RuntimeException )
381 if ( !m_pClient || !m_pClient->GetViewShell() )
382 throw uno::RuntimeException();
384 m_pClient->GetViewShell()->UIDeactivated( m_pClient );
385 m_bUIActive = sal_False;
388 //--------------------------------------------------------------------
389 uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL SfxInPlaceClient_Impl::getLayoutManager()
390 throw ( embed::WrongStateException,
391 uno::RuntimeException )
393 uno::Reference < beans::XPropertySet > xFrame( GetFrame(), uno::UNO_QUERY );
394 if ( !xFrame.is() )
395 throw uno::RuntimeException();
397 uno::Reference< ::com::sun::star::frame::XLayoutManager > xMan;
400 uno::Any aAny = xFrame->getPropertyValue( "LayoutManager" );
401 aAny >>= xMan;
403 catch ( uno::Exception& )
405 throw uno::RuntimeException();
408 return xMan;
411 //--------------------------------------------------------------------
412 uno::Reference< frame::XDispatchProvider > SAL_CALL SfxInPlaceClient_Impl::getInplaceDispatchProvider()
413 throw ( embed::WrongStateException,
414 uno::RuntimeException )
416 return uno::Reference < frame::XDispatchProvider >( GetFrame(), uno::UNO_QUERY_THROW );
419 //--------------------------------------------------------------------
420 awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getPlacement()
421 throw ( embed::WrongStateException,
422 uno::RuntimeException )
424 if ( !m_pClient || !m_pClient->GetViewShell() )
425 throw uno::RuntimeException();
427 // apply scaling to object area and convert to pixels
428 Rectangle aRealObjArea( m_aObjArea );
429 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
430 Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
432 aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
433 return AWTRectangle( aRealObjArea );
436 //--------------------------------------------------------------------
437 awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getClipRectangle()
438 throw ( embed::WrongStateException,
439 uno::RuntimeException )
441 if ( !m_pClient || !m_pClient->GetViewShell() )
442 throw uno::RuntimeException();
444 // currently(?) same as placement
445 Rectangle aRealObjArea( m_aObjArea );
446 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
447 Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
449 aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
450 return AWTRectangle( aRealObjArea );
453 //--------------------------------------------------------------------
454 void SAL_CALL SfxInPlaceClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ )
455 throw ( embed::WrongStateException,
456 uno::RuntimeException )
458 if ( !m_pClient || !m_pClient->GetViewShell() )
459 throw uno::RuntimeException();
461 // TODO/MBA: keyboard accelerators
464 //--------------------------------------------------------------------
465 void SAL_CALL SfxInPlaceClient_Impl::scrollObject( const awt::Size& /*aOffset*/ )
466 throw ( embed::WrongStateException,
467 uno::RuntimeException )
469 if ( !m_pClient || !m_pClient->GetViewShell() )
470 throw uno::RuntimeException();
473 //--------------------------------------------------------------------
474 void SAL_CALL SfxInPlaceClient_Impl::changedPlacement( const awt::Rectangle& aPosRect )
475 throw ( embed::WrongStateException,
476 uno::Exception,
477 uno::RuntimeException )
479 uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY );
480 if ( !xInplace.is() || !m_pClient || !m_pClient->GetEditWin() || !m_pClient->GetViewShell() )
481 throw uno::RuntimeException();
483 // check if the change is at least one pixel in size
484 awt::Rectangle aOldRect = getPlacement();
485 Rectangle aNewPixelRect = VCLRectangle( aPosRect );
486 Rectangle aOldPixelRect = VCLRectangle( aOldRect );
487 if ( aOldPixelRect == aNewPixelRect )
488 // nothing has changed
489 return;
491 // new scaled object area
492 Rectangle aNewLogicRect = m_pClient->GetEditWin()->PixelToLogic( aNewPixelRect );
494 // all the size changes in this method should happen without scaling
495 // SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True );
497 // allow container to apply restrictions on the requested new area;
498 // the container might change the object view during size calculation;
499 // currently only writer does it
500 m_pClient->RequestNewObjectArea( aNewLogicRect);
502 if ( aNewLogicRect != m_pClient->GetScaledObjArea() )
504 // the calculation of the object area has not changed the object size
505 // it should be done here then
506 SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True );
508 // new size of the object area without scaling
509 Size aNewObjSize( Fraction( aNewLogicRect.GetWidth() ) / m_aScaleWidth,
510 Fraction( aNewLogicRect.GetHeight() ) / m_aScaleHeight );
512 // now remove scaling from new placement and keep this a the new object area
513 aNewLogicRect.SetSize( aNewObjSize );
514 m_aObjArea = aNewLogicRect;
516 // let the window size be recalculated
517 SizeHasChanged();
520 // notify container view about changes
521 m_pClient->ObjectAreaChanged();
524 // XComponentSupplier
525 //--------------------------------------------------------------------
526 uno::Reference< util::XCloseable > SAL_CALL SfxInPlaceClient_Impl::getComponent()
527 throw ( uno::RuntimeException )
529 if ( !m_pClient || !m_pClient->GetViewShell() )
530 throw uno::RuntimeException();
532 SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell();
533 if ( !pDocShell )
534 throw uno::RuntimeException();
536 // all the components must implement XCloseable
537 uno::Reference< util::XCloseable > xComp( pDocShell->GetModel(), uno::UNO_QUERY );
538 if ( !xComp.is() )
539 throw uno::RuntimeException();
541 return xComp;
545 // XWindowSupplier
546 //--------------------------------------------------------------------
547 uno::Reference< awt::XWindow > SAL_CALL SfxInPlaceClient_Impl::getWindow()
548 throw ( uno::RuntimeException )
550 if ( !m_pClient || !m_pClient->GetEditWin() )
551 throw uno::RuntimeException();
553 uno::Reference< awt::XWindow > xWin( m_pClient->GetEditWin()->GetComponentInterface(), uno::UNO_QUERY );
554 return xWin;
557 //--------------------------------------------------------------------
558 // notification to the client implementation that either the object area or the scaling has been changed
559 // as a result the logical size of the window has changed also
560 void SfxInPlaceClient_Impl::SizeHasChanged()
562 if ( !m_pClient || !m_pClient->GetViewShell() )
563 throw uno::RuntimeException();
565 try {
566 if ( m_xObject.is()
567 && ( m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
568 || m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) )
570 // only possible in active states
571 uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY );
572 if ( !xInplace.is() )
573 throw uno::RuntimeException();
575 if ( m_bResizeNoScale )
577 // the resizing should be done without scaling
578 // set the correct size to the object to avoid the scaling
579 MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_xObject->getMapUnit( m_nAspect ) ) );
580 MapMode aClientMap( m_pClient->GetEditWin()->GetMapMode().GetMapUnit() );
582 // convert to logical coordinates of the embedded object
583 Size aNewSize = m_pClient->GetEditWin()->LogicToLogic( m_aObjArea.GetSize(), &aClientMap, &aObjectMap );
584 m_xObject->setVisualAreaSize( m_nAspect, awt::Size( aNewSize.Width(), aNewSize.Height() ) );
587 xInplace->setObjectRectangles( getPlacement(), getClipRectangle() );
590 catch( uno::Exception& )
592 // TODO/LATER: handle error
596 //--------------------------------------------------------------------
597 IMPL_LINK_NOARG(SfxInPlaceClient_Impl, TimerHdl)
599 if ( m_pClient && m_xObject.is() )
600 m_pClient->GetViewShell()->CheckIPClient_Impl( m_pClient, m_pClient->GetViewShell()->GetObjectShell()->GetVisArea() );
601 return 0;
605 //====================================================================
606 // SfxInPlaceClient
608 //--------------------------------------------------------------------
609 SfxInPlaceClient::SfxInPlaceClient( SfxViewShell* pViewShell, Window *pDraw, sal_Int64 nAspect ) :
610 m_pImp( new SfxInPlaceClient_Impl ),
611 m_pViewSh( pViewShell ),
612 m_pEditWin( pDraw )
614 m_pImp->acquire();
615 m_pImp->m_pClient = this;
616 m_pImp->m_nAspect = nAspect;
617 m_pImp->m_aScaleWidth = m_pImp->m_aScaleHeight = Fraction(1,1);
618 m_pImp->m_xClient = static_cast< embed::XEmbeddedClient* >( m_pImp );
619 pViewShell->NewIPClient_Impl(this);
620 m_pImp->m_aTimer.SetTimeout( SFX_CLIENTACTIVATE_TIMEOUT );
621 m_pImp->m_aTimer.SetTimeoutHdl( LINK( m_pImp, SfxInPlaceClient_Impl, TimerHdl ) );
624 //--------------------------------------------------------------------
626 SfxInPlaceClient::~SfxInPlaceClient()
628 m_pViewSh->IPClientGone_Impl(this);
630 // deleting the client before storing the object means discarding all changes
631 m_pImp->m_bStoreObject = sal_False;
632 SetObject(0);
634 m_pImp->m_pClient = NULL;
636 // the next call will destroy m_pImp if no other reference to it exists
637 m_pImp->m_xClient = uno::Reference < embed::XEmbeddedClient >();
638 m_pImp->release();
640 // TODO/LATER:
641 // the class is not intended to be used in multithreaded environment;
642 // if it will this disconnection and all the parts that use the m_pClient
643 // must be guarded with mutex
646 //--------------------------------------------------------------------
647 void SfxInPlaceClient::SetObjectState( sal_Int32 nState )
649 if ( GetObject().is() )
651 if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON
652 && ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE ) )
654 OSL_FAIL( "Iconified object should not be activated inplace!\n" );
655 return;
660 GetObject()->changeState( nState );
662 catch ( uno::Exception& )
667 //--------------------------------------------------------------------
668 sal_Int64 SfxInPlaceClient::GetObjectMiscStatus() const
670 if ( GetObject().is() )
671 return GetObject()->getStatus( m_pImp->m_nAspect );
672 return 0;
675 //--------------------------------------------------------------------
676 uno::Reference < embed::XEmbeddedObject > SfxInPlaceClient::GetObject() const
678 return m_pImp->m_xObject;
681 //--------------------------------------------------------------------
682 void SfxInPlaceClient::SetObject( const uno::Reference < embed::XEmbeddedObject >& rObject )
684 if ( m_pImp->m_xObject.is() && rObject != m_pImp->m_xObject )
686 DBG_ASSERT( GetObject()->getClientSite() == m_pImp->m_xClient, "Wrong ClientSite!" );
687 if ( GetObject()->getClientSite() == m_pImp->m_xClient )
689 if ( GetObject()->getCurrentState() != embed::EmbedStates::LOADED )
690 SetObjectState( embed::EmbedStates::RUNNING );
691 m_pImp->m_xObject->removeEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
692 m_pImp->m_xObject->removeStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
695 m_pImp->m_xObject->setClientSite( 0 );
697 catch( uno::Exception& )
699 OSL_FAIL( "Can not clean the client site!\n" );
704 if ( !m_pViewSh || m_pViewSh->GetViewFrame()->GetFrame().IsClosing_Impl() )
705 // sometimes applications reconnect clients on shutting down because it happens in their Paint methods
706 return;
708 m_pImp->m_xObject = rObject;
710 if ( rObject.is() )
712 // as soon as an object was connected to a client it has to be checked whether the object wants
713 // to be activated
714 rObject->addStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
715 rObject->addEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
719 rObject->setClientSite( m_pImp->m_xClient );
721 catch( uno::Exception& )
723 OSL_FAIL( "Can not set the client site!\n" );
726 m_pImp->m_aTimer.Start();
728 else
729 m_pImp->m_aTimer.Stop();
732 //--------------------------------------------------------------------
733 sal_Bool SfxInPlaceClient::SetObjArea( const Rectangle& rArea )
735 if( rArea != m_pImp->m_aObjArea )
737 m_pImp->m_aObjArea = rArea;
738 m_pImp->SizeHasChanged();
740 Invalidate();
741 return sal_True;
744 return sal_False;
747 //--------------------------------------------------------------------
748 Rectangle SfxInPlaceClient::GetObjArea() const
750 return m_pImp->m_aObjArea;
753 Rectangle SfxInPlaceClient::GetScaledObjArea() const
755 Rectangle aRealObjArea( m_pImp->m_aObjArea );
756 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth,
757 Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) );
758 return aRealObjArea;
761 //--------------------------------------------------------------------
762 void SfxInPlaceClient::SetSizeScale( const Fraction & rScaleWidth, const Fraction & rScaleHeight )
764 if ( m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight )
766 m_pImp->m_aScaleWidth = rScaleWidth;
767 m_pImp->m_aScaleHeight = rScaleHeight;
769 m_pImp->SizeHasChanged();
771 // TODO/LATER: Invalidate seems to trigger (wrong) recalculations of the ObjArea, so it's better
772 // not to call it here, but maybe it sounds reasonable to do so.
773 //Invalidate();
777 //--------------------------------------------------------------------
778 sal_Bool SfxInPlaceClient::SetObjAreaAndScale( const Rectangle& rArea, const Fraction& rScaleWidth, const Fraction& rScaleHeight )
780 if( rArea != m_pImp->m_aObjArea || m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight )
782 m_pImp->m_aObjArea = rArea;
783 m_pImp->m_aScaleWidth = rScaleWidth;
784 m_pImp->m_aScaleHeight = rScaleHeight;
786 m_pImp->SizeHasChanged();
788 Invalidate();
789 return sal_True;
792 return sal_False;
795 //--------------------------------------------------------------------
796 const Fraction& SfxInPlaceClient::GetScaleWidth() const
798 return m_pImp->m_aScaleWidth;
801 //--------------------------------------------------------------------
802 const Fraction& SfxInPlaceClient::GetScaleHeight() const
804 return m_pImp->m_aScaleHeight;
807 //--------------------------------------------------------------------
808 void SfxInPlaceClient::Invalidate()
810 // TODO/LATER: do we need both?
812 // the object area is provided in logical coordinates of the window but without scaling applied
813 Rectangle aRealObjArea( m_pImp->m_aObjArea );
814 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth,
815 Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) );
816 m_pEditWin->Invalidate( aRealObjArea );
818 ViewChanged();
821 //--------------------------------------------------------------------
822 sal_Bool SfxInPlaceClient::IsObjectUIActive() const
824 try {
825 return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) );
827 catch( uno::Exception& )
830 return sal_False;
833 //--------------------------------------------------------------------
834 sal_Bool SfxInPlaceClient::IsObjectInPlaceActive() const
836 try {
837 return(
839 m_pImp->m_xObject.is() &&
840 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE)
841 ) ||
843 m_pImp->m_xObject.is() &&
844 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE)
848 catch( uno::Exception& )
851 return sal_False;
854 //--------------------------------------------------------------------
855 SfxInPlaceClient* SfxInPlaceClient::GetClient( SfxObjectShell* pDoc, const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& xObject )
857 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDoc); pFrame; pFrame=SfxViewFrame::GetNext(*pFrame,pDoc) )
859 if( pFrame->GetViewShell() )
861 SfxInPlaceClient* pClient = pFrame->GetViewShell()->FindIPClient( xObject, NULL );
862 if ( pClient )
863 return pClient;
867 return NULL;
870 sal_Int64 SfxInPlaceClient::GetAspect() const
872 return m_pImp->m_nAspect;
875 ErrCode SfxInPlaceClient::DoVerb( long nVerb )
877 SfxErrorContext aEc( ERRCTX_SO_DOVERB, m_pViewSh->GetWindow(), RID_SO_ERRCTX );
878 ErrCode nError = ERRCODE_NONE;
880 if ( m_pImp->m_xObject.is() )
882 sal_Bool bSaveCopyAs = sal_False;
883 if ( nVerb == -8 ) // "Save Copy as..."
885 svt::EmbeddedObjectRef::TryRunningState( m_pImp->m_xObject );
886 // TODO/LATER: this special verb should disappear when outplace activation is completely available
887 uno::Reference< frame::XModel > xEmbModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY );
888 if ( xEmbModel.is() )
890 bSaveCopyAs = sal_True;
894 SfxStoringHelper aHelper;
895 uno::Sequence< beans::PropertyValue > aDispatchArgs( 1 );
896 aDispatchArgs[0].Name = "SaveTo";
897 aDispatchArgs[0].Value <<= (sal_Bool)sal_True;
899 aHelper.GUIStoreModel( xEmbModel,
900 "SaveAs",
901 aDispatchArgs,
902 sal_False,
903 "" );
905 catch( const task::ErrorCodeIOException& aErrorEx )
907 nError = (sal_uInt32)aErrorEx.ErrCode;
909 catch( uno::Exception& )
911 nError = ERRCODE_IO_GENERAL;
912 // TODO/LATER: better error handling
917 if ( !bSaveCopyAs )
919 if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON )
921 if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_PRIMARY || nVerb == embed::EmbedVerbs::MS_OLEVERB_SHOW )
922 nVerb = embed::EmbedVerbs::MS_OLEVERB_OPEN; // outplace activation
923 else if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE
924 || nVerb == embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE )
925 nError = ERRCODE_SO_GENERALERROR;
928 if ( !nError )
931 if ( m_pViewSh )
932 m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(sal_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 == 0 || nVerb == embed::EmbedVerbs::MS_OLEVERB_OPEN )
943 // a workaround for the default verb, usually makes sence 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: "
966 << e.Message);
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 if ( m_pViewSh )
986 SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
987 pFrame->GetTopFrame().LockResize_Impl(sal_False);
988 pFrame->GetTopFrame().Resize();
994 if( nError )
995 ErrorHandler::HandleError( nError );
997 return nError;
1000 void SfxInPlaceClient::VisAreaChanged()
1002 uno::Reference < embed::XInplaceObject > xObj( m_pImp->m_xObject, uno::UNO_QUERY );
1003 uno::Reference < embed::XInplaceClient > xClient( m_pImp->m_xClient, uno::UNO_QUERY );
1004 if ( xObj.is() && xClient.is() )
1005 m_pImp->SizeHasChanged();
1008 void SfxInPlaceClient::ObjectAreaChanged()
1010 // dummy implementation
1013 void SfxInPlaceClient::RequestNewObjectArea( Rectangle& )
1015 // dummy implementation
1018 void SfxInPlaceClient::ViewChanged()
1020 // dummy implementation
1023 void SfxInPlaceClient::MakeVisible()
1025 // dummy implementation
1028 void SfxInPlaceClient::FormatChanged()
1030 // dummy implementation
1033 void SfxInPlaceClient::DeactivateObject()
1035 if ( GetObject().is() )
1039 m_pImp->m_bUIActive = sal_False;
1040 sal_Bool bHasFocus = sal_False;
1041 uno::Reference< frame::XModel > xModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY );
1042 if ( xModel.is() )
1044 uno::Reference< frame::XController > xController = xModel->getCurrentController();
1045 if ( xController.is() )
1047 Window* pWindow = VCLUnoHelper::GetWindow( xController->getFrame()->getContainerWindow() );
1048 bHasFocus = pWindow->HasChildPathFocus( sal_True );
1052 if ( m_pViewSh )
1053 m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(sal_True);
1055 if ( m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
1057 m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1058 if ( bHasFocus && m_pViewSh )
1059 m_pViewSh->GetWindow()->GrabFocus();
1061 else
1063 // the links should not stay in running state for long time because of locking
1064 uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY );
1065 if ( xLink.is() && xLink->isLink() )
1066 m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED );
1067 else
1068 m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING );
1071 if ( m_pViewSh )
1073 SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
1074 SfxViewFrame::SetViewFrame( pFrame );
1075 pFrame->GetTopFrame().LockResize_Impl(sal_False);
1076 pFrame->GetTopFrame().Resize();
1079 catch (com::sun::star::uno::Exception& )
1084 void SfxInPlaceClient::ResetObject()
1086 if ( GetObject().is() )
1090 m_pImp->m_bUIActive = sal_False;
1091 if ( m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
1092 m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1093 else
1095 // the links should not stay in running state for long time because of locking
1096 uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY );
1097 if ( xLink.is() && xLink->isLink() )
1098 m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED );
1099 else
1100 m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING );
1103 catch (com::sun::star::uno::Exception& )
1108 sal_Bool SfxInPlaceClient::IsUIActive()
1110 return m_pImp->m_bUIActive;
1113 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */