Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / svx / source / svdraw / svdouno.cxx
blob95c73228e64ef885e8bd642d36796a072711e085
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sdr/contact/viewcontactofunocontrol.hxx>
21 #include <sdr/contact/viewobjectcontactofunocontrol.hxx>
22 #include <com/sun/star/container/XChild.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/util/XCloneable.hpp>
25 #include <com/sun/star/uno/XComponentContext.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <svx/svdouno.hxx>
28 #include <svx/svdpagv.hxx>
29 #include <svx/svdmodel.hxx>
30 #include <svx/dialmgr.hxx>
31 #include <svx/strings.hrc>
32 #include <svx/svdview.hxx>
33 #include <svx/svdorect.hxx>
34 #include <svx/svdviter.hxx>
35 #include <rtl/ustrbuf.hxx>
36 #include <rtl/ref.hxx>
37 #include <svx/sdrpagewindow.hxx>
38 #include <tools/diagnose_ex.h>
39 #include <tools/debug.hxx>
40 #include <o3tl/sorted_vector.hxx>
42 using namespace ::com::sun::star;
43 using namespace sdr::contact;
46 // Defines
49 // Helper class SdrControlEventListenerImpl
51 #include <com/sun/star/lang/XEventListener.hpp>
53 #include <cppuhelper/implbase.hxx>
56 class SdrControlEventListenerImpl : public ::cppu::WeakImplHelper< css::lang::XEventListener >
58 protected:
59 SdrUnoObj* pObj;
61 public:
62 explicit SdrControlEventListenerImpl(SdrUnoObj* _pObj)
63 : pObj(_pObj)
66 // XEventListener
67 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
69 void StopListening(const uno::Reference< lang::XComponent >& xComp);
70 void StartListening(const uno::Reference< lang::XComponent >& xComp);
73 // XEventListener
74 void SAL_CALL SdrControlEventListenerImpl::disposing( const css::lang::EventObject& /*Source*/)
76 if (pObj)
78 pObj->xUnoControlModel = nullptr;
82 void SdrControlEventListenerImpl::StopListening(const uno::Reference< lang::XComponent >& xComp)
84 if (xComp.is())
85 xComp->removeEventListener(this);
88 void SdrControlEventListenerImpl::StartListening(const uno::Reference< lang::XComponent >& xComp)
90 if (xComp.is())
91 xComp->addEventListener(this);
95 struct SdrUnoObjDataHolder
97 mutable ::rtl::Reference< SdrControlEventListenerImpl >
98 pEventListener;
102 namespace
104 void lcl_ensureControlVisibility( SdrView const * _pView, const SdrUnoObj* _pObject, bool _bVisible )
106 OSL_PRECOND( _pObject, "lcl_ensureControlVisibility: no object -> no survival!" );
108 SdrPageView* pPageView = _pView ? _pView->GetSdrPageView() : nullptr;
109 DBG_ASSERT( pPageView, "lcl_ensureControlVisibility: no view found!" );
110 if ( !pPageView )
111 return;
113 ViewContact& rUnoControlContact( _pObject->GetViewContact() );
115 for ( sal_uInt32 i = 0; i < pPageView->PageWindowCount(); ++i )
117 SdrPageWindow* pPageWindow = pPageView->GetPageWindow( i );
118 DBG_ASSERT( pPageWindow, "lcl_ensureControlVisibility: invalid PageViewWindow!" );
119 if ( !pPageWindow )
120 continue;
122 if ( !pPageWindow->HasObjectContact() )
123 continue;
125 ObjectContact& rPageViewContact( pPageWindow->GetObjectContact() );
126 const ViewObjectContact& rViewObjectContact( rUnoControlContact.GetViewObjectContact( rPageViewContact ) );
127 const ViewObjectContactOfUnoControl* pUnoControlContact = dynamic_cast< const ViewObjectContactOfUnoControl* >( &rViewObjectContact );
128 DBG_ASSERT( pUnoControlContact, "lcl_ensureControlVisibility: wrong ViewObjectContact type!" );
129 if ( !pUnoControlContact )
130 continue;
132 pUnoControlContact->ensureControlVisibility( _bVisible );
137 SdrUnoObj::SdrUnoObj(
138 SdrModel& rSdrModel,
139 const OUString& rModelName)
140 : SdrRectObj(rSdrModel),
141 m_pImpl( new SdrUnoObjDataHolder )
143 bIsUnoObj = true;
145 m_pImpl->pEventListener = new SdrControlEventListenerImpl(this);
147 // only an owner may create independently
148 if (!rModelName.isEmpty())
149 CreateUnoControlModel(rModelName);
152 SdrUnoObj::SdrUnoObj(
153 SdrModel& rSdrModel,
154 const OUString& rModelName,
155 const uno::Reference< lang::XMultiServiceFactory >& rxSFac)
156 : SdrRectObj(rSdrModel),
157 m_pImpl( new SdrUnoObjDataHolder )
159 bIsUnoObj = true;
161 m_pImpl->pEventListener = new SdrControlEventListenerImpl(this);
163 // only an owner may create independently
164 if (!rModelName.isEmpty())
165 CreateUnoControlModel(rModelName,rxSFac);
168 SdrUnoObj::~SdrUnoObj()
172 // clean up the control model
173 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
174 if (xComp.is())
176 // is the control model owned by its environment?
177 uno::Reference< container::XChild > xContent(xUnoControlModel, uno::UNO_QUERY);
178 if (xContent.is() && !xContent->getParent().is())
179 xComp->dispose();
180 else
181 m_pImpl->pEventListener->StopListening(xComp);
184 catch( const uno::Exception& )
186 TOOLS_WARN_EXCEPTION( "svx", "SdrUnoObj::~SdrUnoObj" );
190 void SdrUnoObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
192 rInfo.bRotateFreeAllowed = false;
193 rInfo.bRotate90Allowed = false;
194 rInfo.bMirrorFreeAllowed = false;
195 rInfo.bMirror45Allowed = false;
196 rInfo.bMirror90Allowed = false;
197 rInfo.bTransparenceAllowed = false;
198 rInfo.bShearAllowed = false;
199 rInfo.bEdgeRadiusAllowed = false;
200 rInfo.bNoOrthoDesired = false;
201 rInfo.bCanConvToPath = false;
202 rInfo.bCanConvToPoly = false;
203 rInfo.bCanConvToPathLineToArea = false;
204 rInfo.bCanConvToPolyLineToArea = false;
205 rInfo.bCanConvToContour = false;
208 SdrObjKind SdrUnoObj::GetObjIdentifier() const
210 return OBJ_UNO;
213 void SdrUnoObj::SetContextWritingMode( const sal_Int16 _nContextWritingMode )
217 uno::Reference< beans::XPropertySet > xModelProperties( GetUnoControlModel(), uno::UNO_QUERY_THROW );
218 xModelProperties->setPropertyValue( "ContextWritingMode", uno::makeAny( _nContextWritingMode ) );
220 catch( const uno::Exception& )
222 DBG_UNHANDLED_EXCEPTION("svx");
226 OUString SdrUnoObj::TakeObjNameSingul() const
228 OUStringBuffer sName(SvxResId(STR_ObjNameSingulUno));
230 OUString aName(GetName());
231 if (!aName.isEmpty())
233 sName.append(' ');
234 sName.append('\'');
235 sName.append(aName);
236 sName.append('\'');
239 return sName.makeStringAndClear();
242 OUString SdrUnoObj::TakeObjNamePlural() const
244 return SvxResId(STR_ObjNamePluralUno);
247 SdrUnoObj* SdrUnoObj::CloneSdrObject(SdrModel& rTargetModel) const
249 return CloneHelper< SdrUnoObj >(rTargetModel);
252 SdrUnoObj& SdrUnoObj::operator= (const SdrUnoObj& rObj)
254 if( this == &rObj )
255 return *this;
256 SdrRectObj::operator= (rObj);
258 // release the reference to the current control model
259 SetUnoControlModel( nullptr );
261 aUnoControlModelTypeName = rObj.aUnoControlModelTypeName;
262 aUnoControlTypeName = rObj.aUnoControlTypeName;
264 // copy the uno control model
265 const uno::Reference< awt::XControlModel > xSourceControlModel = rObj.GetUnoControlModel();
266 if ( xSourceControlModel.is() )
270 uno::Reference< util::XCloneable > xClone( xSourceControlModel, uno::UNO_QUERY_THROW );
271 xUnoControlModel.set( xClone->createClone(), uno::UNO_QUERY_THROW );
273 catch( const uno::Exception& )
275 DBG_UNHANDLED_EXCEPTION("svx");
279 // get service name of the control from the control model
280 uno::Reference< beans::XPropertySet > xSet(xUnoControlModel, uno::UNO_QUERY);
281 if (xSet.is())
283 uno::Any aValue( xSet->getPropertyValue("DefaultControl") );
284 OUString aStr;
286 if( aValue >>= aStr )
287 aUnoControlTypeName = aStr;
290 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
291 if (xComp.is())
292 m_pImpl->pEventListener->StartListening(xComp);
293 return *this;
296 void SdrUnoObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
298 SdrRectObj::NbcResize(rRef,xFact,yFact);
300 if (aGeo.nShearAngle==0 && aGeo.nRotationAngle==0)
301 return;
303 // small correctors
304 if (aGeo.nRotationAngle>=9000 && aGeo.nRotationAngle<27000)
306 maRect.Move(maRect.Left()-maRect.Right(),maRect.Top()-maRect.Bottom());
309 aGeo.nRotationAngle = 0;
310 aGeo.nShearAngle = 0;
311 aGeo.nSin = 0.0;
312 aGeo.nCos = 1.0;
313 aGeo.nTan = 0.0;
314 SetRectsDirty();
318 bool SdrUnoObj::hasSpecialDrag() const
320 // no special drag; we have no rounding rect and
321 // do want frame handles
322 return false;
325 void SdrUnoObj::NbcSetLayer( SdrLayerID _nLayer )
327 if ( GetLayer() == _nLayer )
328 { // redundant call -> not interested in doing anything here
329 SdrRectObj::NbcSetLayer( _nLayer );
330 return;
333 // we need some special handling here in case we're moved from an invisible layer
334 // to a visible one, or vice versa
335 // (relative to a layer. Remember that the visibility of a layer is a view attribute
336 // - the same layer can be visible in one view, and invisible in another view, at the
337 // same time)
339 // collect all views in which our old layer is visible
340 o3tl::sorted_vector< SdrView* > aPreviouslyVisible;
343 SdrViewIter aIter( this );
344 for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() )
345 aPreviouslyVisible.insert( pView );
348 SdrRectObj::NbcSetLayer( _nLayer );
350 // collect all views in which our new layer is visible
351 o3tl::sorted_vector< SdrView* > aNewlyVisible;
354 SdrViewIter aIter( this );
355 for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() )
357 if ( aPreviouslyVisible.erase(pView) == 0 )
359 // in pView, we were visible _before_ the layer change, and are
360 // _not_ visible after the layer change
361 // => remember this view, as our visibility there changed
362 aNewlyVisible.insert( pView );
367 // now aPreviouslyVisible contains all views where we became invisible
368 for (const auto& rpView : aPreviouslyVisible)
370 lcl_ensureControlVisibility( rpView, this, false );
373 // and aNewlyVisible all views where we became visible
374 for (const auto& rpView : aNewlyVisible)
376 lcl_ensureControlVisibility( rpView, this, true );
380 void SdrUnoObj::CreateUnoControlModel(const OUString& rModelName)
382 DBG_ASSERT(!xUnoControlModel.is(), "model already exists");
384 aUnoControlModelTypeName = rModelName;
386 uno::Reference< awt::XControlModel > xModel;
387 uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
388 if (!aUnoControlModelTypeName.isEmpty() )
390 xModel.set(xContext->getServiceManager()->createInstanceWithContext(
391 aUnoControlModelTypeName, xContext), uno::UNO_QUERY);
393 if (xModel.is())
394 SetChanged();
397 SetUnoControlModel(xModel);
400 void SdrUnoObj::CreateUnoControlModel(const OUString& rModelName,
401 const uno::Reference< lang::XMultiServiceFactory >& rxSFac)
403 DBG_ASSERT(!xUnoControlModel.is(), "model already exists");
405 aUnoControlModelTypeName = rModelName;
407 uno::Reference< awt::XControlModel > xModel;
408 if (!aUnoControlModelTypeName.isEmpty() && rxSFac.is() )
410 xModel.set(rxSFac->createInstance(aUnoControlModelTypeName), uno::UNO_QUERY);
412 if (xModel.is())
413 SetChanged();
416 SetUnoControlModel(xModel);
419 void SdrUnoObj::SetUnoControlModel( const uno::Reference< awt::XControlModel >& xModel)
421 if (xUnoControlModel.is())
423 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
424 if (xComp.is())
425 m_pImpl->pEventListener->StopListening(xComp);
428 xUnoControlModel = xModel;
430 // control model has to contain service name of the control
431 if (xUnoControlModel.is())
433 uno::Reference< beans::XPropertySet > xSet(xUnoControlModel, uno::UNO_QUERY);
434 if (xSet.is())
436 uno::Any aValue( xSet->getPropertyValue("DefaultControl") );
437 OUString aStr;
438 if( aValue >>= aStr )
439 aUnoControlTypeName = aStr;
442 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
443 if (xComp.is())
444 m_pImpl->pEventListener->StartListening(xComp);
447 // invalidate all ViewObject contacts
448 ViewContactOfUnoControl* pVC = nullptr;
449 if ( impl_getViewContact( pVC ) )
451 // flushViewObjectContacts() removes all existing VOCs for the local DrawHierarchy. This
452 // is always allowed since they will be re-created on demand (and with the changed model)
453 GetViewContact().flushViewObjectContacts();
458 uno::Reference< awt::XControl > SdrUnoObj::GetUnoControl(const SdrView& _rView, const OutputDevice& _rOut) const
460 uno::Reference< awt::XControl > xControl;
462 SdrPageView* pPageView = _rView.GetSdrPageView();
463 OSL_ENSURE( pPageView && getSdrPageFromSdrObject() == pPageView->GetPage(), "SdrUnoObj::GetUnoControl: This object is not displayed in that particular view!" );
464 if ( !pPageView || getSdrPageFromSdrObject() != pPageView->GetPage() )
465 return nullptr;
467 SdrPageWindow* pPageWindow = pPageView->FindPageWindow( _rOut );
468 OSL_ENSURE( pPageWindow, "SdrUnoObj::GetUnoControl: did not find my SdrPageWindow!" );
469 if ( !pPageWindow )
470 return nullptr;
472 ViewObjectContact& rViewObjectContact( GetViewContact().GetViewObjectContact( pPageWindow->GetObjectContact() ) );
473 ViewObjectContactOfUnoControl* pUnoContact = dynamic_cast< ViewObjectContactOfUnoControl* >( &rViewObjectContact );
474 OSL_ENSURE( pUnoContact, "SdrUnoObj::GetUnoControl: wrong contact type!" );
475 if ( pUnoContact )
476 xControl = pUnoContact->getControl();
478 return xControl;
482 uno::Reference< awt::XControl > SdrUnoObj::GetTemporaryControlForWindow(
483 const vcl::Window& _rWindow, uno::Reference< awt::XControlContainer >& _inout_ControlContainer ) const
485 uno::Reference< awt::XControl > xControl;
487 ViewContactOfUnoControl* pVC = nullptr;
488 if ( impl_getViewContact( pVC ) )
489 xControl = pVC->getTemporaryControlForWindow( _rWindow, _inout_ControlContainer );
491 return xControl;
495 bool SdrUnoObj::impl_getViewContact( ViewContactOfUnoControl*& _out_rpContact ) const
497 ViewContact& rViewContact( GetViewContact() );
498 _out_rpContact = dynamic_cast< ViewContactOfUnoControl* >( &rViewContact );
499 DBG_ASSERT( _out_rpContact, "SdrUnoObj::impl_getViewContact: could not find my ViewContact!" );
500 return ( _out_rpContact != nullptr );
504 std::unique_ptr<sdr::contact::ViewContact> SdrUnoObj::CreateObjectSpecificViewContact()
506 return std::make_unique<sdr::contact::ViewContactOfUnoControl>( *this );
510 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */