1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
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
>
62 explicit SdrControlEventListenerImpl(SdrUnoObj
* _pObj
)
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
);
74 void SAL_CALL
SdrControlEventListenerImpl::disposing( const css::lang::EventObject
& /*Source*/)
78 pObj
->xUnoControlModel
= nullptr;
82 void SdrControlEventListenerImpl::StopListening(const uno::Reference
< lang::XComponent
>& xComp
)
85 xComp
->removeEventListener(this);
88 void SdrControlEventListenerImpl::StartListening(const uno::Reference
< lang::XComponent
>& xComp
)
91 xComp
->addEventListener(this);
95 struct SdrUnoObjDataHolder
97 mutable ::rtl::Reference
< SdrControlEventListenerImpl
>
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!" );
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!" );
122 if ( !pPageWindow
->HasObjectContact() )
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
)
132 pUnoControlContact
->ensureControlVisibility( _bVisible
);
137 SdrUnoObj::SdrUnoObj(
139 const OUString
& rModelName
)
140 : SdrRectObj(rSdrModel
),
141 m_pImpl( new SdrUnoObjDataHolder
)
145 m_pImpl
->pEventListener
= new SdrControlEventListenerImpl(this);
147 // only an owner may create independently
148 if (!rModelName
.isEmpty())
149 CreateUnoControlModel(rModelName
);
152 SdrUnoObj::SdrUnoObj(
154 const OUString
& rModelName
,
155 const uno::Reference
< lang::XMultiServiceFactory
>& rxSFac
)
156 : SdrRectObj(rSdrModel
),
157 m_pImpl( new SdrUnoObjDataHolder
)
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
);
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())
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
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())
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
)
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
);
283 uno::Any
aValue( xSet
->getPropertyValue("DefaultControl") );
286 if( aValue
>>= aStr
)
287 aUnoControlTypeName
= aStr
;
290 uno::Reference
< lang::XComponent
> xComp(xUnoControlModel
, uno::UNO_QUERY
);
292 m_pImpl
->pEventListener
->StartListening(xComp
);
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)
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;
318 bool SdrUnoObj::hasSpecialDrag() const
320 // no special drag; we have no rounding rect and
321 // do want frame handles
325 void SdrUnoObj::NbcSetLayer( SdrLayerID _nLayer
)
327 if ( GetLayer() == _nLayer
)
328 { // redundant call -> not interested in doing anything here
329 SdrRectObj::NbcSetLayer( _nLayer
);
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
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
);
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
);
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
);
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
);
436 uno::Any
aValue( xSet
->getPropertyValue("DefaultControl") );
438 if( aValue
>>= aStr
)
439 aUnoControlTypeName
= aStr
;
442 uno::Reference
< lang::XComponent
> xComp(xUnoControlModel
, uno::UNO_QUERY
);
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() )
467 SdrPageWindow
* pPageWindow
= pPageView
->FindPageWindow( _rOut
);
468 OSL_ENSURE( pPageWindow
, "SdrUnoObj::GetUnoControl: did not find my SdrPageWindow!" );
472 ViewObjectContact
& rViewObjectContact( GetViewContact().GetViewObjectContact( pPageWindow
->GetObjectContact() ) );
473 ViewObjectContactOfUnoControl
* pUnoContact
= dynamic_cast< ViewObjectContactOfUnoControl
* >( &rViewObjectContact
);
474 OSL_ENSURE( pUnoContact
, "SdrUnoObj::GetUnoControl: wrong contact type!" );
476 xControl
= pUnoContact
->getControl();
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
);
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: */