1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 #include <com/sun/star/embed/EmbedStates.hpp>
27 #include <com/sun/star/embed/XVisualObject.hpp>
28 #include <com/sun/star/embed/XEmbeddedClient.hpp>
29 #include <com/sun/star/embed/XInplaceClient.hpp>
30 #include <com/sun/star/embed/XInplaceObject.hpp>
31 #include <com/sun/star/embed/XComponentSupplier.hpp>
32 #include <com/sun/star/embed/XWindowSupplier.hpp>
33 #include <com/sun/star/embed/XEmbedPersist.hpp>
34 #include <com/sun/star/embed/EmbedVerbs.hpp>
35 #include <com/sun/star/container/XChild.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <com/sun/star/beans/PropertyValue.hpp>
38 #include <com/sun/star/embed/XStateChangeListener.hpp>
39 #include <com/sun/star/embed/StateChangeInProgressException.hpp>
40 #include <com/sun/star/embed/XLinkageSupport.hpp>
41 #include <com/sun/star/lang/XInitialization.hpp>
42 #include <com/sun/star/task/XStatusIndicatorFactory.hpp>
43 #include <com/sun/star/task/XStatusIndicator.hpp>
44
45 #include <com/sun/star/embed/EmbedMisc.hpp>
46 #include <svtools/embedhlp.hxx>
47 #include <vcl/svapp.hxx>
48
49 #include <sfx2/ipclient.hxx>
50 #include <sfx2/viewsh.hxx>
51 #include <sfx2/viewfrm.hxx>
52 #include <sfx2/objsh.hxx>
53 #include <sfx2/dispatch.hxx>
54 #include "workwin.hxx"
55 #include "guisaveas.hxx"
56 #include <sfx2/viewfrm.hxx>
57 #include <cppuhelper/implbase5.hxx>
58 #include <vcl/salbtype.hxx>
59 #include <svtools/ehdl.hxx>
60
61 #include <vcl/timer.hxx>
62 #include <vcl/window.hxx>
63 #include <toolkit/awt/vclxwindow.hxx>
64 #include <toolkit/helper/vclunohelper.hxx>
65 #include <toolkit/helper/convert.hxx>
66 #include <tools/fract.hxx>
67 #include <tools/gen.hxx>
68 #include <svl/rectitem.hxx>
69 #include <svtools/soerr.hxx>
70 #include <comphelper/processfactory.hxx>
71
72 #define SFX_CLIENTACTIVATE_TIMEOUT 100
73
74 using namespace com::sun::star;
75
76 //====================================================================
77 // SfxEmbedResizeGuard
78 class SfxBooleanFlagGuard
79 {
80 sal_Bool& m_rFlag;
81 sal_Bool m_bLifeValue;
82 public:
SfxBooleanFlagGuard(sal_Bool & bFlag,sal_Bool bLifeValue)83 SfxBooleanFlagGuard( sal_Bool& bFlag, sal_Bool bLifeValue )
84 : m_rFlag( bFlag )
85 , m_bLifeValue( bLifeValue )
86 {
87 m_rFlag = m_bLifeValue;
88 }
89
~SfxBooleanFlagGuard()90 ~SfxBooleanFlagGuard()
91 {
92 m_rFlag = !m_bLifeValue;
93 }
94 };
95
96 //====================================================================
97 // SfxInPlaceClient_Impl
98
99 //--------------------------------------------------------------------
100 class SfxInPlaceClient_Impl : public ::cppu::WeakImplHelper5< embed::XEmbeddedClient,
101 embed::XInplaceClient,
102 document::XEventListener,
103 embed::XStateChangeListener,
104 embed::XWindowSupplier >
105 {
106 public:
107 Timer m_aTimer; // activation timeout, starts after object connection
108 Rectangle m_aObjArea; // area of object in coordinate system of the container (without scaling)
109 Fraction m_aScaleWidth; // scaling that was applied to the object when it was not active
110 Fraction m_aScaleHeight;
111 SfxInPlaceClient* m_pClient;
112 sal_Int64 m_nAspect; // ViewAspect that is assigned from the container
113 Rectangle m_aLastObjAreaPixel; // area of object in coordinate system of the container (without scaling)
114 sal_Bool m_bStoreObject;
115 sal_Bool m_bUIActive; // set and cleared when notification for UI (de)activation is sent
116 sal_Bool m_bResizeNoScale;
117
118 uno::Reference < embed::XEmbeddedObject > m_xObject;
119 uno::Reference < embed::XEmbeddedClient > m_xClient;
120
121
SfxInPlaceClient_Impl()122 SfxInPlaceClient_Impl()
123 : m_pClient( NULL )
124 , m_nAspect( 0 )
125 , m_bStoreObject( sal_True )
126 , m_bUIActive( sal_False )
127 , m_bResizeNoScale( sal_False )
128 {}
129
130 ~SfxInPlaceClient_Impl();
131
132 void SizeHasChanged();
133 DECL_LINK (TimerHdl, Timer*);
134 uno::Reference < frame::XFrame > GetFrame() const;
135
136 // XEmbeddedClient
137 virtual void SAL_CALL saveObject();
138 virtual void SAL_CALL visibilityChanged( sal_Bool bVisible );
139
140 // XInplaceClient
141 virtual sal_Bool SAL_CALL canInplaceActivate();
142 virtual void SAL_CALL activatingInplace();
143 virtual void SAL_CALL activatingUI();
144 virtual void SAL_CALL deactivatedInplace();
145 virtual void SAL_CALL deactivatedUI();
146 virtual uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL getLayoutManager();
147 virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider();
148 virtual awt::Rectangle SAL_CALL getPlacement();
149 virtual awt::Rectangle SAL_CALL getClipRectangle();
150 virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys );
151 virtual void SAL_CALL scrollObject( const awt::Size& aOffset );
152 virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect );
153
154 // XComponentSupplier
155 virtual uno::Reference< util::XCloseable > SAL_CALL getComponent();
156
157 // XWindowSupplier
158 virtual uno::Reference< awt::XWindow > SAL_CALL getWindow();
159
160 // document::XEventListener
161 virtual void SAL_CALL notifyEvent( const document::EventObject& aEvent );
162
163 // XStateChangeListener
164 virtual void SAL_CALL changingState( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState );
165 virtual void SAL_CALL stateChanged( const ::com::sun::star::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState );
166 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& aEvent );
167 };
168
~SfxInPlaceClient_Impl()169 SfxInPlaceClient_Impl::~SfxInPlaceClient_Impl()
170 {
171 }
172
changingState(const::com::sun::star::lang::EventObject &,::sal_Int32,::sal_Int32)173 void SAL_CALL SfxInPlaceClient_Impl::changingState(
174 const ::com::sun::star::lang::EventObject& /*aEvent*/,
175 ::sal_Int32 /*nOldState*/,
176 ::sal_Int32 /*nNewState*/ )
177 {
178 }
179
stateChanged(const::com::sun::star::lang::EventObject &,::sal_Int32 nOldState,::sal_Int32 nNewState)180 void SAL_CALL SfxInPlaceClient_Impl::stateChanged(
181 const ::com::sun::star::lang::EventObject& /*aEvent*/,
182 ::sal_Int32 nOldState,
183 ::sal_Int32 nNewState )
184 {
185 if ( m_pClient && nOldState != embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING )
186 {
187 // deactivation of object
188 uno::Reference< frame::XModel > xDocument;
189 if ( m_pClient->GetViewShell()->GetObjectShell() )
190 xDocument = m_pClient->GetViewShell()->GetObjectShell()->GetModel();
191 SfxObjectShell::SetCurrentComponent( xDocument );
192 }
193 else if ( m_pClient && nNewState == embed::EmbedStates::UI_ACTIVE )
194 {
195 /*
196 uno::Reference < lang::XUnoTunnel > xObj( m_xObject->getComponent(), uno::UNO_QUERY );
197 uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
198 sal_Int64 nHandle = xObj.is() ? xObj->getSomething( aSeq ) : 0;
199 if ( nHandle )
200 {
201 // currently needs SFX code
202 SfxObjectShell* pDoc = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
203 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( pDoc );
204 SfxWorkWindow *pWorkWin = pFrame->GetFrame().GetWorkWindow_Impl();
205 pWorkWin->UpdateObjectBars_Impl();
206 }
207 */
208 }
209 }
210
notifyEvent(const document::EventObject & aEvent)211 void SAL_CALL SfxInPlaceClient_Impl::notifyEvent( const document::EventObject& aEvent )
212 {
213 ::vos::OGuard aGuard( Application::GetSolarMutex() );
214
215 if ( m_pClient && aEvent.EventName.equalsAscii("OnVisAreaChanged") && m_nAspect != embed::Aspects::MSOLE_ICON )
216 {
217 m_pClient->FormatChanged(); // for Writer when format of the object is changed with the area
218 m_pClient->ViewChanged();
219 m_pClient->Invalidate();
220 }
221 }
222
disposing(const::com::sun::star::lang::EventObject &)223 void SAL_CALL SfxInPlaceClient_Impl::disposing( const ::com::sun::star::lang::EventObject& /*aEvent*/ )
224 {
225 DELETEZ( m_pClient );
226 }
227
228 // XEmbeddedClient
229 //--------------------------------------------------------------------
GetFrame() const230 uno::Reference < frame::XFrame > SfxInPlaceClient_Impl::GetFrame() const
231 {
232 if ( !m_pClient )
233 throw uno::RuntimeException();
234 return m_pClient->GetViewShell()->GetViewFrame()->GetFrame().GetFrameInterface();
235 }
236
saveObject()237 void SAL_CALL SfxInPlaceClient_Impl::saveObject()
238 {
239 if ( !m_bStoreObject )
240 // client wants to discard the object (usually it means the container document is closed while an object is active
241 // and the user didn't request saving the changes
242 return;
243
244 // the common persistence is supported by objects and links
245 uno::Reference< embed::XCommonEmbedPersist > xPersist( m_xObject, uno::UNO_QUERY );
246 if ( !xPersist.is() )
247 throw uno::RuntimeException();
248
249 uno::Reference< frame::XFrame > xFrame;
250 uno::Reference< task::XStatusIndicator > xStatusIndicator;
251 uno::Reference< frame::XModel > xModel( m_xObject->getComponent(), uno::UNO_QUERY );
252 uno::Reference< lang::XMultiServiceFactory > xSrvMgr( ::comphelper::getProcessServiceFactory() );
253
254 if ( xModel.is() )
255 {
256 uno::Reference< frame::XController > xController = xModel->getCurrentController();
257 if ( xController.is() )
258 xFrame = xController->getFrame();
259 }
260
261 if ( xSrvMgr.is() && xFrame.is() )
262 {
263 // set non-reschedule progress to prevent problems when asynchronous calls are made
264 // during storing of the embedded object
265 uno::Reference< lang::XInitialization > xInit(
266 xSrvMgr->createInstance(
267 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.framework.StatusIndicatorFactory" ))),
268 uno::UNO_QUERY_THROW );
269 beans::PropertyValue aProperty;
270 uno::Sequence< uno::Any > aArgs( 2 );
271 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DisableReschedule" ));
272 aProperty.Value = uno::makeAny( sal_True );
273 aArgs[0] = uno::makeAny( aProperty );
274 aProperty.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Frame" ));
275 aProperty.Value = uno::makeAny( xFrame );
276 aArgs[1] = uno::makeAny( aProperty );
277
278 xInit->initialize( aArgs );
279
280 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
281 if ( xPropSet.is() )
282 {
283 try
284 {
285 uno::Reference< task::XStatusIndicatorFactory > xStatusIndicatorFactory( xInit, uno::UNO_QUERY_THROW );
286 xStatusIndicator = xStatusIndicatorFactory->createStatusIndicator();
287 xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IndicatorInterception" )), uno::makeAny( xStatusIndicator ));
288 }
289 catch ( uno::RuntimeException& e )
290 {
291 throw e;
292 }
293 catch ( uno::Exception& )
294 {
295 }
296 }
297 }
298
299 try
300 {
301 xPersist->storeOwn();
302 m_xObject->update();
303 }
304 catch ( uno::Exception& )
305 {
306 //TODO/LATER: what should happen if object can't be saved?!
307 }
308
309 // reset status indicator interception after storing
310 try
311 {
312 uno::Reference< beans::XPropertySet > xPropSet( xFrame, uno::UNO_QUERY );
313 if ( xPropSet.is() )
314 {
315 xStatusIndicator.clear();
316 xPropSet->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IndicatorInterception" )), uno::makeAny( xStatusIndicator ));
317 }
318 }
319 catch ( uno::RuntimeException& e )
320 {
321 throw e;
322 }
323 catch ( uno::Exception& )
324 {
325 }
326
327 // the client can exist only in case there is a view shell
328 if ( !m_pClient || !m_pClient->GetViewShell() )
329 throw uno::RuntimeException();
330
331 SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell();
332 if ( !pDocShell )
333 throw uno::RuntimeException();
334
335 pDocShell->SetModified( sal_True );
336
337 //TODO/LATER: invalidation might be necessary when object was modified, but is not
338 //saved through this method
339 // m_pClient->Invalidate();
340 }
341
342 //--------------------------------------------------------------------
visibilityChanged(sal_Bool bVisible)343 void SAL_CALL SfxInPlaceClient_Impl::visibilityChanged( sal_Bool bVisible )
344 {
345 ::vos::OGuard aGuard( Application::GetSolarMutex() );
346
347 if ( !m_pClient || !m_pClient->GetViewShell() )
348 throw uno::RuntimeException();
349
350 m_pClient->GetViewShell()->OutplaceActivated( bVisible, m_pClient );
351 m_pClient->Invalidate();
352 }
353
354
355 // XInplaceClient
356 //--------------------------------------------------------------------
canInplaceActivate()357 sal_Bool SAL_CALL SfxInPlaceClient_Impl::canInplaceActivate()
358 {
359 if ( !m_xObject.is() )
360 throw uno::RuntimeException();
361
362 // we don't want to switch directly from outplace to inplace mode
363 if ( m_xObject->getCurrentState() == embed::EmbedStates::ACTIVE || m_nAspect == embed::Aspects::MSOLE_ICON )
364 return sal_False;
365
366 return sal_True;
367 }
368
369 //--------------------------------------------------------------------
activatingInplace()370 void SAL_CALL SfxInPlaceClient_Impl::activatingInplace()
371 {
372 if ( !m_pClient || !m_pClient->GetViewShell() )
373 throw uno::RuntimeException();
374
375 m_pClient->GetViewShell()->InplaceActivating( m_pClient );
376 }
377
378 //--------------------------------------------------------------------
activatingUI()379 void SAL_CALL SfxInPlaceClient_Impl::activatingUI()
380 {
381 if ( !m_pClient || !m_pClient->GetViewShell() )
382 throw uno::RuntimeException();
383
384 m_pClient->GetViewShell()->ResetAllClients_Impl(m_pClient);
385 m_bUIActive = sal_True;
386 m_pClient->GetViewShell()->UIActivating( m_pClient );
387 }
388
389 //--------------------------------------------------------------------
deactivatedInplace()390 void SAL_CALL SfxInPlaceClient_Impl::deactivatedInplace()
391 {
392 if ( !m_pClient || !m_pClient->GetViewShell() )
393 throw uno::RuntimeException();
394
395 m_pClient->GetViewShell()->InplaceDeactivated( m_pClient );
396 }
397
398 //--------------------------------------------------------------------
deactivatedUI()399 void SAL_CALL SfxInPlaceClient_Impl::deactivatedUI()
400 {
401 if ( !m_pClient || !m_pClient->GetViewShell() )
402 throw uno::RuntimeException();
403
404 m_pClient->GetViewShell()->UIDeactivated( m_pClient );
405 m_bUIActive = sal_False;
406 }
407
408 //--------------------------------------------------------------------
getLayoutManager()409 uno::Reference< ::com::sun::star::frame::XLayoutManager > SAL_CALL SfxInPlaceClient_Impl::getLayoutManager()
410 {
411 uno::Reference < beans::XPropertySet > xFrame( GetFrame(), uno::UNO_QUERY );
412 if ( !xFrame.is() )
413 throw uno::RuntimeException();
414
415 uno::Reference< ::com::sun::star::frame::XLayoutManager > xMan;
416 try
417 {
418 uno::Any aAny = xFrame->getPropertyValue( ::rtl::OUString::createFromAscii("LayoutManager") );
419 aAny >>= xMan;
420 }
421 catch ( uno::Exception& )
422 {
423 throw uno::RuntimeException();
424 }
425
426 return xMan;
427 }
428
429 //--------------------------------------------------------------------
getInplaceDispatchProvider()430 uno::Reference< frame::XDispatchProvider > SAL_CALL SfxInPlaceClient_Impl::getInplaceDispatchProvider()
431 {
432 return uno::Reference < frame::XDispatchProvider >( GetFrame(), uno::UNO_QUERY_THROW );
433 }
434
435 //--------------------------------------------------------------------
getPlacement()436 awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getPlacement()
437 {
438 if ( !m_pClient || !m_pClient->GetViewShell() )
439 throw uno::RuntimeException();
440
441 // apply scaling to object area and convert to pixels
442 Rectangle aRealObjArea( m_aObjArea );
443 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
444 Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
445
446 aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
447 return AWTRectangle( aRealObjArea );
448 }
449
450 //--------------------------------------------------------------------
getClipRectangle()451 awt::Rectangle SAL_CALL SfxInPlaceClient_Impl::getClipRectangle()
452 {
453 if ( !m_pClient || !m_pClient->GetViewShell() )
454 throw uno::RuntimeException();
455
456 // currently(?) same as placement
457 Rectangle aRealObjArea( m_aObjArea );
458 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_aScaleWidth,
459 Fraction( aRealObjArea.GetHeight() ) * m_aScaleHeight ) );
460
461 aRealObjArea = m_pClient->GetEditWin()->LogicToPixel( aRealObjArea );
462 return AWTRectangle( aRealObjArea );
463 }
464
465 //--------------------------------------------------------------------
translateAccelerators(const uno::Sequence<awt::KeyEvent> &)466 void SAL_CALL SfxInPlaceClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ )
467 {
468 if ( !m_pClient || !m_pClient->GetViewShell() )
469 throw uno::RuntimeException();
470
471 // TODO/MBA: keyboard accelerators
472 }
473
474 //--------------------------------------------------------------------
scrollObject(const awt::Size &)475 void SAL_CALL SfxInPlaceClient_Impl::scrollObject( const awt::Size& /*aOffset*/ )
476 {
477 if ( !m_pClient || !m_pClient->GetViewShell() )
478 throw uno::RuntimeException();
479 }
480
481 //--------------------------------------------------------------------
changedPlacement(const awt::Rectangle & aPosRect)482 void SAL_CALL SfxInPlaceClient_Impl::changedPlacement( const awt::Rectangle& aPosRect )
483 {
484 uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY );
485 if ( !xInplace.is() || !m_pClient || !m_pClient->GetEditWin() || !m_pClient->GetViewShell() )
486 throw uno::RuntimeException();
487
488 // check if the change is at least one pixel in size
489 awt::Rectangle aOldRect = getPlacement();
490 Rectangle aNewPixelRect = VCLRectangle( aPosRect );
491 Rectangle aOldPixelRect = VCLRectangle( aOldRect );
492 if ( aOldPixelRect == aNewPixelRect )
493 // nothing has changed
494 return;
495
496 // new scaled object area
497 Rectangle aNewLogicRect = m_pClient->GetEditWin()->PixelToLogic( aNewPixelRect );
498
499 // all the size changes in this method should happen without scaling
500 // SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True );
501
502 // allow container to apply restrictions on the requested new area;
503 // the container might change the object view during size calculation;
504 // currently only writer does it
505 m_pClient->RequestNewObjectArea( aNewLogicRect);
506
507 if ( aNewLogicRect != m_pClient->GetScaledObjArea() )
508 {
509 // the calculation of the object area has not changed the object size
510 // it should be done here then
511 SfxBooleanFlagGuard aGuard( m_bResizeNoScale, sal_True );
512
513 // new size of the object area without scaling
514 Size aNewObjSize( Fraction( aNewLogicRect.GetWidth() ) / m_aScaleWidth,
515 Fraction( aNewLogicRect.GetHeight() ) / m_aScaleHeight );
516
517 // now remove scaling from new placement and keep this a the new object area
518 aNewLogicRect.SetSize( aNewObjSize );
519 m_aObjArea = aNewLogicRect;
520
521 // let the window size be recalculated
522 SizeHasChanged();
523 }
524
525 // notify container view about changes
526 m_pClient->ObjectAreaChanged();
527 }
528
529 // XComponentSupplier
530 //--------------------------------------------------------------------
getComponent()531 uno::Reference< util::XCloseable > SAL_CALL SfxInPlaceClient_Impl::getComponent()
532 {
533 if ( !m_pClient || !m_pClient->GetViewShell() )
534 throw uno::RuntimeException();
535
536 SfxObjectShell* pDocShell = m_pClient->GetViewShell()->GetObjectShell();
537 if ( !pDocShell )
538 throw uno::RuntimeException();
539
540 // all the components must implement XCloseable
541 uno::Reference< util::XCloseable > xComp( pDocShell->GetModel(), uno::UNO_QUERY );
542 if ( !xComp.is() )
543 throw uno::RuntimeException();
544
545 return xComp;
546 }
547
548
549 // XWindowSupplier
550 //--------------------------------------------------------------------
getWindow()551 uno::Reference< awt::XWindow > SAL_CALL SfxInPlaceClient_Impl::getWindow()
552 {
553 if ( !m_pClient || !m_pClient->GetEditWin() )
554 throw uno::RuntimeException();
555
556 uno::Reference< awt::XWindow > xWin( m_pClient->GetEditWin()->GetComponentInterface(), uno::UNO_QUERY );
557 return xWin;
558 }
559
560 //--------------------------------------------------------------------
561 // notification to the client implementation that either the object area or the scaling has been changed
562 // as a result the logical size of the window has changed also
SizeHasChanged()563 void SfxInPlaceClient_Impl::SizeHasChanged()
564 {
565 if ( !m_pClient || !m_pClient->GetViewShell() )
566 throw uno::RuntimeException();
567
568 try {
569 if ( m_xObject.is()
570 && ( m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
571 || m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) )
572 {
573 // only possible in active states
574 uno::Reference< embed::XInplaceObject > xInplace( m_xObject, uno::UNO_QUERY );
575 if ( !xInplace.is() )
576 throw uno::RuntimeException();
577
578 if ( m_bResizeNoScale )
579 {
580 // the resizing should be done without scaling
581 // set the correct size to the object to avoid the scaling
582 MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_xObject->getMapUnit( m_nAspect ) ) );
583 MapMode aClientMap( m_pClient->GetEditWin()->GetMapMode().GetMapUnit() );
584
585 // convert to logical coordinates of the embedded object
586 Size aNewSize = m_pClient->GetEditWin()->LogicToLogic( m_aObjArea.GetSize(), &aClientMap, &aObjectMap );
587 m_xObject->setVisualAreaSize( m_nAspect, awt::Size( aNewSize.Width(), aNewSize.Height() ) );
588 }
589
590 xInplace->setObjectRectangles( getPlacement(), getClipRectangle() );
591 }
592 }
593 catch( uno::Exception& )
594 {
595 // TODO/LATER: handle error
596 }
597 }
598
599 //--------------------------------------------------------------------
IMPL_LINK(SfxInPlaceClient_Impl,TimerHdl,Timer *,EMPTYARG)600 IMPL_LINK( SfxInPlaceClient_Impl, TimerHdl, Timer*, EMPTYARG )
601 {
602 if ( m_pClient && m_xObject.is() )
603 m_pClient->GetViewShell()->CheckIPClient_Impl( m_pClient, m_pClient->GetViewShell()->GetObjectShell()->GetVisArea() );
604 return 0;
605 }
606
607
608 //====================================================================
609 // SfxInPlaceClient
610
611 //--------------------------------------------------------------------
SfxInPlaceClient(SfxViewShell * pViewShell,Window * pDraw,sal_Int64 nAspect)612 SfxInPlaceClient::SfxInPlaceClient( SfxViewShell* pViewShell, Window *pDraw, sal_Int64 nAspect ) :
613 m_pImp( new SfxInPlaceClient_Impl ),
614 m_pViewSh( pViewShell ),
615 m_pEditWin( pDraw )
616 {
617 m_pImp->acquire();
618 m_pImp->m_pClient = this;
619 m_pImp->m_nAspect = nAspect;
620 m_pImp->m_aScaleWidth = m_pImp->m_aScaleHeight = Fraction(1,1);
621 m_pImp->m_xClient = static_cast< embed::XEmbeddedClient* >( m_pImp );
622 pViewShell->NewIPClient_Impl(this);
623 m_pImp->m_aTimer.SetTimeout( SFX_CLIENTACTIVATE_TIMEOUT );
624 m_pImp->m_aTimer.SetTimeoutHdl( LINK( m_pImp, SfxInPlaceClient_Impl, TimerHdl ) );
625 }
626
627 //--------------------------------------------------------------------
628
~SfxInPlaceClient()629 SfxInPlaceClient::~SfxInPlaceClient()
630 {
631 m_pViewSh->IPClientGone_Impl(this);
632
633 // deleting the client before storing the object means discarding all changes
634 m_pImp->m_bStoreObject = sal_False;
635 SetObject(0);
636
637 m_pImp->m_pClient = NULL;
638
639 // the next call will destroy m_pImp if no other reference to it exists
640 m_pImp->m_xClient = uno::Reference < embed::XEmbeddedClient >();
641 m_pImp->release();
642
643 // TODO/LATER:
644 // the class is not intended to be used in multithreaded environment;
645 // if it will this disconnection and all the parts that use the m_pClient
646 // must be guarded with mutex
647 }
648
649 //--------------------------------------------------------------------
SetObjectState(sal_Int32 nState)650 void SfxInPlaceClient::SetObjectState( sal_Int32 nState )
651 {
652 if ( GetObject().is() )
653 {
654 if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON
655 && ( nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::INPLACE_ACTIVE ) )
656 {
657 OSL_ENSURE( sal_False, "Iconified object should not be activated inplace!\n" );
658 return;
659 }
660
661 try
662 {
663 GetObject()->changeState( nState );
664 }
665 catch ( uno::Exception& )
666 {}
667 }
668 }
669
670 //--------------------------------------------------------------------
GetObjectMiscStatus() const671 sal_Int64 SfxInPlaceClient::GetObjectMiscStatus() const
672 {
673 if ( GetObject().is() )
674 return GetObject()->getStatus( m_pImp->m_nAspect );
675 return 0;
676 }
677
678 //--------------------------------------------------------------------
GetObject() const679 uno::Reference < embed::XEmbeddedObject > SfxInPlaceClient::GetObject() const
680 {
681 return m_pImp->m_xObject;
682 }
683
684 //--------------------------------------------------------------------
SetObject(const uno::Reference<embed::XEmbeddedObject> & rObject)685 void SfxInPlaceClient::SetObject( const uno::Reference < embed::XEmbeddedObject >& rObject )
686 {
687 if ( m_pImp->m_xObject.is() && rObject != m_pImp->m_xObject )
688 {
689 DBG_ASSERT( GetObject()->getClientSite() == m_pImp->m_xClient, "Wrong ClientSite!" );
690 if ( GetObject()->getClientSite() == m_pImp->m_xClient )
691 {
692 if ( GetObject()->getCurrentState() != embed::EmbedStates::LOADED )
693 SetObjectState( embed::EmbedStates::RUNNING );
694 m_pImp->m_xObject->removeEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
695 m_pImp->m_xObject->removeStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
696 try
697 {
698 m_pImp->m_xObject->setClientSite( 0 );
699 }
700 catch( uno::Exception& )
701 {
702 OSL_ENSURE( sal_False, "Can not clean the client site!\n" );
703 }
704 }
705 }
706
707 if ( !m_pViewSh || m_pViewSh->GetViewFrame()->GetFrame().IsClosing_Impl() )
708 // sometimes applications reconnect clients on shutting down because it happens in their Paint methods
709 return;
710
711 m_pImp->m_xObject = rObject;
712
713 if ( rObject.is() )
714 {
715 // as soon as an object was connected to a client it has to be checked whether the object wants
716 // to be activated
717 rObject->addStateChangeListener( uno::Reference < embed::XStateChangeListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
718 rObject->addEventListener( uno::Reference < document::XEventListener >( m_pImp->m_xClient, uno::UNO_QUERY ) );
719
720 try
721 {
722 rObject->setClientSite( m_pImp->m_xClient );
723 }
724 catch( uno::Exception& )
725 {
726 OSL_ENSURE( sal_False, "Can not set the client site!\n" );
727 }
728
729 m_pImp->m_aTimer.Start();
730 }
731 else
732 m_pImp->m_aTimer.Stop();
733 }
734
735 //--------------------------------------------------------------------
SetObjArea(const Rectangle & rArea)736 sal_Bool SfxInPlaceClient::SetObjArea( const Rectangle& rArea )
737 {
738 if( rArea != m_pImp->m_aObjArea )
739 {
740 m_pImp->m_aObjArea = rArea;
741 m_pImp->SizeHasChanged();
742
743 Invalidate();
744 return sal_True;
745 }
746
747 return sal_False;
748 }
749
750 //--------------------------------------------------------------------
GetObjArea() const751 Rectangle SfxInPlaceClient::GetObjArea() const
752 {
753 return m_pImp->m_aObjArea;
754 }
755
GetScaledObjArea() const756 Rectangle SfxInPlaceClient::GetScaledObjArea() const
757 {
758 Rectangle aRealObjArea( m_pImp->m_aObjArea );
759 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth,
760 Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) );
761 return aRealObjArea;
762 }
763
764 //--------------------------------------------------------------------
SetSizeScale(const Fraction & rScaleWidth,const Fraction & rScaleHeight)765 void SfxInPlaceClient::SetSizeScale( const Fraction & rScaleWidth, const Fraction & rScaleHeight )
766 {
767 if ( m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight )
768 {
769 m_pImp->m_aScaleWidth = rScaleWidth;
770 m_pImp->m_aScaleHeight = rScaleHeight;
771
772 m_pImp->SizeHasChanged();
773
774 // TODO/LATER: Invalidate seems to trigger (wrong) recalculations of the ObjArea, so it's better
775 // not to call it here, but maybe it sounds reasonable to do so.
776 //Invalidate();
777 }
778 }
779
780 //--------------------------------------------------------------------
SetObjAreaAndScale(const Rectangle & rArea,const Fraction & rScaleWidth,const Fraction & rScaleHeight)781 sal_Bool SfxInPlaceClient::SetObjAreaAndScale( const Rectangle& rArea, const Fraction& rScaleWidth, const Fraction& rScaleHeight )
782 {
783 if( rArea != m_pImp->m_aObjArea || m_pImp->m_aScaleWidth != rScaleWidth || m_pImp->m_aScaleHeight != rScaleHeight )
784 {
785 m_pImp->m_aObjArea = rArea;
786 m_pImp->m_aScaleWidth = rScaleWidth;
787 m_pImp->m_aScaleHeight = rScaleHeight;
788
789 m_pImp->SizeHasChanged();
790
791 Invalidate();
792 return sal_True;
793 }
794
795 return sal_False;
796 }
797
798 //--------------------------------------------------------------------
GetScaleWidth() const799 const Fraction& SfxInPlaceClient::GetScaleWidth() const
800 {
801 return m_pImp->m_aScaleWidth;
802 }
803
804 //--------------------------------------------------------------------
GetScaleHeight() const805 const Fraction& SfxInPlaceClient::GetScaleHeight() const
806 {
807 return m_pImp->m_aScaleHeight;
808 }
809
810 //--------------------------------------------------------------------
Invalidate()811 void SfxInPlaceClient::Invalidate()
812 {
813 // TODO/LATER: do we need both?
814
815 // the object area is provided in logical coordinates of the window but without scaling applied
816 Rectangle aRealObjArea( m_pImp->m_aObjArea );
817 aRealObjArea.SetSize( Size( Fraction( aRealObjArea.GetWidth() ) * m_pImp->m_aScaleWidth,
818 Fraction( aRealObjArea.GetHeight() ) * m_pImp->m_aScaleHeight ) );
819 m_pEditWin->Invalidate( aRealObjArea );
820
821 ViewChanged();
822 }
823
824 //--------------------------------------------------------------------
IsObjectUIActive() const825 sal_Bool SfxInPlaceClient::IsObjectUIActive() const
826 {
827 try {
828 return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE ) );
829 }
830 catch( uno::Exception& )
831 {}
832
833 return sal_False;
834 }
835
836 //--------------------------------------------------------------------
IsObjectInPlaceActive() const837 sal_Bool SfxInPlaceClient::IsObjectInPlaceActive() const
838 {
839 try {
840 return(
841 (
842 m_pImp->m_xObject.is() &&
843 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE)
844 ) ||
845 (
846 m_pImp->m_xObject.is() &&
847 (m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE)
848 )
849 );
850 }
851 catch( uno::Exception& )
852 {}
853
854 return sal_False;
855 }
856
857 //--------------------------------------------------------------------
IsObjectActive() const858 sal_Bool SfxInPlaceClient::IsObjectActive() const
859 {
860 try {
861 return ( m_pImp->m_xObject.is() && ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::ACTIVE ) );
862 }
863 catch( uno::Exception& )
864 {}
865
866 return sal_False;
867 }
868
869 //--------------------------------------------------------------------
GetActiveWindow(SfxObjectShell * pDoc,const com::sun::star::uno::Reference<com::sun::star::embed::XEmbeddedObject> & xObject)870 Window* SfxInPlaceClient::GetActiveWindow( SfxObjectShell* pDoc, const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& xObject )
871 {
872 SfxInPlaceClient* pClient = GetClient( pDoc, xObject );
873 if ( pClient )
874 return pClient->GetEditWin();
875 return NULL;
876 }
877
878 //--------------------------------------------------------------------
GetClient(SfxObjectShell * pDoc,const com::sun::star::uno::Reference<com::sun::star::embed::XEmbeddedObject> & xObject)879 SfxInPlaceClient* SfxInPlaceClient::GetClient( SfxObjectShell* pDoc, const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject >& xObject )
880 {
881 for ( SfxViewFrame* pFrame = SfxViewFrame::GetFirst(pDoc); pFrame; pFrame=SfxViewFrame::GetNext(*pFrame,pDoc) )
882 {
883 if( pFrame->GetViewShell() )
884 {
885 SfxInPlaceClient* pClient = pFrame->GetViewShell()->FindIPClient( xObject, NULL );
886 if ( pClient )
887 return pClient;
888 }
889 }
890
891 return NULL;
892 }
893
GetAspect() const894 sal_Int64 SfxInPlaceClient::GetAspect() const
895 {
896 return m_pImp->m_nAspect;
897 }
898
DoVerb(long nVerb)899 ErrCode SfxInPlaceClient::DoVerb( long nVerb )
900 {
901 SfxErrorContext aEc( ERRCTX_SO_DOVERB, m_pViewSh->GetWindow(), RID_SO_ERRCTX );
902 ErrCode nError = ERRCODE_NONE;
903
904 if ( m_pImp->m_xObject.is() )
905 {
906 sal_Bool bSaveCopyAs = sal_False;
907 if ( nVerb == -8 ) // "Save Copy as..."
908 {
909 svt::EmbeddedObjectRef::TryRunningState( m_pImp->m_xObject );
910 // TODO/LATER: this special verb should disappear when outplace activation is completely available
911 uno::Reference< frame::XModel > xEmbModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY );
912 if ( xEmbModel.is() )
913 {
914 bSaveCopyAs = sal_True;
915
916 try
917 {
918 uno::Reference< lang::XMultiServiceFactory > xEmptyFactory;
919 SfxStoringHelper aHelper( xEmptyFactory );
920 uno::Sequence< beans::PropertyValue > aDispatchArgs( 1 );
921 aDispatchArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SaveTo" ) );
922 aDispatchArgs[0].Value <<= (sal_Bool)sal_True;
923
924 aHelper.GUIStoreModel( xEmbModel,
925 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SaveAs" ) ),
926 aDispatchArgs,
927 sal_False,
928 ::rtl::OUString() );
929 }
930 catch( task::ErrorCodeIOException& aErrorEx )
931 {
932 nError = (sal_uInt32)aErrorEx.ErrCode;
933 }
934 catch( uno::Exception& )
935 {
936 nError = ERRCODE_IO_GENERAL;
937 // TODO/LATER: better error handling
938 }
939 }
940 }
941
942 if ( !bSaveCopyAs )
943 {
944 if ( m_pImp->m_nAspect == embed::Aspects::MSOLE_ICON )
945 {
946 if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_PRIMARY || nVerb == embed::EmbedVerbs::MS_OLEVERB_SHOW )
947 nVerb = embed::EmbedVerbs::MS_OLEVERB_OPEN; // outplace activation
948 else if ( nVerb == embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE
949 || nVerb == embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE )
950 nError = ERRCODE_SO_GENERALERROR;
951 }
952
953 if ( !nError )
954 {
955
956 if ( m_pViewSh )
957 m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(sal_True);
958 try
959 {
960 m_pImp->m_xObject->setClientSite( m_pImp->m_xClient );
961
962 m_pImp->m_xObject->doVerb( nVerb );
963 }
964 catch ( embed::UnreachableStateException& )
965 {
966 if ( nVerb == 0 || nVerb == embed::EmbedVerbs::MS_OLEVERB_OPEN )
967 {
968 // a workaround for the default verb, usually makes sense for alien objects
969 try
970 {
971 m_pImp->m_xObject->doVerb( -9 ); // open own view, a workaround verb that is not visible
972
973 if ( m_pImp->m_xObject->getCurrentState() == embed::EmbedStates::UI_ACTIVE )
974 {
975 // the object was converted to OOo object
976 awt::Size aSize = m_pImp->m_xObject->getVisualAreaSize( m_pImp->m_nAspect );
977 MapMode aObjectMap( VCLUnoHelper::UnoEmbed2VCLMapUnit( m_pImp->m_xObject->getMapUnit( m_pImp->m_nAspect ) ) );
978 MapMode aClientMap( GetEditWin()->GetMapMode().GetMapUnit() );
979 Size aNewSize = GetEditWin()->LogicToLogic( Size( aSize.Width, aSize.Height ), &aObjectMap, &aClientMap );
980
981 Rectangle aScaledArea = GetScaledObjArea();
982 m_pImp->m_aObjArea.SetSize( aNewSize );
983 m_pImp->m_aScaleWidth = Fraction( aScaledArea.GetWidth(), aNewSize.Width() );
984 m_pImp->m_aScaleHeight = Fraction( aScaledArea.GetHeight(), aNewSize.Height() );
985 }
986 }
987 catch ( uno::Exception& )
988 {
989 nError = ERRCODE_SO_GENERALERROR;
990 }
991 }
992 }
993 catch ( embed::StateChangeInProgressException& )
994 {
995 // TODO/LATER: it would be nice to be able to provide the current target state outside
996 nError = ERRCODE_SO_CANNOT_DOVERB_NOW;
997 }
998 catch ( uno::Exception& )
999 {
1000 nError = ERRCODE_SO_GENERALERROR;
1001 //TODO/LATER: better error handling
1002 }
1003
1004 if ( m_pViewSh )
1005 {
1006 SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
1007 pFrame->GetTopFrame().LockResize_Impl(sal_False);
1008 pFrame->GetTopFrame().Resize();
1009 }
1010 }
1011 }
1012 }
1013
1014 if( nError )
1015 ErrorHandler::HandleError( nError );
1016
1017 return nError;
1018 }
1019
VisAreaChanged()1020 void SfxInPlaceClient::VisAreaChanged()
1021 {
1022 uno::Reference < embed::XInplaceObject > xObj( m_pImp->m_xObject, uno::UNO_QUERY );
1023 uno::Reference < embed::XInplaceClient > xClient( m_pImp->m_xClient, uno::UNO_QUERY );
1024 if ( xObj.is() && xClient.is() )
1025 m_pImp->SizeHasChanged();
1026 }
1027
ObjectAreaChanged()1028 void SfxInPlaceClient::ObjectAreaChanged()
1029 {
1030 // dummy implementation
1031 }
1032
RequestNewObjectArea(Rectangle &)1033 void SfxInPlaceClient::RequestNewObjectArea( Rectangle& )
1034 {
1035 // dummy implementation
1036 }
1037
ViewChanged()1038 void SfxInPlaceClient::ViewChanged()
1039 {
1040 // dummy implementation
1041 }
1042
MakeVisible()1043 void SfxInPlaceClient::MakeVisible()
1044 {
1045 // dummy implementation
1046 }
1047
FormatChanged()1048 void SfxInPlaceClient::FormatChanged()
1049 {
1050 // dummy implementation
1051 }
1052
DeactivateObject()1053 void SfxInPlaceClient::DeactivateObject()
1054 {
1055 if ( GetObject().is() )
1056 {
1057 try
1058 {
1059 m_pImp->m_bUIActive = sal_False;
1060 sal_Bool bHasFocus = sal_False;
1061 uno::Reference< frame::XModel > xModel( m_pImp->m_xObject->getComponent(), uno::UNO_QUERY );
1062 if ( xModel.is() )
1063 {
1064 uno::Reference< frame::XController > xController = xModel->getCurrentController();
1065 if ( xController.is() )
1066 {
1067 Window* pWindow = VCLUnoHelper::GetWindow( xController->getFrame()->getContainerWindow() );
1068 bHasFocus = pWindow->HasChildPathFocus( sal_True );
1069 }
1070 }
1071
1072 if ( m_pViewSh )
1073 m_pViewSh->GetViewFrame()->GetTopFrame().LockResize_Impl(sal_True);
1074
1075 if ( m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
1076 {
1077 m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1078 if ( bHasFocus && m_pViewSh )
1079 m_pViewSh->GetWindow()->GrabFocus();
1080 }
1081 else
1082 {
1083 // the links should not stay in running state for long time because of locking
1084 uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY );
1085 if ( xLink.is() && xLink->isLink() )
1086 m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED );
1087 else
1088 m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING );
1089 }
1090
1091 if ( m_pViewSh )
1092 {
1093 SfxViewFrame* pFrame = m_pViewSh->GetViewFrame();
1094 SfxViewFrame::SetViewFrame( pFrame );
1095 pFrame->GetTopFrame().LockResize_Impl(sal_False);
1096 pFrame->GetTopFrame().Resize();
1097 }
1098 }
1099 catch (com::sun::star::uno::Exception& )
1100 {}
1101 }
1102 }
1103
ResetObject()1104 void SfxInPlaceClient::ResetObject()
1105 {
1106 if ( GetObject().is() )
1107 {
1108 try
1109 {
1110 m_pImp->m_bUIActive = sal_False;
1111 if ( m_pImp->m_xObject->getStatus( m_pImp->m_nAspect ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
1112 m_pImp->m_xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
1113 else
1114 {
1115 // the links should not stay in running state for long time because of locking
1116 uno::Reference< embed::XLinkageSupport > xLink( m_pImp->m_xObject, uno::UNO_QUERY );
1117 if ( xLink.is() && xLink->isLink() )
1118 m_pImp->m_xObject->changeState( embed::EmbedStates::LOADED );
1119 else
1120 m_pImp->m_xObject->changeState( embed::EmbedStates::RUNNING );
1121 }
1122 }
1123 catch (com::sun::star::uno::Exception& )
1124 {}
1125 }
1126 }
1127
IsUIActive()1128 sal_Bool SfxInPlaceClient::IsUIActive()
1129 {
1130 return m_pImp->m_bUIActive;
1131 }
1132