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/awt/XWindow.hpp>
24 #include <com/sun/star/awt/PosSize.hpp>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <com/sun/star/io/XPersistObject.hpp>
27 #include <com/sun/star/io/XOutputStream.hpp>
28 #include <com/sun/star/io/XInputStream.hpp>
29 #include <com/sun/star/io/XActiveDataSink.hpp>
30 #include <com/sun/star/io/XActiveDataSource.hpp>
31 #include <com/sun/star/io/XObjectOutputStream.hpp>
32 #include <com/sun/star/io/XObjectInputStream.hpp>
33 #include <com/sun/star/util/XCloneable.hpp>
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/types.hxx>
36 #include <vcl/pdfextoutdevdata.hxx>
37 #include <svx/svdouno.hxx>
38 #include <svx/svdpagv.hxx>
39 #include <svx/svdmodel.hxx>
40 #include "svdglob.hxx"
41 #include "svx/svdstr.hrc"
42 #include <svx/svdetc.hxx>
43 #include <svx/svdview.hxx>
44 #include <svx/svdorect.hxx>
45 #include "svx/svdviter.hxx"
46 #include <rtl/ref.hxx>
48 #include <svx/sdrpagewindow.hxx>
49 #include <svx/sdrpaintwindow.hxx>
50 #include <tools/diagnose_ex.h>
51 #include <svx/svdograf.hxx>
53 using namespace ::com::sun::star
;
54 using namespace sdr::contact
;
61 // Helper class SdrControlEventListenerImpl
63 #include <com/sun/star/lang/XEventListener.hpp>
65 #include <cppuhelper/implbase1.hxx>
68 class SdrControlEventListenerImpl
: public ::cppu::WeakImplHelper1
< ::com::sun::star::lang::XEventListener
>
74 SdrControlEventListenerImpl(SdrUnoObj
* _pObj
)
79 virtual void SAL_CALL
disposing( const ::com::sun::star::lang::EventObject
& Source
) throw(::com::sun::star::uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
81 void StopListening(const uno::Reference
< lang::XComponent
>& xComp
);
82 void StartListening(const uno::Reference
< lang::XComponent
>& xComp
);
86 void SAL_CALL
SdrControlEventListenerImpl::disposing( const ::com::sun::star::lang::EventObject
& /*Source*/)
87 throw(::com::sun::star::uno::RuntimeException
, std::exception
)
91 pObj
->xUnoControlModel
= NULL
;
95 void SdrControlEventListenerImpl::StopListening(const uno::Reference
< lang::XComponent
>& xComp
)
98 xComp
->removeEventListener(this);
101 void SdrControlEventListenerImpl::StartListening(const uno::Reference
< lang::XComponent
>& xComp
)
104 xComp
->addEventListener(this);
108 struct SdrUnoObjDataHolder
110 mutable ::rtl::Reference
< SdrControlEventListenerImpl
>
117 void lcl_ensureControlVisibility( SdrView
* _pView
, const SdrUnoObj
* _pObject
, bool _bVisible
)
119 OSL_PRECOND( _pObject
, "lcl_ensureControlVisibility: no object -> no survival!" );
121 SdrPageView
* pPageView
= _pView
? _pView
->GetSdrPageView() : NULL
;
122 DBG_ASSERT( pPageView
, "lcl_ensureControlVisibility: no view found!" );
126 ViewContact
& rUnoControlContact( _pObject
->GetViewContact() );
128 for ( sal_uInt32 i
= 0; i
< pPageView
->PageWindowCount(); ++i
)
130 SdrPageWindow
* pPageWindow
= pPageView
->GetPageWindow( i
);
131 DBG_ASSERT( pPageWindow
, "lcl_ensureControlVisibility: invalid PageViewWindow!" );
135 if ( !pPageWindow
->HasObjectContact() )
138 ObjectContact
& rPageViewContact( pPageWindow
->GetObjectContact() );
139 const ViewObjectContact
& rViewObjectContact( rUnoControlContact
.GetViewObjectContact( rPageViewContact
) );
140 const ViewObjectContactOfUnoControl
* pUnoControlContact
= dynamic_cast< const ViewObjectContactOfUnoControl
* >( &rViewObjectContact
);
141 DBG_ASSERT( pUnoControlContact
, "lcl_ensureControlVisibility: wrong ViewObjectContact type!" );
142 if ( !pUnoControlContact
)
145 pUnoControlContact
->ensureControlVisibility( _bVisible
);
150 TYPEINIT1(SdrUnoObj
, SdrRectObj
);
152 SdrUnoObj::SdrUnoObj(const OUString
& rModelName
, bool _bOwnUnoControlModel
)
153 : m_pImpl( new SdrUnoObjDataHolder
),
154 bOwnUnoControlModel( _bOwnUnoControlModel
)
158 m_pImpl
->pEventListener
= new SdrControlEventListenerImpl(this);
160 // only an owner may create independently
161 if (!rModelName
.isEmpty())
162 CreateUnoControlModel(rModelName
);
165 SdrUnoObj::SdrUnoObj(const OUString
& rModelName
,
166 const uno::Reference
< lang::XMultiServiceFactory
>& rxSFac
,
167 bool _bOwnUnoControlModel
)
168 : m_pImpl( new SdrUnoObjDataHolder
),
169 bOwnUnoControlModel( _bOwnUnoControlModel
)
173 m_pImpl
->pEventListener
= new SdrControlEventListenerImpl(this);
175 // only an owner may create independently
176 if (!rModelName
.isEmpty())
177 CreateUnoControlModel(rModelName
,rxSFac
);
180 SdrUnoObj::~SdrUnoObj()
184 // clean up the control model
185 uno::Reference
< lang::XComponent
> xComp(xUnoControlModel
, uno::UNO_QUERY
);
188 // is the control model owned by its environment?
189 uno::Reference
< container::XChild
> xContent(xUnoControlModel
, uno::UNO_QUERY
);
190 if (xContent
.is() && !xContent
->getParent().is())
193 m_pImpl
->pEventListener
->StopListening(xComp
);
196 catch( const uno::Exception
& )
198 OSL_FAIL( "SdrUnoObj::~SdrUnoObj: caught an exception!" );
203 void SdrUnoObj::SetModel(SdrModel
* pNewModel
)
205 SdrRectObj::SetModel(pNewModel
);
208 void SdrUnoObj::SetPage(SdrPage
* pNewPage
)
210 SdrRectObj::SetPage(pNewPage
);
213 void SdrUnoObj::TakeObjInfo(SdrObjTransformInfoRec
& rInfo
) const
215 rInfo
.bRotateFreeAllowed
= false;
216 rInfo
.bRotate90Allowed
= false;
217 rInfo
.bMirrorFreeAllowed
= false;
218 rInfo
.bMirror45Allowed
= false;
219 rInfo
.bMirror90Allowed
= false;
220 rInfo
.bTransparenceAllowed
= false;
221 rInfo
.bGradientAllowed
= false;
222 rInfo
.bShearAllowed
= false;
223 rInfo
.bEdgeRadiusAllowed
= false;
224 rInfo
.bNoOrthoDesired
= false;
225 rInfo
.bCanConvToPath
= false;
226 rInfo
.bCanConvToPoly
= false;
227 rInfo
.bCanConvToPathLineToArea
= false;
228 rInfo
.bCanConvToPolyLineToArea
= false;
229 rInfo
.bCanConvToContour
= false;
232 sal_uInt16
SdrUnoObj::GetObjIdentifier() const
234 return sal_uInt16(OBJ_UNO
);
237 void SdrUnoObj::SetContextWritingMode( const sal_Int16 _nContextWritingMode
)
241 uno::Reference
< beans::XPropertySet
> xModelProperties( GetUnoControlModel(), uno::UNO_QUERY_THROW
);
242 xModelProperties
->setPropertyValue(
243 OUString( "ContextWritingMode" ),
244 uno::makeAny( _nContextWritingMode
)
247 catch( const uno::Exception
& )
249 DBG_UNHANDLED_EXCEPTION();
253 OUString
SdrUnoObj::TakeObjNameSingul() const
255 OUStringBuffer
sName(ImpGetResStr(STR_ObjNameSingulUno
));
257 OUString
aName(GetName());
258 if (!aName
.isEmpty())
266 return sName
.makeStringAndClear();
269 OUString
SdrUnoObj::TakeObjNamePlural() const
271 return ImpGetResStr(STR_ObjNamePluralUno
);
274 SdrUnoObj
* SdrUnoObj::Clone() const
276 return CloneHelper
< SdrUnoObj
>();
279 SdrUnoObj
& SdrUnoObj::operator= (const SdrUnoObj
& rObj
)
283 SdrRectObj::operator= (rObj
);
285 // release the reference to the current control model
286 SetUnoControlModel( NULL
);
288 aUnoControlModelTypeName
= rObj
.aUnoControlModelTypeName
;
289 aUnoControlTypeName
= rObj
.aUnoControlTypeName
;
291 // copy the uno control model
292 const uno::Reference
< awt::XControlModel
> xSourceControlModel( rObj
.GetUnoControlModel(), uno::UNO_QUERY
);
293 if ( xSourceControlModel
.is() )
297 uno::Reference
< util::XCloneable
> xClone( xSourceControlModel
, uno::UNO_QUERY_THROW
);
298 xUnoControlModel
.set( xClone
->createClone(), uno::UNO_QUERY_THROW
);
300 catch( const uno::Exception
& )
302 DBG_UNHANDLED_EXCEPTION();
306 // get service name of the control from the control model
307 uno::Reference
< beans::XPropertySet
> xSet(xUnoControlModel
, uno::UNO_QUERY
);
310 uno::Any
aValue( xSet
->getPropertyValue("DefaultControl") );
313 if( aValue
>>= aStr
)
314 aUnoControlTypeName
= aStr
;
317 uno::Reference
< lang::XComponent
> xComp(xUnoControlModel
, uno::UNO_QUERY
);
319 m_pImpl
->pEventListener
->StartListening(xComp
);
323 void SdrUnoObj::NbcResize(const Point
& rRef
, const Fraction
& xFact
, const Fraction
& yFact
)
325 SdrRectObj::NbcResize(rRef
,xFact
,yFact
);
327 if (aGeo
.nShearAngle
!=0 || aGeo
.nRotationAngle
!=0)
330 if (aGeo
.nRotationAngle
>=9000 && aGeo
.nRotationAngle
<27000)
332 maRect
.Move(maRect
.Left()-maRect
.Right(),maRect
.Top()-maRect
.Bottom());
335 aGeo
.nRotationAngle
= 0;
336 aGeo
.nShearAngle
= 0;
346 bool SdrUnoObj::hasSpecialDrag() const
348 // no special drag; we have no rounding rect and
349 // do want frame handles
353 bool SdrUnoObj::supportsFullDrag() const
355 // override to have the possibility to enable/disable in debug and
356 // to check some things out. Current solution is working, so default is
358 static bool bDoSupportFullDrag(true);
360 return bDoSupportFullDrag
;
363 SdrObject
* SdrUnoObj::getFullDragClone() const
365 SdrObject
* pRetval
= 0;
366 static bool bHandleSpecial(false);
370 // special handling for SdrUnoObj (FormControl). Create a SdrGrafObj
371 // for drag containing the graphical representation. This does not work too
372 // well, so the default is to simply clone
373 pRetval
= new SdrGrafObj(SdrDragView::GetObjGraphic(GetModel(), this), GetLogicRect());
377 // call parent (simply clone)
378 pRetval
= SdrRectObj::getFullDragClone();
385 void SdrUnoObj::NbcSetLayer( SdrLayerID _nLayer
)
387 if ( GetLayer() == _nLayer
)
388 { // redundant call -> not interested in doing anything here
389 SdrRectObj::NbcSetLayer( _nLayer
);
393 // we need some special handling here in case we're moved from an invisible layer
394 // to a visible one, or vice versa
395 // (relative to a layer. Remember that the visibility of a layer is a view attribute
396 // - the same layer can be visible in one view, and invisible in another view, at the
399 // collect all views in which our old layer is visible
400 ::std::set
< SdrView
* > aPreviouslyVisible
;
403 SdrViewIter
aIter( this );
404 for ( SdrView
* pView
= aIter
.FirstView(); pView
; pView
= aIter
.NextView() )
405 aPreviouslyVisible
.insert( pView
);
408 SdrRectObj::NbcSetLayer( _nLayer
);
410 // collect all views in which our new layer is visible
411 ::std::set
< SdrView
* > aNewlyVisible
;
414 SdrViewIter
aIter( this );
415 for ( SdrView
* pView
= aIter
.FirstView(); pView
; pView
= aIter
.NextView() )
417 ::std::set
< SdrView
* >::const_iterator aPrevPos
= aPreviouslyVisible
.find( pView
);
418 if ( aPreviouslyVisible
.end() != aPrevPos
)
419 { // in pView, we were visible _before_ the layer change, and are
420 // visible _after_ the layer change, too
421 // -> we're not interested in this view at all
422 aPreviouslyVisible
.erase( aPrevPos
);
426 // in pView, we were visible _before_ the layer change, and are
427 // _not_ visible after the layer change
428 // => remember this view, as our visibility there changed
429 aNewlyVisible
.insert( pView
);
434 // now aPreviouslyVisible contains all views where we became invisible
435 ::std::set
< SdrView
* >::const_iterator aLoopViews
;
436 for ( aLoopViews
= aPreviouslyVisible
.begin();
437 aLoopViews
!= aPreviouslyVisible
.end();
441 lcl_ensureControlVisibility( *aLoopViews
, this, false );
444 // and aNewlyVisible all views where we became visible
445 for ( aLoopViews
= aNewlyVisible
.begin();
446 aLoopViews
!= aNewlyVisible
.end();
450 lcl_ensureControlVisibility( *aLoopViews
, this, true );
454 void SdrUnoObj::CreateUnoControlModel(const OUString
& rModelName
)
456 DBG_ASSERT(!xUnoControlModel
.is(), "model already exists");
458 aUnoControlModelTypeName
= rModelName
;
460 uno::Reference
< awt::XControlModel
> xModel
;
461 uno::Reference
< uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
462 if (!aUnoControlModelTypeName
.isEmpty() )
464 xModel
= uno::Reference
< awt::XControlModel
>(xContext
->getServiceManager()->createInstanceWithContext(
465 aUnoControlModelTypeName
, xContext
), uno::UNO_QUERY
);
471 SetUnoControlModel(xModel
);
474 void SdrUnoObj::CreateUnoControlModel(const OUString
& rModelName
,
475 const uno::Reference
< lang::XMultiServiceFactory
>& rxSFac
)
477 DBG_ASSERT(!xUnoControlModel
.is(), "model already exists");
479 aUnoControlModelTypeName
= rModelName
;
481 uno::Reference
< awt::XControlModel
> xModel
;
482 if (!aUnoControlModelTypeName
.isEmpty() && rxSFac
.is() )
484 xModel
= uno::Reference
< awt::XControlModel
>(rxSFac
->createInstance(
485 aUnoControlModelTypeName
), uno::UNO_QUERY
);
491 SetUnoControlModel(xModel
);
494 void SdrUnoObj::SetUnoControlModel( const uno::Reference
< awt::XControlModel
>& xModel
)
496 if (xUnoControlModel
.is())
498 uno::Reference
< lang::XComponent
> xComp(xUnoControlModel
, uno::UNO_QUERY
);
500 m_pImpl
->pEventListener
->StopListening(xComp
);
503 xUnoControlModel
= xModel
;
505 // control model has to contain service name of the control
506 if (xUnoControlModel
.is())
508 uno::Reference
< beans::XPropertySet
> xSet(xUnoControlModel
, uno::UNO_QUERY
);
511 uno::Any
aValue( xSet
->getPropertyValue("DefaultControl") );
513 if( aValue
>>= aStr
)
514 aUnoControlTypeName
= aStr
;
517 uno::Reference
< lang::XComponent
> xComp(xUnoControlModel
, uno::UNO_QUERY
);
519 m_pImpl
->pEventListener
->StartListening(xComp
);
522 // invalidate all ViewObject contacts
523 ViewContactOfUnoControl
* pVC
= NULL
;
524 if ( impl_getViewContact( pVC
) )
526 // flushViewObjectContacts() removes all existing VOCs for the local DrawHierarchy. This
527 // is always allowed since they will be re-created on demand (and with the changed model)
528 GetViewContact().flushViewObjectContacts(true);
533 uno::Reference
< awt::XControl
> SdrUnoObj::GetUnoControl(const SdrView
& _rView
, const OutputDevice
& _rOut
) const
535 uno::Reference
< awt::XControl
> xControl
;
537 SdrPageView
* pPageView
= _rView
.GetSdrPageView();
538 OSL_ENSURE( pPageView
&& GetPage() == pPageView
->GetPage(), "SdrUnoObj::GetUnoControl: This object is not displayed in that particular view!" );
539 if ( !pPageView
|| GetPage() != pPageView
->GetPage() )
542 SdrPageWindow
* pPageWindow
= pPageView
->FindPageWindow( _rOut
);
543 OSL_ENSURE( pPageWindow
, "SdrUnoObj::GetUnoControl: did not find my SdrPageWindow!" );
547 ViewObjectContact
& rViewObjectContact( GetViewContact().GetViewObjectContact( pPageWindow
->GetObjectContact() ) );
548 ViewObjectContactOfUnoControl
* pUnoContact
= dynamic_cast< ViewObjectContactOfUnoControl
* >( &rViewObjectContact
);
549 OSL_ENSURE( pUnoContact
, "SdrUnoObj::GetUnoControl: wrong contact type!" );
551 xControl
= pUnoContact
->getControl();
557 uno::Reference
< awt::XControl
> SdrUnoObj::GetTemporaryControlForWindow(
558 const vcl::Window
& _rWindow
, uno::Reference
< awt::XControlContainer
>& _inout_ControlContainer
) const
560 uno::Reference
< awt::XControl
> xControl
;
562 ViewContactOfUnoControl
* pVC
= NULL
;
563 if ( impl_getViewContact( pVC
) )
564 xControl
= pVC
->getTemporaryControlForWindow( _rWindow
, _inout_ControlContainer
);
570 bool SdrUnoObj::impl_getViewContact( ViewContactOfUnoControl
*& _out_rpContact
) const
572 ViewContact
& rViewContact( GetViewContact() );
573 _out_rpContact
= dynamic_cast< ViewContactOfUnoControl
* >( &rViewContact
);
574 DBG_ASSERT( _out_rpContact
, "SdrUnoObj::impl_getViewContact: could not find my ViewContact!" );
575 return ( _out_rpContact
!= NULL
);
579 sdr::contact::ViewContact
* SdrUnoObj::CreateObjectSpecificViewContact()
581 return new sdr::contact::ViewContactOfUnoControl( *this );
585 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */