bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / svdraw / svdouno.cxx
blobaac9a6d8711ff24d7d9332581851cf88d46df080
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/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>
47 #include <set>
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;
57 // Defines
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 >
70 protected:
71 SdrUnoObj* pObj;
73 public:
74 SdrControlEventListenerImpl(SdrUnoObj* _pObj)
75 : pObj(_pObj)
78 // XEventListener
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);
85 // XEventListener
86 void SAL_CALL SdrControlEventListenerImpl::disposing( const ::com::sun::star::lang::EventObject& /*Source*/)
87 throw(::com::sun::star::uno::RuntimeException, std::exception)
89 if (pObj)
91 pObj->xUnoControlModel = NULL;
95 void SdrControlEventListenerImpl::StopListening(const uno::Reference< lang::XComponent >& xComp)
97 if (xComp.is())
98 xComp->removeEventListener(this);
101 void SdrControlEventListenerImpl::StartListening(const uno::Reference< lang::XComponent >& xComp)
103 if (xComp.is())
104 xComp->addEventListener(this);
108 struct SdrUnoObjDataHolder
110 mutable ::rtl::Reference< SdrControlEventListenerImpl >
111 pEventListener;
115 namespace
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!" );
123 if ( !pPageView )
124 return;
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!" );
132 if ( !pPageWindow )
133 continue;
135 if ( !pPageWindow->HasObjectContact() )
136 continue;
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 )
143 continue;
145 pUnoControlContact->ensureControlVisibility( _bVisible );
150 TYPEINIT1(SdrUnoObj, SdrRectObj);
152 SdrUnoObj::SdrUnoObj(const OUString& rModelName, bool _bOwnUnoControlModel)
153 : m_pImpl( new SdrUnoObjDataHolder ),
154 bOwnUnoControlModel( _bOwnUnoControlModel )
156 bIsUnoObj = true;
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 )
171 bIsUnoObj = true;
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);
186 if (xComp.is())
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())
191 xComp->dispose();
192 else
193 m_pImpl->pEventListener->StopListening(xComp);
196 catch( const uno::Exception& )
198 OSL_FAIL( "SdrUnoObj::~SdrUnoObj: caught an exception!" );
200 delete m_pImpl;
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())
260 sName.append(' ');
261 sName.append('\'');
262 sName.append(aName);
263 sName.append('\'');
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)
281 if( this == &rObj )
282 return *this;
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);
308 if (xSet.is())
310 uno::Any aValue( xSet->getPropertyValue("DefaultControl") );
311 OUString aStr;
313 if( aValue >>= aStr )
314 aUnoControlTypeName = aStr;
317 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
318 if (xComp.is())
319 m_pImpl->pEventListener->StartListening(xComp);
320 return *this;
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)
329 // small correctures
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;
337 aGeo.nSin = 0.0;
338 aGeo.nCos = 1.0;
339 aGeo.nTan = 0.0;
340 SetRectsDirty();
346 bool SdrUnoObj::hasSpecialDrag() const
348 // no special drag; we have no rounding rect and
349 // do want frame handles
350 return false;
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
357 // enabled
358 static bool bDoSupportFullDrag(true);
360 return bDoSupportFullDrag;
363 SdrObject* SdrUnoObj::getFullDragClone() const
365 SdrObject* pRetval = 0;
366 static bool bHandleSpecial(false);
368 if(bHandleSpecial)
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());
375 else
377 // call parent (simply clone)
378 pRetval = SdrRectObj::getFullDragClone();
381 return pRetval;
385 void SdrUnoObj::NbcSetLayer( SdrLayerID _nLayer )
387 if ( GetLayer() == _nLayer )
388 { // redundant call -> not interested in doing anything here
389 SdrRectObj::NbcSetLayer( _nLayer );
390 return;
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
397 // same time)
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 );
424 else
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();
438 ++aLoopViews
441 lcl_ensureControlVisibility( *aLoopViews, this, false );
444 // and aNewlyVisible all views where we became visible
445 for ( aLoopViews = aNewlyVisible.begin();
446 aLoopViews != aNewlyVisible.end();
447 ++aLoopViews
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);
467 if (xModel.is())
468 SetChanged();
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);
487 if (xModel.is())
488 SetChanged();
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);
499 if (xComp.is())
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);
509 if (xSet.is())
511 uno::Any aValue( xSet->getPropertyValue("DefaultControl") );
512 OUString aStr;
513 if( aValue >>= aStr )
514 aUnoControlTypeName = aStr;
517 uno::Reference< lang::XComponent > xComp(xUnoControlModel, uno::UNO_QUERY);
518 if (xComp.is())
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() )
540 return NULL;
542 SdrPageWindow* pPageWindow = pPageView->FindPageWindow( _rOut );
543 OSL_ENSURE( pPageWindow, "SdrUnoObj::GetUnoControl: did not find my SdrPageWindow!" );
544 if ( !pPageWindow )
545 return NULL;
547 ViewObjectContact& rViewObjectContact( GetViewContact().GetViewObjectContact( pPageWindow->GetObjectContact() ) );
548 ViewObjectContactOfUnoControl* pUnoContact = dynamic_cast< ViewObjectContactOfUnoControl* >( &rViewObjectContact );
549 OSL_ENSURE( pUnoContact, "SdrUnoObj::GetUnoControl: wrong contact type!" );
550 if ( pUnoContact )
551 xControl = pUnoContact->getControl();
553 return xControl;
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 );
566 return xControl;
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: */