Update ooo320-m1
[ooovba.git] / svx / source / sdr / contact / viewobjectcontactofunocontrol.cxx
blob90295f7ce678b8d168b79c2f7545bde840504d81
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: viewobjectcontactofunocontrol.cxx,v $
10 * $Revision: 1.18 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <svx/sdr/contact/viewobjectcontactofunocontrol.hxx>
35 #include <svx/sdr/contact/viewcontactofunocontrol.hxx>
36 #include <svx/sdr/contact/displayinfo.hxx>
37 #include <svx/sdr/properties/properties.hxx>
38 #include <svx/sdr/contact/objectcontactofpageview.hxx>
39 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
40 #include <svx/svdouno.hxx>
41 #include <svx/svdpagv.hxx>
42 #include <svx/svdview.hxx>
43 #include <svx/sdrpagewindow.hxx>
44 #include "sdrpaintwindow.hxx"
46 /** === begin UNO includes === **/
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/awt/XControl.hpp>
49 #include <com/sun/star/awt/XControlModel.hpp>
50 #include <com/sun/star/awt/XControlContainer.hpp>
51 #include <com/sun/star/awt/XWindow2.hpp>
52 #include <com/sun/star/awt/PosSize.hpp>
53 #include <com/sun/star/awt/XView.hpp>
54 #include <com/sun/star/beans/XPropertySet.hpp>
55 #include <com/sun/star/lang/XComponent.hpp>
56 #include <com/sun/star/awt/InvalidateStyle.hpp>
57 #include <com/sun/star/util/XModeChangeListener.hpp>
58 #include <com/sun/star/util/XModeChangeBroadcaster.hpp>
59 #include <com/sun/star/container/XContainerListener.hpp>
60 #include <com/sun/star/container/XContainer.hpp>
61 /** === end UNO includes === **/
63 #include <toolkit/helper/formpdfexport.hxx>
64 #include <vcl/pdfextoutdevdata.hxx>
65 #include <vcl/svapp.hxx>
66 #include <vos/mutex.hxx>
67 #include <comphelper/processfactory.hxx>
68 #include <comphelper/scopeguard.hxx>
69 #include <cppuhelper/implbase4.hxx>
70 #include <toolkit/helper/vclunohelper.hxx>
71 #include <tools/diagnose_ex.h>
72 #include <basegfx/matrix/b2dhommatrix.hxx>
73 #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
75 #include <boost/shared_ptr.hpp>
76 #include <boost/bind.hpp>
78 //........................................................................
79 namespace sdr { namespace contact {
80 //........................................................................
82 /** === begin UNO using === **/
83 using namespace ::com::sun::star::awt::InvalidateStyle;
84 using ::com::sun::star::uno::Reference;
85 using ::com::sun::star::uno::XInterface;
86 using ::com::sun::star::uno::UNO_QUERY;
87 using ::com::sun::star::uno::UNO_QUERY_THROW;
88 using ::com::sun::star::uno::UNO_SET_THROW;
89 using ::com::sun::star::uno::Exception;
90 using ::com::sun::star::uno::RuntimeException;
91 using ::com::sun::star::awt::XControl;
92 using ::com::sun::star::lang::XMultiServiceFactory;
93 using ::com::sun::star::awt::XControlModel;
94 using ::com::sun::star::awt::XControlContainer;
95 using ::com::sun::star::awt::XWindow;
96 using ::com::sun::star::awt::XWindow2;
97 using ::com::sun::star::awt::XWindowListener;
98 using ::com::sun::star::awt::PosSize::POSSIZE;
99 using ::com::sun::star::awt::XView;
100 using ::com::sun::star::awt::XGraphics;
101 using ::com::sun::star::awt::WindowEvent;
102 using ::com::sun::star::beans::XPropertySet;
103 using ::com::sun::star::beans::XPropertySetInfo;
104 using ::com::sun::star::lang::XComponent;
105 using ::com::sun::star::awt::XWindowPeer;
106 using ::com::sun::star::beans::XPropertyChangeListener;
107 using ::com::sun::star::util::XModeChangeListener;
108 using ::com::sun::star::util::XModeChangeBroadcaster;
109 using ::com::sun::star::util::ModeChangeEvent;
110 using ::com::sun::star::lang::EventObject;
111 using ::com::sun::star::beans::PropertyChangeEvent;
112 using ::com::sun::star::lang::XComponent;
113 using ::com::sun::star::container::XContainerListener;
114 using ::com::sun::star::container::XContainer;
115 using ::com::sun::star::container::ContainerEvent;
116 using ::com::sun::star::uno::Any;
117 /** === end UNO using === **/
119 //====================================================================
120 //= ControlHolder
121 //====================================================================
122 class ControlHolder
124 private:
125 Reference< XControl > m_xControl;
126 Reference< XWindow2 > m_xControlWindow;
127 Reference< XView > m_xControlView;
129 public:
130 ControlHolder()
131 :m_xControl()
132 ,m_xControlWindow()
133 ,m_xControlView()
137 explicit ControlHolder( const Reference< XControl >& _rxControl )
138 :m_xControl()
139 ,m_xControlWindow()
140 ,m_xControlView()
142 *this = _rxControl;
145 ControlHolder& operator=( const Reference< XControl >& _rxControl )
147 clear();
149 m_xControl = _rxControl;
150 if ( m_xControl.is() )
152 m_xControlWindow.set( m_xControl, UNO_QUERY );
153 m_xControlView.set( m_xControl, UNO_QUERY );
154 if ( !m_xControlWindow.is() || !m_xControlView.is() )
156 OSL_ENSURE( false, "ControlHolder::operator=: invalid XControl, missing required interfaces!" );
157 clear();
161 return *this;
164 public:
165 inline bool is() const { return m_xControl.is() && m_xControlWindow.is() && m_xControlView.is(); }
166 inline void clear() { m_xControl.clear(); m_xControlWindow.clear(); m_xControlView.clear(); }
168 // delegators for the methods of the UNO interfaces
169 // Note all those will crash if called for a NULL object.
170 inline bool isDesignMode() const { return m_xControl->isDesignMode(); }
171 inline void setDesignMode( const bool _bDesign ) const { m_xControl->setDesignMode( _bDesign ); }
172 inline bool isVisible() const { return m_xControlWindow->isVisible(); }
173 inline void setVisible( const bool _bVisible ) const { m_xControlWindow->setVisible( _bVisible ); }
174 inline Reference< XControlModel >
175 getModel() const { return m_xControl->getModel(); }
176 inline void setModel( const Reference< XControlModel >& _m ) const { m_xControl->setModel( _m ); }
177 inline bool isTransparent() const { return m_xControl->isTransparent(); }
178 inline Reference< XWindowPeer >
179 getPeer() const { return m_xControl->getPeer(); }
181 inline void addWindowListener( const Reference< XWindowListener >& _l ) const { m_xControlWindow->addWindowListener( _l ); }
182 inline void removeWindowListener( const Reference< XWindowListener >& _l ) const { m_xControlWindow->removeWindowListener( _l ); }
183 void setPosSize( const Rectangle& _rPosSize ) const;
184 Rectangle
185 getPosSize() const;
186 void setZoom( const ::basegfx::B2DVector& _rScale ) const;
187 ::basegfx::B2DVector
188 getZoom() const;
190 inline void setGraphics( const Reference< XGraphics >& _g ) const { m_xControlView->setGraphics( _g ); }
191 inline Reference< XGraphics >
192 getGraphics() const { return m_xControlView->getGraphics(); }
193 inline void draw( const Point& _rTopLeft ) const { m_xControlView->draw( _rTopLeft.X(), _rTopLeft.Y() ); }
195 public:
196 inline const Reference< XControl >& getControl() const { return m_xControl; }
199 //--------------------------------------------------------------------
200 bool operator==( const ControlHolder& _rControl, const Reference< XInterface >& _rxCompare )
202 return _rControl.getControl() == _rxCompare;
205 //--------------------------------------------------------------------
206 bool operator==( const Reference< XInterface >& _rxCompare, const ControlHolder& _rControl )
208 return _rxCompare == _rControl.getControl();
211 //--------------------------------------------------------------------
212 bool operator==( const ControlHolder& _rControl, const Any& _rxCompare )
214 return _rControl == Reference< XInterface >( _rxCompare, UNO_QUERY );
217 //--------------------------------------------------------------------
218 bool operator==( const Any& _rxCompare, const ControlHolder& _rControl )
220 return Reference< XInterface >( _rxCompare, UNO_QUERY ) == _rControl;
223 //--------------------------------------------------------------------
224 void ControlHolder::setPosSize( const Rectangle& _rPosSize ) const
226 // no check whether we're valid, this is the responsibility of the caller
228 // don't call setPosSize when pos/size did not change
229 // #i104181# / 2009-08-18 / frank.schoenheit@sun.com
230 ::Rectangle aCurrentRect( getPosSize() );
231 if ( aCurrentRect != _rPosSize )
233 m_xControlWindow->setPosSize(
234 _rPosSize.Left(), _rPosSize.Top(), _rPosSize.GetWidth(), _rPosSize.GetHeight(),
235 POSSIZE
240 //--------------------------------------------------------------------
241 ::Rectangle ControlHolder::getPosSize() const
243 // no check whether we're valid, this is the responsibility of the caller
244 return VCLUnoHelper::ConvertToVCLRect( m_xControlWindow->getPosSize() );
247 //--------------------------------------------------------------------
248 void ControlHolder::setZoom( const ::basegfx::B2DVector& _rScale ) const
250 // no check whether we're valid, this is the responsibility of the caller
251 m_xControlView->setZoom( (float)_rScale.getX(), (float)_rScale.getY() );
254 //--------------------------------------------------------------------
255 ::basegfx::B2DVector ControlHolder::getZoom() const
257 // no check whether we're valid, this is the responsibility of the caller
259 // Argh. Why does XView have a setZoom only, but not a getZoom?
260 Window* pWindow = VCLUnoHelper::GetWindow( m_xControlWindow );
261 OSL_ENSURE( pWindow, "ControlHolder::setZoom: no implementation access!" );
263 ::basegfx::B2DVector aZoom( 1, 1 );
264 if ( pWindow )
266 const Fraction& rZoom( pWindow->GetZoom() );
267 aZoom.setX( (double)rZoom );
268 aZoom.setY( (double)rZoom );
270 return aZoom;
273 //====================================================================
274 //= UnoControlContactHelper
275 //====================================================================
276 class UnoControlContactHelper
278 public:
279 /** positions a control, and sets its zoom mode, using a given transformation and output device
281 static void adjustControlGeometry_throw(
282 const ControlHolder& _rControl,
283 const Rectangle& _rLogicBoundingRect,
284 const ::basegfx::B2DHomMatrix& _rViewTransformation,
285 const ::basegfx::B2DHomMatrix& _rZoomLevelNormalization
288 /** disposes the given control
290 static void disposeAndClearControl_nothrow(
291 ControlHolder& _rControl
294 private:
295 UnoControlContactHelper(); // never implemented
296 UnoControlContactHelper( const UnoControlContactHelper& ); // never implemented
297 UnoControlContactHelper& operator=( const UnoControlContactHelper& ); // never implemented
300 //--------------------------------------------------------------------
301 void UnoControlContactHelper::adjustControlGeometry_throw( const ControlHolder& _rControl, const Rectangle& _rLogicBoundingRect,
302 const basegfx::B2DHomMatrix& _rViewTransformation, const ::basegfx::B2DHomMatrix& _rZoomLevelNormalization )
304 OSL_PRECOND( _rControl.is(), "UnoControlContactHelper::adjustControlGeometry_throw: illegal control!" );
305 if ( !_rControl.is() )
306 return;
308 // transform the logic bound rect, using the view transformation, to pixel coordinates
309 ::basegfx::B2DPoint aTopLeft( _rLogicBoundingRect.Left(), _rLogicBoundingRect.Top() );
310 aTopLeft *= _rViewTransformation;
311 ::basegfx::B2DPoint aBottomRight( _rLogicBoundingRect.Right(), _rLogicBoundingRect.Bottom() );
312 aBottomRight *= _rViewTransformation;
314 const Rectangle aPaintRectPixel( (long)aTopLeft.getX(), (long)aTopLeft.getY(), (long)aBottomRight.getX(), (long)aBottomRight.getY() );
315 _rControl.setPosSize( aPaintRectPixel );
317 // determine the scale from the current view transformation, and the normalization matrix
318 ::basegfx::B2DHomMatrix aObtainResolutionDependentScale( _rViewTransformation * _rZoomLevelNormalization );
319 ::basegfx::B2DVector aScale, aTranslate;
320 double fRotate, fShearX;
321 aObtainResolutionDependentScale.decompose( aScale, aTranslate, fRotate, fShearX );
322 _rControl.setZoom( aScale );
325 //--------------------------------------------------------------------
326 void UnoControlContactHelper::disposeAndClearControl_nothrow( ControlHolder& _rControl )
330 Reference< XComponent > xControlComp( _rControl.getControl(), UNO_QUERY );
331 if ( xControlComp.is() )
332 xControlComp->dispose();
334 catch( const Exception& )
336 DBG_UNHANDLED_EXCEPTION();
338 _rControl.clear();
341 //====================================================================
342 //= IPageViewAccess
343 //====================================================================
344 /** interface encapsulating access to an SdrPageView, stripped down to the methods we really need
346 class IPageViewAccess
348 public:
349 /** determines whether the view is currently in design mode
351 virtual bool isDesignMode() const = 0;
353 /** retrieves the control container for a given output device
355 virtual Reference< XControlContainer >
356 getControlContainer( const OutputDevice& _rDevice ) const = 0;
358 /** determines whether a given layer is visible
360 virtual bool isLayerVisible( SdrLayerID _nLayerID ) const = 0;
363 //====================================================================
364 //= SdrPageViewAccess
365 //====================================================================
366 /** is a ->IPageViewAccess implementation based on a real ->SdrPageView instance
368 class SdrPageViewAccess : public IPageViewAccess
370 const SdrPageView& m_rPageView;
371 public:
372 SdrPageViewAccess( const SdrPageView& _rPageView ) : m_rPageView( _rPageView ) { }
374 virtual bool isDesignMode() const;
375 virtual Reference< XControlContainer >
376 getControlContainer( const OutputDevice& _rDevice ) const;
377 virtual bool isLayerVisible( SdrLayerID _nLayerID ) const;
380 //--------------------------------------------------------------------
381 bool SdrPageViewAccess::isDesignMode() const
383 return m_rPageView.GetView().IsDesignMode();
386 //--------------------------------------------------------------------
387 Reference< XControlContainer > SdrPageViewAccess::getControlContainer( const OutputDevice& _rDevice ) const
389 Reference< XControlContainer > xControlContainer = m_rPageView.GetControlContainer( _rDevice );
390 DBG_ASSERT( xControlContainer.is() || NULL == m_rPageView.FindPageWindow( ( const_cast< OutputDevice& >( _rDevice ) ) ),
391 "SdrPageViewAccess::getControlContainer: the output device is known, but there is no control container for it?" );
392 return xControlContainer;
395 //--------------------------------------------------------------------
396 bool SdrPageViewAccess::isLayerVisible( SdrLayerID _nLayerID ) const
398 return m_rPageView.GetVisibleLayers().IsSet( _nLayerID );
401 //====================================================================
402 //= InvisibleControlViewAccess
403 //====================================================================
404 /** is a ->IPageViewAccess implementation which can be used to create an invisble control for
405 an arbitrary device
407 class InvisibleControlViewAccess : public IPageViewAccess
409 private:
410 Reference< XControlContainer >& m_rControlContainer;
411 public:
412 InvisibleControlViewAccess( Reference< XControlContainer >& _inout_ControlContainer )
413 :m_rControlContainer( _inout_ControlContainer )
417 virtual bool isDesignMode() const;
418 virtual Reference< XControlContainer >
419 getControlContainer( const OutputDevice& _rDevice ) const;
420 virtual bool isLayerVisible( SdrLayerID _nLayerID ) const;
423 //--------------------------------------------------------------------
424 bool InvisibleControlViewAccess::isDesignMode() const
426 return true;
429 //--------------------------------------------------------------------
430 Reference< XControlContainer > InvisibleControlViewAccess::getControlContainer( const OutputDevice& _rDevice ) const
432 if ( !m_rControlContainer.is() )
434 const Window* pWindow = dynamic_cast< const Window* >( &_rDevice );
435 OSL_ENSURE( pWindow, "InvisibleControlViewAccess::getControlContainer: expected to be called for a window only!" );
436 if ( pWindow )
437 m_rControlContainer = VCLUnoHelper::CreateControlContainer( const_cast< Window* >( pWindow ) );
439 return m_rControlContainer;
442 //--------------------------------------------------------------------
443 bool InvisibleControlViewAccess::isLayerVisible( SdrLayerID /*_nLayerID*/ ) const
445 return false;
448 //====================================================================
449 //= ViewObjectContactOfUnoControl_Impl
450 //====================================================================
451 typedef ::cppu::WeakImplHelper4 < XWindowListener
452 , XPropertyChangeListener
453 , XContainerListener
454 , XModeChangeListener
455 > ViewObjectContactOfUnoControl_Impl_Base;
457 class SVX_DLLPRIVATE ViewObjectContactOfUnoControl_Impl : public ViewObjectContactOfUnoControl_Impl_Base
459 private:
460 /// the instance whose IMPL we are
461 ViewObjectContactOfUnoControl* m_pAntiImpl;
463 /// are we currently inside impl_ensureControl_nothrow?
464 bool m_bCreatingControl;
466 /** thread safety
468 (not really. ATM only our X* implementations are guarded with this, but not
469 the object as a whole.)
471 mutable ::osl::Mutex m_aMutex;
473 /// the control we're responsible for
474 ControlHolder m_aControl;
476 /// the ControlContainer where we inserted our control
477 Reference< XContainer > m_xContainer;
479 /// the output device for which the control was created
480 const OutputDevice* m_pOutputDeviceForWindow;
482 /// flag indicating whether the control is currently visible
483 bool m_bControlIsVisible;
485 /// are we currently listening at a design mode control?
486 bool m_bIsDesignModeListening;
488 enum ViewControlMode
490 eDesign,
491 eAlive,
492 eUnknown
494 /// is the control currently in design mode?
495 mutable ViewControlMode m_eControlDesignMode;
497 ::basegfx::B2DHomMatrix m_aZoomLevelNormalization;
499 public:
500 ViewObjectContactOfUnoControl_Impl( ViewObjectContactOfUnoControl* _pAntiImpl );
502 /** disposes the instance, which is nonfunctional afterwards
504 void dispose();
506 /** determines whether the instance is disposed
508 bool isDisposed() const { return impl_isDisposed_nofail(); }
510 /** determines whether the instance is alive
512 bool isAlive() const { return !isDisposed(); }
514 /** returns the SdrUnoObject associated with the ViewContact
516 @precond
517 We're not disposed.
519 bool getUnoObject( SdrUnoObj*& _out_rpObject ) const;
521 /** ensures that we have an ->XControl
523 Must only be called if a control is needed when no DisplayInfo is present, yet.
525 For creating a control, an ->OutputDevice is needed, and an ->SdrPageView. Both will be obtained
526 from a ->ObjectContactOfPageView. So, if our (anti-impl's) object contact is not a ->ObjectContactOfPageView,
527 this method fill fail.
529 Failure of this method will be reported via an assertion in a non-product version.
531 bool ensureControl();
533 /** returns our XControl, if it already has been created
535 If you want to ensure that the control exists before accessing it, use ->ensureControl
537 inline const ControlHolder&
538 getExistentControl() const { return m_aControl; }
540 inline bool
541 hasControl() const { return m_aControl.is(); }
543 /** positions our XControl according to the geometry settings in the SdrUnoObj, modified by the given
544 transformation, and sets proper zoom settings according to our device
546 @precond
547 ->m_pOutputDeviceForWindow and ->m_aControl are not <NULL/>
549 void positionAndZoomControl( const basegfx::B2DHomMatrix& _rViewTransformation ) const;
551 /** determines whether or not our control is printable
553 Effectively, this method returns the value of the "Printable" property
554 of the control's model. If we have no control, <FALSE/> is returned.
556 bool isPrintableControl() const;
558 /** sets the design mode on the control, or at least remembers the flag for the
559 time the control is created
561 void setControlDesignMode( bool _bDesignMode ) const;
563 /** determines whether our control is currently visible
564 @nofail
566 bool isControlVisible() const { return impl_isControlVisible_nofail(); }
568 /** determines whether the instance belongs to a given OutputDevice
569 @precond
570 The instance knows the device it belongs to, or can determine it.
571 If this is not the case, you will notice an assertion, and the method will
572 return false.
574 bool belongsToDevice( const OutputDevice* _pDevice ) const;
576 /// creates an XControl for the given device and SdrUnoObj
577 static bool
578 createControlForDevice(
579 IPageViewAccess& _rPageView,
580 const OutputDevice& _rDevice,
581 const SdrUnoObj& _rUnoObject,
582 ControlHolder& _out_rControl
585 struct GuardAccess { friend class VOCGuard; private: GuardAccess() { } };
586 ::osl::Mutex& getMutex( GuardAccess ) const { return m_aMutex; }
588 const ViewContactOfUnoControl&
589 getViewContact() const
591 ENSURE_OR_THROW( !impl_isDisposed_nofail(), "already disposed" );
592 return static_cast< const ViewContactOfUnoControl& >( m_pAntiImpl->GetViewContact() );
595 protected:
596 ~ViewObjectContactOfUnoControl_Impl();
598 // XEventListener
599 virtual void SAL_CALL disposing( const EventObject& Source ) throw(RuntimeException);
601 // XWindowListener
602 virtual void SAL_CALL windowResized( const WindowEvent& e ) throw(RuntimeException);
603 virtual void SAL_CALL windowMoved( const WindowEvent& e ) throw(RuntimeException);
604 virtual void SAL_CALL windowShown( const EventObject& e ) throw(RuntimeException);
605 virtual void SAL_CALL windowHidden( const EventObject& e ) throw(RuntimeException);
607 // XPropertyChangeListener
608 virtual void SAL_CALL propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException);
610 // XModeChangeListener
611 virtual void SAL_CALL modeChanged( const ModeChangeEvent& _rSource ) throw (RuntimeException);
613 // XContainerListener
614 virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
615 virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
616 virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
618 private:
619 /** retrieves the SdrPageView which our associated SdrPageViewWindow belongs to
621 @param out_rpPageView
622 a reference to a pointer holding, upon return, the desired SdrPageView
624 @return
625 <TRUE/> if and only if a ->SdrPageView could be obtained
627 @precond
628 We really belong to an SdrPageViewWindow. Perhaps (I'm not sure ATM :)
629 there are instance for which this might not be true, but those instances
630 should never have a need to call this method.
632 @precond
633 We're not disposed.
635 @postcond
636 The method expects success, if it returns with <FALSE/>, this will have been
637 asserted.
639 @nothrow
641 bool impl_getPageView_nothrow( SdrPageView*& _out_rpPageView );
643 /** adjusts the control visibility so it respects its layer's visibility
645 @param _bForce
646 set to <TRUE/> if you want to force a ->XWindow::setVisible call,
647 no matter if the control visibility is already correct
649 @precond
650 ->m_aControl is not <NULL/>
652 @precond
653 We're not disposed.
655 @precond
656 We really belong to an SdrPageViewWindow. There are instance for which this
657 might not be true, but those instances should never have a need to call
658 this method.
660 void impl_adjustControlVisibilityToLayerVisibility_throw( bool _bForce );
662 /** adjusts the control visibility so it respects its layer's visibility
664 The control must never be visibile if it's in design mode.
665 In alive mode, it must be visibility if and only it's on a visible layer.
667 @param _rxControl
668 the control whose visibility is to be adjusted
670 @param _rPageView
671 provides access to the attributes of the SdrPageView which the control finally belongs to
673 @param _rUnoObject
674 our SdrUnoObj
676 @param _bIsCurrentlyVisible
677 determines whether the control is currently visible. Note that this is only a shortcut for
678 querying _rxControl for the XWindow2 interface, and calling isVisible at this interface.
679 This shortcut has been chosen since the caller usually already has this information.
680 If _bForce is <TRUE/>, _bIsCurrentlyVisible is ignored.
682 @param _bForce
683 set to <TRUE/> if you want to force a ->XWindow::setVisible call,
684 no matter if the control visibility is already correct
686 @precond
687 We're not disposed.
689 static void impl_adjustControlVisibilityToLayerVisibility_throw( const ControlHolder& _rxControl, const SdrUnoObj& _rUnoObject,
690 IPageViewAccess& _rPageView, bool _bIsCurrentlyVisible, bool _bForce );
692 /** starts or stops listening at various aspects of our control
694 @precond
695 ->m_aControl is not <NULL/>
697 void impl_switchControlListening_nothrow( bool _bStart );
699 /** starts or stops listening at our control container
701 @precond
702 ->m_xContainer is not <NULL/>
704 void impl_switchContainerListening_nothrow( bool _bStart );
706 /** starts or stops listening at the control for design-mode relevant facets
708 void impl_switchDesignModeListening_nothrow( bool _bStart );
710 /** starts or stops listening for all properties at our control
712 @param _bStart
713 determines whether to start or to stop listening
715 @precond
716 ->m_aControl is not <NULL/>
718 void impl_switchPropertyListening_nothrow( bool _bStart );
720 /** disposes the instance
721 @param _bAlsoDisposeControl
722 determines whether the XControl should be disposed, too
724 void impl_dispose_nothrow( bool _bAlsoDisposeControl );
726 /** determines whether the instance is disposed
727 @nofail
729 bool impl_isDisposed_nofail() const { return m_pAntiImpl == NULL; }
731 /** determines whether our control is currently visible
732 @nofail
734 bool impl_isControlVisible_nofail() const { return m_bControlIsVisible; }
736 /** determines whether we are currently a listener at the control for desgin-mode relevant facets
737 @nofail
739 bool impl_isDesignModeListening_nofail() const { return m_bIsDesignModeListening; }
741 /** determines whether the control currently is in design mode
743 @precond
744 The design mode must already be known. It is known when we first had access to
745 an SdrPageView (which carries this flag), or somebody explicitly set it from
746 outside.
748 inline bool impl_isControlDesignMode_nothrow() const
750 DBG_ASSERT( m_eControlDesignMode != eUnknown, "ViewObjectContactOfUnoControl_Impl::impl_isControlDesignMode_nothrow: mode is still unknown!" );
751 return m_eControlDesignMode == eDesign;
754 /** ensures that we have a control for the given PageView/OutputDevice
756 bool impl_ensureControl_nothrow( IPageViewAccess& _rPageView, const OutputDevice& _rDevice );
758 /** retrieves the device which a PageView belongs to, starting from its ObjectContactOfPageView
760 Since #i72752#, the PaintWindow (and thus the OutputDevice) associated with a PageView is not
761 constant over its lifetime. Instead, during some paint operations, the PaintWindow/OutputDevice
762 might be temporarily patched.
764 This method cares for this, by retrieving the very original OutputDevice.
766 static const OutputDevice& imp_getPageViewDevice_nothrow( const ObjectContactOfPageView& _rObjectContact );
767 const OutputDevice& imp_getPageViewDevice_nothrow() const;
769 private:
770 ViewObjectContactOfUnoControl_Impl(); // never implemented
771 ViewObjectContactOfUnoControl_Impl( const ViewObjectContactOfUnoControl_Impl& ); // never implemented
772 ViewObjectContactOfUnoControl_Impl& operator=( const ViewObjectContactOfUnoControl_Impl& ); // never implemented
775 //====================================================================
776 //= VOCGuard
777 //====================================================================
778 /** class for guarding a ViewObjectContactOfUnoControl_Impl method
780 class VOCGuard
782 private:
783 ::osl::MutexGuard m_aMutexGuard;
785 public:
786 VOCGuard( const ViewObjectContactOfUnoControl_Impl& _rImpl )
787 :m_aMutexGuard( _rImpl.getMutex( ViewObjectContactOfUnoControl_Impl::GuardAccess() ) )
792 //====================================================================
793 //= LazyControlCreationPrimitive2D
794 //====================================================================
795 class LazyControlCreationPrimitive2D : public ::drawinglayer::primitive2d::BasePrimitive2D
797 private:
798 typedef ::drawinglayer::primitive2d::BasePrimitive2D BasePrimitive2D;
800 protected:
801 virtual ::drawinglayer::primitive2d::Primitive2DSequence
802 get2DDecomposition(
803 const ::drawinglayer::geometry::ViewInformation2D& rViewInformation
804 ) const;
806 virtual ::drawinglayer::primitive2d::Primitive2DSequence
807 createLocalDecomposition(
808 const ::drawinglayer::geometry::ViewInformation2D& rViewInformation
809 ) const;
811 virtual ::basegfx::B2DRange
812 getB2DRange(
813 const ::drawinglayer::geometry::ViewInformation2D& rViewInformation
814 ) const;
816 public:
817 LazyControlCreationPrimitive2D( const ::rtl::Reference< ViewObjectContactOfUnoControl_Impl >& _pVOCImpl )
818 :m_pVOCImpl( _pVOCImpl )
820 ENSURE_OR_THROW( m_pVOCImpl.is(), "Illegal argument." );
821 getTransformation( m_pVOCImpl->getViewContact(), m_aTransformation );
824 virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
826 // declare unique ID for this primitive class
827 DeclPrimitrive2DIDBlock()
829 static void getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation );
831 private:
832 ::rtl::Reference< ViewObjectContactOfUnoControl_Impl > m_pVOCImpl;
833 /** The geometry is part of the identity of an primitive, so we cannot calculate it on demand
834 (since the data the calculation is based on might have changed then), but need to calc
835 it at construction time, and remember it.
837 ::basegfx::B2DHomMatrix m_aTransformation;
840 //====================================================================
841 //= ViewObjectContactOfUnoControl_Impl
842 //====================================================================
843 DBG_NAME( ViewObjectContactOfUnoControl_Impl )
844 //--------------------------------------------------------------------
845 ViewObjectContactOfUnoControl_Impl::ViewObjectContactOfUnoControl_Impl( ViewObjectContactOfUnoControl* _pAntiImpl )
846 :m_pAntiImpl( _pAntiImpl )
847 ,m_bCreatingControl( false )
848 ,m_pOutputDeviceForWindow( NULL )
849 ,m_bControlIsVisible( false )
850 ,m_bIsDesignModeListening( false )
851 ,m_eControlDesignMode( eUnknown )
852 ,m_aZoomLevelNormalization()
854 DBG_CTOR( ViewObjectContactOfUnoControl_Impl, NULL );
855 DBG_ASSERT( m_pAntiImpl, "ViewObjectContactOfUnoControl_Impl::ViewObjectContactOfUnoControl_Impl: invalid AntiImpl!" );
857 const OutputDevice& rPageViewDevice( imp_getPageViewDevice_nothrow() );
858 m_aZoomLevelNormalization = rPageViewDevice.GetInverseViewTransformation();
860 ::basegfx::B2DHomMatrix aScaleNormalization;
861 MapMode aCurrentDeviceMapMode( rPageViewDevice.GetMapMode() );
862 aScaleNormalization.set( 0, 0, (double)aCurrentDeviceMapMode.GetScaleX() );
863 aScaleNormalization.set( 1, 1, (double)aCurrentDeviceMapMode.GetScaleY() );
864 m_aZoomLevelNormalization *= aScaleNormalization;
867 //--------------------------------------------------------------------
868 ViewObjectContactOfUnoControl_Impl::~ViewObjectContactOfUnoControl_Impl()
870 if ( !impl_isDisposed_nofail() )
872 acquire();
873 dispose();
876 DBG_DTOR( ViewObjectContactOfUnoControl_Impl, NULL );
879 //--------------------------------------------------------------------
880 void ViewObjectContactOfUnoControl_Impl::impl_dispose_nothrow( bool _bAlsoDisposeControl )
882 if ( impl_isDisposed_nofail() )
883 return;
885 if ( m_aControl.is() )
886 impl_switchControlListening_nothrow( false );
888 if ( m_xContainer.is() )
889 impl_switchContainerListening_nothrow( false );
891 // dispose the control
892 if ( _bAlsoDisposeControl )
893 UnoControlContactHelper::disposeAndClearControl_nothrow( m_aControl );
895 m_aControl.clear();
896 m_xContainer.clear();
897 m_pOutputDeviceForWindow = NULL;
898 m_bControlIsVisible = false;
900 m_pAntiImpl = NULL;
903 //--------------------------------------------------------------------
904 void ViewObjectContactOfUnoControl_Impl::dispose()
906 VOCGuard aGuard( *this );
907 impl_dispose_nothrow( true );
910 //--------------------------------------------------------------------
911 bool ViewObjectContactOfUnoControl_Impl::getUnoObject( SdrUnoObj*& _out_rpObject ) const
913 OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::getUnoObject: already disposed()" );
914 if ( impl_isDisposed_nofail() )
915 _out_rpObject = NULL;
916 else
918 _out_rpObject = dynamic_cast< SdrUnoObj* >( m_pAntiImpl->GetViewContact().TryToGetSdrObject() );
919 DBG_ASSERT( _out_rpObject || !m_pAntiImpl->GetViewContact().TryToGetSdrObject(),
920 "ViewObjectContactOfUnoControl_Impl::getUnoObject: invalid SdrObject!" );
922 return ( _out_rpObject != NULL );
925 //--------------------------------------------------------------------
926 void ViewObjectContactOfUnoControl_Impl::positionAndZoomControl( const basegfx::B2DHomMatrix& _rViewTransformation ) const
928 OSL_PRECOND( ( m_pOutputDeviceForWindow != NULL ) && m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::positionAndZoomControl: no output device or no control!" );
929 if ( ( m_pOutputDeviceForWindow == NULL ) || !m_aControl.is() )
930 return;
934 SdrUnoObj* pUnoObject( NULL );
935 if ( getUnoObject( pUnoObject ) )
937 UnoControlContactHelper::adjustControlGeometry_throw( m_aControl, pUnoObject->GetLogicRect(), _rViewTransformation, m_aZoomLevelNormalization );
939 else
940 OSL_ENSURE( false, "ViewObjectContactOfUnoControl_Impl::positionAndZoomControl: no SdrUnoObj!" );
942 catch( const Exception& )
944 DBG_UNHANDLED_EXCEPTION();
948 //--------------------------------------------------------------------
949 bool ViewObjectContactOfUnoControl_Impl::ensureControl()
951 OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::ensureControl: already disposed()" );
952 if ( impl_isDisposed_nofail() )
953 return false;
955 ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
956 DBG_ASSERT( pPageViewContact, "ViewObjectContactOfUnoControl_Impl::ensureControl: cannot create a control if I don't have a PageView!" );
957 if ( !pPageViewContact )
958 return false;
960 SdrPageViewAccess aPVAccess( pPageViewContact->GetPageWindow().GetPageView() );
961 return impl_ensureControl_nothrow(
962 aPVAccess,
963 imp_getPageViewDevice_nothrow( *pPageViewContact )
967 //--------------------------------------------------------------------
968 const OutputDevice& ViewObjectContactOfUnoControl_Impl::imp_getPageViewDevice_nothrow() const
970 ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
971 ENSURE_OR_THROW( pPageViewContact, "need a ObjectContactOfPageView." );
972 return imp_getPageViewDevice_nothrow( *pPageViewContact );
975 //--------------------------------------------------------------------
976 const OutputDevice& ViewObjectContactOfUnoControl_Impl::imp_getPageViewDevice_nothrow( const ObjectContactOfPageView& _rObjectContact )
978 // if the PageWindow has a patched PaintWindow, use the original PaintWindow
979 // this ensures that our control is _not_ re-created just because somebody
980 // (temporarily) changed the window to paint onto.
981 // #i72429# / 2007-02-20 / frank.schoenheit@sun.com
982 SdrPageWindow& rPageWindow( _rObjectContact.GetPageWindow() );
983 if ( rPageWindow.GetOriginalPaintWindow() )
984 return rPageWindow.GetOriginalPaintWindow()->GetOutputDevice();
986 return rPageWindow.GetPaintWindow().GetOutputDevice();
989 namespace
991 static void lcl_resetFlag( bool& rbFlag )
993 rbFlag = false;
997 //--------------------------------------------------------------------
998 bool ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow( IPageViewAccess& _rPageView, const OutputDevice& _rDevice )
1000 if ( m_bCreatingControl )
1002 OSL_ENSURE( false, "ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow: reentrance is not really good here!" );
1003 // We once had a situation where this was called reentrantly, which lead to all kind of strange effects. All
1004 // those affected the grid control, which is the only control so far which is visible in design mode (and
1005 // not only in alive mode).
1006 // Creating the control triggered an Window::Update on some of its child windows, which triggered a
1007 // Paint on parent of the grid control (e.g. the SwEditWin), which triggered a reentrant call to this method,
1008 // which it is not really prepared for.
1010 // /me thinks that re-entrance should be caught on a higher level, i.e. the Drawing Layer should not allow
1011 // reentrant paint requests. For the moment, until /me can discuss this with AW, catch it here.
1012 // 2009-08-27 / #i104544# frank.schoenheit@sun.com
1013 return false;
1016 m_bCreatingControl = true;
1017 ::comphelper::ScopeGuard aGuard( ::boost::bind( lcl_resetFlag, ::boost::ref( m_bCreatingControl ) ) );
1019 if ( m_aControl.is() )
1021 if ( m_pOutputDeviceForWindow == &_rDevice )
1022 return true;
1024 // Somebody requested a control for a new device, which means either of
1025 // - our PageView's paint window changed since we were last here
1026 // - we don't belong to a page view, and are simply painted onto different devices
1027 // The first sounds strange (doens't it?), the second means we could perhaps
1028 // optimize this in the future - there is no need to re-create the control every time,
1029 // is it?
1030 // #i74523# / 2007-02-15 / frank.schoenheit@sun.com
1031 if ( m_xContainer.is() )
1032 impl_switchContainerListening_nothrow( false );
1033 impl_switchControlListening_nothrow( false );
1034 UnoControlContactHelper::disposeAndClearControl_nothrow( m_aControl );
1037 SdrUnoObj* pUnoObject( NULL );
1038 if ( !getUnoObject( pUnoObject ) )
1039 return false;
1041 ControlHolder aControl;
1042 if ( !createControlForDevice( _rPageView, _rDevice, *pUnoObject, aControl ) )
1043 return false;
1045 m_pOutputDeviceForWindow = &_rDevice;
1046 m_aControl = aControl;
1047 m_xContainer = m_xContainer.query( _rPageView.getControlContainer( _rDevice ) );
1048 DBG_ASSERT( ( m_xContainer.is() // either have a XControlContainer
1049 || ( ( !_rPageView.getControlContainer( _rDevice ).is() ) // or don't have any container,
1050 && ( dynamic_cast< const Window* >( &_rDevice ) == NULL ) // which is allowed for non-Window instances only
1053 "ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow: no XContainer at the ControlContainer!" );
1057 m_eControlDesignMode = m_aControl.isDesignMode() ? eDesign : eAlive;
1058 m_bControlIsVisible = m_aControl.isVisible();
1060 catch( const Exception& )
1062 DBG_UNHANDLED_EXCEPTION();
1065 // start listening at all aspects of the control which are interesting to us ...
1066 impl_switchControlListening_nothrow( true );
1068 // start listening at the control container, in case somebody tampers with our control
1069 if ( m_xContainer.is() )
1070 impl_switchContainerListening_nothrow( true );
1072 return m_aControl.is();
1075 //--------------------------------------------------------------------
1076 bool ViewObjectContactOfUnoControl_Impl::createControlForDevice( IPageViewAccess& _rPageView,
1077 const OutputDevice& _rDevice, const SdrUnoObj& _rUnoObject, ControlHolder& _out_rControl )
1079 _out_rControl.clear();
1081 Reference< XControlModel > xControlModel( _rUnoObject.GetUnoControlModel() );
1082 DBG_ASSERT( xControlModel.is(), "ViewObjectContactOfUnoControl_Impl::createControlForDevice: no control model at the SdrUnoObject!?" );
1083 if ( !xControlModel.is() )
1084 return false;
1086 bool bSuccess = false;
1089 const ::rtl::OUString sControlServiceName( _rUnoObject.GetUnoControlTypeName() );
1091 Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW );
1092 _out_rControl = Reference< XControl >( xFactory->createInstance( sControlServiceName ), UNO_QUERY_THROW );
1094 // knit the model and the control
1095 _out_rControl.setModel( xControlModel );
1097 // proper geometry
1098 UnoControlContactHelper::adjustControlGeometry_throw(
1099 _out_rControl,
1100 _rUnoObject.GetLogicRect(),
1101 _rDevice.GetViewTransformation(),
1102 _rDevice.GetInverseViewTransformation()
1105 // #107049# set design mode before peer is created,
1106 // this is also needed for accessibility
1107 _out_rControl.setDesignMode( _rPageView.isDesignMode() );
1109 // adjust the initial visibility according to the visibility of the layer
1110 // 2003-06-03 - #110592# - fs@openoffice.org
1111 impl_adjustControlVisibilityToLayerVisibility_throw( _out_rControl, _rUnoObject, _rPageView, false, true );
1113 // add the control to the respective control container
1114 // #108327# do this last
1115 Reference< XControlContainer > xControlContainer( _rPageView.getControlContainer( _rDevice ) );
1116 if ( xControlContainer.is() )
1117 xControlContainer->addControl( sControlServiceName, _out_rControl.getControl() );
1119 bSuccess = true;
1121 catch( const Exception& )
1123 DBG_UNHANDLED_EXCEPTION();
1126 if ( !bSuccess )
1128 // delete the control which might have been created already
1129 UnoControlContactHelper::disposeAndClearControl_nothrow( _out_rControl );
1132 return _out_rControl.is();
1135 //--------------------------------------------------------------------
1136 bool ViewObjectContactOfUnoControl_Impl::impl_getPageView_nothrow( SdrPageView*& _out_rpPageView )
1138 OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::impl_getPageView_nothrow: already disposed!" );
1140 _out_rpPageView = NULL;
1141 if ( impl_isDisposed_nofail() )
1142 return false;
1144 ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
1145 if ( pPageViewContact )
1146 _out_rpPageView = &pPageViewContact->GetPageWindow().GetPageView();
1148 DBG_ASSERT( _out_rpPageView != NULL, "ViewObjectContactOfUnoControl_Impl::impl_getPageView_nothrow: this method is expected to always have success!" );
1149 return ( _out_rpPageView != NULL );
1152 //--------------------------------------------------------------------
1153 void ViewObjectContactOfUnoControl_Impl::impl_adjustControlVisibilityToLayerVisibility_throw( bool _bForce )
1155 OSL_PRECOND( m_aControl.is(),
1156 "ViewObjectContactOfUnoControl_Impl::impl_adjustControlVisibilityToLayerVisibility_throw: only valid if we have a control!" );
1158 SdrPageView* pPageView( NULL );
1159 if ( !impl_getPageView_nothrow( pPageView ) )
1160 return;
1162 SdrUnoObj* pUnoObject( NULL );
1163 if ( !getUnoObject( pUnoObject ) )
1164 return;
1166 SdrPageViewAccess aPVAccess( *pPageView );
1167 impl_adjustControlVisibilityToLayerVisibility_throw( m_aControl, *pUnoObject, aPVAccess, impl_isControlVisible_nofail(), _bForce );
1170 //--------------------------------------------------------------------
1171 void ViewObjectContactOfUnoControl_Impl::impl_adjustControlVisibilityToLayerVisibility_throw( const ControlHolder& _rControl,
1172 const SdrUnoObj& _rUnoObject, IPageViewAccess& _rPageView, bool _bIsCurrentlyVisible, bool _bForce )
1174 // in design mode, there is no problem with the visibility: The XControl is hidden by
1175 // default, and the Drawing Layer will simply not call our paint routine, if we're in
1176 // a hidden layer. So, only alive mode matters.
1177 if ( !_rControl.isDesignMode() )
1179 // the layer of our object
1180 SdrLayerID nObjectLayer = _rUnoObject.GetLayer();
1181 // is the layer we're residing in visible in this view?
1182 bool bIsObjectLayerVisible = _rPageView.isLayerVisible( nObjectLayer );
1184 if ( _bForce || ( bIsObjectLayerVisible != _bIsCurrentlyVisible ) )
1186 _rControl.setVisible( bIsObjectLayerVisible );
1191 //--------------------------------------------------------------------
1192 void ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow( bool _bStart )
1194 OSL_PRECOND( m_xContainer.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow: no control container!" );
1195 if ( !m_xContainer.is() )
1196 return;
1200 if ( _bStart )
1201 m_xContainer->addContainerListener( this );
1202 else
1203 m_xContainer->removeContainerListener( this );
1205 catch( const Exception& )
1207 DBG_UNHANDLED_EXCEPTION();
1211 //--------------------------------------------------------------------
1212 void ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow( bool _bStart )
1214 OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow: invalid control!" );
1215 if ( !m_aControl.is() )
1216 return;
1220 // listen for visibility changes
1221 if ( _bStart )
1222 m_aControl.addWindowListener( this );
1223 else
1224 m_aControl.removeWindowListener( this );
1226 // in design mode, listen for some more aspects
1227 impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() && _bStart );
1229 // listen for design mode changes
1230 Reference< XModeChangeBroadcaster > xDesignModeChanges( m_aControl.getControl(), UNO_QUERY_THROW );
1231 if ( _bStart )
1232 xDesignModeChanges->addModeChangeListener( this );
1233 else
1234 xDesignModeChanges->removeModeChangeListener( this );
1236 catch( const Exception& )
1238 DBG_UNHANDLED_EXCEPTION();
1242 //--------------------------------------------------------------------
1243 void ViewObjectContactOfUnoControl_Impl::impl_switchDesignModeListening_nothrow( bool _bStart )
1245 if ( impl_isDesignModeListening_nofail() != _bStart )
1247 m_bIsDesignModeListening = _bStart;
1248 impl_switchPropertyListening_nothrow( _bStart );
1252 //------------------------------------------------------------------------------
1253 void ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow( bool _bStart )
1255 OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow: no control!" );
1256 if ( !m_aControl.is() )
1257 return;
1261 Reference< XPropertySet > xModelProperties( m_aControl.getModel(), UNO_QUERY_THROW );
1262 if ( _bStart )
1263 xModelProperties->addPropertyChangeListener( ::rtl::OUString(), this );
1264 else
1265 xModelProperties->removePropertyChangeListener( ::rtl::OUString(), this );
1267 catch( const Exception& )
1269 DBG_UNHANDLED_EXCEPTION();
1273 //--------------------------------------------------------------------
1274 bool ViewObjectContactOfUnoControl_Impl::isPrintableControl() const
1276 SdrUnoObj* pUnoObject( NULL );
1277 if ( !getUnoObject( pUnoObject ) )
1278 return false;
1280 bool bIsPrintable = false;
1283 Reference< XPropertySet > xModelProperties( pUnoObject->GetUnoControlModel(), UNO_QUERY_THROW );
1284 static const ::rtl::OUString s_sPrintablePropertyName( RTL_CONSTASCII_USTRINGPARAM( "Printable" ) );
1285 OSL_VERIFY( xModelProperties->getPropertyValue( s_sPrintablePropertyName ) >>= bIsPrintable );
1287 catch( const Exception& )
1289 DBG_UNHANDLED_EXCEPTION();
1291 return bIsPrintable;
1294 //--------------------------------------------------------------------
1295 void SAL_CALL ViewObjectContactOfUnoControl_Impl::disposing( const EventObject& Source ) throw(RuntimeException)
1297 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1298 // some code below - in particular our disposal - might trigger actions which require the
1299 // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
1300 // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
1301 // is the real bug. Toolkit really is infested with solar mutex usage ... :(
1302 // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
1303 VOCGuard aGuard( *this );
1305 if ( !m_aControl.is() )
1306 return;
1308 if ( ( m_aControl == Source.Source )
1309 || ( m_aControl.getModel() == Source.Source )
1312 // the model or the control is dying ... hmm, not much sense in that we ourself continue
1313 // living
1314 impl_dispose_nothrow( false );
1315 return;
1318 DBG_ASSERT( Source.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::disposing: Who's this?" );
1321 //--------------------------------------------------------------------
1322 void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowResized( const WindowEvent& /*e*/ ) throw(RuntimeException)
1324 // not interested in
1327 //--------------------------------------------------------------------
1328 void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowMoved( const WindowEvent& /*e*/ ) throw(RuntimeException)
1330 // not interested in
1333 //--------------------------------------------------------------------
1334 void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowShown( const EventObject& /*e*/ ) throw(RuntimeException)
1336 VOCGuard aGuard( *this );
1337 m_bControlIsVisible = true;
1340 //--------------------------------------------------------------------
1341 void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowHidden( const EventObject& /*e*/ ) throw(RuntimeException)
1343 VOCGuard aGuard( *this );
1344 m_bControlIsVisible = false;
1347 //--------------------------------------------------------------------
1348 void SAL_CALL ViewObjectContactOfUnoControl_Impl::propertyChange( const PropertyChangeEvent& /*_rEvent*/ ) throw(RuntimeException)
1350 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1351 // (re)painting might require VCL operations, which need the SolarMutex
1353 OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::propertyChange: already disposed()" );
1354 if ( impl_isDisposed_nofail() )
1355 return;
1357 VOCGuard aGuard( *this );
1358 DBG_ASSERT( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::propertyChange: " );
1359 if ( !m_aControl.is() )
1360 return;
1362 // a generic property changed. If we're in design mode, we need to repaint the control
1363 if ( impl_isControlDesignMode_nothrow() )
1365 m_pAntiImpl->propertyChange();
1369 //--------------------------------------------------------------------
1370 void SAL_CALL ViewObjectContactOfUnoControl_Impl::modeChanged( const ModeChangeEvent& _rSource ) throw (RuntimeException)
1372 VOCGuard aGuard( *this );
1374 DBG_ASSERT( _rSource.NewMode.equalsAscii( "design" ) || _rSource.NewMode.equalsAscii( "alive" ),
1375 "ViewObjectContactOfUnoControl_Impl::modeChanged: unexpected mode!" );
1377 m_eControlDesignMode = _rSource.NewMode.equalsAscii( "design" ) ? eDesign : eAlive;
1379 impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() );
1383 // if the control is part of a invisible layer, we need to explicitly hide it in alive mode
1384 // 2003-06-03 - #110592# - fs@openoffice.org
1385 impl_adjustControlVisibilityToLayerVisibility_throw( false );
1387 catch( const Exception& )
1389 DBG_UNHANDLED_EXCEPTION();
1393 //--------------------------------------------------------------------
1394 void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementInserted( const ContainerEvent& /*_Event*/ ) throw (RuntimeException)
1396 // not interested in
1399 //--------------------------------------------------------------------
1400 void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementRemoved( const ContainerEvent& Event ) throw (RuntimeException)
1402 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1403 // some code below - in particular our disposal - might trigger actions which require the
1404 // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
1405 // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
1406 // is the real bug. Toolkit really is infested with solar mutex usage ... :(
1407 // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
1408 VOCGuard aGuard( *this );
1409 DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementRemoved: where did this come from?" );
1411 if ( m_aControl == Event.Element )
1412 impl_dispose_nothrow( false );
1415 //--------------------------------------------------------------------
1416 void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementReplaced( const ContainerEvent& Event ) throw (RuntimeException)
1418 VOCGuard aGuard( *this );
1419 DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementReplaced: where did this come from?" );
1421 if ( m_aControl == Event.ReplacedElement )
1423 Reference< XControl > xNewControl( Event.Element, UNO_QUERY );
1424 DBG_ASSERT( xNewControl.is(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: invalid new control!" );
1425 if ( !xNewControl.is() )
1426 return;
1428 ENSURE_OR_THROW( m_pOutputDeviceForWindow, "calling this without /me having an output device should be impossible." );
1430 DBG_ASSERT( xNewControl->getModel() == m_aControl.getModel(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: another model at the new control?" );
1431 // another model should - in the drawing layer - also imply another SdrUnoObj, which
1432 // should also result in new ViewContact, and thus in new ViewObjectContacts
1434 impl_switchControlListening_nothrow( false );
1436 ControlHolder aNewControl( xNewControl );
1437 aNewControl.setZoom( m_aControl.getZoom() );
1438 aNewControl.setPosSize( m_aControl.getPosSize() );
1439 aNewControl.setDesignMode( impl_isControlDesignMode_nothrow() );
1441 m_aControl = xNewControl;
1442 m_bControlIsVisible = m_aControl.isVisible();
1444 impl_switchControlListening_nothrow( true );
1448 //--------------------------------------------------------------------
1449 void ViewObjectContactOfUnoControl_Impl::setControlDesignMode( bool _bDesignMode ) const
1451 if ( ( m_eControlDesignMode != eUnknown ) && ( _bDesignMode == impl_isControlDesignMode_nothrow() ) )
1452 // nothing to do
1453 return;
1454 m_eControlDesignMode = _bDesignMode ? eDesign : eAlive;
1456 if ( !m_aControl.is() )
1457 // nothing to do, the setting will be respected as soon as the control
1458 // is created
1459 return;
1463 m_aControl.setDesignMode( _bDesignMode );
1465 catch( const Exception& )
1467 DBG_UNHANDLED_EXCEPTION();
1471 //====================================================================
1472 //= LazyControlCreationPrimitive2D
1473 //====================================================================
1474 //--------------------------------------------------------------------
1475 bool LazyControlCreationPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
1477 if ( !BasePrimitive2D::operator==( rPrimitive ) )
1478 return false;
1480 const LazyControlCreationPrimitive2D* pRHS = dynamic_cast< const LazyControlCreationPrimitive2D* >( &rPrimitive );
1481 if ( !pRHS )
1482 return false;
1484 if ( m_pVOCImpl != pRHS->m_pVOCImpl )
1485 return false;
1487 if ( m_aTransformation != pRHS->m_aTransformation )
1488 return false;
1490 return true;
1493 //--------------------------------------------------------------------
1494 void LazyControlCreationPrimitive2D::getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation )
1496 // Do use model data directly to create the correct geometry. Do NOT
1497 // use getBoundRect()/getSnapRect() here; tese will use the sequence of
1498 // primitives themselves in the long run.
1499 const Rectangle aSdrGeoData( _rVOC.GetSdrUnoObj().GetGeoRect() );
1500 const basegfx::B2DRange aRange(
1501 aSdrGeoData.Left(),
1502 aSdrGeoData.Top(),
1503 aSdrGeoData.Right(),
1504 aSdrGeoData.Bottom()
1507 _out_Transformation.identity();
1508 _out_Transformation.set( 0, 0, aRange.getWidth() );
1509 _out_Transformation.set( 1, 1, aRange.getHeight() );
1510 _out_Transformation.set( 0, 2, aRange.getMinX() );
1511 _out_Transformation.set( 1, 2, aRange.getMinY() );
1514 //--------------------------------------------------------------------
1515 ::basegfx::B2DRange LazyControlCreationPrimitive2D::getB2DRange( const ::drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/ ) const
1517 ::basegfx::B2DRange aRange( 0.0, 0.0, 1.0, 1.0 );
1518 aRange.transform( m_aTransformation );
1519 return aRange;
1522 //--------------------------------------------------------------------
1523 ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::get2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
1525 if ( m_pVOCImpl->hasControl() )
1526 m_pVOCImpl->positionAndZoomControl( _rViewInformation.getObjectToViewTransformation() );
1527 return BasePrimitive2D::get2DDecomposition( _rViewInformation );
1530 //--------------------------------------------------------------------
1531 ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::createLocalDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
1533 // force control here to make it a VCL ChildWindow. Will be fetched
1534 // and used below by getExistentControl()
1535 m_pVOCImpl->ensureControl();
1536 m_pVOCImpl->positionAndZoomControl( _rViewInformation.getObjectToViewTransformation() );
1538 // get needed data
1539 const ViewContactOfUnoControl& rViewContactOfUnoControl( m_pVOCImpl->getViewContact() );
1540 Reference< XControlModel > xControlModel( rViewContactOfUnoControl.GetSdrUnoObj().GetUnoControlModel() );
1541 const ControlHolder& rControl( m_pVOCImpl->getExistentControl() );
1543 // check if we already have an XControl.
1544 if ( !xControlModel.is() || !rControl.is() )
1545 // use the default mechanism. This will create a ControlPrimitive2D without
1546 // handing over a XControl. If not even a XControlModel exists, it will
1547 // create the SdrObject fallback visualisation
1548 return rViewContactOfUnoControl.getViewIndependentPrimitive2DSequence();
1550 // create a primitive and hand over the existing xControl. This will
1551 // allow the primitive to not need to create another one on demand.
1552 const drawinglayer::primitive2d::Primitive2DReference xRetval( new ::drawinglayer::primitive2d::ControlPrimitive2D(
1553 m_aTransformation, xControlModel, rControl.getControl() ) );
1555 return drawinglayer::primitive2d::Primitive2DSequence(&xRetval, 1);
1558 //--------------------------------------------------------------------
1559 ImplPrimitrive2DIDBlock( LazyControlCreationPrimitive2D, PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D )
1561 //====================================================================
1562 //= ViewObjectContactOfUnoControl
1563 //====================================================================
1564 DBG_NAME( ViewObjectContactOfUnoControl )
1565 //--------------------------------------------------------------------
1566 ViewObjectContactOfUnoControl::ViewObjectContactOfUnoControl( ObjectContact& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1567 :ViewObjectContactOfSdrObj( _rObjectContact, _rViewContact )
1568 ,m_pImpl( new ViewObjectContactOfUnoControl_Impl( this ) )
1570 DBG_CTOR( ViewObjectContactOfUnoControl, NULL );
1573 //--------------------------------------------------------------------
1574 ViewObjectContactOfUnoControl::~ViewObjectContactOfUnoControl()
1576 m_pImpl->dispose();
1577 m_pImpl = NULL;
1579 DBG_DTOR( ViewObjectContactOfUnoControl, NULL );
1582 //--------------------------------------------------------------------
1583 bool ViewObjectContactOfUnoControl::isControlVisible() const
1585 VOCGuard aGuard( *m_pImpl );
1586 const ControlHolder& rControl( m_pImpl->getExistentControl() );
1587 return rControl.is() && rControl.isVisible();
1590 //--------------------------------------------------------------------
1591 Reference< XControl > ViewObjectContactOfUnoControl::getControl()
1593 VOCGuard aGuard( *m_pImpl );
1594 m_pImpl->ensureControl();
1595 return m_pImpl->getExistentControl().getControl();
1598 //--------------------------------------------------------------------
1599 Reference< XControl > ViewObjectContactOfUnoControl::getTemporaryControlForWindow(
1600 const Window& _rWindow, Reference< XControlContainer >& _inout_ControlContainer, const SdrUnoObj& _rUnoObject )
1602 ControlHolder aControl;
1604 InvisibleControlViewAccess aSimulatePageView( _inout_ControlContainer );
1605 OSL_VERIFY( ViewObjectContactOfUnoControl_Impl::createControlForDevice( aSimulatePageView, _rWindow, _rUnoObject, aControl ) );
1606 return aControl.getControl();
1609 //--------------------------------------------------------------------
1610 void ViewObjectContactOfUnoControl::ensureControlVisibility( bool _bVisible ) const
1612 VOCGuard aGuard( *m_pImpl );
1616 const ControlHolder& rControl( m_pImpl->getExistentControl() );
1617 if ( !rControl.is() )
1618 return;
1620 // only need to care for alive mode
1621 if ( rControl.isDesignMode() )
1622 return;
1624 // is the visibility correct?
1625 if ( m_pImpl->isControlVisible() == _bVisible )
1626 return;
1628 // no -> adjust it
1629 rControl.setVisible( _bVisible );
1630 DBG_ASSERT( m_pImpl->isControlVisible() == _bVisible, "ViewObjectContactOfUnoControl::ensureControlVisibility: this didn't work!" );
1631 // now this would mean that either isControlVisible is not reliable,
1632 // or that showing/hiding the window did not work as intended.
1634 catch( const Exception& )
1636 DBG_UNHANDLED_EXCEPTION();
1640 //--------------------------------------------------------------------
1641 void ViewObjectContactOfUnoControl::setControlDesignMode( bool _bDesignMode ) const
1643 VOCGuard aGuard( *m_pImpl );
1644 m_pImpl->setControlDesignMode( _bDesignMode );
1646 if(!_bDesignMode)
1648 // when live mode is switched on, a refresh is needed. The edit mode visualisation
1649 // needs to be repainted and the now used VCL-Window needs to be positioned and
1650 // sized. Both is done from the repant refresh.
1651 const_cast< ViewObjectContactOfUnoControl* >(this)->ActionChanged();
1655 //--------------------------------------------------------------------
1656 drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfUnoControl::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/) const
1658 if ( m_pImpl->isDisposed() )
1659 // our control already died.
1660 // TODO: Is it worth re-creating the control? Finally, this is a pathological situation, it means some instance
1661 // disposed the control though it doesn't own it. So, /me thinks we should not bother here.
1662 return drawinglayer::primitive2d::Primitive2DSequence();
1664 ::drawinglayer::primitive2d::Primitive2DReference xPrimitive( new LazyControlCreationPrimitive2D( m_pImpl ) );
1665 return ::drawinglayer::primitive2d::Primitive2DSequence( &xPrimitive, 1 );
1668 //--------------------------------------------------------------------
1669 void ViewObjectContactOfUnoControl::propertyChange()
1671 // graphical invalidate at all views
1672 ActionChanged();
1674 // #i93318# flush Primitive2DSequence to force recreation with updated XControlModel
1675 // since e.g. background color has changed and existing decompositions are possibly no
1676 // longer valid. Unfortunately this is not detected from ControlPrimitive2D::operator==
1677 // since it only has a uno reference to the XControlModel
1678 flushPrimitive2DSequence();
1681 //--------------------------------------------------------------------
1682 void ViewObjectContactOfUnoControl::ActionChanged()
1684 // call parent
1685 ViewObjectContactOfSdrObj::ActionChanged();
1686 const ControlHolder& rControl(m_pImpl->getExistentControl());
1688 if(rControl.is() && !rControl.isDesignMode())
1690 // #i93180# if layer visibility has changed and control is in live mode, it is necessary
1691 // to correct visibility to make those control vanish on SdrObject LayerID changes
1692 const SdrPageView* pSdrPageView = GetObjectContact().TryToGetSdrPageView();
1694 if(pSdrPageView)
1696 const bool bIsLayerVisible(pSdrPageView->GetVisibleLayers().IsSet(getSdrObject().GetLayer()));
1698 if(rControl.isVisible() != bIsLayerVisible)
1700 rControl.setVisible(bIsLayerVisible);
1706 //====================================================================
1707 //= UnoControlDefaultContact
1708 //====================================================================
1709 DBG_NAME( UnoControlDefaultContact )
1710 //--------------------------------------------------------------------
1711 UnoControlDefaultContact::UnoControlDefaultContact( ObjectContact& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1712 :ViewObjectContactOfUnoControl( _rObjectContact, _rViewContact )
1714 DBG_CTOR( UnoControlDefaultContact, NULL );
1717 //--------------------------------------------------------------------
1718 UnoControlDefaultContact::~UnoControlDefaultContact()
1720 DBG_DTOR( UnoControlDefaultContact, NULL );
1723 //====================================================================
1724 //= UnoControlWindowContact
1725 //====================================================================
1726 DBG_NAME( UnoControlWindowContact )
1727 //--------------------------------------------------------------------
1728 UnoControlWindowContact::UnoControlWindowContact( ObjectContactOfPageView& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1729 :ViewObjectContactOfUnoControl( _rObjectContact, _rViewContact )
1731 DBG_CTOR( UnoControlWindowContact, NULL );
1734 //--------------------------------------------------------------------
1735 UnoControlWindowContact::~UnoControlWindowContact()
1737 DBG_DTOR( UnoControlWindowContact, NULL );
1740 //====================================================================
1741 //= UnoControlPrintOrPreviewContact
1742 //====================================================================
1743 DBG_NAME( UnoControlPrintOrPreviewContact )
1744 //--------------------------------------------------------------------
1745 UnoControlPrintOrPreviewContact::UnoControlPrintOrPreviewContact( ObjectContactOfPageView& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1746 :ViewObjectContactOfUnoControl( _rObjectContact, _rViewContact )
1748 DBG_CTOR( UnoControlPrintOrPreviewContact, NULL );
1751 //--------------------------------------------------------------------
1752 UnoControlPrintOrPreviewContact::~UnoControlPrintOrPreviewContact()
1754 DBG_DTOR( UnoControlPrintOrPreviewContact, NULL );
1757 //--------------------------------------------------------------------
1758 drawinglayer::primitive2d::Primitive2DSequence UnoControlPrintOrPreviewContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo ) const
1760 if ( !m_pImpl->isPrintableControl() )
1761 return drawinglayer::primitive2d::Primitive2DSequence();
1762 return ViewObjectContactOfUnoControl::createPrimitive2DSequence( rDisplayInfo );
1765 //====================================================================
1766 //= UnoControlPDFExportContact
1767 //====================================================================
1768 DBG_NAME( UnoControlPDFExportContact )
1769 //--------------------------------------------------------------------
1770 UnoControlPDFExportContact::UnoControlPDFExportContact( ObjectContactOfPageView& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1771 :ViewObjectContactOfUnoControl( _rObjectContact, _rViewContact )
1773 DBG_CTOR( UnoControlPDFExportContact, NULL );
1776 //--------------------------------------------------------------------
1777 UnoControlPDFExportContact::~UnoControlPDFExportContact()
1779 DBG_DTOR( UnoControlPDFExportContact, NULL );
1782 //........................................................................
1783 } } // namespace sdr::contact
1784 //........................................................................