LCOV - code coverage report
Current view: top level - svx/source/sdr/contact - viewobjectcontactofunocontrol.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 416 523 79.5 %
Date: 2015-06-13 12:38:46 Functions: 94 113 83.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11