Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / svdraw / svdouno.cxx
blob6ea734a7341c51ebe52d93674c44b633cf259eb0
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/ref.hxx>
36 #include <svx/sdrpagewindow.hxx>
37 #include <comphelper/diagnose_ex.hxx>
38 #include <tools/debug.hxx>
39 #include <o3tl/sorted_vector.hxx>
41 using namespace ::com::sun::star;
42 using namespace sdr::contact;
45 // Defines
48 // Helper class SdrControlEventListenerImpl
50 #include <com/sun/star/lang/XEventListener.hpp>
52 #include <cppuhelper/implbase.hxx>
55 class SdrControlEventListenerImpl : public ::cppu::WeakImplHelper< css::lang::XEventListener >
57 protected:
58 SdrUnoObj* pObj;
60 public:
61 explicit SdrControlEventListenerImpl(SdrUnoObj* _pObj)
62 : pObj(_pObj)
65 // XEventListener
66 virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
68 void StopListening(const uno::Reference< lang::XComponent >& xComp);
69 void StartListening(const uno::Reference< lang::XComponent >& xComp);
72 // XEventListener
73 void SAL_CALL SdrControlEventListenerImpl::disposing( const css::lang::EventObject& /*Source*/)
75 if (pObj)
77 pObj->xUnoControlModel = nullptr;
81 void SdrControlEventListenerImpl::StopListening(const uno::Reference< lang::XComponent >& xComp)
83 if (xComp.is())
84 xComp->removeEventListener(this);
87 void SdrControlEventListenerImpl::StartListening(const uno::Reference< lang::XComponent >& xComp)
89 if (xComp.is())
90 xComp->addEventListener(this);
94 struct SdrUnoObjDataHolder
96 mutable ::rtl::Reference< SdrControlEventListenerImpl >
97 pEventListener;
101 namespace
103 void lcl_ensureControlVisibility( SdrView const * _pView, const SdrUnoObj* _pObject, bool _bVisible )
105 OSL_PRECOND( _pObject, "lcl_ensureControlVisibility: no object -> no survival!" );
107 SdrPageView* pPageView = _pView ? _pView->GetSdrPageView() : nullptr;
108 DBG_ASSERT( pPageView, "lcl_ensureControlVisibility: no view found!" );
109 if ( !pPageView )
110 return;
112 ViewContact& rUnoControlContact( _pObject->GetViewContact() );
114 for ( sal_uInt32 i = 0; i < pPageView->PageWindowCount(); ++i )
116 SdrPageWindow* pPageWindow = pPageView->GetPageWindow( i );
117 DBG_ASSERT( pPageWindow, "lcl_ensureControlVisibility: invalid PageViewWindow!" );
118 if ( !pPageWindow )
119 continue;
121 if ( !pPageWindow->HasObjectContact() )
122 continue;
124 ObjectContact& rPageViewContact( pPageWindow->GetObjectContact() );
125 const ViewObjectContact& rViewObjectContact( rUnoControlContact.GetViewObjectContact( rPageViewContact ) );
126 const ViewObjectContactOfUnoControl* pUnoControlContact = dynamic_cast< const ViewObjectContactOfUnoControl* >( &rViewObjectContact );
127 DBG_ASSERT( pUnoControlContact, "lcl_ensureControlVisibility: wrong ViewObjectContact type!" );
128 if ( !pUnoControlContact )
129 continue;
131 pUnoControlContact->ensureControlVisibility( _bVisible );
136 SdrUnoObj::SdrUnoObj(
137 SdrModel& rSdrModel,
138 const OUString& rModelName)
139 : SdrRectObj(rSdrModel),
140 m_pImpl( new SdrUnoObjDataHolder )
142 osl_atomic_increment(&m_refCount); // prevent deletion during creation
143 m_bIsUnoObj = true;
145 m_pImpl->pEventListener = new SdrControlEventListenerImpl(this);
147 // only an owner may create independently
148 if (!rModelName.isEmpty())
149 CreateUnoControlModel(rModelName);
150 osl_atomic_decrement(&m_refCount);
153 SdrUnoObj::SdrUnoObj( SdrModel& rSdrModel, SdrUnoObj const & rSource)
154 : SdrRectObj(rSdrModel, rSource),
155 m_pImpl( new SdrUnoObjDataHolder )
157 m_bIsUnoObj = true;
159 m_pImpl->pEventListener = new SdrControlEventListenerImpl(this);
161 aUnoControlModelTypeName = rSource.aUnoControlModelTypeName;
162 aUnoControlTypeName = rSource.aUnoControlTypeName;
164 // copy the uno control model
165 const uno::Reference< awt::XControlModel > xSourceControlModel = rSource.GetUnoControlModel();
166 if ( xSourceControlModel.is() )
170 uno::Reference< util::XCloneable > xClone( xSourceControlModel, uno::UNO_QUERY_THROW );
171 xUnoControlModel.set( xClone->createClone(), uno::UNO_QUERY_THROW );
173 catch( const uno::Exception& )
175 DBG_UNHANDLED_EXCEPTION("svx");
179 // get service name of the control from the control model
180 uno::Reference< beans::XPropertySet > xSet(xUnoControlModel, uno::UNO_QUERY);
181 if (xSet.is())
183 uno::Any aValue( xSet->getPropertyValue("DefaultControl") );
184 OUString aStr;
186 if( aValue >>= aStr )
187 aUnoControlTypeName = aStr;
190 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
191 if (xComp.is())
192 m_pImpl->pEventListener->StartListening(xComp);
195 SdrUnoObj::SdrUnoObj(
196 SdrModel& rSdrModel,
197 const OUString& rModelName,
198 const uno::Reference< lang::XMultiServiceFactory >& rxSFac)
199 : SdrRectObj(rSdrModel),
200 m_pImpl( new SdrUnoObjDataHolder )
202 m_bIsUnoObj = true;
204 m_pImpl->pEventListener = new SdrControlEventListenerImpl(this);
206 // only an owner may create independently
207 if (!rModelName.isEmpty())
208 CreateUnoControlModel(rModelName,rxSFac);
211 SdrUnoObj::~SdrUnoObj()
215 // clean up the control model
216 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
217 if (xComp.is())
219 // is the control model owned by its environment?
220 uno::Reference< container::XChild > xContent(xUnoControlModel, uno::UNO_QUERY);
221 if (xContent.is() && !xContent->getParent().is())
222 xComp->dispose();
223 else
224 m_pImpl->pEventListener->StopListening(xComp);
227 catch( const uno::Exception& )
229 TOOLS_WARN_EXCEPTION( "svx", "SdrUnoObj::~SdrUnoObj" );
233 void SdrUnoObj::TakeObjInfo(SdrObjTransformInfoRec& rInfo) const
235 rInfo.bRotateFreeAllowed = false;
236 rInfo.bRotate90Allowed = false;
237 rInfo.bMirrorFreeAllowed = false;
238 rInfo.bMirror45Allowed = false;
239 rInfo.bMirror90Allowed = false;
240 rInfo.bTransparenceAllowed = false;
241 rInfo.bShearAllowed = false;
242 rInfo.bEdgeRadiusAllowed = false;
243 rInfo.bNoOrthoDesired = false;
244 rInfo.bCanConvToPath = false;
245 rInfo.bCanConvToPoly = false;
246 rInfo.bCanConvToPathLineToArea = false;
247 rInfo.bCanConvToPolyLineToArea = false;
248 rInfo.bCanConvToContour = false;
251 SdrObjKind SdrUnoObj::GetObjIdentifier() const
253 return SdrObjKind::UNO;
256 void SdrUnoObj::SetContextWritingMode( const sal_Int16 _nContextWritingMode )
260 uno::Reference< beans::XPropertySet > xModelProperties( GetUnoControlModel(), uno::UNO_QUERY_THROW );
261 xModelProperties->setPropertyValue( "ContextWritingMode", uno::Any( _nContextWritingMode ) );
263 catch( const uno::Exception& )
265 DBG_UNHANDLED_EXCEPTION("svx");
269 OUString SdrUnoObj::TakeObjNameSingul() const
271 OUString sName(SvxResId(STR_ObjNameSingulUno));
273 OUString aName(GetName());
274 if (!aName.isEmpty())
275 sName += " '" + aName + "'";
277 return sName;
280 OUString SdrUnoObj::TakeObjNamePlural() const
282 return SvxResId(STR_ObjNamePluralUno);
285 rtl::Reference<SdrObject> SdrUnoObj::CloneSdrObject(SdrModel& rTargetModel) const
287 return new SdrUnoObj(rTargetModel, *this);
290 void SdrUnoObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
292 SdrRectObj::NbcResize(rRef,xFact,yFact);
294 if (maGeo.nShearAngle==0_deg100 && maGeo.nRotationAngle==0_deg100)
295 return;
297 // small correctors
298 if (maGeo.nRotationAngle>=9000_deg100 && maGeo.nRotationAngle<27000_deg100)
300 moveRectangle(getRectangle().Left() - getRectangle().Right(), getRectangle().Top() - getRectangle().Bottom());
303 maGeo.nRotationAngle = 0_deg100;
304 maGeo.nShearAngle = 0_deg100;
305 maGeo.mfSinRotationAngle = 0.0;
306 maGeo.mfCosRotationAngle = 1.0;
307 maGeo.mfTanShearAngle = 0.0;
308 SetBoundAndSnapRectsDirty();
312 bool SdrUnoObj::hasSpecialDrag() const
314 // no special drag; we have no rounding rect and
315 // do want frame handles
316 return false;
319 void SdrUnoObj::NbcSetLayer( SdrLayerID _nLayer )
321 if ( GetLayer() == _nLayer )
322 { // redundant call -> not interested in doing anything here
323 SdrRectObj::NbcSetLayer( _nLayer );
324 return;
327 // we need some special handling here in case we're moved from an invisible layer
328 // to a visible one, or vice versa
329 // (relative to a layer. Remember that the visibility of a layer is a view attribute
330 // - the same layer can be visible in one view, and invisible in another view, at the
331 // same time)
333 // collect all views in which our old layer is visible
334 o3tl::sorted_vector< SdrView* > aPreviouslyVisible;
337 SdrViewIter aIter( this );
338 for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() )
339 aPreviouslyVisible.insert( pView );
342 SdrRectObj::NbcSetLayer( _nLayer );
344 // collect all views in which our new layer is visible
345 o3tl::sorted_vector< SdrView* > aNewlyVisible;
348 SdrViewIter aIter( this );
349 for ( SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView() )
351 if ( aPreviouslyVisible.erase(pView) == 0 )
353 // in pView, we were visible _before_ the layer change, and are
354 // _not_ visible after the layer change
355 // => remember this view, as our visibility there changed
356 aNewlyVisible.insert( pView );
361 // now aPreviouslyVisible contains all views where we became invisible
362 for (const auto& rpView : aPreviouslyVisible)
364 lcl_ensureControlVisibility( rpView, this, false );
367 // and aNewlyVisible all views where we became visible
368 for (const auto& rpView : aNewlyVisible)
370 lcl_ensureControlVisibility( rpView, this, true );
374 void SdrUnoObj::CreateUnoControlModel(const OUString& rModelName)
376 DBG_ASSERT(!xUnoControlModel.is(), "model already exists");
378 aUnoControlModelTypeName = rModelName;
380 uno::Reference< awt::XControlModel > xModel;
381 uno::Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
382 if (!aUnoControlModelTypeName.isEmpty() )
384 xModel.set(xContext->getServiceManager()->createInstanceWithContext(
385 aUnoControlModelTypeName, xContext), uno::UNO_QUERY);
387 if (xModel.is())
388 SetChanged();
391 SetUnoControlModel(xModel);
394 void SdrUnoObj::CreateUnoControlModel(const OUString& rModelName,
395 const uno::Reference< lang::XMultiServiceFactory >& rxSFac)
397 DBG_ASSERT(!xUnoControlModel.is(), "model already exists");
399 aUnoControlModelTypeName = rModelName;
401 uno::Reference< awt::XControlModel > xModel;
402 if (!aUnoControlModelTypeName.isEmpty() && rxSFac.is() )
404 xModel.set(rxSFac->createInstance(aUnoControlModelTypeName), uno::UNO_QUERY);
406 if (xModel.is())
407 SetChanged();
410 SetUnoControlModel(xModel);
413 void SdrUnoObj::SetUnoControlModel( const uno::Reference< awt::XControlModel >& xModel)
415 if (xUnoControlModel.is())
417 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
418 if (xComp.is())
419 m_pImpl->pEventListener->StopListening(xComp);
422 xUnoControlModel = xModel;
424 // control model has to contain service name of the control
425 if (xUnoControlModel.is())
427 uno::Reference< beans::XPropertySet > xSet(xUnoControlModel, uno::UNO_QUERY);
428 if (xSet.is())
430 uno::Any aValue( xSet->getPropertyValue("DefaultControl") );
431 OUString aStr;
432 if( aValue >>= aStr )
433 aUnoControlTypeName = aStr;
436 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
437 if (xComp.is())
438 m_pImpl->pEventListener->StartListening(xComp);
441 // invalidate all ViewObject contacts
442 ViewContactOfUnoControl* pVC = nullptr;
443 if ( impl_getViewContact( pVC ) )
445 // flushViewObjectContacts() removes all existing VOCs for the local DrawHierarchy. This
446 // is always allowed since they will be re-created on demand (and with the changed model)
447 GetViewContact().flushViewObjectContacts();
452 uno::Reference< awt::XControl > SdrUnoObj::GetUnoControl(const SdrView& _rView, const OutputDevice& _rOut) const
454 uno::Reference< awt::XControl > xControl;
456 SdrPageView* pPageView = _rView.GetSdrPageView();
457 OSL_ENSURE( pPageView && getSdrPageFromSdrObject() == pPageView->GetPage(), "SdrUnoObj::GetUnoControl: This object is not displayed in that particular view!" );
458 if ( !pPageView || getSdrPageFromSdrObject() != pPageView->GetPage() )
459 return nullptr;
461 SdrPageWindow* pPageWindow = pPageView->FindPageWindow( _rOut );
462 OSL_ENSURE( pPageWindow, "SdrUnoObj::GetUnoControl: did not find my SdrPageWindow!" );
463 if ( !pPageWindow )
464 return nullptr;
466 ViewObjectContact& rViewObjectContact( GetViewContact().GetViewObjectContact( pPageWindow->GetObjectContact() ) );
467 ViewObjectContactOfUnoControl* pUnoContact = dynamic_cast< ViewObjectContactOfUnoControl* >( &rViewObjectContact );
468 OSL_ENSURE( pUnoContact, "SdrUnoObj::GetUnoControl: wrong contact type!" );
469 if ( pUnoContact )
470 xControl = pUnoContact->getControl();
472 return xControl;
476 uno::Reference< awt::XControl > SdrUnoObj::GetTemporaryControlForWindow(
477 const vcl::Window& _rWindow, uno::Reference< awt::XControlContainer >& _inout_ControlContainer ) const
479 uno::Reference< awt::XControl > xControl;
481 ViewContactOfUnoControl* pVC = nullptr;
482 if ( impl_getViewContact( pVC ) )
483 xControl = pVC->getTemporaryControlForWindow( _rWindow, _inout_ControlContainer );
485 return xControl;
489 bool SdrUnoObj::impl_getViewContact( ViewContactOfUnoControl*& _out_rpContact ) const
491 ViewContact& rViewContact( GetViewContact() );
492 _out_rpContact = dynamic_cast< ViewContactOfUnoControl* >( &rViewContact );
493 DBG_ASSERT( _out_rpContact, "SdrUnoObj::impl_getViewContact: could not find my ViewContact!" );
494 return ( _out_rpContact != nullptr );
498 std::unique_ptr<sdr::contact::ViewContact> SdrUnoObj::CreateObjectSpecificViewContact()
500 return std::make_unique<sdr::contact::ViewContactOfUnoControl>( *this );
504 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */