1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #include <svx/sdr/contact/viewobjectcontactofunocontrol.hxx>
32 #include <svx/sdr/contact/viewcontactofunocontrol.hxx>
33 #include <svx/sdr/contact/displayinfo.hxx>
34 #include <svx/sdr/properties/properties.hxx>
35 #include <svx/sdr/contact/objectcontactofpageview.hxx>
36 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
37 #include <svx/svdouno.hxx>
38 #include <svx/svdpagv.hxx>
39 #include <svx/svdview.hxx>
40 #include <svx/sdrpagewindow.hxx>
41 #include "svx/sdrpaintwindow.hxx"
42 
43 /** === begin UNO includes === **/
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/awt/XControl.hpp>
46 #include <com/sun/star/awt/XControlModel.hpp>
47 #include <com/sun/star/awt/XControlContainer.hpp>
48 #include <com/sun/star/awt/XWindow2.hpp>
49 #include <com/sun/star/awt/PosSize.hpp>
50 #include <com/sun/star/awt/XView.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/lang/XComponent.hpp>
53 #include <com/sun/star/awt/InvalidateStyle.hpp>
54 #include <com/sun/star/util/XModeChangeListener.hpp>
55 #include <com/sun/star/util/XModeChangeBroadcaster.hpp>
56 #include <com/sun/star/container/XContainerListener.hpp>
57 #include <com/sun/star/container/XContainer.hpp>
58 /** === end UNO includes === **/
59 
60 #include <vcl/svapp.hxx>
61 #include <vos/mutex.hxx>
62 #include <comphelper/processfactory.hxx>
63 #include <comphelper/scopeguard.hxx>
64 #include <cppuhelper/implbase4.hxx>
65 #include <toolkit/helper/vclunohelper.hxx>
66 #include <tools/diagnose_ex.h>
67 #include <basegfx/matrix/b2dhommatrix.hxx>
68 #include <drawinglayer/primitive2d/controlprimitive2d.hxx>
69 
70 #include <boost/bind.hpp>
71 
72 /*
73 
74 Form controls (more precise: UNO Controls) in the drawing layer are ... prone to breakage, since they have some
75 specialities which the drawing layer currently doesn't capture too well. In particular, having a living VCL
76 window as child of the document window, and coupling this Window to a drawing layer object, makes things
77 difficult sometimes.
78 
79 Below is a list of issues which existed in the past. Whenever you change code here, you're encouraged to
80 verify those issues are still fixed. (Whenever you have some additional time, you're encouraged to write
81 an automatic test for one or more of those issues for which this is possible :)
82 
83 http://www.openoffice.org/issues/show_bug.cgi?id=105992
84 zooming documents containg (alive) form controls improperly positions the controls
85 
86 http://www.openoffice.org/issues/show_bug.cgi?id=104362
87 crash when copy a control
88 
89 http://www.openoffice.org/issues/show_bug.cgi?id=104544
90 Gridcontrol duplicated after design view on/off
91 
92 http://www.openoffice.org/issues/show_bug.cgi?id=102089
93 print preview shows control elements with property printable=false
94 
95 http://www.openoffice.org/issues/show_bug.cgi?id=102090
96 problem with setVisible on TextControl
97 
98 http://www.openoffice.org/issues/show_bug.cgi?id=103138
99 loop when insert a control in draw
100 
101 http://www.openoffice.org/issues/show_bug.cgi?id=101398
102 initially-displaying a document with many controls is very slow
103 
104 http://www.openoffice.org/issues/show_bug.cgi?id=72429
105 repaint error in form wizard in bugdoc database
106 
107 http://www.openoffice.org/issues/show_bug.cgi?id=72694
108 form control artifacts when scrolling a text fast
109 
110 
111 issues in the old (Sun-internal) bug tracking system:
112 
113 #110592#
114 form controls being in redlining or in hidden section are visible in alive-mode
115 
116 */
117 
118 //........................................................................
119 namespace sdr { namespace contact {
120 //........................................................................
121 
122     /** === begin UNO using === **/
123     using namespace ::com::sun::star::awt::InvalidateStyle;
124     using ::com::sun::star::uno::Reference;
125     using ::com::sun::star::uno::XInterface;
126     using ::com::sun::star::uno::UNO_QUERY;
127     using ::com::sun::star::uno::UNO_QUERY_THROW;
128     using ::com::sun::star::uno::UNO_SET_THROW;
129     using ::com::sun::star::uno::Exception;
130     using ::com::sun::star::uno::RuntimeException;
131     using ::com::sun::star::awt::XControl;
132     using ::com::sun::star::lang::XMultiServiceFactory;
133     using ::com::sun::star::awt::XControlModel;
134     using ::com::sun::star::awt::XControlContainer;
135     using ::com::sun::star::awt::XWindow;
136     using ::com::sun::star::awt::XWindow2;
137     using ::com::sun::star::awt::XWindowListener;
138     using ::com::sun::star::awt::PosSize::POSSIZE;
139     using ::com::sun::star::awt::XView;
140     using ::com::sun::star::awt::XGraphics;
141     using ::com::sun::star::awt::WindowEvent;
142     using ::com::sun::star::beans::XPropertySet;
143     using ::com::sun::star::beans::XPropertySetInfo;
144     using ::com::sun::star::lang::XComponent;
145     using ::com::sun::star::awt::XWindowPeer;
146     using ::com::sun::star::beans::XPropertyChangeListener;
147     using ::com::sun::star::util::XModeChangeListener;
148     using ::com::sun::star::util::XModeChangeBroadcaster;
149     using ::com::sun::star::util::ModeChangeEvent;
150     using ::com::sun::star::lang::EventObject;
151     using ::com::sun::star::beans::PropertyChangeEvent;
152     using ::com::sun::star::lang::XComponent;
153     using ::com::sun::star::container::XContainerListener;
154     using ::com::sun::star::container::XContainer;
155     using ::com::sun::star::container::ContainerEvent;
156     using ::com::sun::star::uno::Any;
157     /** === end UNO using === **/
158 
159     //====================================================================
160     //= ControlHolder
161     //====================================================================
162     class ControlHolder
163     {
164     private:
165         Reference< XControl >   m_xControl;
166         Reference< XWindow2 >   m_xControlWindow;
167         Reference< XView    >   m_xControlView;
168 
169     public:
170         ControlHolder()
171             :m_xControl()
172             ,m_xControlWindow()
173             ,m_xControlView()
174         {
175         }
176 
177         explicit ControlHolder( const Reference< XControl >& _rxControl )
178             :m_xControl()
179             ,m_xControlWindow()
180             ,m_xControlView()
181         {
182             *this = _rxControl;
183         }
184 
185         ControlHolder& operator=( const Reference< XControl >& _rxControl )
186         {
187             clear();
188 
189             m_xControl = _rxControl;
190             if ( m_xControl.is() )
191             {
192                 m_xControlWindow.set( m_xControl, UNO_QUERY );
193                 m_xControlView.set( m_xControl, UNO_QUERY );
194                 if ( !m_xControlWindow.is() || !m_xControlView.is() )
195                 {
196                     OSL_ENSURE( false, "ControlHolder::operator=: invalid XControl, missing required interfaces!" );
197                     clear();
198                 }
199             }
200 
201             return *this;
202         }
203 
204     public:
205         inline  bool    is() const { return m_xControl.is() && m_xControlWindow.is() && m_xControlView.is(); }
206         inline  void    clear() { m_xControl.clear(); m_xControlWindow.clear(); m_xControlView.clear(); }
207 
208         // delegators for the methods of the UNO interfaces
209         // Note all those will crash if called for a NULL object.
210         inline bool     isDesignMode() const                        { return m_xControl->isDesignMode();         }
211         inline void     setDesignMode( const bool _bDesign ) const  { m_xControl->setDesignMode( _bDesign );     }
212         inline bool     isVisible() const                           { return m_xControlWindow->isVisible();      }
213         inline void     setVisible( const bool _bVisible ) const    { m_xControlWindow->setVisible( _bVisible ); }
214         inline Reference< XControlModel >
215                         getModel() const { return m_xControl->getModel(); }
216         inline void     setModel( const Reference< XControlModel >& _m ) const { m_xControl->setModel( _m ); }
217         inline bool     isTransparent() const { return m_xControl->isTransparent(); }
218         inline Reference< XWindowPeer >
219                         getPeer() const { return m_xControl->getPeer(); }
220 
221         inline void     addWindowListener( const Reference< XWindowListener >& _l ) const    { m_xControlWindow->addWindowListener( _l );    }
222         inline void     removeWindowListener( const Reference< XWindowListener >& _l ) const { m_xControlWindow->removeWindowListener( _l ); }
223                void     setPosSize( const Rectangle& _rPosSize ) const;
224                Rectangle
225                         getPosSize() const;
226                void     setZoom( const ::basegfx::B2DVector& _rScale ) const;
227                ::basegfx::B2DVector
228                         getZoom() const;
229 
230         inline void     setGraphics( const Reference< XGraphics >& _g ) const { m_xControlView->setGraphics( _g ); }
231         inline Reference< XGraphics >
232                         getGraphics() const { return m_xControlView->getGraphics(); }
233         inline void     draw( const Point& _rTopLeft ) const { m_xControlView->draw( _rTopLeft.X(), _rTopLeft.Y() ); }
234 
235                void     invalidate() const;
236 
237     public:
238         inline  const Reference< XControl >&    getControl() const  { return m_xControl; }
239     };
240 
241     //--------------------------------------------------------------------
242     bool operator==( const ControlHolder& _rControl, const Reference< XInterface >& _rxCompare )
243     {
244         return _rControl.getControl() == _rxCompare;
245     }
246 
247     //--------------------------------------------------------------------
248     bool operator==( const Reference< XInterface >& _rxCompare, const ControlHolder& _rControl )
249     {
250         return _rxCompare == _rControl.getControl();
251     }
252 
253     //--------------------------------------------------------------------
254     bool operator==( const ControlHolder& _rControl, const Any& _rxCompare )
255     {
256         return _rControl == Reference< XInterface >( _rxCompare, UNO_QUERY );
257     }
258 
259     //--------------------------------------------------------------------
260     bool operator==( const Any& _rxCompare, const ControlHolder& _rControl )
261     {
262         return Reference< XInterface >( _rxCompare, UNO_QUERY ) == _rControl;
263     }
264 
265     //--------------------------------------------------------------------
266     void ControlHolder::setPosSize( const Rectangle& _rPosSize ) const
267     {
268         // no check whether we're valid, this is the responsibility of the caller
269 
270         // don't call setPosSize when pos/size did not change
271         // #i104181# / 2009-08-18 / frank.schoenheit@sun.com
272         ::Rectangle aCurrentRect( getPosSize() );
273         if ( aCurrentRect != _rPosSize )
274         {
275             m_xControlWindow->setPosSize(
276                 _rPosSize.Left(), _rPosSize.Top(), _rPosSize.GetWidth(), _rPosSize.GetHeight(),
277                 POSSIZE
278             );
279         }
280     }
281 
282     //--------------------------------------------------------------------
283     ::Rectangle ControlHolder::getPosSize() const
284     {
285         // no check whether we're valid, this is the responsibility of the caller
286         return VCLUnoHelper::ConvertToVCLRect( m_xControlWindow->getPosSize() );
287     }
288 
289     //--------------------------------------------------------------------
290     void ControlHolder::setZoom( const ::basegfx::B2DVector& _rScale ) const
291     {
292         // no check whether we're valid, this is the responsibility of the caller
293         m_xControlView->setZoom( (float)_rScale.getX(), (float)_rScale.getY() );
294     }
295 
296     //--------------------------------------------------------------------
297     void ControlHolder::invalidate() const
298     {
299         Reference< XWindowPeer > xPeer( m_xControl->getPeer() );
300         if ( xPeer.is() )
301         {
302             Window* pWindow = VCLUnoHelper::GetWindow( xPeer );
303             OSL_ENSURE( pWindow, "ControlHolder::invalidate: no implementation access!" );
304             if ( pWindow )
305                 pWindow->Invalidate();
306         }
307     }
308 
309     //--------------------------------------------------------------------
310     ::basegfx::B2DVector ControlHolder::getZoom() const
311     {
312         // no check whether we're valid, this is the responsibility of the caller
313 
314         // Argh. Why does XView have a setZoom only, but not a getZoom?
315         Window* pWindow = VCLUnoHelper::GetWindow( m_xControl->getPeer() );
316         OSL_ENSURE( pWindow, "ControlHolder::getZoom: no implementation access!" );
317 
318         ::basegfx::B2DVector aZoom( 1, 1 );
319         if ( pWindow )
320         {
321             const Fraction& rZoom( pWindow->GetZoom() );
322             aZoom.setX( (double)rZoom );
323             aZoom.setY( (double)rZoom );
324         }
325         return aZoom;
326     }
327 
328     //====================================================================
329     //= UnoControlContactHelper
330     //====================================================================
331     class UnoControlContactHelper
332     {
333     public:
334         /** positions a control, and sets its zoom mode, using a given transformation and output device
335         */
336         static void adjustControlGeometry_throw(
337                 const ControlHolder& _rControl,
338                 const Rectangle& _rLogicBoundingRect,
339                 const ::basegfx::B2DHomMatrix& _rViewTransformation,
340                 const ::basegfx::B2DHomMatrix& _rZoomLevelNormalization
341             );
342 
343         /** disposes the given control
344         */
345         static void disposeAndClearControl_nothrow(
346                 ControlHolder& _rControl
347             );
348 
349     private:
350         UnoControlContactHelper();                                              // never implemented
351         UnoControlContactHelper( const UnoControlContactHelper& );              // never implemented
352         UnoControlContactHelper& operator=( const UnoControlContactHelper& );   // never implemented
353     };
354 
355     //--------------------------------------------------------------------
356     void UnoControlContactHelper::adjustControlGeometry_throw( const ControlHolder& _rControl, const Rectangle& _rLogicBoundingRect,
357         const basegfx::B2DHomMatrix& _rViewTransformation, const ::basegfx::B2DHomMatrix& _rZoomLevelNormalization )
358     {
359         OSL_PRECOND( _rControl.is(), "UnoControlContactHelper::adjustControlGeometry_throw: illegal control!" );
360         if ( !_rControl.is() )
361             return;
362 
363     #if OSL_DEBUG_LEVEL > 0
364         ::basegfx::B2DTuple aViewScale, aViewTranslate;
365         double nViewRotate(0), nViewShearX(0);
366         _rViewTransformation.decompose( aViewScale, aViewTranslate, nViewRotate, nViewShearX );
367 
368         ::basegfx::B2DTuple aZoomScale, aZoomTranslate;
369         double nZoomRotate(0), nZoomShearX(0);
370         _rZoomLevelNormalization.decompose( aZoomScale, aZoomTranslate, nZoomRotate, nZoomShearX );
371     #endif
372 
373         // transform the logic bound rect, using the view transformation, to pixel coordinates
374         ::basegfx::B2DPoint aTopLeft( _rLogicBoundingRect.Left(), _rLogicBoundingRect.Top() );
375         aTopLeft *= _rViewTransformation;
376         ::basegfx::B2DPoint aBottomRight( _rLogicBoundingRect.Right(), _rLogicBoundingRect.Bottom() );
377         aBottomRight *= _rViewTransformation;
378 
379         const Rectangle aPaintRectPixel( (long)aTopLeft.getX(), (long)aTopLeft.getY(), (long)aBottomRight.getX(), (long)aBottomRight.getY() );
380         _rControl.setPosSize( aPaintRectPixel );
381 
382         // determine the scale from the current view transformation, and the normalization matrix
383         ::basegfx::B2DHomMatrix aObtainResolutionDependentScale( _rViewTransformation * _rZoomLevelNormalization );
384         ::basegfx::B2DVector aScale, aTranslate;
385 		double fRotate, fShearX;
386 		aObtainResolutionDependentScale.decompose( aScale, aTranslate, fRotate, fShearX );
387         _rControl.setZoom( aScale );
388     }
389 
390     //--------------------------------------------------------------------
391     void UnoControlContactHelper::disposeAndClearControl_nothrow( ControlHolder& _rControl )
392     {
393         try
394         {
395             Reference< XComponent > xControlComp( _rControl.getControl(), UNO_QUERY );
396             if ( xControlComp.is() )
397                 xControlComp->dispose();
398         }
399         catch( const Exception& )
400         {
401             DBG_UNHANDLED_EXCEPTION();
402         }
403         _rControl.clear();
404     }
405 
406     //====================================================================
407     //= IPageViewAccess
408     //====================================================================
409     /** interface encapsulating access to an SdrPageView, stripped down to the methods we really need
410      */
411     class IPageViewAccess
412     {
413     public:
414         /** determines whether the view is currently in design mode
415          */
416         virtual bool    isDesignMode() const = 0;
417 
418         /** retrieves the control container for a given output device
419          */
420         virtual Reference< XControlContainer >
421                         getControlContainer( const OutputDevice& _rDevice ) const = 0;
422 
423         /** determines whether a given layer is visible
424          */
425         virtual bool    isLayerVisible( SdrLayerID _nLayerID ) const = 0;
426     };
427 
428     //====================================================================
429     //= SdrPageViewAccess
430     //====================================================================
431     /** is a ->IPageViewAccess implementation based on a real ->SdrPageView instance
432      */
433     class SdrPageViewAccess : public IPageViewAccess
434     {
435         const SdrPageView&  m_rPageView;
436     public:
437         SdrPageViewAccess( const SdrPageView& _rPageView ) : m_rPageView( _rPageView ) { }
438 
439         virtual bool    isDesignMode() const;
440         virtual Reference< XControlContainer >
441                         getControlContainer( const OutputDevice& _rDevice ) const;
442         virtual bool    isLayerVisible( SdrLayerID _nLayerID ) const;
443     };
444 
445     //--------------------------------------------------------------------
446     bool SdrPageViewAccess::isDesignMode() const
447     {
448         return m_rPageView.GetView().IsDesignMode();
449     }
450 
451     //--------------------------------------------------------------------
452     Reference< XControlContainer > SdrPageViewAccess::getControlContainer( const OutputDevice& _rDevice ) const
453     {
454         Reference< XControlContainer > xControlContainer = m_rPageView.GetControlContainer( _rDevice );
455         DBG_ASSERT( xControlContainer.is() || NULL == m_rPageView.FindPageWindow( ( const_cast< OutputDevice& >( _rDevice ) ) ),
456             "SdrPageViewAccess::getControlContainer: the output device is known, but there is no control container for it?" );
457         return xControlContainer;
458     }
459 
460     //--------------------------------------------------------------------
461     bool SdrPageViewAccess::isLayerVisible( SdrLayerID _nLayerID ) const
462     {
463         return m_rPageView.GetVisibleLayers().IsSet( _nLayerID );
464     }
465 
466     //====================================================================
467     //= InvisibleControlViewAccess
468     //====================================================================
469     /** is a ->IPageViewAccess implementation which can be used to create an invisble control for
470         an arbitrary window
471      */
472     class InvisibleControlViewAccess : public IPageViewAccess
473     {
474     private:
475         Reference< XControlContainer >& m_rControlContainer;
476     public:
477         InvisibleControlViewAccess( Reference< XControlContainer >& _inout_ControlContainer )
478             :m_rControlContainer( _inout_ControlContainer )
479         {
480         }
481 
482         virtual bool    isDesignMode() const;
483         virtual Reference< XControlContainer >
484                         getControlContainer( const OutputDevice& _rDevice ) const;
485         virtual bool    isLayerVisible( SdrLayerID _nLayerID ) const;
486     };
487 
488     //--------------------------------------------------------------------
489     bool InvisibleControlViewAccess::isDesignMode() const
490     {
491         return true;
492     }
493 
494     //--------------------------------------------------------------------
495     Reference< XControlContainer > InvisibleControlViewAccess::getControlContainer( const OutputDevice& _rDevice ) const
496     {
497         if ( !m_rControlContainer.is() )
498         {
499             const Window* pWindow = dynamic_cast< const Window* >( &_rDevice );
500             OSL_ENSURE( pWindow, "InvisibleControlViewAccess::getControlContainer: expected to be called for a window only!" );
501             if ( pWindow )
502                 m_rControlContainer = VCLUnoHelper::CreateControlContainer( const_cast< Window* >( pWindow ) );
503         }
504         return m_rControlContainer;
505     }
506 
507     //--------------------------------------------------------------------
508     bool InvisibleControlViewAccess::isLayerVisible( SdrLayerID /*_nLayerID*/ ) const
509     {
510         return false;
511     }
512 
513     //====================================================================
514     //= DummyPageViewAccess
515     //====================================================================
516     /** is a ->IPageViewAccess implementation which can be used to create a control for an arbitrary
517         non-Window device
518 
519         The implementation will report the "PageView" as being in design mode, all layers to be visible,
520         and will not return any ControlContainer, so all control container related features (notifications etc)
521         are not available.
522      */
523     class DummyPageViewAccess : public IPageViewAccess
524     {
525     public:
526         DummyPageViewAccess()
527         {
528         }
529 
530         virtual bool    isDesignMode() const;
531         virtual Reference< XControlContainer >
532                         getControlContainer( const OutputDevice& _rDevice ) const;
533         virtual bool    isLayerVisible( SdrLayerID _nLayerID ) const;
534     };
535 
536     //--------------------------------------------------------------------
537     bool DummyPageViewAccess::isDesignMode() const
538     {
539         return true;
540     }
541 
542     //--------------------------------------------------------------------
543     Reference< XControlContainer > DummyPageViewAccess::getControlContainer( const OutputDevice& /*_rDevice*/ ) const
544     {
545         return NULL;
546     }
547 
548     //--------------------------------------------------------------------
549     bool DummyPageViewAccess::isLayerVisible( SdrLayerID /*_nLayerID*/ ) const
550     {
551         return true;
552     }
553 
554     //====================================================================
555     //= ViewObjectContactOfUnoControl_Impl
556     //====================================================================
557     typedef     ::cppu::WeakImplHelper4 <   XWindowListener
558                                         ,   XPropertyChangeListener
559                                         ,   XContainerListener
560                                         ,   XModeChangeListener
561                                         >   ViewObjectContactOfUnoControl_Impl_Base;
562 
563     class SVX_DLLPRIVATE ViewObjectContactOfUnoControl_Impl : public ViewObjectContactOfUnoControl_Impl_Base
564     {
565     private:
566         /// the instance whose IMPL we are
567         ViewObjectContactOfUnoControl*  m_pAntiImpl;
568 
569         /// are we currently inside impl_ensureControl_nothrow?
570         bool                            m_bCreatingControl;
571 
572         /** thread safety
573 
574             (not really. ATM only our X* implementations are guarded with this, but not
575             the object as a whole.)
576         */
577         mutable ::osl::Mutex            m_aMutex;
578 
579         /// the control we're responsible for
580         ControlHolder                   m_aControl;
581 
582         /// the ControlContainer where we inserted our control
583         Reference< XContainer >         m_xContainer;
584 
585         /// the output device for which the control was created
586         const OutputDevice*             m_pOutputDeviceForWindow;
587 
588         /// flag indicating whether the control is currently visible
589         bool                            m_bControlIsVisible;
590 
591         /// are we currently listening at a design mode control?
592         bool                            m_bIsDesignModeListening;
593 
594         enum ViewControlMode
595         {
596             eDesign,
597             eAlive,
598             eUnknown
599         };
600         /// is the control currently in design mode?
601         mutable ViewControlMode         m_eControlDesignMode;
602 
603         ::basegfx::B2DHomMatrix         m_aZoomLevelNormalization;
604 
605     public:
606         ViewObjectContactOfUnoControl_Impl( ViewObjectContactOfUnoControl* _pAntiImpl );
607 
608         /** disposes the instance, which is nonfunctional afterwards
609         */
610         void dispose();
611 
612         /** determines whether the instance is disposed
613         */
614         bool isDisposed() const { return impl_isDisposed_nofail(); }
615 
616         /** determines whether the instance is alive
617         */
618         bool isAlive() const { return !isDisposed(); }
619 
620         /** returns the SdrUnoObject associated with the ViewContact
621 
622             @precond
623                 We're not disposed.
624         */
625         bool    getUnoObject( SdrUnoObj*& _out_rpObject ) const;
626 
627         /** ensures that we have an ->XControl
628 
629             Must only be called if a control is needed when no DisplayInfo is present, yet.
630 
631             For creating a control, an ->OutputDevice is needed, and an ->SdrPageView. Both will be obtained
632             from a ->ObjectContactOfPageView. So, if our (anti-impl's) object contact is not a ->ObjectContactOfPageView,
633             this method fill fail.
634 
635             Failure of this method will be reported via an assertion in a non-product version.
636         */
637         bool    ensureControl( const basegfx::B2DHomMatrix* _pInitialViewTransformationOrNULL );
638 
639         /** returns our XControl, if it already has been created
640 
641             If you want to ensure that the control exists before accessing it, use ->ensureControl
642         */
643         inline const ControlHolder&
644                 getExistentControl() const { return m_aControl; }
645 
646         inline bool
647                 hasControl() const { return m_aControl.is(); }
648 
649         /** positions our XControl according to the geometry settings in the SdrUnoObj, modified by the given
650             transformation, and sets proper zoom settings according to our device
651 
652             @precond
653                 ->m_pOutputDeviceForWindow and ->m_aControl are not <NULL/>
654         */
655         void    positionAndZoomControl( const basegfx::B2DHomMatrix& _rViewTransformation ) const;
656 
657         /** determines whether or not our control is printable
658 
659             Effectively, this method returns the value of the "Printable" property
660             of the control's model. If we have no control, <FALSE/> is returned.
661         */
662         bool    isPrintableControl() const;
663 
664         /** sets the design mode on the control, or at least remembers the flag for the
665             time the control is created
666         */
667         void    setControlDesignMode( bool _bDesignMode ) const;
668 
669         /** determines whether our control is currently visible
670             @nofail
671         */
672         bool    isControlVisible() const { return impl_isControlVisible_nofail(); }
673 
674         /// creates an XControl for the given device and SdrUnoObj
675         static bool
676                 createControlForDevice(
677                     IPageViewAccess& _rPageView,
678                     const OutputDevice& _rDevice,
679                     const SdrUnoObj& _rUnoObject,
680                     const basegfx::B2DHomMatrix& _rInitialViewTransformation,
681                     const basegfx::B2DHomMatrix& _rInitialZoomNormalization,
682                     ControlHolder& _out_rControl
683                 );
684 
685         struct GuardAccess { friend class VOCGuard; private: GuardAccess() { } };
686         ::osl::Mutex&   getMutex( GuardAccess ) const { return m_aMutex; }
687 
688         const ViewContactOfUnoControl&
689                 getViewContact() const
690         {
691             ENSURE_OR_THROW( !impl_isDisposed_nofail(), "already disposed" );
692             return static_cast< const ViewContactOfUnoControl& >( m_pAntiImpl->GetViewContact() );
693         }
694 
695     protected:
696         ~ViewObjectContactOfUnoControl_Impl();
697 
698         // XEventListener
699         virtual void SAL_CALL disposing( const EventObject& Source ) throw(RuntimeException);
700 
701         // XWindowListener
702         virtual void SAL_CALL windowResized( const WindowEvent& e ) throw(RuntimeException);
703         virtual void SAL_CALL windowMoved( const WindowEvent& e ) throw(RuntimeException);
704         virtual void SAL_CALL windowShown( const EventObject& e ) throw(RuntimeException);
705         virtual void SAL_CALL windowHidden( const EventObject& e ) throw(RuntimeException);
706 
707         // XPropertyChangeListener
708         virtual void SAL_CALL propertyChange( const PropertyChangeEvent& evt ) throw(RuntimeException);
709 
710         // XModeChangeListener
711         virtual void SAL_CALL modeChanged( const ModeChangeEvent& _rSource ) throw (RuntimeException);
712 
713         // XContainerListener
714         virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
715         virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
716         virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
717 
718     private:
719         /** retrieves the SdrPageView which our associated SdrPageViewWindow belongs to
720 
721             @param out_rpPageView
722                 a reference to a pointer holding, upon return, the desired SdrPageView
723 
724             @return
725                 <TRUE/> if and only if a ->SdrPageView could be obtained
726 
727             @precond
728                 We really belong to an SdrPageViewWindow. Perhaps (I'm not sure ATM :)
729                 there are instance for which this might not be true, but those instances
730                 should never have a need to call this method.
731 
732             @precond
733                 We're not disposed.
734 
735             @postcond
736                 The method expects success, if it returns with <FALSE/>, this will have been
737                 asserted.
738 
739             @nothrow
740         */
741         bool    impl_getPageView_nothrow( SdrPageView*& _out_rpPageView );
742 
743         /** adjusts the control visibility so it respects its layer's visibility
744 
745             @param _bForce
746                 set to <TRUE/> if you want to force a ->XWindow::setVisible call,
747                 no matter if the control visibility is already correct
748 
749             @precond
750                 ->m_aControl is not <NULL/>
751 
752             @precond
753                 We're not disposed.
754 
755             @precond
756                 We really belong to an SdrPageViewWindow. There are instance for which this
757                 might not be true, but those instances should never have a need to call
758                 this method.
759         */
760         void impl_adjustControlVisibilityToLayerVisibility_throw( bool _bForce );
761 
762         /** adjusts the control visibility so it respects its layer's visibility
763 
764             The control must never be visibile if it's in design mode.
765             In alive mode, it must be visibility if and only it's on a visible layer.
766 
767             @param _rxControl
768                 the control whose visibility is to be adjusted
769 
770             @param _rPageView
771                 provides access to the attributes of the SdrPageView which the control finally belongs to
772 
773             @param _rUnoObject
774                 our SdrUnoObj
775 
776             @param _bIsCurrentlyVisible
777                 determines whether the control is currently visible. Note that this is only a shortcut for
778                 querying _rxControl for the XWindow2 interface, and calling isVisible at this interface.
779                 This shortcut has been chosen since the caller usually already has this information.
780                 If _bForce is <TRUE/>, _bIsCurrentlyVisible is ignored.
781 
782             @param _bForce
783                 set to <TRUE/> if you want to force a ->XWindow::setVisible call,
784                 no matter if the control visibility is already correct
785 
786             @precond
787                 We're not disposed.
788         */
789         static void impl_adjustControlVisibilityToLayerVisibility_throw( const ControlHolder& _rxControl, const SdrUnoObj& _rUnoObject,
790             IPageViewAccess& _rPageView, bool _bIsCurrentlyVisible, bool _bForce );
791 
792         /** starts or stops listening at various aspects of our control
793 
794             @precond
795                 ->m_aControl is not <NULL/>
796         */
797         void impl_switchControlListening_nothrow( bool _bStart );
798 
799         /** starts or stops listening at our control container
800 
801             @precond
802                 ->m_xContainer is not <NULL/>
803         */
804         void impl_switchContainerListening_nothrow( bool _bStart );
805 
806         /** starts or stops listening at the control for design-mode relevant facets
807         */
808         void impl_switchDesignModeListening_nothrow( bool _bStart );
809 
810         /** starts or stops listening for all properties at our control
811 
812             @param _bStart
813                 determines whether to start or to stop listening
814 
815             @precond
816                 ->m_aControl is not <NULL/>
817         */
818         void impl_switchPropertyListening_nothrow( bool _bStart );
819 
820         /** disposes the instance
821             @param _bAlsoDisposeControl
822                 determines whether the XControl should be disposed, too
823         */
824         void impl_dispose_nothrow( bool _bAlsoDisposeControl );
825 
826         /** determines whether the instance is disposed
827             @nofail
828         */
829         bool    impl_isDisposed_nofail() const { return m_pAntiImpl == NULL; }
830 
831         /** determines whether our control is currently visible
832             @nofail
833         */
834         bool    impl_isControlVisible_nofail() const { return m_bControlIsVisible; }
835 
836         /** determines whether we are currently a listener at the control for desgin-mode relevant facets
837             @nofail
838         */
839         bool    impl_isDesignModeListening_nofail() const { return m_bIsDesignModeListening; }
840 
841         /** determines whether the control currently is in design mode
842 
843             @precond
844                 The design mode must already be known. It is known when we first had access to
845                 an SdrPageView (which carries this flag), or somebody explicitly set it from
846                 outside.
847         */
848         inline bool impl_isControlDesignMode_nothrow() const
849         {
850             DBG_ASSERT( m_eControlDesignMode != eUnknown, "ViewObjectContactOfUnoControl_Impl::impl_isControlDesignMode_nothrow: mode is still unknown!" );
851             return m_eControlDesignMode == eDesign;
852         }
853 
854         /** ensures that we have a control for the given PageView/OutputDevice
855         */
856         bool impl_ensureControl_nothrow(
857                 IPageViewAccess& _rPageView,
858                 const OutputDevice& _rDevice,
859                 const basegfx::B2DHomMatrix& _rInitialViewTransformation
860              );
861 
862         /** retrieves the device which a PageView belongs to, starting from its ObjectContactOfPageView
863 
864             Since #i72752#, the PaintWindow (and thus the OutputDevice) associated with a PageView is not
865             constant over its lifetime. Instead, during some paint operations, the PaintWindow/OutputDevice
866             might be temporarily patched.
867 
868             This method cares for this, by retrieving the very original OutputDevice.
869         */
870         static const OutputDevice& impl_getPageViewOutputDevice_nothrow( const ObjectContactOfPageView& _rObjectContact );
871 
872         const OutputDevice& impl_getOutputDevice_throw() const;
873 
874     private:
875         ViewObjectContactOfUnoControl_Impl();                                                       // never implemented
876         ViewObjectContactOfUnoControl_Impl( const ViewObjectContactOfUnoControl_Impl& );            // never implemented
877         ViewObjectContactOfUnoControl_Impl& operator=( const ViewObjectContactOfUnoControl_Impl& ); // never implemented
878     };
879 
880     //====================================================================
881     //= VOCGuard
882     //====================================================================
883     /** class for guarding a ViewObjectContactOfUnoControl_Impl method
884      */
885     class VOCGuard
886     {
887     private:
888         ::osl::MutexGuard   m_aMutexGuard;
889 
890     public:
891         VOCGuard( const ViewObjectContactOfUnoControl_Impl& _rImpl )
892             :m_aMutexGuard( _rImpl.getMutex( ViewObjectContactOfUnoControl_Impl::GuardAccess() ) )
893         {
894         }
895     };
896 
897     //====================================================================
898     //= LazyControlCreationPrimitive2D
899     //====================================================================
900     class LazyControlCreationPrimitive2D : public ::drawinglayer::primitive2d::BufferedDecompositionPrimitive2D
901     {
902     private:
903         typedef ::drawinglayer::primitive2d::BufferedDecompositionPrimitive2D  BufferedDecompositionPrimitive2D;
904 
905     protected:
906         virtual ::drawinglayer::primitive2d::Primitive2DSequence
907             get2DDecomposition(
908                 const ::drawinglayer::geometry::ViewInformation2D& rViewInformation
909             ) const;
910 
911         virtual ::drawinglayer::primitive2d::Primitive2DSequence
912             create2DDecomposition(
913                 const ::drawinglayer::geometry::ViewInformation2D& rViewInformation
914             ) const;
915 
916         virtual ::basegfx::B2DRange
917             getB2DRange(
918                 const ::drawinglayer::geometry::ViewInformation2D& rViewInformation
919             ) const;
920 
921     public:
922         LazyControlCreationPrimitive2D( const ::rtl::Reference< ViewObjectContactOfUnoControl_Impl >& _pVOCImpl )
923             :m_pVOCImpl( _pVOCImpl )
924         {
925             ENSURE_OR_THROW( m_pVOCImpl.is(), "Illegal argument." );
926             getTransformation( m_pVOCImpl->getViewContact(), m_aTransformation );
927         }
928 
929         virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
930 
931         // declare unique ID for this primitive class
932         DeclPrimitrive2DIDBlock()
933 
934         static void getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation );
935 
936     private:
937         void impl_positionAndZoomControl( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
938         {
939             if ( !_rViewInformation.getViewport().isEmpty() )
940                 m_pVOCImpl->positionAndZoomControl( _rViewInformation.getObjectToViewTransformation() );
941         }
942 
943     private:
944         ::rtl::Reference< ViewObjectContactOfUnoControl_Impl >  m_pVOCImpl;
945         /** The geometry is part of the identity of an primitive, so we cannot calculate it on demand
946             (since the data the calculation is based on might have changed then), but need to calc
947             it at construction time, and remember it.
948         */
949         ::basegfx::B2DHomMatrix                                 m_aTransformation;
950     };
951 
952     //====================================================================
953     //= ViewObjectContactOfUnoControl_Impl
954     //====================================================================
955     DBG_NAME( ViewObjectContactOfUnoControl_Impl )
956     //--------------------------------------------------------------------
957     ViewObjectContactOfUnoControl_Impl::ViewObjectContactOfUnoControl_Impl( ViewObjectContactOfUnoControl* _pAntiImpl )
958         :m_pAntiImpl( _pAntiImpl )
959         ,m_bCreatingControl( false )
960         ,m_pOutputDeviceForWindow( NULL )
961         ,m_bControlIsVisible( false )
962         ,m_bIsDesignModeListening( false )
963         ,m_eControlDesignMode( eUnknown )
964         ,m_aZoomLevelNormalization()
965     {
966         DBG_CTOR( ViewObjectContactOfUnoControl_Impl, NULL );
967         DBG_ASSERT( m_pAntiImpl, "ViewObjectContactOfUnoControl_Impl::ViewObjectContactOfUnoControl_Impl: invalid AntiImpl!" );
968 
969         const OutputDevice& rPageViewDevice( impl_getOutputDevice_throw() );
970         m_aZoomLevelNormalization = rPageViewDevice.GetInverseViewTransformation();
971 
972     #if OSL_DEBUG_LEVEL > 1
973         ::basegfx::B2DVector aScale, aTranslate;
974         double fRotate, fShearX;
975         m_aZoomLevelNormalization.decompose( aScale, aTranslate, fRotate, fShearX );
976     #endif
977 
978         ::basegfx::B2DHomMatrix aScaleNormalization;
979         MapMode aCurrentDeviceMapMode( rPageViewDevice.GetMapMode() );
980         aScaleNormalization.set( 0, 0, (double)aCurrentDeviceMapMode.GetScaleX() );
981         aScaleNormalization.set( 1, 1, (double)aCurrentDeviceMapMode.GetScaleY() );
982         m_aZoomLevelNormalization *= aScaleNormalization;
983 
984     #if OSL_DEBUG_LEVEL > 1
985         m_aZoomLevelNormalization.decompose( aScale, aTranslate, fRotate, fShearX );
986     #endif
987    }
988 
989     //--------------------------------------------------------------------
990     ViewObjectContactOfUnoControl_Impl::~ViewObjectContactOfUnoControl_Impl()
991     {
992         if ( !impl_isDisposed_nofail() )
993         {
994             acquire();
995             dispose();
996         }
997 
998         DBG_DTOR( ViewObjectContactOfUnoControl_Impl, NULL );
999     }
1000 
1001     //--------------------------------------------------------------------
1002     void ViewObjectContactOfUnoControl_Impl::impl_dispose_nothrow( bool _bAlsoDisposeControl )
1003     {
1004         if ( impl_isDisposed_nofail() )
1005             return;
1006 
1007         if ( m_aControl.is() )
1008             impl_switchControlListening_nothrow( false );
1009 
1010         if ( m_xContainer.is() )
1011             impl_switchContainerListening_nothrow( false );
1012 
1013         // dispose the control
1014         if ( _bAlsoDisposeControl )
1015             UnoControlContactHelper::disposeAndClearControl_nothrow( m_aControl );
1016 
1017         m_aControl.clear();
1018         m_xContainer.clear();
1019         m_pOutputDeviceForWindow = NULL;
1020         m_bControlIsVisible = false;
1021 
1022         m_pAntiImpl = NULL;
1023     }
1024 
1025     //--------------------------------------------------------------------
1026     void ViewObjectContactOfUnoControl_Impl::dispose()
1027     {
1028         VOCGuard aGuard( *this );
1029         impl_dispose_nothrow( true );
1030     }
1031 
1032     //--------------------------------------------------------------------
1033     bool ViewObjectContactOfUnoControl_Impl::getUnoObject( SdrUnoObj*& _out_rpObject ) const
1034     {
1035         OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::getUnoObject: already disposed()" );
1036         if ( impl_isDisposed_nofail() )
1037             _out_rpObject = NULL;
1038         else
1039         {
1040             _out_rpObject = dynamic_cast< SdrUnoObj* >( m_pAntiImpl->GetViewContact().TryToGetSdrObject() );
1041             DBG_ASSERT( _out_rpObject || !m_pAntiImpl->GetViewContact().TryToGetSdrObject(),
1042                 "ViewObjectContactOfUnoControl_Impl::getUnoObject: invalid SdrObject!" );
1043         }
1044         return ( _out_rpObject != NULL );
1045     }
1046 
1047     //--------------------------------------------------------------------
1048     void ViewObjectContactOfUnoControl_Impl::positionAndZoomControl( const basegfx::B2DHomMatrix& _rViewTransformation ) const
1049     {
1050         OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::positionAndZoomControl: no output device or no control!" );
1051         if ( !m_aControl.is() )
1052             return;
1053 
1054         try
1055         {
1056             SdrUnoObj* pUnoObject( NULL );
1057             if ( getUnoObject( pUnoObject ) )
1058             {
1059                 UnoControlContactHelper::adjustControlGeometry_throw( m_aControl, pUnoObject->GetLogicRect(), _rViewTransformation, m_aZoomLevelNormalization );
1060             }
1061             else
1062                 OSL_ENSURE( false, "ViewObjectContactOfUnoControl_Impl::positionAndZoomControl: no SdrUnoObj!" );
1063         }
1064         catch( const Exception& )
1065         {
1066             DBG_UNHANDLED_EXCEPTION();
1067         }
1068     }
1069 
1070     //--------------------------------------------------------------------
1071     bool ViewObjectContactOfUnoControl_Impl::ensureControl( const basegfx::B2DHomMatrix* _pInitialViewTransformationOrNULL )
1072     {
1073         OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::ensureControl: already disposed()" );
1074         if ( impl_isDisposed_nofail() )
1075             return false;
1076 
1077         ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
1078         if ( pPageViewContact )
1079         {
1080             SdrPageViewAccess aPVAccess( pPageViewContact->GetPageWindow().GetPageView() );
1081             const OutputDevice& rDevice( impl_getPageViewOutputDevice_nothrow( *pPageViewContact ) );
1082             return impl_ensureControl_nothrow(
1083                 aPVAccess,
1084                 rDevice,
1085                 _pInitialViewTransformationOrNULL ? *_pInitialViewTransformationOrNULL : rDevice.GetViewTransformation()
1086             );
1087         }
1088 
1089         DummyPageViewAccess aNoPageView;
1090         const OutputDevice& rDevice( impl_getOutputDevice_throw() );
1091         return impl_ensureControl_nothrow(
1092             aNoPageView,
1093             rDevice,
1094             _pInitialViewTransformationOrNULL ? *_pInitialViewTransformationOrNULL : rDevice.GetViewTransformation()
1095         );
1096     }
1097 
1098     //--------------------------------------------------------------------
1099     const OutputDevice& ViewObjectContactOfUnoControl_Impl::impl_getOutputDevice_throw() const
1100     {
1101         ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
1102         if ( pPageViewContact )
1103         {
1104             // do not use ObjectContact::TryToGetOutputDevice here, it would not care for the PageWindow's
1105             // OriginalPaintWindow
1106             return impl_getPageViewOutputDevice_nothrow( *pPageViewContact );
1107         }
1108 
1109         const OutputDevice* pDevice = m_pAntiImpl->GetObjectContact().TryToGetOutputDevice();
1110         ENSURE_OR_THROW( pDevice, "no output device -> no control" );
1111         return *pDevice;
1112     }
1113 
1114     //--------------------------------------------------------------------
1115     const OutputDevice& ViewObjectContactOfUnoControl_Impl::impl_getPageViewOutputDevice_nothrow( const ObjectContactOfPageView& _rObjectContact )
1116     {
1117         // if the PageWindow has a patched PaintWindow, use the original PaintWindow
1118         // this ensures that our control is _not_ re-created just because somebody
1119         // (temporarily) changed the window to paint onto.
1120         // #i72429# / 2007-02-20 / frank.schoenheit@sun.com
1121         SdrPageWindow& rPageWindow( _rObjectContact.GetPageWindow() );
1122         if ( rPageWindow.GetOriginalPaintWindow() )
1123             return rPageWindow.GetOriginalPaintWindow()->GetOutputDevice();
1124 
1125         return rPageWindow.GetPaintWindow().GetOutputDevice();
1126     }
1127 
1128     namespace
1129     {
1130         static void lcl_resetFlag( bool& rbFlag )
1131         {
1132             rbFlag = false;
1133         }
1134     }
1135 
1136     //--------------------------------------------------------------------
1137     bool ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow( IPageViewAccess& _rPageView, const OutputDevice& _rDevice,
1138         const basegfx::B2DHomMatrix& _rInitialViewTransformation )
1139     {
1140         if ( m_bCreatingControl )
1141         {
1142             OSL_ENSURE( false, "ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow: reentrance is not really good here!" );
1143             // We once had a situation where this was called reentrantly, which lead to all kind of strange effects. All
1144             // those affected the grid control, which is the only control so far which is visible in design mode (and
1145             // not only in alive mode).
1146             // Creating the control triggered an Window::Update on some of its child windows, which triggered a
1147             // Paint on parent of the grid control (e.g. the SwEditWin), which triggered a reentrant call to this method,
1148             // which it is not really prepared for.
1149             //
1150             // /me thinks that re-entrance should be caught on a higher level, i.e. the Drawing Layer should not allow
1151             // reentrant paint requests. For the moment, until /me can discuss this with AW, catch it here.
1152             // 2009-08-27 / #i104544# frank.schoenheit@sun.com
1153             return false;
1154         }
1155 
1156         m_bCreatingControl = true;
1157         ::comphelper::ScopeGuard aGuard( ::boost::bind( lcl_resetFlag, ::boost::ref( m_bCreatingControl ) ) );
1158 
1159         if ( m_aControl.is() )
1160         {
1161             if ( m_pOutputDeviceForWindow == &_rDevice )
1162                 return true;
1163 
1164             // Somebody requested a control for a new device, which means either of
1165             // - our PageView's paint window changed since we were last here
1166             // - we don't belong to a page view, and are simply painted onto different devices
1167             // The first sounds strange (doens't it?), the second means we could perhaps
1168             // optimize this in the future - there is no need to re-create the control every time,
1169             // is it?
1170             // #i74523# / 2007-02-15 / frank.schoenheit@sun.com
1171             if ( m_xContainer.is() )
1172                 impl_switchContainerListening_nothrow( false );
1173             impl_switchControlListening_nothrow( false );
1174             UnoControlContactHelper::disposeAndClearControl_nothrow( m_aControl );
1175         }
1176 
1177         SdrUnoObj* pUnoObject( NULL );
1178         if ( !getUnoObject( pUnoObject ) )
1179             return false;
1180 
1181         ControlHolder aControl;
1182         if ( !createControlForDevice( _rPageView, _rDevice, *pUnoObject, _rInitialViewTransformation, m_aZoomLevelNormalization, aControl ) )
1183             return false;
1184 
1185         m_pOutputDeviceForWindow = &_rDevice;
1186         m_aControl = aControl;
1187         m_xContainer = m_xContainer.query( _rPageView.getControlContainer( _rDevice ) );
1188         DBG_ASSERT( (   m_xContainer.is()                                           // either have a XControlContainer
1189                     ||  (   ( !_rPageView.getControlContainer( _rDevice ).is() )    // or don't have any container,
1190                         &&  ( dynamic_cast< const Window* >( &_rDevice ) == NULL )  // which is allowed for non-Window instances only
1191                         )
1192                     ),
1193             "ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow: no XContainer at the ControlContainer!" );
1194 
1195         try
1196         {
1197             m_eControlDesignMode = m_aControl.isDesignMode() ? eDesign : eAlive;
1198             m_bControlIsVisible = m_aControl.isVisible();
1199         }
1200         catch( const Exception& )
1201         {
1202             DBG_UNHANDLED_EXCEPTION();
1203         }
1204 
1205         // start listening at all aspects of the control which are interesting to us ...
1206         impl_switchControlListening_nothrow( true );
1207 
1208         // start listening at the control container, in case somebody tampers with our control
1209         if ( m_xContainer.is() )
1210             impl_switchContainerListening_nothrow( true );
1211 
1212         return m_aControl.is();
1213     }
1214 
1215     //--------------------------------------------------------------------
1216     bool ViewObjectContactOfUnoControl_Impl::createControlForDevice( IPageViewAccess& _rPageView,
1217         const OutputDevice& _rDevice, const SdrUnoObj& _rUnoObject, const basegfx::B2DHomMatrix& _rInitialViewTransformation,
1218         const basegfx::B2DHomMatrix& _rInitialZoomNormalization, ControlHolder& _out_rControl )
1219     {
1220         _out_rControl.clear();
1221 
1222         Reference< XControlModel > xControlModel( _rUnoObject.GetUnoControlModel() );
1223         DBG_ASSERT( xControlModel.is(), "ViewObjectContactOfUnoControl_Impl::createControlForDevice: no control model at the SdrUnoObject!?" );
1224         if ( !xControlModel.is() )
1225             return false;
1226 
1227         bool bSuccess = false;
1228         try
1229         {
1230             const ::rtl::OUString sControlServiceName( _rUnoObject.GetUnoControlTypeName() );
1231 
1232             Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW );
1233             _out_rControl = Reference< XControl >( xFactory->createInstance( sControlServiceName ), UNO_QUERY_THROW );
1234 
1235             // knit the model and the control
1236             _out_rControl.setModel( xControlModel );
1237 
1238             // proper geometry
1239             UnoControlContactHelper::adjustControlGeometry_throw(
1240                 _out_rControl,
1241                 _rUnoObject.GetLogicRect(),
1242                 _rInitialViewTransformation,
1243                 _rInitialZoomNormalization
1244             );
1245 
1246             // #107049# set design mode before peer is created,
1247             // this is also needed for accessibility
1248             _out_rControl.setDesignMode( _rPageView.isDesignMode() );
1249 
1250             // adjust the initial visibility according to the visibility of the layer
1251             // 2003-06-03 - #110592# - fs@openoffice.org
1252             impl_adjustControlVisibilityToLayerVisibility_throw( _out_rControl, _rUnoObject, _rPageView, false, true );
1253 
1254             // add the control to the respective control container
1255             // #108327# do this last
1256             Reference< XControlContainer > xControlContainer( _rPageView.getControlContainer( _rDevice ) );
1257             if ( xControlContainer.is() )
1258                 xControlContainer->addControl( sControlServiceName, _out_rControl.getControl() );
1259 
1260             bSuccess = true;
1261         }
1262         catch( const Exception& )
1263         {
1264             DBG_UNHANDLED_EXCEPTION();
1265         }
1266 
1267         if ( !bSuccess )
1268         {
1269             // delete the control which might have been created already
1270             UnoControlContactHelper::disposeAndClearControl_nothrow( _out_rControl );
1271         }
1272 
1273         return _out_rControl.is();
1274     }
1275 
1276     //--------------------------------------------------------------------
1277     bool ViewObjectContactOfUnoControl_Impl::impl_getPageView_nothrow( SdrPageView*& _out_rpPageView )
1278     {
1279         OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::impl_getPageView_nothrow: already disposed!" );
1280 
1281         _out_rpPageView = NULL;
1282         if ( impl_isDisposed_nofail() )
1283             return false;
1284 
1285         ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
1286         if ( pPageViewContact )
1287             _out_rpPageView = &pPageViewContact->GetPageWindow().GetPageView();
1288 
1289         DBG_ASSERT( _out_rpPageView != NULL, "ViewObjectContactOfUnoControl_Impl::impl_getPageView_nothrow: this method is expected to always have success!" );
1290         return ( _out_rpPageView != NULL );
1291     }
1292 
1293     //--------------------------------------------------------------------
1294     void ViewObjectContactOfUnoControl_Impl::impl_adjustControlVisibilityToLayerVisibility_throw( bool _bForce )
1295     {
1296         OSL_PRECOND( m_aControl.is(),
1297             "ViewObjectContactOfUnoControl_Impl::impl_adjustControlVisibilityToLayerVisibility_throw: only valid if we have a control!" );
1298 
1299         SdrPageView* pPageView( NULL );
1300         if ( !impl_getPageView_nothrow( pPageView ) )
1301             return;
1302 
1303         SdrUnoObj* pUnoObject( NULL );
1304         if ( !getUnoObject( pUnoObject ) )
1305             return;
1306 
1307         SdrPageViewAccess aPVAccess( *pPageView );
1308         impl_adjustControlVisibilityToLayerVisibility_throw( m_aControl, *pUnoObject, aPVAccess, impl_isControlVisible_nofail(), _bForce );
1309     }
1310 
1311     //--------------------------------------------------------------------
1312     void ViewObjectContactOfUnoControl_Impl::impl_adjustControlVisibilityToLayerVisibility_throw( const ControlHolder& _rControl,
1313         const SdrUnoObj& _rUnoObject, IPageViewAccess& _rPageView, bool _bIsCurrentlyVisible, bool _bForce )
1314     {
1315         // in design mode, there is no problem with the visibility: The XControl is hidden by
1316         // default, and the Drawing Layer will simply not call our paint routine, if we're in
1317         // a hidden layer. So, only alive mode matters.
1318         if ( !_rControl.isDesignMode() )
1319         {
1320             // the layer of our object
1321             SdrLayerID nObjectLayer = _rUnoObject.GetLayer();
1322             // is the object we're residing in visible in this view?
1323             bool bIsObjectVisible = _rUnoObject.IsVisible() && _rPageView.isLayerVisible( nObjectLayer );
1324 
1325             if ( _bForce || ( bIsObjectVisible != _bIsCurrentlyVisible ) )
1326             {
1327                 _rControl.setVisible( bIsObjectVisible );
1328             }
1329         }
1330     }
1331 
1332     //--------------------------------------------------------------------
1333     void ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow( bool _bStart )
1334     {
1335         OSL_PRECOND( m_xContainer.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow: no control container!" );
1336         if ( !m_xContainer.is() )
1337             return;
1338 
1339         try
1340         {
1341             if ( _bStart )
1342                 m_xContainer->addContainerListener( this );
1343             else
1344                 m_xContainer->removeContainerListener( this );
1345         }
1346         catch( const Exception& )
1347         {
1348             DBG_UNHANDLED_EXCEPTION();
1349         }
1350     }
1351 
1352     //--------------------------------------------------------------------
1353     void ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow( bool _bStart )
1354     {
1355         OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow: invalid control!" );
1356         if ( !m_aControl.is() )
1357             return;
1358 
1359         try
1360         {
1361             // listen for visibility changes
1362             if ( _bStart )
1363                 m_aControl.addWindowListener( this );
1364             else
1365                 m_aControl.removeWindowListener( this );
1366 
1367             // in design mode, listen for some more aspects
1368             impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() && _bStart );
1369 
1370             // listen for design mode changes
1371             Reference< XModeChangeBroadcaster > xDesignModeChanges( m_aControl.getControl(), UNO_QUERY_THROW );
1372             if ( _bStart )
1373                 xDesignModeChanges->addModeChangeListener( this );
1374             else
1375                 xDesignModeChanges->removeModeChangeListener( this );
1376         }
1377         catch( const Exception& )
1378         {
1379             DBG_UNHANDLED_EXCEPTION();
1380         }
1381     }
1382 
1383     //--------------------------------------------------------------------
1384     void ViewObjectContactOfUnoControl_Impl::impl_switchDesignModeListening_nothrow( bool _bStart )
1385     {
1386         if ( impl_isDesignModeListening_nofail() != _bStart )
1387         {
1388             m_bIsDesignModeListening = _bStart;
1389             impl_switchPropertyListening_nothrow( _bStart );
1390         }
1391     }
1392 
1393     //------------------------------------------------------------------------------
1394     void ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow( bool _bStart )
1395     {
1396         OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow: no control!" );
1397         if ( !m_aControl.is() )
1398             return;
1399 
1400         try
1401         {
1402             Reference< XPropertySet > xModelProperties( m_aControl.getModel(), UNO_QUERY_THROW );
1403             if ( _bStart )
1404                 xModelProperties->addPropertyChangeListener( ::rtl::OUString(), this );
1405             else
1406                 xModelProperties->removePropertyChangeListener( ::rtl::OUString(), this );
1407         }
1408         catch( const Exception& )
1409         {
1410             DBG_UNHANDLED_EXCEPTION();
1411         }
1412     }
1413 
1414     //--------------------------------------------------------------------
1415     bool ViewObjectContactOfUnoControl_Impl::isPrintableControl() const
1416     {
1417         SdrUnoObj* pUnoObject( NULL );
1418         if ( !getUnoObject( pUnoObject ) )
1419             return false;
1420 
1421         bool bIsPrintable = false;
1422         try
1423         {
1424             Reference< XPropertySet > xModelProperties( pUnoObject->GetUnoControlModel(), UNO_QUERY_THROW );
1425             static const ::rtl::OUString s_sPrintablePropertyName( RTL_CONSTASCII_USTRINGPARAM( "Printable" ) );
1426             OSL_VERIFY( xModelProperties->getPropertyValue( s_sPrintablePropertyName ) >>= bIsPrintable );
1427         }
1428         catch( const Exception& )
1429         {
1430             DBG_UNHANDLED_EXCEPTION();
1431         }
1432         return bIsPrintable;
1433     }
1434 
1435     //--------------------------------------------------------------------
1436     void SAL_CALL ViewObjectContactOfUnoControl_Impl::disposing( const EventObject& Source ) throw(RuntimeException)
1437     {
1438         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1439             // some code below - in particular our disposal - might trigger actions which require the
1440             // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
1441             // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
1442             // is the real bug. Toolkit really is infested with solar mutex usage ... :(
1443             // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
1444         VOCGuard aGuard( *this );
1445 
1446         if ( !m_aControl.is() )
1447             return;
1448 
1449         if  (   ( m_aControl            == Source.Source )
1450             ||  ( m_aControl.getModel() == Source.Source )
1451             )
1452         {
1453             // the model or the control is dying ... hmm, not much sense in that we ourself continue
1454             // living
1455             impl_dispose_nothrow( false );
1456             return;
1457         }
1458 
1459         DBG_ASSERT( Source.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::disposing: Who's this?" );
1460     }
1461 
1462     //--------------------------------------------------------------------
1463     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowResized( const WindowEvent& /*e*/ ) throw(RuntimeException)
1464     {
1465         // not interested in
1466     }
1467 
1468     //--------------------------------------------------------------------
1469     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowMoved( const WindowEvent& /*e*/ ) throw(RuntimeException)
1470     {
1471         // not interested in
1472     }
1473 
1474     //--------------------------------------------------------------------
1475     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowShown( const EventObject& /*e*/ ) throw(RuntimeException)
1476     {
1477         VOCGuard aGuard( *this );
1478         m_bControlIsVisible = true;
1479     }
1480 
1481     //--------------------------------------------------------------------
1482     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowHidden( const EventObject& /*e*/ ) throw(RuntimeException)
1483     {
1484         VOCGuard aGuard( *this );
1485         m_bControlIsVisible = false;
1486     }
1487 
1488     //--------------------------------------------------------------------
1489     void SAL_CALL ViewObjectContactOfUnoControl_Impl::propertyChange( const PropertyChangeEvent& /*_rEvent*/ ) throw(RuntimeException)
1490     {
1491         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1492             // (re)painting might require VCL operations, which need the SolarMutex
1493 
1494         OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::propertyChange: already disposed()" );
1495         if ( impl_isDisposed_nofail() )
1496             return;
1497 
1498         VOCGuard aGuard( *this );
1499         DBG_ASSERT( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::propertyChange: " );
1500         if ( !m_aControl.is() )
1501             return;
1502 
1503         // a generic property changed. If we're in design mode, we need to repaint the control
1504         if ( impl_isControlDesignMode_nothrow() )
1505         {
1506             m_pAntiImpl->propertyChange();
1507         }
1508     }
1509 
1510     //--------------------------------------------------------------------
1511     void SAL_CALL ViewObjectContactOfUnoControl_Impl::modeChanged( const ModeChangeEvent& _rSource ) throw (RuntimeException)
1512     {
1513         VOCGuard aGuard( *this );
1514 
1515         DBG_ASSERT( _rSource.NewMode.equalsAscii( "design" ) || _rSource.NewMode.equalsAscii( "alive" ),
1516             "ViewObjectContactOfUnoControl_Impl::modeChanged: unexpected mode!" );
1517 
1518         m_eControlDesignMode = _rSource.NewMode.equalsAscii( "design" ) ? eDesign : eAlive;
1519 
1520         impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() );
1521 
1522         try
1523         {
1524             // if the control is part of a invisible layer, we need to explicitly hide it in alive mode
1525             // 2003-06-03 - #110592# - fs@openoffice.org
1526             impl_adjustControlVisibilityToLayerVisibility_throw( false );
1527         }
1528         catch( const Exception& )
1529         {
1530             DBG_UNHANDLED_EXCEPTION();
1531         }
1532     }
1533 
1534     //--------------------------------------------------------------------
1535     void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementInserted( const ContainerEvent& /*_Event*/ ) throw (RuntimeException)
1536     {
1537         // not interested in
1538     }
1539 
1540     //--------------------------------------------------------------------
1541     void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementRemoved( const ContainerEvent& Event ) throw (RuntimeException)
1542     {
1543         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1544             // some code below - in particular our disposal - might trigger actions which require the
1545             // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
1546             // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
1547             // is the real bug. Toolkit really is infested with solar mutex usage ... :(
1548             // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
1549         VOCGuard aGuard( *this );
1550         DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementRemoved: where did this come from?" );
1551 
1552         if ( m_aControl == Event.Element )
1553             impl_dispose_nothrow( false );
1554     }
1555 
1556     //--------------------------------------------------------------------
1557     void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementReplaced( const ContainerEvent& Event ) throw (RuntimeException)
1558     {
1559         VOCGuard aGuard( *this );
1560         DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementReplaced: where did this come from?" );
1561 
1562         if ( ! ( m_aControl == Event.ReplacedElement ) )
1563             return;
1564 
1565         Reference< XControl > xNewControl( Event.Element, UNO_QUERY );
1566         DBG_ASSERT( xNewControl.is(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: invalid new control!" );
1567         if ( !xNewControl.is() )
1568             return;
1569 
1570         ENSURE_OR_THROW( m_pOutputDeviceForWindow, "calling this without /me having an output device should be impossible." );
1571 
1572         DBG_ASSERT( xNewControl->getModel() == m_aControl.getModel(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: another model at the new control?" );
1573         // another model should - in the drawing layer - also imply another SdrUnoObj, which
1574         // should also result in new ViewContact, and thus in new ViewObjectContacts
1575 
1576         impl_switchControlListening_nothrow( false );
1577 
1578         ControlHolder aNewControl( xNewControl );
1579         aNewControl.setZoom( m_aControl.getZoom() );
1580         aNewControl.setPosSize( m_aControl.getPosSize() );
1581         aNewControl.setDesignMode( impl_isControlDesignMode_nothrow() );
1582 
1583         m_aControl = xNewControl;
1584         m_bControlIsVisible = m_aControl.isVisible();
1585 
1586         impl_switchControlListening_nothrow( true );
1587 
1588         m_pAntiImpl->onControlChangedOrModified( ViewObjectContactOfUnoControl::ImplAccess() );
1589     }
1590 
1591     //--------------------------------------------------------------------
1592     void ViewObjectContactOfUnoControl_Impl::setControlDesignMode( bool _bDesignMode ) const
1593     {
1594         if ( ( m_eControlDesignMode != eUnknown ) && ( _bDesignMode == impl_isControlDesignMode_nothrow() ) )
1595             // nothing to do
1596             return;
1597         m_eControlDesignMode = _bDesignMode ? eDesign : eAlive;
1598 
1599         if ( !m_aControl.is() )
1600             // nothing to do, the setting will be respected as soon as the control
1601             // is created
1602             return;
1603 
1604         try
1605         {
1606             m_aControl.setDesignMode( _bDesignMode );
1607         }
1608         catch( const Exception& )
1609         {
1610             DBG_UNHANDLED_EXCEPTION();
1611         }
1612     }
1613 
1614     //====================================================================
1615     //= LazyControlCreationPrimitive2D
1616     //====================================================================
1617     //--------------------------------------------------------------------
1618     bool LazyControlCreationPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
1619     {
1620         if ( !BufferedDecompositionPrimitive2D::operator==( rPrimitive ) )
1621             return false;
1622 
1623         const LazyControlCreationPrimitive2D* pRHS = dynamic_cast< const LazyControlCreationPrimitive2D* >( &rPrimitive );
1624         if ( !pRHS )
1625             return false;
1626 
1627         if ( m_pVOCImpl != pRHS->m_pVOCImpl )
1628             return false;
1629 
1630         if ( m_aTransformation != pRHS->m_aTransformation )
1631             return false;
1632 
1633         return true;
1634     }
1635 
1636     //--------------------------------------------------------------------
1637     void LazyControlCreationPrimitive2D::getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation )
1638     {
1639         // Do use model data directly to create the correct geometry. Do NOT
1640         // use getBoundRect()/getSnapRect() here; tese will use the sequence of
1641         // primitives themselves in the long run.
1642         const Rectangle aSdrGeoData( _rVOC.GetSdrUnoObj().GetGeoRect() );
1643         const basegfx::B2DRange aRange(
1644             aSdrGeoData.Left(),
1645             aSdrGeoData.Top(),
1646             aSdrGeoData.Right(),
1647             aSdrGeoData.Bottom()
1648         );
1649 
1650         _out_Transformation.identity();
1651         _out_Transformation.set( 0, 0, aRange.getWidth() );
1652         _out_Transformation.set( 1, 1, aRange.getHeight() );
1653         _out_Transformation.set( 0, 2, aRange.getMinX() );
1654         _out_Transformation.set( 1, 2, aRange.getMinY() );
1655     }
1656 
1657     //--------------------------------------------------------------------
1658     ::basegfx::B2DRange LazyControlCreationPrimitive2D::getB2DRange( const ::drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/ ) const
1659     {
1660         ::basegfx::B2DRange aRange( 0.0, 0.0, 1.0, 1.0 );
1661         aRange.transform( m_aTransformation );
1662         return aRange;
1663     }
1664 
1665     //--------------------------------------------------------------------
1666 	::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::get2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
1667     {
1668     #if OSL_DEBUG_LEVEL > 1
1669         ::basegfx::B2DVector aScale, aTranslate;
1670         double fRotate, fShearX;
1671         _rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
1672     #endif
1673         if ( m_pVOCImpl->hasControl() )
1674             impl_positionAndZoomControl( _rViewInformation );
1675         return BufferedDecompositionPrimitive2D::get2DDecomposition( _rViewInformation );
1676     }
1677 
1678     //--------------------------------------------------------------------
1679     ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::create2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
1680     {
1681     #if OSL_DEBUG_LEVEL > 1
1682         ::basegfx::B2DVector aScale, aTranslate;
1683 	    double fRotate, fShearX;
1684 	    _rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
1685     #endif
1686         const bool bHadControl = m_pVOCImpl->getExistentControl().is();
1687 
1688         // force control here to make it a VCL ChildWindow. Will be fetched
1689         // and used below by getExistentControl()
1690         m_pVOCImpl->ensureControl( &_rViewInformation.getObjectToViewTransformation() );
1691         impl_positionAndZoomControl( _rViewInformation );
1692 
1693         // get needed data
1694         const ViewContactOfUnoControl& rViewContactOfUnoControl( m_pVOCImpl->getViewContact() );
1695         Reference< XControlModel > xControlModel( rViewContactOfUnoControl.GetSdrUnoObj().GetUnoControlModel() );
1696         const ControlHolder& rControl( m_pVOCImpl->getExistentControl() );
1697 
1698         if ( !bHadControl && rControl.is() && rControl.isVisible() )
1699             rControl.invalidate();
1700 
1701         if ( !bHadControl && rControl.is() && rControl.isVisible() )
1702             rControl.invalidate();
1703 
1704         // check if we already have an XControl.
1705         if ( !xControlModel.is() || !rControl.is() )
1706             // use the default mechanism. This will create a ControlPrimitive2D without
1707             // handing over a XControl. If not even a XControlModel exists, it will
1708             // create the SdrObject fallback visualisation
1709             return rViewContactOfUnoControl.getViewIndependentPrimitive2DSequence();
1710 
1711         // create a primitive and hand over the existing xControl. This will
1712         // allow the primitive to not need to create another one on demand.
1713         const drawinglayer::primitive2d::Primitive2DReference xRetval( new ::drawinglayer::primitive2d::ControlPrimitive2D(
1714             m_aTransformation, xControlModel, rControl.getControl() ) );
1715 
1716         return drawinglayer::primitive2d::Primitive2DSequence(&xRetval, 1);
1717     }
1718 
1719     //--------------------------------------------------------------------
1720     ImplPrimitrive2DIDBlock( LazyControlCreationPrimitive2D, PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D )
1721 
1722     //====================================================================
1723     //= ViewObjectContactOfUnoControl
1724     //====================================================================
1725     DBG_NAME( ViewObjectContactOfUnoControl )
1726     //--------------------------------------------------------------------
1727     ViewObjectContactOfUnoControl::ViewObjectContactOfUnoControl( ObjectContact& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1728         :ViewObjectContactOfSdrObj( _rObjectContact, _rViewContact )
1729         ,m_pImpl( new ViewObjectContactOfUnoControl_Impl( this ) )
1730     {
1731         DBG_CTOR( ViewObjectContactOfUnoControl, NULL );
1732     }
1733 
1734     //--------------------------------------------------------------------
1735     ViewObjectContactOfUnoControl::~ViewObjectContactOfUnoControl()
1736     {
1737         m_pImpl->dispose();
1738         m_pImpl = NULL;
1739 
1740         DBG_DTOR( ViewObjectContactOfUnoControl, NULL );
1741     }
1742 
1743     //--------------------------------------------------------------------
1744     bool ViewObjectContactOfUnoControl::isControlVisible() const
1745     {
1746         VOCGuard aGuard( *m_pImpl );
1747         const ControlHolder& rControl( m_pImpl->getExistentControl() );
1748         return rControl.is() && rControl.isVisible();
1749     }
1750 
1751     //--------------------------------------------------------------------
1752     Reference< XControl > ViewObjectContactOfUnoControl::getControl()
1753     {
1754         VOCGuard aGuard( *m_pImpl );
1755         m_pImpl->ensureControl( NULL );
1756         return m_pImpl->getExistentControl().getControl();
1757     }
1758 
1759     //--------------------------------------------------------------------
1760     Reference< XControl > ViewObjectContactOfUnoControl::getTemporaryControlForWindow(
1761         const Window& _rWindow, Reference< XControlContainer >& _inout_ControlContainer, const SdrUnoObj& _rUnoObject )
1762     {
1763         ControlHolder aControl;
1764 
1765         InvisibleControlViewAccess aSimulatePageView( _inout_ControlContainer );
1766         OSL_VERIFY( ViewObjectContactOfUnoControl_Impl::createControlForDevice( aSimulatePageView, _rWindow, _rUnoObject,
1767             _rWindow.GetViewTransformation(), _rWindow.GetInverseViewTransformation(), aControl ) );
1768         return aControl.getControl();
1769     }
1770 
1771     //--------------------------------------------------------------------
1772     void ViewObjectContactOfUnoControl::ensureControlVisibility( bool _bVisible ) const
1773     {
1774         VOCGuard aGuard( *m_pImpl );
1775 
1776         try
1777         {
1778             const ControlHolder& rControl( m_pImpl->getExistentControl() );
1779             if ( !rControl.is() )
1780                 return;
1781 
1782             // only need to care for alive mode
1783             if ( rControl.isDesignMode() )
1784                 return;
1785 
1786             // is the visibility correct?
1787             if ( m_pImpl->isControlVisible() == _bVisible )
1788                 return;
1789 
1790             // no -> adjust it
1791             rControl.setVisible( _bVisible );
1792             DBG_ASSERT( m_pImpl->isControlVisible() == _bVisible, "ViewObjectContactOfUnoControl::ensureControlVisibility: this didn't work!" );
1793                 // now this would mean that either isControlVisible is not reliable,
1794                 // or that showing/hiding the window did not work as intended.
1795         }
1796         catch( const Exception& )
1797         {
1798             DBG_UNHANDLED_EXCEPTION();
1799         }
1800     }
1801 
1802     //--------------------------------------------------------------------
1803     void ViewObjectContactOfUnoControl::setControlDesignMode( bool _bDesignMode ) const
1804     {
1805         VOCGuard aGuard( *m_pImpl );
1806         m_pImpl->setControlDesignMode( _bDesignMode );
1807 
1808         if(!_bDesignMode)
1809         {
1810             // when live mode is switched on, a refresh is needed. The edit mode visualisation
1811             // needs to be repainted and the now used VCL-Window needs to be positioned and
1812             // sized. Both is done from the repant refresh.
1813             const_cast< ViewObjectContactOfUnoControl* >(this)->ActionChanged();
1814         }
1815     }
1816 
1817     //--------------------------------------------------------------------
1818     drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfUnoControl::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/) const
1819     {
1820         if ( m_pImpl->isDisposed() )
1821             // our control already died.
1822             // TODO: Is it worth re-creating the control? Finally, this is a pathological situation, it means some instance
1823             // disposed the control though it doesn't own it. So, /me thinks we should not bother here.
1824             return drawinglayer::primitive2d::Primitive2DSequence();
1825 
1826         if ( GetObjectContact().getViewInformation2D().getViewTransformation().isIdentity() )
1827             // remove this when #i115754# is fixed
1828             return drawinglayer::primitive2d::Primitive2DSequence();
1829 
1830         // ignore existing controls which are in alive mode and manually switched to "invisible"
1831         // #102090# / 2009-06-05 / frank.schoenheit@sun.com
1832         const ControlHolder& rControl( m_pImpl->getExistentControl() );
1833         if ( rControl.is() && !rControl.isDesignMode() && !rControl.isVisible() )
1834             return drawinglayer::primitive2d::Primitive2DSequence();
1835 
1836         ::drawinglayer::primitive2d::Primitive2DReference xPrimitive( new LazyControlCreationPrimitive2D( m_pImpl ) );
1837         return ::drawinglayer::primitive2d::Primitive2DSequence( &xPrimitive, 1 );
1838     }
1839 
1840     //--------------------------------------------------------------------
1841 	bool ViewObjectContactOfUnoControl::isPrimitiveVisible( const DisplayInfo& _rDisplayInfo ) const
1842 	{
1843         VOCGuard aGuard( *m_pImpl );
1844 
1845         if ( m_pImpl->hasControl() )
1846         {
1847             const ::drawinglayer::geometry::ViewInformation2D& rViewInformation( GetObjectContact().getViewInformation2D() );
1848         #if OSL_DEBUG_LEVEL > 1
1849             ::basegfx::B2DVector aScale, aTranslate;
1850             double fRotate, fShearX;
1851             rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
1852         #endif
1853 
1854             if ( !rViewInformation.getViewport().isEmpty() )
1855                 m_pImpl->positionAndZoomControl( rViewInformation.getObjectToViewTransformation() );
1856         }
1857 
1858         return ViewObjectContactOfSdrObj::isPrimitiveVisible( _rDisplayInfo );
1859 	}
1860 
1861     //--------------------------------------------------------------------
1862     void ViewObjectContactOfUnoControl::propertyChange()
1863     {
1864         impl_onControlChangedOrModified();
1865     }
1866 
1867     //--------------------------------------------------------------------
1868     void ViewObjectContactOfUnoControl::ActionChanged()
1869     {
1870         // call parent
1871         ViewObjectContactOfSdrObj::ActionChanged();
1872         const ControlHolder& rControl(m_pImpl->getExistentControl());
1873 
1874         if(rControl.is() && !rControl.isDesignMode())
1875         {
1876             // #i93180# if layer visibility has changed and control is in live mode, it is necessary
1877             // to correct visibility to make those control vanish on SdrObject LayerID changes
1878             const SdrPageView* pSdrPageView = GetObjectContact().TryToGetSdrPageView();
1879 
1880             if(pSdrPageView)
1881             {
1882 				const SdrObject& rObject = getSdrObject();
1883                 const bool bIsLayerVisible( rObject.IsVisible() && pSdrPageView->GetVisibleLayers().IsSet(rObject.GetLayer()));
1884 
1885                 if(rControl.isVisible() != bIsLayerVisible)
1886                 {
1887                     rControl.setVisible(bIsLayerVisible);
1888                 }
1889             }
1890         }
1891     }
1892 
1893     //--------------------------------------------------------------------
1894     void ViewObjectContactOfUnoControl::impl_onControlChangedOrModified()
1895     {
1896         // graphical invalidate at all views
1897         ActionChanged();
1898 
1899         // #i93318# flush Primitive2DSequence to force recreation with updated XControlModel
1900         // since e.g. background color has changed and existing decompositions are possibly no
1901         // longer valid. Unfortunately this is not detected from ControlPrimitive2D::operator==
1902         // since it only has a uno reference to the XControlModel
1903         flushPrimitive2DSequence();
1904     }
1905 
1906     //====================================================================
1907     //= UnoControlPrintOrPreviewContact
1908     //====================================================================
1909     DBG_NAME( UnoControlPrintOrPreviewContact )
1910     //--------------------------------------------------------------------
1911     UnoControlPrintOrPreviewContact::UnoControlPrintOrPreviewContact( ObjectContactOfPageView& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1912         :ViewObjectContactOfUnoControl( _rObjectContact, _rViewContact )
1913     {
1914         DBG_CTOR( UnoControlPrintOrPreviewContact, NULL );
1915     }
1916 
1917     //--------------------------------------------------------------------
1918     UnoControlPrintOrPreviewContact::~UnoControlPrintOrPreviewContact()
1919     {
1920         DBG_DTOR( UnoControlPrintOrPreviewContact, NULL );
1921     }
1922 
1923     //--------------------------------------------------------------------
1924     drawinglayer::primitive2d::Primitive2DSequence UnoControlPrintOrPreviewContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo ) const
1925     {
1926         if ( !m_pImpl->isPrintableControl() )
1927             return drawinglayer::primitive2d::Primitive2DSequence();
1928         return ViewObjectContactOfUnoControl::createPrimitive2DSequence( rDisplayInfo );
1929     }
1930 
1931 //........................................................................
1932 } } // namespace sdr::contact
1933 //........................................................................
1934 
1935