bump product version to 5.0.4.1
[LibreOffice.git] / sfx2 / source / view / ipclient.cxx
blob5a30bbab54c2e292a42fbe0dd0a66c1598b9755a
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/ErrorCodeIOException.hpp>
37 #include <com/sun/star/task/StatusIndicatorFactory.hpp>
38 #include <com/sun/star/task/XStatusIndicator.hpp>
40 #include <com/sun/star/embed/EmbedMisc.hpp>
41 #include <svtools/embedhlp.hxx>
42 #include <vcl/svapp.hxx>
44 #include <sfx2/ipclient.hxx>
45 #include <sfx2/viewsh.hxx>
46 #include <sfx2/viewfrm.hxx>
47 #include <sfx2/objsh.hxx>
48 #include <sfx2/dispatch.hxx>
49 #include "workwin.hxx"
50 #include "guisaveas.hxx"
51 #include <cppuhelper/implbase5.hxx>
52 #include <svtools/ehdl.hxx>
54 #include <vcl/timer.hxx>
55 #include <vcl/window.hxx>
56 #include <toolkit/awt/vclxwindow.hxx>
57 #include <toolkit/helper/vclunohelper.hxx>
58 #include <toolkit/helper/convert.hxx>
59 #include <tools/fract.hxx>
60 #include <tools/gen.hxx>
61 #include <svl/rectitem.hxx>
62 #include <svtools/soerr.hxx>
63 #include <comphelper/processfactory.hxx>
65 #define SFX_CLIENTACTIVATE_TIMEOUT 100
67 using namespace com::sun::star;
70 // SfxEmbedResizeGuard
71 class SfxBooleanFlagGuard
73 bool& m_rFlag;
74 bool m_bLifeValue;
75 public:
76 SfxBooleanFlagGuard( bool& bFlag, bool bLifeValue )
77 : m_rFlag( bFlag )
78 , m_bLifeValue( bLifeValue )
80 m_rFlag = m_bLifeValue;
83 ~SfxBooleanFlagGuard()
85 m_rFlag = !m_bLifeValue;
90 // SfxInPlaceClient_Impl
93 class SfxInPlaceClient_Impl : public ::cppu::WeakImplHelper5< embed::XEmbeddedClient,
94 embed::XInplaceClient,
95 document::XEventListener,
96 embed::XStateChangeListener,
97 embed::XWindowSupplier >
99 public:
100 Timer m_aTimer; // activation timeout, starts after object connection
101 Rectangle m_aObjArea; // area of object in coordinate system of the container (without scaling)
102 Fraction m_aScaleWidth; // scaling that was applied to the object when it was not active
103 Fraction m_aScaleHeight;
104 SfxInPlaceClient* m_pClient;
105 sal_Int64 m_nAspect; // ViewAspect that is assigned from the container
106 Rectangle m_aLastObjAreaPixel; // area of object in coordinate system of the container (without scaling)
107 bool m_bStoreObject;
108 bool m_bUIActive; // set and cleared when notification for UI (de)activation is sent
109 bool m_bResizeNoScale;
111 uno::Reference < embed::XEmbeddedObject > m_xObject;
112 uno::Reference < embed::XEmbeddedClient > m_xClient;
115 SfxInPlaceClient_Impl()
116 : m_pClient( NULL )
117 , m_nAspect( 0 )
118 , m_bStoreObject( true )
119 , m_bUIActive( false )
120 , m_bResizeNoScale( false )
123 virtual ~SfxInPlaceClient_Impl();
125 void SizeHasChanged();
126 DECL_LINK_TYPED(TimerHdl, Timer *, void);
127 uno::Reference < frame::XFrame > GetFrame() const;
129 // XEmbeddedClient
130 virtual void SAL_CALL saveObject() throw ( embed::ObjectSaveVetoException, uno::Exception, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
131 virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
133 // XInplaceClient
134 virtual sal_Bool SAL_CALL canInplaceActivate() throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
135 virtual void SAL_CALL activatingInplace() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
136 virtual void SAL_CALL activatingUI() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
137 virtual void SAL_CALL deactivatedInplace() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
138 virtual void SAL_CALL deactivatedUI() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
139 virtual uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL getLayoutManager() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
140 virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
141 virtual awt::Rectangle SAL_CALL getPlacement() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
142 virtual awt::Rectangle SAL_CALL getClipRectangle() throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
143 virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys ) throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
144 virtual void SAL_CALL scrollObject( const awt::Size& aOffset ) throw ( embed::WrongStateException, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
145 virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect ) throw ( embed::WrongStateException, uno::Exception, uno::RuntimeException, std::exception ) SAL_OVERRIDE;
147 // XComponentSupplier
148 virtual uno::Reference< util::XCloseable > SAL_CALL getComponent() throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
150 // XWindowSupplier
151 virtual uno::Reference< awt::XWindow > SAL_CALL getWindow() throw ( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
153 // document::XEventListener
154 virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception ) SAL_OVERRIDE;
156 // XStateChangeListener
157 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, std::exception) SAL_OVERRIDE;
158 virtual void SAL_CALL stateChanged( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
159 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
162 SfxInPlaceClient_Impl::~SfxInPlaceClient_Impl()
166 void SAL_CALL SfxInPlaceClient_Impl::changingState(
167 const ::com::sun::star::lang::EventObject& /*aEvent*/,
168 ::sal_Int32 /*nOldState*/,
169 ::sal_Int32 /*nNewState*/ )
170 throw (::com::sun::star::embed::WrongStateException, ::com::sun::star::uno::RuntimeException, std::exception)
174 void SAL_CALL SfxInPlaceClient_Impl::stateChanged(
175 const ::com::sun::star::lang::EventObject& /*aEvent*/,
176 ::sal_Int32 nOldState,
177 ::sal_Int32 nNewState )
178 throw (::com::sun::star::uno::RuntimeException, std::exception)
180 if ( m_pClient && nOldState != embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING )
182 // deactivation of object
183 uno::Reference< frame::XModel > xDocument;
184 if ( m_pClient->GetViewShell()->GetObjectShell() )
185 xDocument = m_pClient->GetViewShell()->GetObjectShell()->GetModel();
186 SfxObjectShell::SetCurrentComponent( xDocument );
190 void SAL_CALL SfxInPlaceClient_Impl::notifyEvent( const document::EventObject& aEvent ) throw( uno::RuntimeException, std::exception )
192 SolarMutexGuard aGuard;
194 if ( m_pClient && aEvent.EventName == "OnVisAreaChanged" && m_nAspect != embed::Aspects::MSOLE_ICON )
196 m_pClient->FormatChanged(); // for Writer when format of the object is changed with the area
197 m_pClient->ViewChanged();
198 m_pClient->Invalidate();
202 void SAL_CALL SfxInPlaceClient_Impl::disposing( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
203 throw (::com::sun::star::uno::RuntimeException, std::exception)
205 DELETEZ( m_pClient );
208 // XEmbeddedClient
210 uno::Reference < frame::XFrame > SfxInPlaceClient_Impl::GetFrame() const
212 if ( !m_pClient )
213 throw uno::RuntimeException();
214 return m_pClient->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
217 void SAL_CALL SfxInPlaceClient_Impl::saveObject()
218 throw ( embed::ObjectSaveVetoException,
219 uno::Exception,
220 uno::RuntimeException, std::exception )
222 if ( !m_bStoreObject )
223 // client wants to discard the object (usually it means the container document is closed while an object is active
224 // and the user didn't request saving the changes
225 return;
227 // the common persistence is supported by objects and links
228 uno::Reference< embed::XCommonEmbedPersist > xPersist( m_xObject, uno::UNO_QUERY );
229 if ( !xPersist.is() )
230 throw uno::RuntimeException();
232 uno::Reference< frame::XFrame > xFrame;
233 uno::Reference< task::XStatusIndicator > xStatusIndicator;
234 uno::Reference< frame::XModel > xModel( m_xObject->getComponent(), uno::UNO_QUERY );
235 uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
237 if ( xModel.is() )
239 uno::Reference< frame::XController > xController = xModel->getCurrentController();
240 if ( xController.is() )
241 xFrame = xController->getFrame();
244 if ( xFrame.is() )
246 // set non-reschedule progress to prevent problems when asynchronous calls are made
247 // during storing of the embedded object
248 uno::Reference< task::XStatusIndicatorFactory > xStatusIndicatorFactory =
249 task::StatusIndicatorFactory::createWithFrame( xContext, xFrame, sal_True/*DisableReschedule*/, sal_False/*AllowParentShow*/ );
251 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
252 if ( xPropSet.is() )
256 xStatusIndicator = xStatusIndicatorFactory->createStatusIndicator();
257 xPropSet->setPropertyValue( "IndicatorInterception" , uno::makeAny( xStatusIndicator ));
259 catch ( const uno::RuntimeException& )
261 throw;
263 catch ( uno::Exception& )
271 xPersist->storeOwn();
272 m_xObject->update();
274 catch ( uno::Exception& )
276 //TODO/LATER: what should happen if object can't be saved?!
279 // reset status indicator interception after storing
282 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
283 if ( xPropSet.is() )
285 xStatusIndicator.clear();
286 xPropSet->setPropertyValue( "IndicatorInterception" , uno::makeAny( xStatusIndicator ));
289 catch ( const uno::RuntimeException& )
291 throw;
293 catch ( uno::Exception& )
297 // the client can exist only in case there is a view shell
298 if ( !m_pClient || !m_pClient->GetViewShell() )
299 throw uno::RuntimeException();
301 SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell();
302 if ( !pDocShell )
303 throw uno::RuntimeException();
305 pDocShell->SetModified( true );
307 //TODO/LATER: invalidation might be necessary when object was modified, but is not
308 //saved through this method
309 // m_pClient->Invalidate();
313 void SAL_CALL SfxInPlaceClient_Impl::visibilityChanged( sal_Bool bVisible )
314 throw ( embed::WrongStateException,
315 uno::RuntimeException, std::exception )
317 SolarMutexGuard aGuard;
319 if ( !m_pClient || !m_pClient->GetViewShell() )
320 throw uno::RuntimeException();
322 m_pClient->GetViewShell()->OutplaceActivated( bVisible, m_pClient );
323 m_pClient->Invalidate();
327 // XInplaceClient
329 sal_Bool SAL_CALL SfxInPlaceClient_Impl::canInplaceActivate()
330 throw ( uno::RuntimeException, std::exception )
332 if ( !m_xObject.is() )
333 throw uno::RuntimeException();
335 // we don't want to switch directly from outplace to inplace mode
336 if ( m_xObject->getCurrentState() == embed::EmbedStates::ACTIVE || m_nAspect == embed::Aspects::MSOLE_ICON )
337 return sal_False;
339 return sal_True;
343 void SAL_CALL SfxInPlaceClient_Impl::activatingInplace()
344 throw ( embed::WrongStateException,
345 uno::RuntimeException, std::exception )
347 if ( !m_pClient || !m_pClient->GetViewShell() )
348 throw uno::RuntimeException();
352 void SAL_CALL SfxInPlaceClient_Impl::activatingUI()
353 throw ( embed::WrongStateException,
354 uno::RuntimeException, std::exception )
356 if ( !m_pClient || !m_pClient->GetViewShell() )
357 throw uno::RuntimeException();
359 m_pClient->GetViewShell()->ResetAllClients_Impl(m_pClient);
360 m_bUIActive = true;
361 m_pClient->GetViewShell()->UIActivating( m_pClient );
365 void SAL_CALL SfxInPlaceClient_Impl::deactivatedInplace()
366 throw ( embed::WrongStateException,
367 uno::RuntimeException, std::exception )
369 if ( !m_pClient || !m_pClient->GetViewShell() )
370 throw uno::RuntimeException();
374 void SAL_CALL SfxInPlaceClient_Impl::deactivatedUI()
375 throw ( embed::WrongStateException,
376 uno::RuntimeException, std::exception )
378 if ( !m_pClient || !m_pClient->GetViewShell() )
379 throw uno::RuntimeException();
381 m_pClient->GetViewShell()->UIDeactivated( m_pClient );
382 m_bUIActive = false;
386 uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL SfxInPlaceClient_Impl::getLayoutManager()
387 throw ( embed::WrongStateException,
388 uno::RuntimeException, std::exception )
390 uno::Reference < beans::XPropertySet > xFrame( GetFrame(), uno::UNO_QUERY );
391 if ( !xFrame.is() )
392 throw uno::RuntimeException();
394 uno::Reference< ::com::sun::star::frame::XLayoutManager > xMan;
397 uno::Any aAny = xFrame->getPropertyValue( "LayoutManager" );
398 aAny >>= xMan;
400 catch ( uno::Exception& )
402 throw uno::RuntimeException();
405 return xMan;
409 uno::Reference< frame::XDispatchProvider > SAL_CALL SfxInPlaceClient_Impl::getInplaceDispatchProvider()
410 throw ( embed::WrongStateException,
411 uno::RuntimeException, std::exception )
413 return uno::Reference < frame::XDispatchProvider >( GetFrame(), uno::UNO_QUERY_THROW );
417 awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getPlacement()
418 throw ( embed::WrongStateException,
419 uno::RuntimeException, std::exception )
421 if ( !m_pClient || !m_pClient->GetViewShell() )
422 throw uno::RuntimeException();
424 // apply scaling to object area and convert to pixels
425 Rectangle aRealObjArea( m_aObjArea );
426 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
427 Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
429 aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
430 return AWTRectangle( aRealObjArea );
434 awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getClipRectangle()
435 throw ( embed::WrongStateException,
436 uno::RuntimeException, std::exception )
438 if ( !m_pClient || !m_pClient->GetViewShell() )
439 throw uno::RuntimeException();
441 // currently(?) same as placement
442 Rectangle aRealObjArea( m_aObjArea );
443 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
444 Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
446 aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
447 return AWTRectangle( aRealObjArea );
451 void SAL_CALL SfxInPlaceClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ )
452 throw ( embed::WrongStateException,
453 uno::RuntimeException, std::exception )
455 if ( !m_pClient || !m_pClient->GetViewShell() )
456 throw uno::RuntimeException();
458 // TODO/MBA: keyboard accelerators
462 void SAL_CALL SfxInPlaceClient_Impl::scrollObject( const awt::Size& /*aOffset*/ )
463 throw ( embed::WrongStateException,
464 uno::RuntimeException, std::exception )
466 if ( !m_pClient || !m_pClient->GetViewShell() )
467 throw uno::RuntimeException();
471 void SAL_CALL SfxInPlaceClient_Impl::changedPlacement( const awt::Rectangle& aPosRect )
472 throw ( embed::WrongStateException,
473 uno::Exception,
474 uno::RuntimeException, std::exception )
476 uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY );
477 if ( !xInplace.is() || !m_pClient || !m_pClient->GetEditWin() || !m_pClient->GetViewShell() )
478 throw uno::RuntimeException();
480 // check if the change is at least one pixel in size
481 awt::Rectangle aOldRect = getPlacement();
482 Rectangle aNewPixelRect = VCLRectangle( aPosRect );
483 Rectangle aOldPixelRect = VCLRectangle( aOldRect );
484 if ( aOldPixelRect == aNewPixelRect )
485 // nothing has changed
486 return;
488 // new scaled object area
489 Rectangle aNewLogicRect = m_pClient->GetEditWin()->PixelToLogic( aNewPixelRect );
491 // all the size changes in this method should happen without scaling
492 // SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True );
494 // allow container to apply restrictions on the requested new area;
495 // the container might change the object view during size calculation;
496 // currently only writer does it
497 m_pClient->RequestNewObjectArea( aNewLogicRect);
499 if ( aNewLogicRect != m_pClient->GetScaledObjArea() )
501 // the calculation of the object area has not changed the object size
502 // it should be done here then
503 SfxBooleanFlagGuard aGuard( m_bResizeNoScale, true );
505 // new size of the object area without scaling
506 Size aNewObjSize( Fraction( aNewLogicRect.GetWidth() ) / m_aScaleWidth,
507 Fraction( aNewLogicRect.GetHeight() ) / m_aScaleHeight );
509 // now remove scaling from new placement and keep this a the new object area
510 aNewLogicRect.SetSize( aNewObjSize );
511 m_aObjArea = aNewLogicRect;
513 // let the window size be recalculated
514 SizeHasChanged();
517 // notify container view about changes
518 m_pClient->ObjectAreaChanged();
521 // XComponentSupplier
523 uno::Reference< util::XCloseable > SAL_CALL SfxInPlaceClient_Impl::getComponent()
524 throw ( uno::RuntimeException, std::exception )
526 if ( !m_pClient || !m_pClient->GetViewShell() )
527 throw uno::RuntimeException();
529 SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell();
530 if ( !pDocShell )
531 throw uno::RuntimeException();
533 // all the components must implement XCloseable
534 uno::Reference< util::XCloseable > xComp( pDocShell->GetModel(), uno::UNO_QUERY );
535 if ( !xComp.is() )
536 throw uno::RuntimeException();
538 return xComp;
542 // XWindowSupplier
544 uno::Reference< awt::XWindow > SAL_CALL SfxInPlaceClient_Impl::getWindow()
545 throw ( uno::RuntimeException, std::exception )
547 if ( !m_pClient || !m_pClient->GetEditWin() )
548 throw uno::RuntimeException();
550 uno::Reference< awt::XWindow > xWin( m_pClient->GetEditWin()->GetComponentInterface(), uno::UNO_QUERY );
551 return xWin;
555 // notification to the client implementation that either the object area or the scaling has been changed
556 // as a result the logical size of the window has changed also
557 void SfxInPlaceClient_Impl::SizeHasChanged()
559 if ( !m_pClient || !m_pClient->GetViewShell() )
560 throw uno::RuntimeException();
562 try {
563 if ( m_xObject.is()
564 && ( m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
565 || m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) )
567 // only possible in active states
568 uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY );
569 if ( !xInplace.is() )
570 throw uno::RuntimeException();
572 if ( m_bResizeNoScale )
574 // the resizing should be done without scaling
575 // set the correct size to the object to avoid the scaling
576 MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_xObject->getMapUnit( m_nAspect ) ) );
577 MapMode aClientMap( m_pClient->GetEditWin()->GetMapMode().GetMapUnit() );
579 // convert to logical coordinates of the embedded object
580 Size aNewSize = m_pClient->GetEditWin()->LogicToLogic( m_aObjArea.GetSize(), &aClientMap, &aObjectMap );
581 m_xObject->setVisualAreaSize( m_nAspect, awt::Size( aNewSize.Width(), aNewSize.Height() ) );
584 xInplace->setObjectRectangles( getPlacement(), getClipRectangle() );
587 catch( uno::Exception& )
589 // TODO/LATER: handle error
594 IMPL_LINK_NOARG_TYPED(SfxInPlaceClient_Impl, TimerHdl, Timer *, void)
596 if ( m_pClient && m_xObject.is() )
597 m_pClient->GetViewShell()->CheckIPClient_Impl( m_pClient, m_pClient->GetViewShell()->GetObjectShell()->GetVisArea() );
602 // SfxInPlaceClient
605 SfxInPlaceClient::SfxInPlaceClient( SfxViewShell* pViewShell, vcl::Window *pDraw, sal_Int64 nAspect ) :
606 m_pImp( new SfxInPlaceClient_Impl ),
607 m_pViewSh( pViewShell ),
608 m_pEditWin( pDraw )
610 m_pImp->acquire();
611 m_pImp->m_pClient = this;
612 m_pImp->m_nAspect = nAspect;
613 m_pImp->m_aScaleWidth = m_pImp->m_aScaleHeight = Fraction(1,1);
614 m_pImp->m_xClient = static_cast< embed::XEmbeddedClient* >( m_pImp );
615 pViewShell->NewIPClient_Impl(this);
616 m_pImp->m_aTimer.SetTimeout( SFX_CLIENTACTIVATE_TIMEOUT );
617 m_pImp->m_aTimer.SetTimeoutHdl( LINK( m_pImp, SfxInPlaceClient_Impl, TimerHdl ) );
622 SfxInPlaceClient::~SfxInPlaceClient()
624 m_pViewSh->IPClientGone_Impl(this);
626 // deleting the client before storing the object means discarding all changes
627 m_pImp->m_bStoreObject = false;
628 SetObject(0);
630 m_pImp->m_pClient = NULL;
632 // the next call will destroy m_pImp if no other reference to it exists
633 m_pImp->m_xClient = uno::Reference < embed::XEmbeddedClient >();
634 m_pImp->release();
636 // TODO/LATER:
637 // the class is not intended to be used in multithreaded environment;
638 // if it will this disconnection and all the parts that use the m_pClient
639 // must be guarded with mutex
643 void SfxInPlaceClient::SetObjectState( sal_Int32 nState )
645 if ( GetObject().is() )
647 if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON
648 && ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE ) )
650 OSL_FAIL( "Iconified object should not be activated inplace!\n" );
651 return;
656 GetObject()->changeState( nState );
658 catch ( uno::Exception& )
664 sal_Int64 SfxInPlaceClient::GetObjectMiscStatus() const
666 if ( GetObject().is() )
667 return GetObject()->getStatus( m_pImp->m_nAspect );
668 return 0;
672 uno::Reference < embed::XEmbeddedObject > SfxInPlaceClient::GetObject() const
674 return m_pImp->m_xObject;
678 void SfxInPlaceClient::SetObject( const uno::Reference < embed::XEmbeddedObject >& rObject )
680 if ( m_pImp->m_xObject.is() && rObject != m_pImp->m_xObject )
682 DBG_ASSERT( GetObject()->getClientSite() == m_pImp->m_xClient, "Wrong ClientSite!" );
683 if ( GetObject()->getClientSite() == m_pImp->m_xClient )
685 if ( GetObject()->getCurrentState() != embed::EmbedStates::LOADED )
686 SetObjectState( embed::EmbedStates::RUNNING );
687 m_pImp->m_xObject->removeEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
688 m_pImp->m_xObject->removeStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
691 m_pImp->m_xObject->setClientSite( 0 );
693 catch( uno::Exception& )
695 OSL_FAIL( "Can not clean the client site!\n" );
700 if ( m_pViewSh->GetViewFrame()->GetFrame().IsClosing_Impl() )
701 // sometimes applications reconnect clients on shutting down because it happens in their Paint methods
702 return;
704 m_pImp->m_xObject = rObject;
706 if ( rObject.is() )
708 // as soon as an object was connected to a client it has to be checked whether the object wants
709 // to be activated
710 rObject->addStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
711 rObject->addEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
715 rObject->setClientSite( m_pImp->m_xClient );
717 catch( uno::Exception& )
719 OSL_FAIL( "Can not set the client site!\n" );
722 m_pImp->m_aTimer.Start();
724 else
725 m_pImp->m_aTimer.Stop();
729 bool SfxInPlaceClient::SetObjArea( const Rectangle& rArea )
731 if( rArea != m_pImp->m_aObjArea )
733 m_pImp->m_aObjArea = rArea;
734 m_pImp->SizeHasChanged();
736 Invalidate();
737 return true;
740 return false;
744 Rectangle SfxInPlaceClient::GetObjArea() const
746 return m_pImp->m_aObjArea;
749 Rectangle SfxInPlaceClient::GetScaledObjArea() const
751 Rectangle aRealObjArea( m_pImp->m_aObjArea );
752 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth,
753 Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) );
754 return aRealObjArea;
758 void SfxInPlaceClient::SetSizeScale( const Fraction & rScaleWidth, const Fraction & rScaleHeight )
760 if ( m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight )
762 m_pImp->m_aScaleWidth = rScaleWidth;
763 m_pImp->m_aScaleHeight = rScaleHeight;
765 m_pImp->SizeHasChanged();
767 // TODO/LATER: Invalidate seems to trigger (wrong) recalculations of the ObjArea, so it's better
768 // not to call it here, but maybe it sounds reasonable to do so.
769 //Invalidate();
774 bool SfxInPlaceClient::SetObjAreaAndScale( const Rectangle& rArea, const Fraction& rScaleWidth, const Fraction& rScaleHeight )
776 if( rArea != m_pImp->m_aObjArea || m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight )
778 m_pImp->m_aObjArea = rArea;
779 m_pImp->m_aScaleWidth = rScaleWidth;
780 m_pImp->m_aScaleHeight = rScaleHeight;
782 m_pImp->SizeHasChanged();
784 Invalidate();
785 return true;
788 return false;
792 const Fraction& SfxInPlaceClient::GetScaleWidth() const
794 return m_pImp->m_aScaleWidth;
798 const Fraction& SfxInPlaceClient::GetScaleHeight() const
800 return m_pImp->m_aScaleHeight;
804 void SfxInPlaceClient::Invalidate()
806 // TODO/LATER: do we need both?
808 // the object area is provided in logical coordinates of the window but without scaling applied
809 Rectangle aRealObjArea( m_pImp->m_aObjArea );
810 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth,
811 Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) );
812 m_pEditWin->Invalidate( aRealObjArea );
814 ViewChanged();
818 bool SfxInPlaceClient::IsObjectUIActive() const
820 try {
821 return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) );
823 catch( uno::Exception& )
826 return false;
830 bool SfxInPlaceClient::IsObjectInPlaceActive() const
832 try {
833 return(
835 m_pImp->m_xObject.is() &&
836 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE)
837 ) ||
839 m_pImp->m_xObject.is() &&
840 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE)
844 catch( uno::Exception& )
847 return false;
851 SfxInPlaceClient* SfxInPlaceClient::GetClient( SfxObjectShell* pDoc, const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& xObject )
853 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDoc); pFrame; pFrame=SfxViewFrame::GetNext(*pFrame,pDoc) )
855 if( pFrame->GetViewShell() )
857 SfxInPlaceClient* pClient = pFrame->GetViewShell()->FindIPClient( xObject, NULL );
858 if ( pClient )
859 return pClient;
863 return NULL;
866 sal_Int64 SfxInPlaceClient::GetAspect() const
868 return m_pImp->m_nAspect;
871 ErrCode SfxInPlaceClient::DoVerb( long nVerb )
873 SfxErrorContext aEc( ERRCTX_SO_DOVERB, m_pViewSh->GetWindow(), RID_SO_ERRCTX );
874 ErrCode nError = ERRCODE_NONE;
876 if ( m_pImp->m_xObject.is() )
878 bool bSaveCopyAs = false;
879 if ( nVerb == -8 ) // "Save Copy as..."
881 svt::EmbeddedObjectRef::TryRunningState( m_pImp->m_xObject );
882 // TODO/LATER: this special verb should disappear when outplace activation is completely available
883 uno::Reference< frame::XModel > xEmbModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY );
884 if ( xEmbModel.is() )
886 bSaveCopyAs = true;
890 SfxStoringHelper aHelper;
891 uno::Sequence< beans::PropertyValue > aDispatchArgs( 1 );
892 aDispatchArgs[0].Name = "SaveTo";
893 aDispatchArgs[0].Value <<= true;
895 aHelper.GUIStoreModel( xEmbModel,
896 "SaveAs",
897 aDispatchArgs,
898 false,
899 "" );
901 catch( const task::ErrorCodeIOException& aErrorEx )
903 nError = (sal_uInt32)aErrorEx.ErrCode;
905 catch( uno::Exception& )
907 nError = ERRCODE_IO_GENERAL;
908 // TODO/LATER: better error handling
913 if ( !bSaveCopyAs )
915 if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON )
917 if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_PRIMARY || nVerb == embed::EmbedVerbs::MS_OLEVERB_SHOW )
918 nVerb = embed::EmbedVerbs::MS_OLEVERB_OPEN; // outplace activation
919 else if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE
920 || nVerb == embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE )
921 nError = ERRCODE_SO_GENERALERROR;
924 if ( !nError )
927 m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(true);
930 m_pImp->m_xObject->setClientSite( m_pImp->m_xClient );
932 m_pImp->m_xObject->doVerb( nVerb );
934 catch ( embed::UnreachableStateException& )
936 if ( nVerb == 0 || nVerb == embed::EmbedVerbs::MS_OLEVERB_OPEN )
938 // a workaround for the default verb, usually makes sense for alien objects
941 m_pImp->m_xObject->doVerb( -9 ); // open own view, a workaround verb that is not visible
943 if ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE )
945 // the object was converted to OOo object
946 awt::Size aSize = m_pImp->m_xObject->getVisualAreaSize( m_pImp->m_nAspect );
947 MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_pImp->m_xObject->getMapUnit( m_pImp->m_nAspect ) ) );
948 MapMode aClientMap( GetEditWin()->GetMapMode().GetMapUnit() );
949 Size aNewSize = GetEditWin()->LogicToLogic( Size( aSize.Width, aSize.Height ), &aObjectMap, &aClientMap );
951 Rectangle aScaledArea = GetScaledObjArea();
952 m_pImp->m_aObjArea.SetSize( aNewSize );
953 m_pImp->m_aScaleWidth = Fraction( aScaledArea.GetWidth(), aNewSize.Width() );
954 m_pImp->m_aScaleHeight = Fraction( aScaledArea.GetHeight(), aNewSize.Height() );
957 catch (uno::Exception const& e)
959 SAL_WARN("embeddedobj", "SfxInPlaceClient::DoVerb:"
960 " -9 fallback path: exception caught: "
961 << e.Message);
962 nError = ERRCODE_SO_GENERALERROR;
966 catch ( embed::StateChangeInProgressException& )
968 // TODO/LATER: it would be nice to be able to provide the current target state outside
969 nError = ERRCODE_SO_CANNOT_DOVERB_NOW;
971 catch (uno::Exception const& e)
973 SAL_WARN("embeddedobj", "SfxInPlaceClient::DoVerb:"
974 " exception caught: " << e.Message);
975 nError = ERRCODE_SO_GENERALERROR;
976 //TODO/LATER: better error handling
979 SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
980 pFrame->GetTopFrame().LockResize_Impl(false);
981 pFrame->GetTopFrame().Resize();
986 if( nError )
987 ErrorHandler::HandleError( nError );
989 return nError;
992 void SfxInPlaceClient::VisAreaChanged()
994 uno::Reference < embed::XInplaceObject > xObj( m_pImp->m_xObject, uno::UNO_QUERY );
995 uno::Reference < embed::XInplaceClient > xClient( m_pImp->m_xClient, uno::UNO_QUERY );
996 if ( xObj.is() && xClient.is() )
997 m_pImp->SizeHasChanged();
1000 void SfxInPlaceClient::ObjectAreaChanged()
1002 // dummy implementation
1005 void SfxInPlaceClient::RequestNewObjectArea( Rectangle& )
1007 // dummy implementation
1010 void SfxInPlaceClient::ViewChanged()
1012 // dummy implementation
1015 void SfxInPlaceClient::MakeVisible()
1017 // dummy implementation
1020 void SfxInPlaceClient::FormatChanged()
1022 // dummy implementation
1025 void SfxInPlaceClient::DeactivateObject()
1027 if ( GetObject().is() )
1031 m_pImp->m_bUIActive = false;
1032 bool bHasFocus = false;
1033 uno::Reference< frame::XModel > xModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY );
1034 if ( xModel.is() )
1036 uno::Reference< frame::XController > xController = xModel->getCurrentController();
1037 if ( xController.is() )
1039 vcl::Window* pWindow = VCLUnoHelper::GetWindow( xController->getFrame()->getContainerWindow() );
1040 bHasFocus = pWindow->HasChildPathFocus( true );
1044 m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(true);
1046 if ( (m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) ||
1047 svt::EmbeddedObjectRef::IsGLChart(m_pImp->m_xObject) )
1049 m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1050 if (bHasFocus)
1051 m_pViewSh->GetWindow()->GrabFocus();
1053 else
1055 // the links should not stay in running state for long time because of locking
1056 uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY );
1057 if ( xLink.is() && xLink->isLink() )
1058 m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED );
1059 else
1060 m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING );
1063 SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
1064 SfxViewFrame::SetViewFrame( pFrame );
1065 pFrame->GetTopFrame().LockResize_Impl(false);
1066 pFrame->GetTopFrame().Resize();
1068 catch (com::sun::star::uno::Exception& )
1073 void SfxInPlaceClient::ResetObject()
1075 if ( GetObject().is() )
1079 m_pImp->m_bUIActive = false;
1080 if ( (m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE) ||
1081 svt::EmbeddedObjectRef::IsGLChart(m_pImp->m_xObject) )
1082 m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1083 else
1085 // the links should not stay in running state for long time because of locking
1086 uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY );
1087 if ( xLink.is() && xLink->isLink() )
1088 m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED );
1089 else
1090 m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING );
1093 catch (com::sun::star::uno::Exception& )
1098 bool SfxInPlaceClient::IsUIActive()
1100 return m_pImp->m_bUIActive;
1103 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */