xref: /core/svx/source/svdraw/svdoole2.cxx (revision bc91cc47)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <svx/svdoole2.hxx>
21 
22 #include <com/sun/star/beans/XPropertySet.hpp>
23 #include <com/sun/star/util/XModifyBroadcaster.hpp>
24 #include <com/sun/star/util/XModifiable.hpp>
25 #include <com/sun/star/embed/EmbedStates.hpp>
26 #include <com/sun/star/embed/EmbedMisc.hpp>
27 #include <com/sun/star/embed/Aspects.hpp>
28 #include <com/sun/star/embed/ObjectSaveVetoException.hpp>
29 #include <com/sun/star/embed/XEmbeddedObject.hpp>
30 #include <com/sun/star/embed/XEmbedPersist2.hpp>
31 #include <com/sun/star/embed/XInplaceClient.hpp>
32 #include <com/sun/star/embed/XInplaceObject.hpp>
33 #include <com/sun/star/embed/XLinkageSupport.hpp>
34 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
35 #include <com/sun/star/embed/XWindowSupplier.hpp>
36 #include <com/sun/star/document/XEventListener.hpp>
37 #include <com/sun/star/container/XChild.hpp>
38 #include <com/sun/star/document/XStorageBasedDocument.hpp>
39 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
40 
41 #include <cppuhelper/exc_hlp.hxx>
42 
43 #include <toolkit/helper/vclunohelper.hxx>
44 #include <toolkit/helper/convert.hxx>
45 
46 #include <svtools/colorcfg.hxx>
47 #include <svtools/embedhlp.hxx>
48 
49 #include <sfx2/objsh.hxx>
50 #include <sfx2/ipclient.hxx>
51 #include <sfx2/lnkbase.hxx>
52 #include <sfx2/linkmgr.hxx>
53 #include <tools/debug.hxx>
54 #include <tools/globname.hxx>
55 #include <comphelper/diagnose_ex.hxx>
56 #include <comphelper/classids.hxx>
57 #include <comphelper/propertyvalue.hxx>
58 
59 #include <sot/formats.hxx>
60 #include <cppuhelper/implbase.hxx>
61 
62 #include <vcl/svapp.hxx>
63 
64 #include <svx/svdmodel.hxx>
65 #include <svx/dialmgr.hxx>
66 #include <svx/strings.hrc>
67 #include <svx/svdetc.hxx>
68 #include <unomlstr.hxx>
69 #include <sdr/contact/viewcontactofsdrole2obj.hxx>
70 #include <svx/svdograf.hxx>
71 #include <sdr/properties/oleproperties.hxx>
72 #include <svx/unoshape.hxx>
73 #include <svx/xlineit0.hxx>
74 #include <svx/xlnclit.hxx>
75 #include <svx/xbtmpit.hxx>
76 #include <svx/xfillit0.hxx>
77 #include <svx/xflbmtit.hxx>
78 #include <svx/xflbstit.hxx>
79 #include <basegfx/matrix/b2dhommatrix.hxx>
80 #include <basegfx/polygon/b2dpolypolygon.hxx>
81 #include <editeng/outlobj.hxx>
82 #include <svx/svdpage.hxx>
83 #include <rtl/ustrbuf.hxx>
84 #include <rtl/ref.hxx>
85 #include <bitmaps.hlst>
86 
87 using namespace ::com::sun::star;
88 
lcl_getFrame_throw(const SdrOle2Obj * _pObject)89 static uno::Reference < beans::XPropertySet > lcl_getFrame_throw(const SdrOle2Obj* _pObject)
90 {
91     uno::Reference < beans::XPropertySet > xFrame;
92     if ( _pObject )
93     {
94         uno::Reference< frame::XController> xController = _pObject->GetParentXModel()->getCurrentController();
95         if ( xController.is() )
96         {
97             xFrame.set( xController->getFrame(),uno::UNO_QUERY_THROW);
98         }
99     } // if ( _pObject )
100     return xFrame;
101 }
102 
103 namespace {
104 
105 class SdrLightEmbeddedClient_Impl : public ::cppu::WeakImplHelper
106                                                             < embed::XStateChangeListener
107                                                             , document::XEventListener
108                                                             , embed::XInplaceClient
109                                                             , embed::XEmbeddedClient
110                                                             , embed::XWindowSupplier
111                                                             >
112 {
113     uno::Reference< awt::XWindow > m_xWindow;
114     SdrOle2Obj* mpObj;
115 
116     Fraction m_aScaleWidth;
117     Fraction m_aScaleHeight;
118 
119 
120 public:
121     explicit SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj );
122     virtual ~SdrLightEmbeddedClient_Impl() override;
123 
SetSizeScale(const Fraction & aScaleWidth,const Fraction & aScaleHeight)124     void SetSizeScale( const Fraction& aScaleWidth, const Fraction& aScaleHeight )
125     {
126         m_aScaleWidth = aScaleWidth;
127         m_aScaleHeight = aScaleHeight;
128     }
129 
GetScaleWidth() const130     const Fraction& GetScaleWidth() const { return m_aScaleWidth; }
GetScaleHeight() const131     const Fraction& GetScaleHeight() const { return m_aScaleHeight; }
132 
133     void setWindow(const uno::Reference< awt::XWindow >& _xWindow);
134 
135     void disconnect();
136 private:
137 
138     tools::Rectangle impl_getScaledRect_nothrow() const;
139     // XStateChangeListener
140     virtual void SAL_CALL changingState( const css::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
141     virtual void SAL_CALL stateChanged( const css::lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) override;
142     virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override;
143 
144     // document::XEventListener
145     virtual void SAL_CALL       notifyEvent( const document::EventObject& aEvent ) override;
146 
147     // XEmbeddedClient
148     virtual void SAL_CALL saveObject() override;
149     virtual void SAL_CALL visibilityChanged( sal_Bool bVisible ) override;
150 
151     // XComponentSupplier
152     virtual uno::Reference< util::XCloseable > SAL_CALL getComponent() override;
153 
154     // XInplaceClient
155     virtual sal_Bool SAL_CALL canInplaceActivate() override;
156     virtual void SAL_CALL activatingInplace() override;
157     virtual void SAL_CALL activatingUI() override;
158     virtual void SAL_CALL deactivatedInplace() override;
159     virtual void SAL_CALL deactivatedUI() override;
160     virtual uno::Reference< css::frame::XLayoutManager > SAL_CALL getLayoutManager() override;
161     virtual uno::Reference< frame::XDispatchProvider > SAL_CALL getInplaceDispatchProvider() override;
162     virtual awt::Rectangle SAL_CALL getPlacement() override;
163     virtual awt::Rectangle SAL_CALL getClipRectangle() override;
164     virtual void SAL_CALL translateAccelerators( const uno::Sequence< awt::KeyEvent >& aKeys ) override;
165     virtual void SAL_CALL scrollObject( const awt::Size& aOffset ) override;
166     virtual void SAL_CALL changedPlacement( const awt::Rectangle& aPosRect ) override;
167 
168     // XWindowSupplier
169     virtual uno::Reference< awt::XWindow > SAL_CALL getWindow() override;
170 };
171 
172 }
173 
SdrLightEmbeddedClient_Impl(SdrOle2Obj * pObj)174 SdrLightEmbeddedClient_Impl::SdrLightEmbeddedClient_Impl( SdrOle2Obj* pObj )
175 : mpObj( pObj )
176 {
177 }
~SdrLightEmbeddedClient_Impl()178 SdrLightEmbeddedClient_Impl::~SdrLightEmbeddedClient_Impl()
179 {
180     assert(!mpObj);
181 }
impl_getScaledRect_nothrow() const182 tools::Rectangle SdrLightEmbeddedClient_Impl::impl_getScaledRect_nothrow() const
183 {
184     tools::Rectangle aLogicRect( mpObj->GetLogicRect() );
185     // apply scaling to object area and convert to pixels
186     aLogicRect.SetSize( Size( tools::Long( aLogicRect.GetWidth() * m_aScaleWidth),
187                               tools::Long( aLogicRect.GetHeight() * m_aScaleHeight) ) );
188     return aLogicRect;
189 }
190 
changingState(const css::lang::EventObject &,::sal_Int32,::sal_Int32)191 void SAL_CALL SdrLightEmbeddedClient_Impl::changingState( const css::lang::EventObject& /*aEvent*/, ::sal_Int32 /*nOldState*/, ::sal_Int32 /*nNewState*/ )
192 {
193 }
194 
stateChanged(const css::lang::EventObject &,::sal_Int32 nOldState,::sal_Int32 nNewState)195 void SAL_CALL SdrLightEmbeddedClient_Impl::stateChanged( const css::lang::EventObject& /*aEvent*/, ::sal_Int32 nOldState, ::sal_Int32 nNewState )
196 {
197     SolarMutexGuard aGuard;
198 
199     if ( mpObj && nOldState == embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING )
200     {
201         mpObj->ObjectLoaded();
202         GetSdrGlobalData().GetOLEObjCache().InsertObj(mpObj);
203     }
204     else if ( mpObj && nNewState == embed::EmbedStates::LOADED && nOldState == embed::EmbedStates::RUNNING )
205     {
206         GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj);
207     }
208 }
209 
disconnect()210 void SdrLightEmbeddedClient_Impl::disconnect()
211 {
212     SolarMutexGuard aGuard;
213     if (!mpObj)
214         return;
215     GetSdrGlobalData().GetOLEObjCache().RemoveObj(mpObj);
216     mpObj = nullptr;
217 }
218 
disposing(const css::lang::EventObject &)219 void SAL_CALL SdrLightEmbeddedClient_Impl::disposing( const css::lang::EventObject& /*aEvent*/ )
220 {
221     disconnect();
222 }
223 
notifyEvent(const document::EventObject & aEvent)224 void SAL_CALL SdrLightEmbeddedClient_Impl::notifyEvent( const document::EventObject& aEvent )
225 {
226     // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
227 
228     SolarMutexGuard aGuard;
229 
230     // the code currently makes sense only in case there is no other client
231     if ( !(mpObj && mpObj->GetAspect() != embed::Aspects::MSOLE_ICON && aEvent.EventName == "OnVisAreaChanged"
232       && mpObj->GetObjRef().is() && mpObj->GetObjRef()->getClientSite() == uno::Reference< embed::XEmbeddedClient >( this )) )
233         return;
234 
235     try
236     {
237         MapUnit aContainerMapUnit( MapUnit::Map100thMM );
238         uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY );
239         if ( xParentVis.is() )
240             aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) );
241 
242         MapUnit aObjMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpObj->GetObjRef()->getMapUnit( mpObj->GetAspect() ) );
243 
244         tools::Rectangle          aVisArea;
245         awt::Size aSz;
246         try
247         {
248             aSz = mpObj->GetObjRef()->getVisualAreaSize( mpObj->GetAspect() );
249         }
250         catch( embed::NoVisualAreaSizeException& )
251         {
252             TOOLS_WARN_EXCEPTION("svx.svdraw", "No visual area size!");
253             aSz.Width = 5000;
254             aSz.Height = 5000;
255         }
256         catch( uno::Exception& )
257         {
258             TOOLS_WARN_EXCEPTION("svx.svdraw", "");
259             aSz.Width = 5000;
260             aSz.Height = 5000;
261         }
262 
263         aVisArea.SetSize( Size( aSz.Width, aSz.Height ) );
264         aVisArea = OutputDevice::LogicToLogic(aVisArea, MapMode(aObjMapUnit), MapMode(aContainerMapUnit));
265         Size aScaledSize( static_cast< tools::Long >( m_aScaleWidth * Fraction( aVisArea.GetWidth() ) ),
266                             static_cast< tools::Long >( m_aScaleHeight * Fraction( aVisArea.GetHeight() ) ) );
267         tools::Rectangle aLogicRect( mpObj->GetLogicRect() );
268 
269         // react to the change if the difference is bigger than one pixel
270         Size aPixelDiff =
271             Application::GetDefaultDevice()->LogicToPixel(
272                 Size( aLogicRect.GetWidth() - aScaledSize.Width(),
273                       aLogicRect.GetHeight() - aScaledSize.Height() ),
274                 MapMode(aContainerMapUnit));
275         if( aPixelDiff.Width() || aPixelDiff.Height() )
276         {
277             mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aScaledSize ) );
278             mpObj->BroadcastObjectChange();
279         }
280         else
281             mpObj->ActionChanged();
282     }
283     catch( uno::Exception& )
284     {
285         TOOLS_WARN_EXCEPTION("svx.svdraw", "");
286     }
287 }
288 
saveObject()289 void SAL_CALL SdrLightEmbeddedClient_Impl::saveObject()
290 {
291     // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
292     uno::Reference< embed::XCommonEmbedPersist > xPersist;
293     uno::Reference< util::XModifiable > xModifiable;
294 
295     {
296         SolarMutexGuard aGuard;
297 
298         if ( !mpObj )
299             throw embed::ObjectSaveVetoException();
300 
301         // the common persistence is supported by objects and links
302         xPersist.set( mpObj->GetObjRef(), uno::UNO_QUERY_THROW );
303         xModifiable.set( mpObj->GetParentXModel(), uno::UNO_QUERY );
304     }
305 
306     xPersist->storeOwn();
307 
308     if ( xModifiable.is() )
309         xModifiable->setModified( true );
310 }
311 
visibilityChanged(sal_Bool)312 void SAL_CALL SdrLightEmbeddedClient_Impl::visibilityChanged( sal_Bool /*bVisible*/ )
313 {
314     // nothing to do currently
315     // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
316     if ( mpObj )
317     {
318         tools::Rectangle aLogicRect( mpObj->GetLogicRect() );
319         Size aLogicSize( aLogicRect.GetWidth(), aLogicRect.GetHeight() );
320 
321         if( mpObj->IsChart() )
322         {
323             //charts never should be stretched see #i84323# for example
324             mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aLogicSize ) );
325             mpObj->BroadcastObjectChange();
326         } // if( mpObj->IsChart() )
327     }
328 }
329 
getComponent()330 uno::Reference< util::XCloseable > SAL_CALL SdrLightEmbeddedClient_Impl::getComponent()
331 {
332     uno::Reference< util::XCloseable > xResult;
333 
334     SolarMutexGuard aGuard;
335     if ( mpObj )
336         xResult.set( mpObj->GetParentXModel(), uno::UNO_QUERY );
337 
338     return xResult;
339 }
340 // XInplaceClient
341 
canInplaceActivate()342 sal_Bool SAL_CALL SdrLightEmbeddedClient_Impl::canInplaceActivate()
343 {
344     bool bRet = false;
345     SolarMutexGuard aGuard;
346     if ( mpObj )
347     {
348         uno::Reference< embed::XEmbeddedObject > xObject = mpObj->GetObjRef();
349         if ( !xObject.is() )
350             throw uno::RuntimeException();
351         // we don't want to switch directly from outplace to inplace mode
352         bRet = ( xObject->getCurrentState() != embed::EmbedStates::ACTIVE && mpObj->GetAspect() != embed::Aspects::MSOLE_ICON );
353     } // if ( mpObj )
354     return bRet;
355 }
356 
activatingInplace()357 void SAL_CALL SdrLightEmbeddedClient_Impl::activatingInplace()
358 {
359 }
360 
activatingUI()361 void SAL_CALL SdrLightEmbeddedClient_Impl::activatingUI()
362 {
363     SolarMutexGuard aGuard;
364 
365     uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj));
366     uno::Reference < frame::XFrame > xOwnFrame( xFrame,uno::UNO_QUERY);
367     uno::Reference < frame::XFramesSupplier > xParentFrame = xOwnFrame->getCreator();
368     if ( xParentFrame.is() )
369         xParentFrame->setActiveFrame( xOwnFrame );
370 
371     OLEObjCache& rObjCache = GetSdrGlobalData().GetOLEObjCache();
372     const size_t nCount = rObjCache.size();
373     for(sal_Int32 i = nCount-1 ; i >= 0;--i)
374     {
375         SdrOle2Obj* pObj = rObjCache[i];
376         if ( pObj != mpObj )
377         {
378             // only deactivate ole objects which belongs to the same frame
379             if ( xFrame == lcl_getFrame_throw(pObj) )
380             {
381                 const uno::Reference< embed::XEmbeddedObject >& xObject = pObj->GetObjRef();
382                 try
383                 {
384                     if ( xObject->getStatus( pObj->GetAspect() ) & embed::EmbedMisc::MS_EMBED_ACTIVATEWHENVISIBLE )
385                         xObject->changeState( embed::EmbedStates::INPLACE_ACTIVE );
386                     else
387                     {
388                         // the links should not stay in running state for long time because of locking
389                         uno::Reference< embed::XLinkageSupport > xLink( xObject, uno::UNO_QUERY );
390                         if ( xLink.is() && xLink->isLink() )
391                             xObject->changeState( embed::EmbedStates::LOADED );
392                         else
393                             xObject->changeState( embed::EmbedStates::RUNNING );
394                     }
395                 }
396                 catch (css::uno::Exception& )
397                 {}
398             }
399         }
400     } // for(sal_Int32 i = nCount-1 ; i >= 0;--i)
401 }
402 
deactivatedInplace()403 void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedInplace()
404 {
405 }
406 
deactivatedUI()407 void SAL_CALL SdrLightEmbeddedClient_Impl::deactivatedUI()
408 {
409     SolarMutexGuard aGuard;
410     css::uno::Reference< css::frame::XLayoutManager > xLayoutManager(getLayoutManager());
411     if ( xLayoutManager.is() )
412     {
413         static constexpr OUString aMenuBarURL = u"private:resource/menubar/menubar"_ustr;
414         if ( !xLayoutManager->isElementVisible( aMenuBarURL ) )
415             xLayoutManager->createElement( aMenuBarURL );
416     }
417 }
418 
getLayoutManager()419 uno::Reference< css::frame::XLayoutManager > SAL_CALL SdrLightEmbeddedClient_Impl::getLayoutManager()
420 {
421     uno::Reference< css::frame::XLayoutManager > xMan;
422     SolarMutexGuard aGuard;
423     uno::Reference < beans::XPropertySet > xFrame( lcl_getFrame_throw(mpObj));
424     try
425     {
426         xMan.set(xFrame->getPropertyValue(u"LayoutManager"_ustr),uno::UNO_QUERY);
427     }
428     catch ( uno::Exception& ex )
429     {
430         css::uno::Any anyEx = cppu::getCaughtException();
431         throw css::lang::WrappedTargetRuntimeException( ex.Message,
432                         nullptr, anyEx );
433     }
434 
435     return xMan;
436 }
437 
getInplaceDispatchProvider()438 uno::Reference< frame::XDispatchProvider > SAL_CALL SdrLightEmbeddedClient_Impl::getInplaceDispatchProvider()
439 {
440     SolarMutexGuard aGuard;
441     return uno::Reference < frame::XDispatchProvider >( lcl_getFrame_throw(mpObj), uno::UNO_QUERY_THROW );
442 }
443 
getPlacement()444 awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getPlacement()
445 {
446     SolarMutexGuard aGuard;
447     if ( !mpObj )
448         throw uno::RuntimeException();
449 
450     tools::Rectangle aLogicRect = impl_getScaledRect_nothrow();
451     MapUnit aContainerMapUnit( MapUnit::Map100thMM );
452     uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY );
453     if ( xParentVis.is() )
454         aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) );
455 
456     aLogicRect = Application::GetDefaultDevice()->LogicToPixel(aLogicRect, MapMode(aContainerMapUnit));
457     return AWTRectangle( aLogicRect );
458 }
459 
getClipRectangle()460 awt::Rectangle SAL_CALL SdrLightEmbeddedClient_Impl::getClipRectangle()
461 {
462     return getPlacement();
463 }
464 
translateAccelerators(const uno::Sequence<awt::KeyEvent> &)465 void SAL_CALL SdrLightEmbeddedClient_Impl::translateAccelerators( const uno::Sequence< awt::KeyEvent >& /*aKeys*/ )
466 {
467 }
468 
scrollObject(const awt::Size &)469 void SAL_CALL SdrLightEmbeddedClient_Impl::scrollObject( const awt::Size& /*aOffset*/ )
470 {
471 }
472 
changedPlacement(const awt::Rectangle & aPosRect)473 void SAL_CALL SdrLightEmbeddedClient_Impl::changedPlacement( const awt::Rectangle& aPosRect )
474 {
475     SolarMutexGuard aGuard;
476     if ( !mpObj )
477         throw uno::RuntimeException();
478 
479     uno::Reference< embed::XInplaceObject > xInplace( mpObj->GetObjRef(), uno::UNO_QUERY_THROW );
480 
481     // check if the change is at least one pixel in size
482     awt::Rectangle aOldRect = getPlacement();
483     tools::Rectangle aNewPixelRect = VCLRectangle( aPosRect );
484     tools::Rectangle aOldPixelRect = VCLRectangle( aOldRect );
485     if ( aOldPixelRect == aNewPixelRect )
486         // nothing has changed
487         return;
488 
489     // new scaled object area
490     MapUnit aContainerMapUnit( MapUnit::Map100thMM );
491     uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY );
492     if ( xParentVis.is() )
493         aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) );
494 
495     tools::Rectangle aNewLogicRect = Application::GetDefaultDevice()->PixelToLogic(aNewPixelRect, MapMode(aContainerMapUnit));
496     tools::Rectangle aLogicRect = impl_getScaledRect_nothrow();
497 
498     if ( aNewLogicRect == aLogicRect )
499         return;
500 
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 );
504 
505     // new size of the object area without scaling
506     Size aNewObjSize( tools::Long( aNewLogicRect.GetWidth() / m_aScaleWidth ),
507                       tools::Long( aNewLogicRect.GetHeight() / m_aScaleHeight ) );
508 
509     // now remove scaling from new placement and keep this at the new object area
510     aNewLogicRect.SetSize( aNewObjSize );
511     // react to the change if the difference is bigger than one pixel
512     Size aPixelDiff =
513         Application::GetDefaultDevice()->LogicToPixel(
514             Size( aLogicRect.GetWidth() - aNewObjSize.Width(),
515                   aLogicRect.GetHeight() - aNewObjSize.Height() ),
516             MapMode(aContainerMapUnit));
517     if( aPixelDiff.Width() || aPixelDiff.Height() )
518     {
519         mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aNewObjSize ) );
520         mpObj->BroadcastObjectChange();
521     }
522     else
523         mpObj->ActionChanged();
524 }
525 // XWindowSupplier
526 
getWindow()527 uno::Reference< awt::XWindow > SAL_CALL SdrLightEmbeddedClient_Impl::getWindow()
528 {
529     SolarMutexGuard aGuard;
530     uno::Reference< awt::XWindow > xCurrent = m_xWindow;
531     if ( !xCurrent.is() )
532     {
533         if ( !mpObj )
534             throw uno::RuntimeException();
535         uno::Reference< frame::XFrame> xFrame(lcl_getFrame_throw(mpObj),uno::UNO_QUERY_THROW);
536         xCurrent = xFrame->getComponentWindow();
537     } // if ( !xCurrent.is() )
538     return xCurrent;
539 }
setWindow(const uno::Reference<awt::XWindow> & _xWindow)540 void SdrLightEmbeddedClient_Impl::setWindow(const uno::Reference< awt::XWindow >& _xWindow)
541 {
542     m_xWindow = _xWindow;
543 }
544 
SdrEmbedObjectLink(SdrOle2Obj * pObject)545 SdrEmbedObjectLink::SdrEmbedObjectLink(SdrOle2Obj* pObject):
546     ::sfx2::SvBaseLink( ::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB ),
547     pObj(pObject)
548 {
549     SetSynchron( false );
550 }
551 
~SdrEmbedObjectLink()552 SdrEmbedObjectLink::~SdrEmbedObjectLink()
553 {
554 }
555 
DataChanged(const OUString &,const css::uno::Any &)556 ::sfx2::SvBaseLink::UpdateResult SdrEmbedObjectLink::DataChanged(
557     const OUString& /*rMimeType*/, const css::uno::Any & /*rValue*/ )
558 {
559     if ( !pObj->UpdateLinkURL_Impl() )
560     {
561         // the link URL was not changed
562         uno::Reference< embed::XEmbeddedObject > xObject = pObj->GetObjRef();
563         OSL_ENSURE( xObject.is(), "The object must exist always!" );
564         if ( xObject.is() )
565         {
566             // let the object reload the link
567             // TODO/LATER: reload call could be used for this case
568 
569             try
570             {
571                 sal_Int32 nState = xObject->getCurrentState();
572                 if ( nState != embed::EmbedStates::LOADED )
573                 {
574                     // in some cases the linked file probably is not locked so it could be changed
575                     xObject->changeState( embed::EmbedStates::LOADED );
576                     xObject->changeState( nState );
577                 }
578             }
579             catch ( uno::Exception& )
580             {
581             }
582         }
583     }
584 
585     pObj->GetNewReplacement();
586     pObj->SetChanged();
587 
588     return SUCCESS;
589 }
590 
Closed()591 void SdrEmbedObjectLink::Closed()
592 {
593     pObj->BreakFileLink_Impl();
594     SvBaseLink::Closed();
595 }
596 
SdrIFrameLink(SdrOle2Obj * pObject)597 SdrIFrameLink::SdrIFrameLink(SdrOle2Obj* pObject)
598     : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SVXB)
599     , m_pObject(pObject)
600 {
601     SetSynchron( false );
602 }
603 
DataChanged(const OUString &,const uno::Any &)604 ::sfx2::SvBaseLink::UpdateResult SdrIFrameLink::DataChanged(
605     const OUString&, const uno::Any& )
606 {
607     uno::Reference<embed::XEmbeddedObject> xObject = m_pObject->GetObjRef();
608     uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, uno::UNO_QUERY);
609     if (xPersObj.is())
610     {
611         // let the IFrameObject reload the link
612         try
613         {
614             xPersObj->reload(uno::Sequence<beans::PropertyValue>(), uno::Sequence<beans::PropertyValue>());
615         }
616         catch (const uno::Exception&)
617         {
618         }
619 
620         m_pObject->SetChanged();
621     }
622 
623     return SUCCESS;
624 }
625 
626 class SdrOle2ObjImpl
627 {
628 public:
629     svt::EmbeddedObjectRef mxObjRef;
630 
631     std::optional<Graphic> moGraphic;
632     OUString        maProgName;
633     OUString        aPersistName;       // name of object in persist
634     rtl::Reference<SdrLightEmbeddedClient_Impl> mxLightClient; // must be registered as client only using AddOwnLightClient() call
635 
636     bool mbFrame:1; // Due to compatibility at SdrTextObj for now
637     bool mbSuppressSetVisAreaSize:1; // #i118524#
638     mutable bool mbTypeAsked:1;
639     mutable bool mbIsChart:1;
640     bool mbLoadingOLEObjectFailed:1; // New local var to avoid repeated loading if load of OLE2 fails
641     bool mbConnected:1;
642 
643     sfx2::SvBaseLink* mpObjectLink;
644     OUString maLinkURL;
645 
646     rtl::Reference<SvxUnoShapeModifyListener> mxModifyListener;
647 
SdrOle2ObjImpl(bool bFrame)648     explicit SdrOle2ObjImpl( bool bFrame ) :
649         mbFrame(bFrame),
650         mbSuppressSetVisAreaSize(false),
651         mbTypeAsked(false),
652         mbIsChart(false),
653         mbLoadingOLEObjectFailed(false),
654         mbConnected(false),
655         mpObjectLink(nullptr)
656     {
657         mxObjRef.Lock();
658     }
659 
SdrOle2ObjImpl(bool bFrame,const svt::EmbeddedObjectRef & rObjRef)660     SdrOle2ObjImpl( bool bFrame, const svt::EmbeddedObjectRef& rObjRef ) :
661         mxObjRef(rObjRef),
662         mbFrame(bFrame),
663         mbSuppressSetVisAreaSize(false),
664         mbTypeAsked(false),
665         mbIsChart(false),
666         mbLoadingOLEObjectFailed(false),
667         mbConnected(false),
668         mpObjectLink(nullptr)
669     {
670         mxObjRef.Lock();
671     }
672 
~SdrOle2ObjImpl()673     ~SdrOle2ObjImpl()
674     {
675         moGraphic.reset();
676 
677         if (mxModifyListener.is())
678         {
679             mxModifyListener->invalidate();
680         }
681     }
682 };
683 
684 // Predicate determining whether the given OLE is an internal math
685 // object
ImplIsMathObj(const uno::Reference<embed::XEmbeddedObject> & rObjRef)686 static bool ImplIsMathObj( const uno::Reference < embed::XEmbeddedObject >& rObjRef )
687 {
688     if ( !rObjRef.is() )
689         return false;
690 
691     SvGlobalName aClassName( rObjRef->getClassID() );
692     return aClassName == SvGlobalName(SO3_SM_CLASSID_30) ||
693         aClassName == SvGlobalName(SO3_SM_CLASSID_40) ||
694         aClassName == SvGlobalName(SO3_SM_CLASSID_50) ||
695         aClassName == SvGlobalName(SO3_SM_CLASSID_60) ||
696         aClassName == SvGlobalName(SO3_SM_CLASSID);
697 }
698 
699 // BaseProperties section
700 
CreateObjectSpecificProperties()701 std::unique_ptr<sdr::properties::BaseProperties> SdrOle2Obj::CreateObjectSpecificProperties()
702 {
703     return std::make_unique<sdr::properties::OleProperties>(*this);
704 }
705 
706 // DrawContact section
707 
CreateObjectSpecificViewContact()708 std::unique_ptr<sdr::contact::ViewContact> SdrOle2Obj::CreateObjectSpecificViewContact()
709 {
710     return std::make_unique<sdr::contact::ViewContactOfSdrOle2Obj>(*this);
711 }
712 
Init()713 void SdrOle2Obj::Init()
714 {
715     // Stuff that was done from old SetModel:
716     // #i43086# #i85304 redo the change for charts for the above bugfix, as #i43086# does not occur anymore
717     // so maybe the ImpSetVisAreaSize call can be removed here completely
718     // Nevertheless I leave it in for other objects as I am not sure about the side effects when removing now
719     if(!getSdrModelFromSdrObject().isLocked() && !IsChart())
720     {
721         ImpSetVisAreaSize();
722     }
723 
724     ::comphelper::IEmbeddedHelper* pDestPers(getSdrModelFromSdrObject().GetPersist());
725     if(pDestPers && !IsEmptyPresObj())
726     {
727         // object wasn't connected, now it should be
728         Connect_Impl();
729     }
730 
731     AddListeners_Impl();
732 }
733 
SdrOle2Obj(SdrModel & rSdrModel,bool bFrame_)734 SdrOle2Obj::SdrOle2Obj(
735     SdrModel& rSdrModel,
736     bool bFrame_)
737 :   SdrRectObj(rSdrModel),
738     mpImpl(new SdrOle2ObjImpl(bFrame_))
739 {
740     Init();
741 }
742 
SdrOle2Obj(SdrModel & rSdrModel,SdrOle2Obj const & rSource)743 SdrOle2Obj::SdrOle2Obj(SdrModel& rSdrModel, SdrOle2Obj const & rSource)
744 :   SdrRectObj(rSdrModel, rSource),
745     mpImpl(new SdrOle2ObjImpl(/*bFrame*/false))
746 {
747     Init();
748 
749     // Manually copying bClosedObj attribute
750     SetClosedObj( rSource.IsClosedObj() );
751 
752     mpImpl->aPersistName = rSource.mpImpl->aPersistName;
753     mpImpl->maProgName = rSource.mpImpl->maProgName;
754     mpImpl->mbFrame = rSource.mpImpl->mbFrame;
755 
756     if (rSource.mpImpl->moGraphic)
757     {
758         mpImpl->moGraphic.emplace(*rSource.mpImpl->moGraphic);
759     }
760 
761     if( IsEmptyPresObj() )
762         return;
763 
764     ::comphelper::IEmbeddedHelper* pDestPers(getSdrModelFromSdrObject().GetPersist());
765     ::comphelper::IEmbeddedHelper* pSrcPers(rSource.getSdrModelFromSdrObject().GetPersist());
766     if( !(pDestPers && pSrcPers) )
767         return;
768 
769     DBG_ASSERT( !mpImpl->mxObjRef.is(), "Object already existing!" );
770     comphelper::EmbeddedObjectContainer& rContainer = pSrcPers->getEmbeddedObjectContainer();
771     uno::Reference < embed::XEmbeddedObject > xObj = rContainer.GetEmbeddedObject( mpImpl->aPersistName );
772     if ( xObj.is() )
773     {
774         OUString aTmp;
775         mpImpl->mxObjRef.Assign( pDestPers->getEmbeddedObjectContainer().CopyAndGetEmbeddedObject(
776             rContainer, xObj, aTmp, pSrcPers->getDocumentBaseURL(), pDestPers->getDocumentBaseURL()), rSource.GetAspect());
777         mpImpl->mbTypeAsked = false;
778         mpImpl->aPersistName = aTmp;
779         CheckFileLink_Impl();
780     }
781 
782     Connect();
783 }
784 
SdrOle2Obj(SdrModel & rSdrModel,const svt::EmbeddedObjectRef & rNewObjRef,const OUString & rNewObjName,const tools::Rectangle & rNewRect)785 SdrOle2Obj::SdrOle2Obj(
786     SdrModel& rSdrModel,
787     const svt::EmbeddedObjectRef& rNewObjRef,
788     const OUString& rNewObjName,
789     const tools::Rectangle& rNewRect)
790 :   SdrRectObj(rSdrModel, rNewRect),
791     mpImpl(new SdrOle2ObjImpl(false/*bFrame_*/, rNewObjRef))
792 {
793     osl_atomic_increment(&m_refCount);
794 
795     mpImpl->aPersistName = rNewObjName;
796 
797     if (mpImpl->mxObjRef.is() && (mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE ) )
798         m_bSizProt = true;
799 
800     // For math objects, set closed state to transparent
801     SetClosedObj(!ImplIsMathObj( mpImpl->mxObjRef.GetObject() ));
802 
803     Init();
804 
805     osl_atomic_decrement(&m_refCount);
806 }
807 
GetStyleString()808 OUString SdrOle2Obj::GetStyleString()
809 {
810     OUString strStyle;
811     if (mpImpl->mxObjRef.is() && mpImpl->mxObjRef.IsChart())
812     {
813         strStyle = mpImpl->mxObjRef.GetChartType();
814     }
815     return strStyle;
816 }
817 
~SdrOle2Obj()818 SdrOle2Obj::~SdrOle2Obj()
819 {
820     if ( mpImpl->mbConnected )
821         Disconnect();
822 
823     DisconnectFileLink_Impl();
824 
825     if (mpImpl->mxLightClient)
826     {
827         mpImpl->mxLightClient->disconnect();
828         mpImpl->mxLightClient.clear();
829     }
830 }
831 
SetAspect(sal_Int64 nAspect)832 void SdrOle2Obj::SetAspect( sal_Int64 nAspect )
833 {
834     mpImpl->mxObjRef.SetViewAspect( nAspect );
835 }
836 
getEmbeddedObjectRef() const837 const svt::EmbeddedObjectRef& SdrOle2Obj::getEmbeddedObjectRef() const
838 {
839     return mpImpl->mxObjRef;
840 }
841 
GetAspect() const842 sal_Int64 SdrOle2Obj::GetAspect() const
843 {
844     return mpImpl->mxObjRef.GetViewAspect();
845 }
846 
isInplaceActive() const847 bool SdrOle2Obj::isInplaceActive() const
848 {
849     return mpImpl->mxObjRef.is() && embed::EmbedStates::INPLACE_ACTIVE == mpImpl->mxObjRef->getCurrentState();
850 }
851 
isUiActive() const852 bool SdrOle2Obj::isUiActive() const
853 {
854     return mpImpl->mxObjRef.is() && embed::EmbedStates::UI_ACTIVE == mpImpl->mxObjRef->getCurrentState();
855 }
856 
SetGraphic(const Graphic & rGrf)857 void SdrOle2Obj::SetGraphic(const Graphic& rGrf)
858 {
859     // only for setting a preview graphic
860     mpImpl->moGraphic.emplace(rGrf);
861 
862     SetChanged();
863     BroadcastObjectChange();
864 }
865 
ClearGraphic()866 void SdrOle2Obj::ClearGraphic()
867 {
868     mpImpl->moGraphic.reset();
869 
870     SetChanged();
871     BroadcastObjectChange();
872 }
873 
SetProgName(const OUString & rName)874 void SdrOle2Obj::SetProgName( const OUString& rName )
875 {
876     mpImpl->maProgName = rName;
877 }
878 
GetProgName() const879 const OUString& SdrOle2Obj::GetProgName() const
880 {
881     return mpImpl->maProgName;
882 }
883 
IsEmpty() const884 bool SdrOle2Obj::IsEmpty() const
885 {
886     return !mpImpl->mxObjRef.is();
887 }
888 
Connect(SvxOle2Shape * pCreator)889 void SdrOle2Obj::Connect(SvxOle2Shape* pCreator)
890 {
891     if( IsEmptyPresObj() )
892         return;
893 
894     if( mpImpl->mbConnected )
895     {
896         // currently there are situations where it seems to be unavoidable to have multiple connects
897         // changing this would need a larger code rewrite, so for now I remove the assertion
898         // OSL_FAIL("Connect() called on connected object!");
899         return;
900     }
901 
902     Connect_Impl(pCreator);
903     AddListeners_Impl();
904 }
905 
UpdateLinkURL_Impl()906 bool SdrOle2Obj::UpdateLinkURL_Impl()
907 {
908     bool bResult = false;
909 
910     if ( mpImpl->mpObjectLink )
911     {
912         sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
913 
914         if ( pLinkManager )
915         {
916             OUString aNewLinkURL;
917             sfx2::LinkManager::GetDisplayNames( mpImpl->mpObjectLink, nullptr, &aNewLinkURL );
918             if ( !aNewLinkURL.equalsIgnoreAsciiCase( mpImpl->maLinkURL ) )
919             {
920                 GetObjRef_Impl();
921                 uno::Reference<embed::XCommonEmbedPersist> xPersObj( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
922                 OSL_ENSURE( xPersObj.is(), "The object must exist!" );
923                 if ( xPersObj.is() )
924                 {
925                     try
926                     {
927                         sal_Int32 nCurState = mpImpl->mxObjRef->getCurrentState();
928                         if ( nCurState != embed::EmbedStates::LOADED )
929                             mpImpl->mxObjRef->changeState(embed::EmbedStates::LOADED);
930 
931                         // TODO/LATER: there should be possible to get current mediadescriptor settings from the object
932                         uno::Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
933                             u"URL"_ustr, aNewLinkURL) };
934                         xPersObj->reload( aArgs, uno::Sequence< beans::PropertyValue >() );
935 
936                         mpImpl->maLinkURL = aNewLinkURL;
937                         bResult = true;
938 
939                         if ( nCurState != embed::EmbedStates::LOADED )
940                             mpImpl->mxObjRef->changeState(nCurState);
941                     }
942                     catch( css::uno::Exception const & )
943                     {
944                         TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::UpdateLinkURL_Impl()" );
945                     }
946                 }
947 
948                 if ( !bResult )
949                 {
950                     // TODO/LATER: return the old name to the link manager, is it possible?
951                 }
952             }
953         }
954     }
955 
956     return bResult;
957 }
958 
BreakFileLink_Impl()959 void SdrOle2Obj::BreakFileLink_Impl()
960 {
961     uno::Reference<document::XStorageBasedDocument> xDoc(getSdrModelFromSdrObject().getUnoModel(), uno::UNO_QUERY);
962 
963     if ( !xDoc.is() )
964         return;
965 
966     uno::Reference< embed::XStorage > xStorage = xDoc->getDocumentStorage();
967     if ( !xStorage.is() )
968         return;
969 
970     try
971     {
972         uno::Reference< embed::XLinkageSupport > xLinkSupport( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY_THROW );
973         xLinkSupport->breakLink( xStorage, mpImpl->aPersistName );
974         DisconnectFileLink_Impl();
975         mpImpl->maLinkURL.clear();
976     }
977     catch( css::uno::Exception& )
978     {
979         TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::BreakFileLink_Impl()" );
980     }
981 }
982 
DisconnectFileLink_Impl()983 void SdrOle2Obj::DisconnectFileLink_Impl()
984 {
985     sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
986 
987     if ( pLinkManager && mpImpl->mpObjectLink )
988     {
989         pLinkManager->Remove( mpImpl->mpObjectLink );
990         mpImpl->mpObjectLink = nullptr;
991     }
992 }
993 
CheckFileLink_Impl()994 void SdrOle2Obj::CheckFileLink_Impl()
995 {
996     if (!mpImpl->mxObjRef.GetObject().is() || mpImpl->mpObjectLink)
997         return;
998 
999     try
1000     {
1001         uno::Reference<embed::XEmbeddedObject> xObject = mpImpl->mxObjRef.GetObject();
1002         if (!xObject)
1003             return;
1004 
1005         bool bIFrame = false;
1006 
1007         OUString aLinkURL;
1008         uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, uno::UNO_QUERY);
1009         if (xLinkSupport)
1010         {
1011             if (xLinkSupport->isLink())
1012                 aLinkURL = xLinkSupport->getLinkURL();
1013         }
1014         else
1015         {
1016             // get IFrame (Floating Frames) listed and updatable from the
1017             // manage links dialog
1018             SvGlobalName aClassId(xObject->getClassID());
1019             if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID))
1020             {
1021                 uno::Reference<beans::XPropertySet> xSet(xObject->getComponent(), uno::UNO_QUERY);
1022                 if (xSet.is())
1023                     xSet->getPropertyValue(u"FrameURL"_ustr) >>= aLinkURL;
1024                 bIFrame = true;
1025             }
1026         }
1027 
1028         if (!aLinkURL.isEmpty()) // this is a file link so the model link manager should handle it
1029         {
1030             sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
1031 
1032             if ( pLinkManager )
1033             {
1034                 SdrEmbedObjectLink* pEmbedObjectLink = nullptr;
1035                 if (!bIFrame)
1036                 {
1037                     pEmbedObjectLink = new SdrEmbedObjectLink(this);
1038                     mpImpl->mpObjectLink = pEmbedObjectLink;
1039                 }
1040                 else
1041                     mpImpl->mpObjectLink = new SdrIFrameLink(this);
1042                 mpImpl->maLinkURL = aLinkURL;
1043                 pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL );
1044                 if (pEmbedObjectLink)
1045                     pEmbedObjectLink->Connect();
1046             }
1047         }
1048     }
1049     catch (const css::uno::Exception&)
1050     {
1051         TOOLS_WARN_EXCEPTION("svx", "SdrOle2Obj::CheckFileLink_Impl()");
1052     }
1053 }
1054 
Connect_Impl(SvxOle2Shape * pCreator)1055 void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator)
1056 {
1057     if(mpImpl->aPersistName.isEmpty() )
1058         return;
1059 
1060     try
1061     {
1062         ::comphelper::IEmbeddedHelper* pPers(getSdrModelFromSdrObject().GetPersist());
1063 
1064         if ( pPers )
1065         {
1066             comphelper::EmbeddedObjectContainer& rContainer = pPers->getEmbeddedObjectContainer();
1067 
1068             if ( !rContainer.HasEmbeddedObject( mpImpl->aPersistName )
1069               || ( mpImpl->mxObjRef.is() && !rContainer.HasEmbeddedObject( mpImpl->mxObjRef.GetObject() ) ) )
1070             {
1071                 // object not known to container document
1072                 // No object -> disaster!
1073                 DBG_ASSERT( mpImpl->mxObjRef.is(), "No object in connect!");
1074                 if ( mpImpl->mxObjRef.is() )
1075                 {
1076                     // object came from the outside, now add it to the container
1077                     OUString aTmp;
1078                     rContainer.InsertEmbeddedObject( mpImpl->mxObjRef.GetObject(), aTmp );
1079                     mpImpl->aPersistName = aTmp;
1080                 }
1081             }
1082             else if ( !mpImpl->mxObjRef.is() )
1083             {
1084                 mpImpl->mxObjRef.Assign( rContainer.GetEmbeddedObject( mpImpl->aPersistName ), mpImpl->mxObjRef.GetViewAspect() );
1085                 mpImpl->mbTypeAsked = false;
1086             }
1087 
1088             if ( mpImpl->mxObjRef.GetObject().is() )
1089             {
1090                 mpImpl->mxObjRef.AssignToContainer( &rContainer, mpImpl->aPersistName );
1091                 mpImpl->mbConnected = true;
1092                 mpImpl->mxObjRef.Lock();
1093             }
1094         }
1095 
1096         if (pCreator)
1097         {
1098             OUString sFrameURL(pCreator->GetAndClearInitialFrameURL());
1099             if (!sFrameURL.isEmpty() && svt::EmbeddedObjectRef::TryRunningState(mpImpl->mxObjRef.GetObject()))
1100             {
1101                 uno::Reference<beans::XPropertySet> xSet(mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY);
1102                 if (xSet.is())
1103                     xSet->setPropertyValue(u"FrameURL"_ustr, uno::Any(sFrameURL));
1104             }
1105         }
1106 
1107         if ( mpImpl->mxObjRef.is() )
1108         {
1109             if ( !mpImpl->mxLightClient.is() )
1110                 mpImpl->mxLightClient = new SdrLightEmbeddedClient_Impl( this );
1111 
1112             mpImpl->mxObjRef->addStateChangeListener( mpImpl->mxLightClient );
1113             mpImpl->mxObjRef->addEventListener( mpImpl->mxLightClient );
1114 
1115             if ( mpImpl->mxObjRef->getCurrentState() != embed::EmbedStates::LOADED )
1116                 GetSdrGlobalData().GetOLEObjCache().InsertObj(this);
1117 
1118             CheckFileLink_Impl();
1119 
1120             uno::Reference< container::XChild > xChild( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
1121             if( xChild.is() )
1122             {
1123                 uno::Reference< uno::XInterface > xParent( getSdrModelFromSdrObject().getUnoModel());
1124                 if( xParent.is())
1125                     xChild->setParent( getSdrModelFromSdrObject().getUnoModel() );
1126             }
1127 
1128         }
1129     }
1130     catch( css::uno::Exception& )
1131     {
1132         TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::Connect_Impl()" );
1133     }
1134 }
1135 
ObjectLoaded()1136 void SdrOle2Obj::ObjectLoaded()
1137 {
1138     AddListeners_Impl();
1139 }
1140 
AddListeners_Impl()1141 void SdrOle2Obj::AddListeners_Impl()
1142 {
1143     if( !(mpImpl->mxObjRef.is() && mpImpl->mxObjRef->getCurrentState() != embed::EmbedStates::LOADED) )
1144         return;
1145 
1146     // register modify listener
1147     if (!mpImpl->mxModifyListener.is())
1148     {
1149         mpImpl->mxModifyListener = new SvxUnoShapeModifyListener(this);
1150     }
1151 
1152     uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY );
1153     if (xBC.is())
1154     {
1155         xBC->addModifyListener( mpImpl->mxModifyListener );
1156     }
1157 }
1158 
Disconnect()1159 void SdrOle2Obj::Disconnect()
1160 {
1161     if( IsEmptyPresObj() )
1162         return;
1163 
1164     if( !mpImpl->mbConnected )
1165     {
1166         OSL_FAIL("Disconnect() called on disconnected object!");
1167         return;
1168     }
1169 
1170     RemoveListeners_Impl();
1171     Disconnect_Impl();
1172 }
1173 
RemoveListeners_Impl()1174 void SdrOle2Obj::RemoveListeners_Impl()
1175 {
1176     if ( !mpImpl->mxObjRef.is() || mpImpl->aPersistName.isEmpty() )
1177         return;
1178 
1179     try
1180     {
1181         sal_Int32 nState = mpImpl->mxObjRef->getCurrentState();
1182         if ( nState != embed::EmbedStates::LOADED )
1183         {
1184             uno::Reference< util::XModifyBroadcaster > xBC( getXModel(), uno::UNO_QUERY );
1185             if (xBC.is() && mpImpl->mxModifyListener.is())
1186             {
1187                 xBC->removeModifyListener( mpImpl->mxModifyListener );
1188             }
1189         }
1190     }
1191     catch( css::uno::Exception& )
1192     {
1193         TOOLS_WARN_EXCEPTION( "svx",  "SdrOle2Obj::RemoveListeners_Impl()" );
1194     }
1195 }
1196 
Disconnect_Impl()1197 void SdrOle2Obj::Disconnect_Impl()
1198 {
1199     try
1200     {
1201         if ( !mpImpl->aPersistName.isEmpty() )
1202         {
1203             if( getSdrModelFromSdrObject().IsInDestruction() )
1204             {
1205                 // TODO/LATER: here we must assume that the destruction of the model is enough to make clear that we will not
1206                 // remove the object from the container, even if the DrawingObject itself is not destroyed (unfortunately this
1207                 // There is no real need to do the following removing of the object from the container
1208                 // in case the model has correct persistence, but in case of problems such a removing
1209                 // would make the behavior of the office more stable
1210 
1211                 comphelper::EmbeddedObjectContainer* pContainer = mpImpl->mxObjRef.GetContainer();
1212                 if ( pContainer )
1213                 {
1214                     pContainer->CloseEmbeddedObject( mpImpl->mxObjRef.GetObject() );
1215                     mpImpl->mxObjRef.AssignToContainer( nullptr, mpImpl->aPersistName );
1216                 }
1217 
1218                 // happens later than the destruction of the model, so we can't assert that).
1219                 //DBG_ASSERT( bInDestruction, "Model is destroyed, but not me?!" );
1220                 //TODO/LATER: should be make sure that the ObjectShell also forgets the object, because we will close it soon?
1221                 /*
1222                 uno::Reference < util::XCloseable > xClose( xObjRef, uno::UNO_QUERY );
1223                 if ( xClose.is() )
1224                 {
1225                     try
1226                     {
1227                         xClose->close( true );
1228                     }
1229                     catch ( util::CloseVetoException& )
1230                     {
1231                         // there's still someone who needs the object!
1232                     }
1233                 }
1234 
1235                 xObjRef = NULL;*/
1236             }
1237             else if ( mpImpl->mxObjRef.is() )
1238             {
1239                 if ( getSdrModelFromSdrObject().getUnoModel().is() )
1240                 {
1241                     // remove object, but don't close it (that's up to someone else)
1242                     comphelper::EmbeddedObjectContainer* pContainer = mpImpl->mxObjRef.GetContainer();
1243                     if ( pContainer )
1244                     {
1245                         pContainer->RemoveEmbeddedObject( mpImpl->mxObjRef.GetObject() );
1246 
1247                         // TODO/LATER: mpImpl->aPersistName contains outdated information, to keep it updated
1248                         // it should be returned from RemoveEmbeddedObject call. Currently it is no problem,
1249                         // since no container is adjusted, actually the empty string could be provided as a name here
1250                         mpImpl->mxObjRef.AssignToContainer( nullptr, mpImpl->aPersistName );
1251                     }
1252 
1253                     DisconnectFileLink_Impl();
1254                 }
1255             }
1256         }
1257 
1258         if ( mpImpl->mxObjRef.is() && mpImpl->mxLightClient.is() )
1259         {
1260             mpImpl->mxObjRef->removeStateChangeListener ( mpImpl->mxLightClient );
1261             mpImpl->mxObjRef->removeEventListener( mpImpl->mxLightClient );
1262             mpImpl->mxObjRef->setClientSite( nullptr );
1263 
1264             GetSdrGlobalData().GetOLEObjCache().RemoveObj(this);
1265         }
1266     }
1267     catch( css::uno::Exception& )
1268     {
1269         TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::Disconnect_Impl()" );
1270     }
1271 
1272     mpImpl->mbConnected = false;
1273 }
1274 
createSdrGrafObjReplacement(bool bAddText) const1275 rtl::Reference<SdrObject> SdrOle2Obj::createSdrGrafObjReplacement(bool bAddText) const
1276 {
1277     const Graphic* pOLEGraphic = GetGraphic();
1278 
1279     if(pOLEGraphic)
1280     {
1281         // #i118485# allow creating a SdrGrafObj representation
1282         rtl::Reference<SdrGrafObj> pClone = new SdrGrafObj(
1283             getSdrModelFromSdrObject(),
1284             *pOLEGraphic);
1285 
1286         // copy transformation
1287         basegfx::B2DHomMatrix aMatrix;
1288         basegfx::B2DPolyPolygon aPolyPolygon;
1289 
1290         TRGetBaseGeometry(aMatrix, aPolyPolygon);
1291         pClone->TRSetBaseGeometry(aMatrix, aPolyPolygon);
1292 
1293         // copy all attributes to support graphic styles for OLEs
1294         pClone->SetStyleSheet(GetStyleSheet(), false);
1295         pClone->SetMergedItemSet(GetMergedItemSet());
1296 
1297         if(bAddText)
1298         {
1299             // #i118485# copy text (Caution! Model needed, as guaranteed in aw080)
1300             OutlinerParaObject* pOPO = GetOutlinerParaObject();
1301 
1302             if(pOPO)
1303             {
1304                 pClone->NbcSetOutlinerParaObject(*pOPO);
1305             }
1306         }
1307 
1308         return rtl::Reference<SdrObject>(pClone);
1309     }
1310     else
1311     {
1312         // #i100710# pOLEGraphic may be zero (no visualisation available),
1313         // so we need to use the OLE replacement graphic
1314         rtl::Reference<SdrRectObj> pClone = new SdrRectObj(
1315             getSdrModelFromSdrObject(),
1316             GetSnapRect());
1317 
1318         // gray outline
1319         pClone->SetMergedItem(XLineStyleItem(css::drawing::LineStyle_SOLID));
1320         const svtools::ColorConfig aColorConfig;
1321         const svtools::ColorConfigValue aColor(aColorConfig.GetColorValue(svtools::OBJECTBOUNDARIES));
1322         pClone->SetMergedItem(XLineColorItem(OUString(), aColor.nColor));
1323 
1324         // bitmap fill
1325         pClone->SetMergedItem(XFillStyleItem(drawing::FillStyle_BITMAP));
1326         pClone->SetMergedItem(XFillBitmapItem(OUString(), GetEmptyOLEReplacementGraphic()));
1327         pClone->SetMergedItem(XFillBmpTileItem(false));
1328         pClone->SetMergedItem(XFillBmpStretchItem(false));
1329 
1330         return rtl::Reference<SdrObject>(pClone);
1331     }
1332 }
1333 
DoConvertToPolyObj(bool bBezier,bool bAddText) const1334 rtl::Reference<SdrObject> SdrOle2Obj::DoConvertToPolyObj(bool bBezier, bool bAddText) const
1335 {
1336     // #i118485# missing converter added
1337     rtl::Reference<SdrObject> pRetval = createSdrGrafObjReplacement(true);
1338 
1339     if(pRetval)
1340     {
1341         return pRetval->DoConvertToPolyObj(bBezier, bAddText);
1342     }
1343 
1344     return nullptr;
1345 }
1346 
handlePageChange(SdrPage * pOldPage,SdrPage * pNewPage)1347 void SdrOle2Obj::handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage)
1348 {
1349     const bool bRemove(pNewPage == nullptr && pOldPage != nullptr);
1350     const bool bInsert(pNewPage != nullptr && pOldPage == nullptr);
1351 
1352     if (bRemove && mpImpl->mbConnected )
1353     {
1354         Disconnect();
1355     }
1356 
1357     // call parent
1358     SdrRectObj::handlePageChange(pOldPage, pNewPage);
1359 
1360     if (bInsert && !mpImpl->mbConnected )
1361     {
1362         Connect();
1363     }
1364 }
1365 
SetObjRef(const css::uno::Reference<css::embed::XEmbeddedObject> & rNewObjRef)1366 void SdrOle2Obj::SetObjRef( const css::uno::Reference < css::embed::XEmbeddedObject >& rNewObjRef )
1367 {
1368     DBG_ASSERT( !rNewObjRef.is() || !mpImpl->mxObjRef.GetObject().is(), "SetObjRef called on already initialized object!");
1369     if( rNewObjRef == mpImpl->mxObjRef.GetObject() )
1370         return;
1371 
1372     // the caller of the method is responsible to control the old object, it will not be closed here
1373     // Otherwise WW8 import crashes because it transfers control to OLENode by this method
1374     if ( mpImpl->mxObjRef.GetObject().is() )
1375         mpImpl->mxObjRef.Lock( false );
1376 
1377     // avoid removal of object in Disconnect! It is definitely a HACK to call SetObjRef(0)!
1378     // This call will try to close the objects; so if anybody else wants to keep it, it must be locked by a CloseListener
1379     mpImpl->mxObjRef.Clear();
1380 
1381     if ( mpImpl->mbConnected )
1382         Disconnect();
1383 
1384     mpImpl->mxObjRef.Assign( rNewObjRef, GetAspect() );
1385     mpImpl->mbTypeAsked = false;
1386 
1387     if ( mpImpl->mxObjRef.is() )
1388     {
1389         mpImpl->moGraphic.reset();
1390 
1391         if ( mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE )
1392             SetResizeProtect(true);
1393 
1394         // For math objects, set closed state to transparent
1395         SetClosedObj(!ImplIsMathObj( rNewObjRef ));
1396 
1397         Connect();
1398     }
1399 
1400     SetChanged();
1401     BroadcastObjectChange();
1402 }
1403 
SetClosedObj(bool bIsClosed)1404 void SdrOle2Obj::SetClosedObj( bool bIsClosed )
1405 {
1406     // TODO/LATER: do we still need this hack?
1407     // Allow changes to the closed state of OLE objects
1408     m_bClosedObj = bIsClosed;
1409 }
1410 
getFullDragClone() const1411 rtl::Reference<SdrObject> SdrOle2Obj::getFullDragClone() const
1412 {
1413     // #i118485# use central replacement generator
1414     return createSdrGrafObjReplacement(false);
1415 }
1416 
SetPersistName(const OUString & rPersistName,SvxOle2Shape * pCreator)1417 void SdrOle2Obj::SetPersistName( const OUString& rPersistName, SvxOle2Shape* pCreator )
1418 {
1419     DBG_ASSERT( mpImpl->aPersistName.isEmpty(), "Persist name changed!");
1420 
1421     mpImpl->aPersistName = rPersistName;
1422     mpImpl->mbLoadingOLEObjectFailed = false;
1423 
1424     Connect(pCreator);
1425     SetChanged();
1426 }
1427 
AbandonObject()1428 void SdrOle2Obj::AbandonObject()
1429 {
1430     mpImpl->aPersistName.clear();
1431     mpImpl->mbLoadingOLEObjectFailed = false;
1432     SetObjRef(nullptr);
1433 }
1434 
GetPersistName() const1435 const OUString& SdrOle2Obj::GetPersistName() const
1436 {
1437     return mpImpl->aPersistName;
1438 }
1439 
TakeObjInfo(SdrObjTransformInfoRec & rInfo) const1440 void SdrOle2Obj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
1441 {
1442     // #i118485# Allowing much more attributes for OLEs
1443     rInfo.bRotateFreeAllowed = true;
1444     rInfo.bRotate90Allowed = true;
1445     rInfo.bMirrorFreeAllowed = true;
1446     rInfo.bMirror45Allowed = true;
1447     rInfo.bMirror90Allowed = true;
1448     rInfo.bTransparenceAllowed = true;
1449     rInfo.bShearAllowed = true;
1450     rInfo.bEdgeRadiusAllowed = false;
1451     rInfo.bNoOrthoDesired = false;
1452     rInfo.bCanConvToPath = true;
1453     rInfo.bCanConvToPoly = true;
1454     rInfo.bCanConvToPathLineToArea = false;
1455     rInfo.bCanConvToPolyLineToArea = false;
1456     rInfo.bCanConvToContour = true;
1457 }
1458 
GetObjIdentifier() const1459 SdrObjKind SdrOle2Obj::GetObjIdentifier() const
1460 {
1461     return mpImpl->mbFrame ? SdrObjKind::OLEPluginFrame : SdrObjKind::OLE2;
1462 }
1463 
TakeObjNameSingul() const1464 OUString SdrOle2Obj::TakeObjNameSingul() const
1465 {
1466     OUStringBuffer sName(SvxResId(mpImpl->mbFrame ? STR_ObjNameSingulFrame : STR_ObjNameSingulOLE2));
1467 
1468     const OUString aName(GetName());
1469 
1470     if (!aName.isEmpty())
1471     {
1472         sName.append(" '" + aName + "\'");
1473     }
1474 
1475     return sName.makeStringAndClear();
1476 }
1477 
TakeObjNamePlural() const1478 OUString SdrOle2Obj::TakeObjNamePlural() const
1479 {
1480     return SvxResId(mpImpl->mbFrame ? STR_ObjNamePluralFrame : STR_ObjNamePluralOLE2);
1481 }
1482 
CloneSdrObject(SdrModel & rTargetModel) const1483 rtl::Reference<SdrObject> SdrOle2Obj::CloneSdrObject(SdrModel& rTargetModel) const
1484 {
1485     return new SdrOle2Obj(rTargetModel, *this);
1486 }
1487 
ImpSetVisAreaSize()1488 void SdrOle2Obj::ImpSetVisAreaSize()
1489 {
1490     // #i118524# do not again set VisAreaSize when the call comes from OLE client (e.g. ObjectAreaChanged)
1491     if (mpImpl->mbSuppressSetVisAreaSize)
1492         return;
1493 
1494     // currently there is no need to recalculate scaling for iconified objects
1495     // TODO/LATER: it might be needed in future when it is possible to change the icon
1496     if ( GetAspect() == embed::Aspects::MSOLE_ICON )
1497         return;
1498 
1499     // the object area of an embedded object was changed, e.g. by user interaction an a selected object
1500     GetObjRef();
1501     if (!mpImpl->mxObjRef.is())
1502         return;
1503 
1504     sal_Int64 nMiscStatus = mpImpl->mxObjRef->getStatus( GetAspect() );
1505 
1506     // the client is required to get access to scaling
1507     SfxInPlaceClient* pClient(
1508         SfxInPlaceClient::GetClient(
1509             dynamic_cast<SfxObjectShell*>(
1510                 getSdrModelFromSdrObject().GetPersist()),
1511                 mpImpl->mxObjRef.GetObject()));
1512     const bool bHasOwnClient(
1513         mpImpl->mxLightClient.is() &&
1514         mpImpl->mxObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->mxLightClient ) );
1515 
1516     if ( pClient || bHasOwnClient )
1517     {
1518         // TODO: IMHO we need to do similar things when object is UIActive or OutplaceActive?!
1519         if ( ((nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) &&
1520                 svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObjRef.GetObject() ))
1521                 || mpImpl->mxObjRef->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
1522                 )
1523         {
1524             Fraction aScaleWidth;
1525             Fraction aScaleHeight;
1526             if ( pClient )
1527             {
1528                 aScaleWidth = pClient->GetScaleWidth();
1529                 aScaleHeight = pClient->GetScaleHeight();
1530             }
1531             else
1532             {
1533                 aScaleWidth = mpImpl->mxLightClient->GetScaleWidth();
1534                 aScaleHeight = mpImpl->mxLightClient->GetScaleHeight();
1535             }
1536 
1537             // The object wants to resize itself (f.e. Chart wants to recalculate the layout)
1538             // or object is inplace active and so has a window that must be resized also
1539             // In these cases the change in the object area size will be reflected in a change of the
1540             // objects' visual area. The scaling will not change, but it might exist already and must
1541             // be used in calculations
1542             MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpImpl->mxObjRef->getMapUnit( GetAspect() ) );
1543             Size aVisSize;
1544             if (sal_Int32(aScaleWidth) != 0 && sal_Int32(aScaleHeight) != 0) // avoid div by zero
1545                 aVisSize = Size( static_cast<tools::Long>( Fraction( getRectangle().GetWidth() ) / aScaleWidth ),
1546                                  static_cast<tools::Long>( Fraction( getRectangle().GetHeight() ) / aScaleHeight ) );
1547 
1548             aVisSize = OutputDevice::LogicToLogic(
1549                 aVisSize,
1550                 MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
1551                 MapMode(aMapUnit));
1552             awt::Size aSz;
1553             aSz.Width = aVisSize.Width();
1554             aSz.Height = aVisSize.Height();
1555             mpImpl->mxObjRef->setVisualAreaSize( GetAspect(), aSz );
1556 
1557             try
1558             {
1559                 aSz = mpImpl->mxObjRef->getVisualAreaSize( GetAspect() );
1560             }
1561             catch( embed::NoVisualAreaSizeException& )
1562             {}
1563 
1564             tools::Rectangle aAcceptedVisArea;
1565             aAcceptedVisArea.SetSize( Size( static_cast<tools::Long>( Fraction( tools::Long( aSz.Width ) ) * aScaleWidth ),
1566                                             static_cast<tools::Long>( Fraction( tools::Long( aSz.Height ) ) * aScaleHeight ) ) );
1567             if (aVisSize != aAcceptedVisArea.GetSize())
1568             {
1569                 // server changed VisArea to its liking and the VisArea is different than the suggested one
1570                 // store the new value as given by the object
1571                 MapUnit aNewMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpImpl->mxObjRef->getMapUnit( GetAspect() ) );
1572                 auto aSize = OutputDevice::LogicToLogic(aAcceptedVisArea.GetSize(), MapMode(aNewMapUnit), MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
1573                 setRectangleSize(aSize.Width(), aSize.Height());
1574             }
1575 
1576             // make the new object area known to the client
1577             // compared to the "else" branch aRect might have been changed by the object and no additional scaling was applied
1578             // WHY this -> OSL_ASSERT( pClient );
1579             if( pClient )
1580                 pClient->SetObjArea(getRectangle());
1581 
1582             // we need a new replacement image as the object has resized itself
1583 
1584             //#i79578# don't request a new replacement image for charts to often
1585             //a chart sends a modified call to the framework if it was changed
1586             //thus the replacement update is already handled there
1587             if( !IsChart() )
1588                 mpImpl->mxObjRef.UpdateReplacement();
1589         }
1590         else
1591         {
1592             // The object isn't active and does not want to resize itself so the changed object area size
1593             // will be reflected in a changed object scaling
1594             Fraction aScaleWidth;
1595             Fraction aScaleHeight;
1596             Size aObjAreaSize;
1597             if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) )
1598             {
1599                 if ( pClient )
1600                 {
1601                     tools::Rectangle aScaleRect(getRectangle().TopLeft(), aObjAreaSize);
1602                     pClient->SetObjAreaAndScale( aScaleRect, aScaleWidth, aScaleHeight);
1603                 }
1604                 else
1605                 {
1606                     mpImpl->mxLightClient->SetSizeScale( aScaleWidth, aScaleHeight );
1607                 }
1608             }
1609         }
1610     }
1611     else if( (nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) &&
1612         svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObjRef.GetObject() ) )
1613     {
1614         //also handle not sfx based ole objects e.g. charts
1615         //#i83860# resizing charts in impress distorts fonts
1616         uno::Reference< embed::XVisualObject > xVisualObject( getXModel(), uno::UNO_QUERY );
1617         if( xVisualObject.is() )
1618         {
1619             const MapUnit aMapUnit(
1620                 VCLUnoHelper::UnoEmbed2VCLMapUnit(
1621                     mpImpl->mxObjRef->getMapUnit(GetAspect())));
1622             const Point aTL( getRectangle().TopLeft() );
1623             const Point aBR( getRectangle().BottomRight() );
1624             const Point aTL2(
1625                 OutputDevice::LogicToLogic(
1626                     aTL,
1627                     MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
1628                     MapMode(aMapUnit)));
1629             const Point aBR2(
1630                 OutputDevice::LogicToLogic(
1631                     aBR,
1632                     MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
1633                     MapMode(aMapUnit)));
1634             const tools::Rectangle aNewRect(
1635                 aTL2,
1636                 aBR2);
1637 
1638             xVisualObject->setVisualAreaSize(
1639                 GetAspect(),
1640                 awt::Size(
1641                     aNewRect.GetWidth(),
1642                     aNewRect.GetHeight()));
1643         }
1644     }
1645 }
1646 
NbcResize(const Point & rRef,const Fraction & xFact,const Fraction & yFact)1647 void SdrOle2Obj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
1648 {
1649     if(!getSdrModelFromSdrObject().isLocked())
1650     {
1651         GetObjRef();
1652 
1653         if ( mpImpl->mxObjRef.is() && ( mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) )
1654         {
1655             // if the object needs recompose on resize
1656             // the client site should be created before the resize will take place
1657             // check whether there is no client site and create it if necessary
1658             AddOwnLightClient();
1659         }
1660     }
1661 
1662     SdrRectObj::NbcResize(rRef,xFact,yFact);
1663 
1664     if( !getSdrModelFromSdrObject().isLocked() )
1665         ImpSetVisAreaSize();
1666 }
1667 
SetGeoData(const SdrObjGeoData & rGeo)1668 void SdrOle2Obj::SetGeoData(const SdrObjGeoData& rGeo)
1669 {
1670     SdrRectObj::SetGeoData(rGeo);
1671 
1672     if( !getSdrModelFromSdrObject().isLocked() )
1673         ImpSetVisAreaSize();
1674 }
1675 
NbcSetSnapRect(const tools::Rectangle & rRect)1676 void SdrOle2Obj::NbcSetSnapRect(const tools::Rectangle& rRect)
1677 {
1678     SdrRectObj::NbcSetSnapRect(rRect);
1679 
1680     if( !getSdrModelFromSdrObject().isLocked() )
1681         ImpSetVisAreaSize();
1682 
1683     if ( mpImpl->mxObjRef.is() && IsChart() )
1684     {
1685         //#i103460# charts do not necessarily have an own size within ODF files,
1686         //for this case they need to use the size settings from the surrounding frame,
1687         //which is made available with this method as there is no other way
1688         mpImpl->mxObjRef.SetDefaultSizeForChart( Size( rRect.GetWidth(), rRect.GetHeight() ) );
1689     }
1690 }
1691 
NbcSetLogicRect(const tools::Rectangle & rRect)1692 void SdrOle2Obj::NbcSetLogicRect(const tools::Rectangle& rRect)
1693 {
1694     SdrRectObj::NbcSetLogicRect(rRect);
1695 
1696     if( !getSdrModelFromSdrObject().isLocked() )
1697         ImpSetVisAreaSize();
1698 }
1699 
GetGraphic() const1700 const Graphic* SdrOle2Obj::GetGraphic() const
1701 {
1702     if ( mpImpl->mxObjRef.is() )
1703         return mpImpl->mxObjRef.GetGraphic();
1704     return mpImpl->moGraphic ? &*mpImpl->moGraphic : nullptr;
1705 }
1706 
GetNewReplacement()1707 void SdrOle2Obj::GetNewReplacement()
1708 {
1709     if ( mpImpl->mxObjRef.is() )
1710         mpImpl->mxObjRef.UpdateReplacement();
1711 }
1712 
GetOrigObjSize(MapMode const * pTargetMapMode) const1713 Size SdrOle2Obj::GetOrigObjSize( MapMode const * pTargetMapMode ) const
1714 {
1715     return mpImpl->mxObjRef.GetSize( pTargetMapMode );
1716 }
1717 
setSuppressSetVisAreaSize(bool bNew)1718 void SdrOle2Obj::setSuppressSetVisAreaSize( bool bNew )
1719 {
1720     mpImpl->mbSuppressSetVisAreaSize = bNew;
1721 }
1722 
NbcMove(const Size & rSize)1723 void SdrOle2Obj::NbcMove(const Size& rSize)
1724 {
1725     SdrRectObj::NbcMove(rSize);
1726 
1727     if( !getSdrModelFromSdrObject().isLocked() )
1728         ImpSetVisAreaSize();
1729 }
1730 
CanUnloadRunningObj(const uno::Reference<embed::XEmbeddedObject> & xObj,sal_Int64 nAspect)1731 bool SdrOle2Obj::CanUnloadRunningObj( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
1732 {
1733     uno::Reference<embed::XEmbedPersist2> xPersist(xObj, uno::UNO_QUERY);
1734     if (xPersist.is())
1735     {
1736         if (!xPersist->isStored())
1737             // It doesn't have persistent storage.  We can't unload this.
1738             return false;
1739     }
1740 
1741     bool bResult = false;
1742 
1743     sal_Int32 nState = xObj->getCurrentState();
1744     if ( nState == embed::EmbedStates::LOADED )
1745     {
1746         // the object is already unloaded
1747         bResult = true;
1748     }
1749     else
1750     {
1751         uno::Reference < util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
1752         if ( !xModifiable.is() )
1753             bResult = true;
1754         else
1755         {
1756             sal_Int64 nMiscStatus = xObj->getStatus( nAspect );
1757 
1758             if ( embed::EmbedMisc::MS_EMBED_ALWAYSRUN != ( nMiscStatus & embed::EmbedMisc::MS_EMBED_ALWAYSRUN ) &&
1759             embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY != ( nMiscStatus & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) &&
1760             !( xModifiable.is() && xModifiable->isModified() ) &&
1761             !( nState == embed::EmbedStates::INPLACE_ACTIVE || nState == embed::EmbedStates::UI_ACTIVE || nState == embed::EmbedStates::ACTIVE ) )
1762             {
1763                 bResult = true;
1764             }
1765         }
1766     }
1767 
1768     return bResult;
1769 }
1770 
Unload(const uno::Reference<embed::XEmbeddedObject> & xObj,sal_Int64 nAspect)1771 bool SdrOle2Obj::Unload( const uno::Reference< embed::XEmbeddedObject >& xObj, sal_Int64 nAspect )
1772 {
1773     bool bResult = false;
1774 
1775     if ( CanUnloadRunningObj( xObj, nAspect ) )
1776     {
1777         try
1778         {
1779             xObj->changeState( embed::EmbedStates::LOADED );
1780             bResult = true;
1781         }
1782         catch( css::uno::Exception& )
1783         {
1784             TOOLS_WARN_EXCEPTION( "svx", "SdrOle2Obj::Unload()" );
1785         }
1786     }
1787 
1788     return bResult;
1789 }
1790 
Unload()1791 bool SdrOle2Obj::Unload()
1792 {
1793     if (!mpImpl->mxObjRef.is())
1794         // Already unloaded.
1795         return true;
1796 
1797     return Unload(mpImpl->mxObjRef.GetObject(), GetAspect());
1798 }
1799 
GetObjRef_Impl()1800 void SdrOle2Obj::GetObjRef_Impl()
1801 {
1802     if ( !mpImpl->mxObjRef.is() && !mpImpl->aPersistName.isEmpty() && getSdrModelFromSdrObject().GetPersist() )
1803     {
1804         // Only try loading if it did not went wrong up to now
1805         if(!mpImpl->mbLoadingOLEObjectFailed)
1806         {
1807             mpImpl->mxObjRef.Assign(
1808                 getSdrModelFromSdrObject().GetPersist()->getEmbeddedObjectContainer().GetEmbeddedObject(mpImpl->aPersistName),
1809                 GetAspect());
1810             mpImpl->mbTypeAsked = false;
1811             CheckFileLink_Impl();
1812 
1813             // If loading of OLE object failed, remember that to not invoke an endless
1814             // loop trying to load it again and again.
1815             if( mpImpl->mxObjRef.is() )
1816             {
1817                 mpImpl->mbLoadingOLEObjectFailed = true;
1818             }
1819 
1820             // For math objects, set closed state to transparent
1821             SetClosedObj(!ImplIsMathObj( mpImpl->mxObjRef.GetObject() ));
1822         }
1823 
1824         if ( mpImpl->mxObjRef.is() )
1825         {
1826             if( !IsEmptyPresObj() )
1827             {
1828                 // remember modified status of model
1829                 const bool bWasChanged(getSdrModelFromSdrObject().IsChanged());
1830 
1831                 // perhaps preview not valid anymore
1832                 // This line changes the modified state of the model
1833                 ClearGraphic();
1834 
1835                 // if status was not set before, force it back
1836                 // to not set, so that SetGraphic(0) above does not
1837                 // set the modified state of the model.
1838                 if(!bWasChanged && getSdrModelFromSdrObject().IsChanged())
1839                 {
1840                     getSdrModelFromSdrObject().SetChanged( false );
1841                 }
1842             }
1843         }
1844 
1845         if ( mpImpl->mxObjRef.is() )
1846             Connect();
1847     }
1848 
1849     if ( mpImpl->mbConnected )
1850     {
1851         // move object to first position in cache
1852         GetSdrGlobalData().GetOLEObjCache().InsertObj(this);
1853     }
1854 }
1855 
GetObjRef() const1856 uno::Reference < embed::XEmbeddedObject > const & SdrOle2Obj::GetObjRef() const
1857 {
1858     const_cast<SdrOle2Obj*>(this)->GetObjRef_Impl();
1859     return mpImpl->mxObjRef.GetObject();
1860 }
1861 
GetObjRef_NoInit() const1862 uno::Reference < embed::XEmbeddedObject > const & SdrOle2Obj::GetObjRef_NoInit() const
1863 {
1864     return mpImpl->mxObjRef.GetObject();
1865 }
1866 
getXModel() const1867 uno::Reference< frame::XModel > SdrOle2Obj::getXModel() const
1868 {
1869     if (svt::EmbeddedObjectRef::TryRunningState(GetObjRef()))
1870         return uno::Reference< frame::XModel >( mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY );
1871     else
1872         return uno::Reference< frame::XModel >();
1873 }
1874 
IsChart() const1875 bool SdrOle2Obj::IsChart() const
1876 {
1877     if (!mpImpl->mbTypeAsked)
1878     {
1879         mpImpl->mbIsChart = mpImpl->mxObjRef.IsChart();
1880         mpImpl->mbTypeAsked = true;
1881     }
1882     return mpImpl->mbIsChart;
1883 }
1884 
SetGraphicToObj(const Graphic & aGraphic)1885 void SdrOle2Obj::SetGraphicToObj( const Graphic& aGraphic )
1886 {
1887     mpImpl->mxObjRef.SetGraphic( aGraphic, OUString() );
1888     // if the object isn't valid, e.g. link to something that doesn't exist, set the fallback
1889     // graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback
1890     if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
1891         mpImpl->moGraphic.emplace(*pObjGraphic);
1892 }
1893 
SetGraphicToObj(const uno::Reference<io::XInputStream> & xGrStream,const OUString & aMediaType)1894 void SdrOle2Obj::SetGraphicToObj( const uno::Reference< io::XInputStream >& xGrStream, const OUString& aMediaType )
1895 {
1896     mpImpl->mxObjRef.SetGraphicStream( xGrStream, aMediaType );
1897     // if the object isn't valid, e.g. link to something that doesn't exist, set the fallback
1898     // graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback
1899     if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
1900         mpImpl->moGraphic.emplace(*pObjGraphic);
1901 }
1902 
IsCalc() const1903 bool SdrOle2Obj::IsCalc() const
1904 {
1905     if ( !mpImpl->mxObjRef.is() )
1906         return false;
1907 
1908     SvGlobalName aObjClsId( mpImpl->mxObjRef->getClassID() );
1909     return SvGlobalName(SO3_SC_CLASSID_30) == aObjClsId
1910         || SvGlobalName(SO3_SC_CLASSID_40) == aObjClsId
1911         || SvGlobalName(SO3_SC_CLASSID_50) == aObjClsId
1912         || SvGlobalName(SO3_SC_CLASSID_60) == aObjClsId
1913         || SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_60) == aObjClsId
1914         || SvGlobalName(SO3_SC_OLE_EMBED_CLASSID_8) == aObjClsId
1915         || SvGlobalName(SO3_SC_CLASSID) == aObjClsId;
1916 }
1917 
GetParentXModel() const1918 uno::Reference< frame::XModel > SdrOle2Obj::GetParentXModel() const
1919 {
1920     return getSdrModelFromSdrObject().getUnoModel();
1921 }
1922 
CalculateNewScaling(Fraction & aScaleWidth,Fraction & aScaleHeight,Size & aObjAreaSize)1923 bool SdrOle2Obj::CalculateNewScaling( Fraction& aScaleWidth, Fraction& aScaleHeight, Size& aObjAreaSize )
1924 {
1925     // TODO/LEAN: to avoid rounding errors scaling always uses the VisArea.
1926     // If we don't cache it for own objects also we must load the object here
1927     if (!mpImpl->mxObjRef.is())
1928         return false;
1929 
1930     MapMode aMapMode(getSdrModelFromSdrObject().GetScaleUnit());
1931     aObjAreaSize = mpImpl->mxObjRef.GetSize( &aMapMode );
1932 
1933     Size aSize = getRectangle().GetSize();
1934     if (!aObjAreaSize.Width() || !aObjAreaSize.Height())
1935     {
1936         // avoid invalid fractions
1937         aScaleWidth = Fraction(1,1);
1938         aScaleHeight = Fraction(1,1);
1939     }
1940     else
1941     {
1942         aScaleWidth = Fraction(aSize.Width(),  aObjAreaSize.Width() );
1943         aScaleHeight = Fraction(aSize.Height(), aObjAreaSize.Height() );
1944         // reduce to 10 binary digits
1945         aScaleHeight.ReduceInaccurate(10);
1946         aScaleWidth.ReduceInaccurate(10);
1947     }
1948 
1949     return true;
1950 }
1951 
AddOwnLightClient()1952 bool SdrOle2Obj::AddOwnLightClient()
1953 {
1954     // The Own Light Client must be registered in object only using this method!
1955     if ( !SfxInPlaceClient::GetClient( dynamic_cast<SfxObjectShell*>(getSdrModelFromSdrObject().GetPersist()), mpImpl->mxObjRef.GetObject() )
1956       && !( mpImpl->mxLightClient.is() && mpImpl->mxObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->mxLightClient ) ) )
1957     {
1958         Connect();
1959 
1960         if ( mpImpl->mxObjRef.is() && mpImpl->mxLightClient.is() )
1961         {
1962             Fraction aScaleWidth;
1963             Fraction aScaleHeight;
1964             Size aObjAreaSize;
1965             if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) )
1966             {
1967                 mpImpl->mxLightClient->SetSizeScale( aScaleWidth, aScaleHeight );
1968                 try {
1969                     mpImpl->mxObjRef->setClientSite( mpImpl->mxLightClient );
1970                     return true;
1971                 } catch( uno::Exception& )
1972                 {}
1973             }
1974 
1975         }
1976 
1977         return false;
1978     }
1979 
1980     return true;
1981 }
1982 
GetEmptyOLEReplacementGraphic()1983 Graphic SdrOle2Obj::GetEmptyOLEReplacementGraphic()
1984 {
1985     return Graphic(BitmapEx(BMP_SVXOLEOBJ));
1986 }
1987 
SetWindow(const css::uno::Reference<css::awt::XWindow> & _xWindow)1988 void SdrOle2Obj::SetWindow(const css::uno::Reference < css::awt::XWindow >& _xWindow)
1989 {
1990     if ( mpImpl->mxObjRef.is() && mpImpl->mxLightClient.is() )
1991     {
1992         mpImpl->mxLightClient->setWindow(_xWindow);
1993     }
1994 }
1995 
1996 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1997