LCOV - code coverage report
Current view: top level - svx/source/sdr/contact - viewobjectcontactofunocontrol.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 416 524 79.4 %
Date: 2014-11-03 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        1562 :     class ControlHolder
     146             :     {
     147             :     private:
     148             :         Reference< XControl >   m_xControl;
     149             :         Reference< XWindow2 >   m_xControlWindow;
     150             :         Reference< XView    >   m_xControlView;
     151             : 
     152             :     public:
     153        1151 :         ControlHolder()
     154             :             :m_xControl()
     155             :             ,m_xControlWindow()
     156        1151 :             ,m_xControlView()
     157             :         {
     158        1151 :         }
     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         411 :         ControlHolder& operator=( const Reference< XControl >& _rxControl )
     169             :         {
     170         411 :             clear();
     171             : 
     172         411 :             m_xControl = _rxControl;
     173         411 :             if ( m_xControl.is() )
     174             :             {
     175         411 :                 m_xControlWindow.set( m_xControl, UNO_QUERY );
     176         411 :                 m_xControlView.set( m_xControl, UNO_QUERY );
     177         411 :                 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         411 :             return *this;
     185             :         }
     186             : 
     187             :     public:
     188       99797 :         inline  bool    is() const { return m_xControl.is() && m_xControlWindow.is() && m_xControlView.is(); }
     189        2248 :         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       21236 :         inline bool     isDesignMode() const                        { return m_xControl->isDesignMode();         }
     194         417 :         inline void     setDesignMode( const bool _bDesign ) const  { m_xControl->setDesignMode( _bDesign );     }
     195        2266 :         inline bool     isVisible() const                           { return m_xControlWindow->isVisible();      }
     196          88 :         inline void     setVisible( const bool _bVisible ) const    { m_xControlWindow->setVisible( _bVisible ); }
     197             :         inline Reference< XControlModel >
     198         788 :                         getModel() const { return m_xControl->getModel(); }
     199         411 :         inline void     setModel( const Reference< XControlModel >& _m ) const { m_xControl->setModel( _m ); }
     200             : 
     201         411 :         inline void     addWindowListener( const Reference< XWindowListener >& _l ) const    { m_xControlWindow->addWindowListener( _l );    }
     202         411 :         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        4442 :         inline  const Reference< XControl >&    getControl() const  { return m_xControl; }
     214             :     };
     215             : 
     216             : 
     217         192 :     bool operator==( const ControlHolder& _rControl, const Reference< XInterface >& _rxCompare )
     218             :     {
     219         192 :         return _rControl.getControl() == _rxCompare;
     220             :     }
     221             : 
     222         164 :     bool operator==( const ControlHolder& _rControl, const Any& _rxCompare )
     223             :     {
     224         164 :         return _rControl == Reference< XInterface >( _rxCompare, UNO_QUERY );
     225             :     }
     226             : 
     227       15367 :     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       15367 :         ::Rectangle aCurrentRect( getPosSize() );
     234       15367 :         if ( aCurrentRect != _rPosSize )
     235             :         {
     236         572 :             m_xControlWindow->setPosSize(
     237        2288 :                 _rPosSize.Left(), _rPosSize.Top(), _rPosSize.GetWidth(), _rPosSize.GetHeight(),
     238             :                 POSSIZE
     239        2860 :             );
     240             :         }
     241       15367 :     }
     242             : 
     243             : 
     244       15367 :     ::Rectangle ControlHolder::getPosSize() const
     245             :     {
     246             :         // no check whether we're valid, this is the responsibility of the caller
     247       15367 :         return VCLUnoHelper::ConvertToVCLRect( m_xControlWindow->getPosSize() );
     248             :     }
     249             : 
     250             : 
     251       15367 :     void ControlHolder::setZoom( const ::basegfx::B2DVector& _rScale ) const
     252             :     {
     253             :         // no check whether we're valid, this is the responsibility of the caller
     254       15367 :         m_xControlView->setZoom( (float)_rScale.getX(), (float)_rScale.getY() );
     255       15367 :     }
     256             : 
     257             : 
     258         234 :     void ControlHolder::invalidate() const
     259             :     {
     260         234 :         Reference< XWindowPeer > xPeer( m_xControl->getPeer() );
     261         234 :         if ( xPeer.is() )
     262             :         {
     263         216 :             vcl::Window* pWindow = VCLUnoHelper::GetWindow( xPeer );
     264             :             OSL_ENSURE( pWindow, "ControlHolder::invalidate: no implementation access!" );
     265         216 :             if ( pWindow )
     266         216 :                 pWindow->Invalidate();
     267         234 :         }
     268         234 :     }
     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       15367 :     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       15367 :         if ( !_rControl.is() )
     298       15367 :             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       15367 :         ::basegfx::B2DPoint aTopLeft( _rLogicBoundingRect.Left(), _rLogicBoundingRect.Top() );
     312       15367 :         aTopLeft *= _rViewTransformation;
     313       30734 :         ::basegfx::B2DPoint aBottomRight( _rLogicBoundingRect.Right(), _rLogicBoundingRect.Bottom() );
     314       15367 :         aBottomRight *= _rViewTransformation;
     315             : 
     316       15367 :         const Rectangle aPaintRectPixel( (long)aTopLeft.getX(), (long)aTopLeft.getY(), (long)aBottomRight.getX(), (long)aBottomRight.getY() );
     317       15367 :         _rControl.setPosSize( aPaintRectPixel );
     318             : 
     319             :         // determine the scale from the current view transformation, and the normalization matrix
     320       30734 :         ::basegfx::B2DHomMatrix aObtainResolutionDependentScale( _rViewTransformation * _rZoomLevelNormalization );
     321       30734 :         ::basegfx::B2DVector aScale, aTranslate;
     322             :         double fRotate, fShearX;
     323       15367 :         aObtainResolutionDependentScale.decompose( aScale, aTranslate, fRotate, fShearX );
     324       30734 :         _rControl.setZoom( aScale );
     325             :     }
     326             : 
     327             :     /** disposes the given control
     328             :      */
     329         686 :     void disposeAndClearControl_nothrow( ControlHolder& _rControl )
     330             :     {
     331             :         try
     332             :         {
     333         686 :             Reference< XComponent > xControlComp( _rControl.getControl(), UNO_QUERY );
     334         686 :             if ( xControlComp.is() )
     335         357 :                 xControlComp->dispose();
     336             :         }
     337           0 :         catch( const Exception& )
     338             :         {
     339             :             DBG_UNHANDLED_EXCEPTION();
     340             :         }
     341         686 :         _rControl.clear();
     342         686 :     }
     343             : 
     344             :     }
     345             : 
     346             :     /** interface encapsulating access to an SdrPageView, stripped down to the methods we really need
     347             :      */
     348        2604 :     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        2604 :         ~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        2602 :         explicit SdrPageViewAccess( const SdrPageView& _rPageView ) : m_rPageView( _rPageView ) { }
     375             : 
     376        2602 :         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         409 :     bool SdrPageViewAccess::isDesignMode() const
     386             :     {
     387         409 :         return m_rPageView.GetView().IsDesignMode();
     388             :     }
     389             : 
     390             : 
     391         818 :     Reference< XControlContainer > SdrPageViewAccess::getControlContainer( const OutputDevice& _rDevice ) const
     392             :     {
     393         818 :         Reference< XControlContainer > xControlContainer = m_rPageView.GetControlContainer( _rDevice );
     394             :         DBG_ASSERT( xControlContainer.is() || NULL == m_rPageView.FindPageWindow( ( const_cast< OutputDevice& >( _rDevice ) ) ),
     395             :             "SdrPageViewAccess::getControlContainer: the output device is known, but there is no control container for it?" );
     396         818 :         return xControlContainer;
     397             :     }
     398             : 
     399             : 
     400         152 :     bool SdrPageViewAccess::isLayerVisible( SdrLayerID _nLayerID ) const
     401             :     {
     402         152 :         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           2 :         DummyPageViewAccess()
     465           2 :         {
     466           2 :         }
     467             : 
     468           2 :         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           2 :     bool DummyPageViewAccess::isDesignMode() const
     478             :     {
     479           2 :         return true;
     480             :     }
     481             : 
     482             : 
     483           4 :     Reference< XControlContainer > DummyPageViewAccess::getControlContainer( const OutputDevice& /*_rDevice*/ ) const
     484             :     {
     485           4 :         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             :         const 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       11942 :         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       30395 :                 getExistentControl() const { return m_aControl; }
     579             : 
     580             :         inline bool
     581       21559 :                 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       14177 :                 getViewContact() const
     621             :         {
     622       14177 :             ENSURE_OR_THROW( !impl_isDisposed_nofail(), "already disposed" );
     623       14177 :             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       56407 :         bool    impl_isDisposed_nofail() const { return m_pAntiImpl == NULL; }
     761             : 
     762             :         /** determines whether our control is currently visible
     763             :             @nofail
     764             :         */
     765         122 :         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         944 :         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       11759 :         inline bool impl_isControlDesignMode_nothrow() const
     780             :         {
     781             :             DBG_ASSERT( m_eControlDesignMode != eUnknown, "ViewObjectContactOfUnoControl_Impl::impl_isControlDesignMode_nothrow: mode is still unknown!" );
     782       11759 :             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       23774 :     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       11887 :         explicit LazyControlCreationPrimitive2D( const ::rtl::Reference< ViewObjectContactOfUnoControl_Impl >& _pVOCImpl )
     819       11887 :             :m_pVOCImpl( _pVOCImpl )
     820             :         {
     821       11887 :             ENSURE_OR_THROW( m_pVOCImpl.is(), "Illegal argument." );
     822       11887 :             getTransformation( m_pVOCImpl->getViewContact(), m_aTransformation );
     823       11887 :         }
     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        4838 :         void impl_positionAndZoomControl( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
     834             :         {
     835        4838 :             if ( !_rViewInformation.getViewport().isEmpty() )
     836        4836 :                 m_pVOCImpl->positionAndZoomControl( _rViewInformation.getObjectToViewTransformation() );
     837        4838 :         }
     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         592 :     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         592 :         ,m_aZoomLevelNormalization()
     856             :     {
     857             :         DBG_ASSERT( m_pAntiImpl, "ViewObjectContactOfUnoControl_Impl::ViewObjectContactOfUnoControl_Impl: invalid AntiImpl!" );
     858             : 
     859         592 :         const OutputDevice& rPageViewDevice( impl_getOutputDevice_throw() );
     860         592 :         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         592 :         ::basegfx::B2DHomMatrix aScaleNormalization;
     869        1184 :         MapMode aCurrentDeviceMapMode( rPageViewDevice.GetMapMode() );
     870         592 :         aScaleNormalization.set( 0, 0, (double)aCurrentDeviceMapMode.GetScaleX() );
     871         592 :         aScaleNormalization.set( 1, 1, (double)aCurrentDeviceMapMode.GetScaleY() );
     872        1184 :         m_aZoomLevelNormalization *= aScaleNormalization;
     873             : 
     874             :     #if OSL_DEBUG_LEVEL > 1
     875             :         m_aZoomLevelNormalization.decompose( aScale, aTranslate, fRotate, fShearX );
     876             :     #endif
     877         592 :    }
     878             : 
     879             : 
     880        1776 :     ViewObjectContactOfUnoControl_Impl::~ViewObjectContactOfUnoControl_Impl()
     881             :     {
     882         592 :         if ( !impl_isDisposed_nofail() )
     883             :         {
     884           0 :             acquire();
     885           0 :             dispose();
     886             :         }
     887             : 
     888        1184 :     }
     889             : 
     890             : 
     891         646 :     void ViewObjectContactOfUnoControl_Impl::impl_dispose_nothrow( bool _bAlsoDisposeControl )
     892             :     {
     893         646 :         if ( impl_isDisposed_nofail() )
     894         700 :             return;
     895             : 
     896         592 :         if ( m_aControl.is() )
     897         411 :             impl_switchControlListening_nothrow( false );
     898             : 
     899         592 :         if ( m_xContainer.is() )
     900         409 :             impl_switchContainerListening_nothrow( false );
     901             : 
     902             :         // dispose the control
     903         592 :         if ( _bAlsoDisposeControl )
     904         538 :             UnoControlContactHelper::disposeAndClearControl_nothrow( m_aControl );
     905             : 
     906         592 :         m_aControl.clear();
     907         592 :         m_xContainer.clear();
     908         592 :         m_pOutputDeviceForWindow = NULL;
     909         592 :         m_bControlIsVisible = false;
     910             : 
     911         592 :         m_pAntiImpl = NULL;
     912             :     }
     913             : 
     914             : 
     915         592 :     void ViewObjectContactOfUnoControl_Impl::dispose()
     916             :     {
     917         592 :         SolarMutexGuard aSolarGuard;
     918         592 :         impl_dispose_nothrow( true );
     919         592 :     }
     920             : 
     921             : 
     922       15637 :     bool ViewObjectContactOfUnoControl_Impl::getUnoObject( SdrUnoObj*& _out_rpObject ) const
     923             :     {
     924             :         OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::getUnoObject: already disposed()" );
     925       15637 :         if ( impl_isDisposed_nofail() )
     926           0 :             _out_rpObject = NULL;
     927             :         else
     928             :         {
     929       15637 :             _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       15637 :         return ( _out_rpObject != NULL );
     934             :     }
     935             : 
     936             : 
     937       15104 :     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       15104 :         if ( !m_aControl.is() )
     941       15252 :             return;
     942             : 
     943             :         try
     944             :         {
     945       14956 :             SdrUnoObj* pUnoObject( NULL );
     946       14956 :             if ( getUnoObject( pUnoObject ) )
     947             :             {
     948       14956 :                 Point aGridOffset = pUnoObject->GetGridOffset();
     949       14956 :                 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       14956 :                 aRect += aGridOffset;
     954       14956 :                 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        2482 :     bool ViewObjectContactOfUnoControl_Impl::ensureControl( const basegfx::B2DHomMatrix* _pInitialViewTransformationOrNULL )
     967             :     {
     968             :         OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::ensureControl: already disposed()" );
     969        2482 :         if ( impl_isDisposed_nofail() )
     970           0 :             return false;
     971             : 
     972        2482 :         ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
     973        2482 :         if ( pPageViewContact )
     974             :         {
     975        2480 :             SdrPageViewAccess aPVAccess( pPageViewContact->GetPageWindow().GetPageView() );
     976        2480 :             const OutputDevice& rDevice( m_pAntiImpl->getPageViewOutputDevice().get() );
     977             :             return impl_ensureControl_nothrow(
     978             :                 aPVAccess,
     979             :                 rDevice,
     980             :                 _pInitialViewTransformationOrNULL ? *_pInitialViewTransformationOrNULL : rDevice.GetViewTransformation()
     981        2480 :             );
     982             :         }
     983             : 
     984           2 :         DummyPageViewAccess aNoPageView;
     985           2 :         const OutputDevice& rDevice( impl_getOutputDevice_throw() );
     986             :         return impl_ensureControl_nothrow(
     987             :             aNoPageView,
     988             :             rDevice,
     989             :             _pInitialViewTransformationOrNULL ? *_pInitialViewTransformationOrNULL : rDevice.GetViewTransformation()
     990           2 :         );
     991             :     }
     992             : 
     993             : 
     994         594 :     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         594 :         boost::optional<const OutputDevice&> oPageOutputDev = m_pAntiImpl->getPageViewOutputDevice();
     999         594 :         if( oPageOutputDev )
    1000         590 :             return oPageOutputDev.get();
    1001             : 
    1002           4 :         const OutputDevice* pDevice = m_pAntiImpl->GetObjectContact().TryToGetOutputDevice();
    1003           4 :         ENSURE_OR_THROW( pDevice, "no output device -> no control" );
    1004           4 :         return *pDevice;
    1005             :     }
    1006             : 
    1007             : 
    1008             :     namespace
    1009             :     {
    1010        2482 :         static void lcl_resetFlag( bool& rbFlag )
    1011             :         {
    1012        2482 :             rbFlag = false;
    1013        2482 :         }
    1014             :     }
    1015             : 
    1016             : 
    1017        2482 :     bool ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow( IPageViewAccess& _rPageView, const OutputDevice& _rDevice,
    1018             :         const basegfx::B2DHomMatrix& _rInitialViewTransformation )
    1019             :     {
    1020        2482 :         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        2482 :         m_bCreatingControl = true;
    1037        2482 :         ::comphelper::ScopeGuard aGuard( ::boost::bind( lcl_resetFlag, ::boost::ref( m_bCreatingControl ) ) );
    1038             : 
    1039        2482 :         if ( m_aControl.is() )
    1040             :         {
    1041        1923 :             if ( m_pOutputDeviceForWindow == &_rDevice )
    1042        1923 :                 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 (doens'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         559 :         SdrUnoObj* pUnoObject( NULL );
    1058         559 :         if ( !getUnoObject( pUnoObject ) )
    1059           0 :             return false;
    1060             : 
    1061        1118 :         ControlHolder aControl;
    1062         559 :         if ( !createControlForDevice( _rPageView, _rDevice, *pUnoObject, _rInitialViewTransformation, m_aZoomLevelNormalization, aControl ) )
    1063         148 :             return false;
    1064             : 
    1065         411 :         m_pOutputDeviceForWindow = &_rDevice;
    1066         411 :         m_aControl = aControl;
    1067         411 :         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         411 :             m_eControlDesignMode = m_aControl.isDesignMode() ? eDesign : eAlive;
    1078         411 :             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         411 :         impl_switchControlListening_nothrow( true );
    1087             : 
    1088             :         // start listening at the control container, in case somebody tampers with our control
    1089         411 :         if ( m_xContainer.is() )
    1090         409 :             impl_switchContainerListening_nothrow( true );
    1091             : 
    1092        2893 :         return m_aControl.is();
    1093             :     }
    1094             : 
    1095             : 
    1096         559 :     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         559 :         _out_rControl.clear();
    1101             : 
    1102         559 :         Reference< XControlModel > xControlModel( _rUnoObject.GetUnoControlModel() );
    1103             :         DBG_ASSERT( xControlModel.is(), "ViewObjectContactOfUnoControl_Impl::createControlForDevice: no control model at the SdrUnoObject!?" );
    1104         559 :         if ( !xControlModel.is() )
    1105           0 :             return false;
    1106             : 
    1107         559 :         bool bSuccess = false;
    1108             :         try
    1109             :         {
    1110         559 :             const OUString sControlServiceName( _rUnoObject.GetUnoControlTypeName() );
    1111             : 
    1112        1118 :             Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
    1113         559 :             _out_rControl = Reference<XControl>( xContext->getServiceManager()->createInstanceWithContext(sControlServiceName, xContext), UNO_QUERY_THROW );
    1114             : 
    1115             :             // knit the model and the control
    1116         411 :             _out_rControl.setModel( xControlModel );
    1117         411 :             Point aGridOffset =  _rUnoObject.GetGridOffset();
    1118         411 :             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         411 :             aRect += aGridOffset;
    1123             : 
    1124             :             // proper geometry
    1125             :             UnoControlContactHelper::adjustControlGeometry_throw(
    1126             :                 _out_rControl,
    1127             :                 aRect,
    1128             :                 _rInitialViewTransformation,
    1129             :                 _rInitialZoomNormalization
    1130         411 :             );
    1131             : 
    1132             :             // set design mode before peer is created,
    1133             :             // this is also needed for accessibility
    1134         411 :             _out_rControl.setDesignMode( _rPageView.isDesignMode() );
    1135             : 
    1136             :             // adjust the initial visibility according to the visibility of the layer
    1137         411 :             impl_adjustControlVisibilityToLayerVisibility_throw( _out_rControl, _rUnoObject, _rPageView, false, true );
    1138             : 
    1139             :             // add the control to the respective control container
    1140             :             // do this last
    1141         822 :             Reference< XControlContainer > xControlContainer( _rPageView.getControlContainer( _rDevice ) );
    1142         411 :             if ( xControlContainer.is() )
    1143         409 :                 xControlContainer->addControl( sControlServiceName, _out_rControl.getControl() );
    1144             : 
    1145         970 :             bSuccess = true;
    1146             :         }
    1147         148 :         catch( const Exception& )
    1148             :         {
    1149             :             DBG_UNHANDLED_EXCEPTION();
    1150             :         }
    1151             : 
    1152         559 :         if ( !bSuccess )
    1153             :         {
    1154             :             // delete the control which might have been created already
    1155         148 :             UnoControlContactHelper::disposeAndClearControl_nothrow( _out_rControl );
    1156             :         }
    1157             : 
    1158         559 :         return _out_rControl.is();
    1159             :     }
    1160             : 
    1161             : 
    1162         122 :     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         122 :         _out_rpPageView = NULL;
    1167         122 :         if ( impl_isDisposed_nofail() )
    1168           0 :             return false;
    1169             : 
    1170         122 :         ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
    1171         122 :         if ( pPageViewContact )
    1172         122 :             _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         122 :         return ( _out_rpPageView != NULL );
    1176             :     }
    1177             : 
    1178             : 
    1179         122 :     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         122 :         SdrPageView* pPageView( NULL );
    1185         122 :         if ( !impl_getPageView_nothrow( pPageView ) )
    1186           0 :             return;
    1187             : 
    1188         122 :         SdrUnoObj* pUnoObject( NULL );
    1189         122 :         if ( !getUnoObject( pUnoObject ) )
    1190           0 :             return;
    1191             : 
    1192         122 :         SdrPageViewAccess aPVAccess( *pPageView );
    1193         122 :         impl_adjustControlVisibilityToLayerVisibility_throw( m_aControl, *pUnoObject, aPVAccess, impl_isControlVisible_nofail(), _bForce );
    1194             :     }
    1195             : 
    1196             : 
    1197         533 :     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         533 :         if ( !_rControl.isDesignMode() )
    1204             :         {
    1205             :             // the layer of our object
    1206         152 :             SdrLayerID nObjectLayer = _rUnoObject.GetLayer();
    1207             :             // is the object we're residing in visible in this view?
    1208         152 :             bool bIsObjectVisible = _rUnoObject.IsVisible() && _rPageView.isLayerVisible( nObjectLayer );
    1209             : 
    1210         152 :             if ( _bForce || ( bIsObjectVisible != _bIsCurrentlyVisible ) )
    1211             :             {
    1212          88 :                 _rControl.setVisible( bIsObjectVisible );
    1213             :             }
    1214             :         }
    1215         533 :     }
    1216             : 
    1217             : 
    1218         818 :     void ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow( bool _bStart )
    1219             :     {
    1220             :         OSL_PRECOND( m_xContainer.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow: no control container!" );
    1221         818 :         if ( !m_xContainer.is() )
    1222         818 :             return;
    1223             : 
    1224             :         try
    1225             :         {
    1226         818 :             if ( _bStart )
    1227         409 :                 m_xContainer->addContainerListener( this );
    1228             :             else
    1229         409 :                 m_xContainer->removeContainerListener( this );
    1230             :         }
    1231           0 :         catch( const Exception& )
    1232             :         {
    1233             :             DBG_UNHANDLED_EXCEPTION();
    1234             :         }
    1235             :     }
    1236             : 
    1237             : 
    1238         822 :     void ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow( bool _bStart )
    1239             :     {
    1240             :         OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow: invalid control!" );
    1241         822 :         if ( !m_aControl.is() )
    1242         822 :             return;
    1243             : 
    1244             :         try
    1245             :         {
    1246             :             // listen for visibility changes
    1247         822 :             if ( _bStart )
    1248         411 :                 m_aControl.addWindowListener( this );
    1249             :             else
    1250         411 :                 m_aControl.removeWindowListener( this );
    1251             : 
    1252             :             // in design mode, listen for some more aspects
    1253         822 :             impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() && _bStart );
    1254             : 
    1255             :             // listen for design mode changes
    1256         822 :             Reference< XModeChangeBroadcaster > xDesignModeChanges( m_aControl.getControl(), UNO_QUERY_THROW );
    1257         822 :             if ( _bStart )
    1258         411 :                 xDesignModeChanges->addModeChangeListener( this );
    1259             :             else
    1260         411 :                 xDesignModeChanges->removeModeChangeListener( this );
    1261             :         }
    1262           0 :         catch( const Exception& )
    1263             :         {
    1264             :             DBG_UNHANDLED_EXCEPTION();
    1265             :         }
    1266             :     }
    1267             : 
    1268             : 
    1269         944 :     void ViewObjectContactOfUnoControl_Impl::impl_switchDesignModeListening_nothrow( bool _bStart )
    1270             :     {
    1271         944 :         if ( impl_isDesignModeListening_nofail() != _bStart )
    1272             :         {
    1273         762 :             m_bIsDesignModeListening = _bStart;
    1274         762 :             impl_switchPropertyListening_nothrow( _bStart );
    1275             :         }
    1276         944 :     }
    1277             : 
    1278             : 
    1279         762 :     void ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow( bool _bStart )
    1280             :     {
    1281             :         OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow: no control!" );
    1282         762 :         if ( !m_aControl.is() )
    1283         762 :             return;
    1284             : 
    1285             :         try
    1286             :         {
    1287         762 :             Reference< XPropertySet > xModelProperties( m_aControl.getModel(), UNO_QUERY_THROW );
    1288         762 :             if ( _bStart )
    1289         381 :                 xModelProperties->addPropertyChangeListener( OUString(), this );
    1290             :             else
    1291         381 :                 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 :             static const OUString s_sPrintablePropertyName( "Printable" );
    1311           0 :             OSL_VERIFY( xModelProperties->getPropertyValue( s_sPrintablePropertyName ) >>= bIsPrintable );
    1312             :         }
    1313           0 :         catch( const Exception& )
    1314             :         {
    1315             :             DBG_UNHANDLED_EXCEPTION();
    1316             :         }
    1317           0 :         return bIsPrintable;
    1318             :     }
    1319             : 
    1320             : 
    1321          28 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::disposing( const EventObject& Source ) throw(RuntimeException, std::exception)
    1322             :     {
    1323          28 :         SolarMutexGuard aSolarGuard;
    1324             :             // some code below - in particular our disposal - might trigger actions which require the
    1325             :             // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
    1326             :             // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
    1327             :             // is the real bug. Toolkit really is infested with solar mutex usage ... :(
    1328             :             // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
    1329             : 
    1330          28 :         if ( !m_aControl.is() )
    1331           0 :             return;
    1332             : 
    1333          86 :         if  (   ( m_aControl            == Source.Source )
    1334         110 :             ||  ( m_aControl.getModel() == Source.Source )
    1335             :             )
    1336             :         {
    1337             :             // the model or the control is dying ... hmm, not much sense in that we ourself continue
    1338             :             // living
    1339          28 :             impl_dispose_nothrow( false );
    1340          28 :             return;
    1341             :         }
    1342             : 
    1343           0 :         DBG_ASSERT( Source.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::disposing: Who's this?" );
    1344             :     }
    1345             : 
    1346             : 
    1347         594 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowResized( const WindowEvent& /*e*/ ) throw(RuntimeException, std::exception)
    1348             :     {
    1349             :         // not interested in
    1350         594 :     }
    1351             : 
    1352             : 
    1353        1120 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowMoved( const WindowEvent& /*e*/ ) throw(RuntimeException, std::exception)
    1354             :     {
    1355             :         // not interested in
    1356        1120 :     }
    1357             : 
    1358             : 
    1359        2608 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowShown( const EventObject& /*e*/ ) throw(RuntimeException, std::exception)
    1360             :     {
    1361        2608 :         SolarMutexGuard aSolarGuard;
    1362        2608 :         m_bControlIsVisible = true;
    1363        2608 :     }
    1364             : 
    1365             : 
    1366        2652 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowHidden( const EventObject& /*e*/ ) throw(RuntimeException, std::exception)
    1367             :     {
    1368        2652 :         SolarMutexGuard aSolarGuard;
    1369        2652 :         m_bControlIsVisible = false;
    1370        2652 :     }
    1371             : 
    1372             : 
    1373       10809 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::propertyChange( const PropertyChangeEvent& /*_rEvent*/ ) throw(RuntimeException, std::exception)
    1374             :     {
    1375       10809 :         SolarMutexGuard aSolarGuard;
    1376             :             // (re)painting might require VCL operations, which need the SolarMutex
    1377             : 
    1378             :         OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::propertyChange: already disposed()" );
    1379       10809 :         if ( impl_isDisposed_nofail() )
    1380           0 :             return;
    1381             : 
    1382             :         DBG_ASSERT( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::propertyChange: " );
    1383       10809 :         if ( !m_aControl.is() )
    1384           0 :             return;
    1385             : 
    1386             :         // a generic property changed. If we're in design mode, we need to repaint the control
    1387       10809 :         if ( impl_isControlDesignMode_nothrow() )
    1388             :         {
    1389       10809 :             m_pAntiImpl->propertyChange();
    1390       10809 :         }
    1391             :     }
    1392             : 
    1393             : 
    1394         122 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::modeChanged( const ModeChangeEvent& _rSource ) throw (RuntimeException, std::exception)
    1395             :     {
    1396         122 :         SolarMutexGuard aSolarGuard;
    1397             : 
    1398             :         DBG_ASSERT( _rSource.NewMode == "design" || _rSource.NewMode == "alive", "ViewObjectContactOfUnoControl_Impl::modeChanged: unexpected mode!" );
    1399             : 
    1400         122 :         m_eControlDesignMode = _rSource.NewMode == "design" ? eDesign : eAlive;
    1401             : 
    1402         122 :         impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() );
    1403             : 
    1404             :         try
    1405             :         {
    1406             :             // if the control is part of a invisible layer, we need to explicitly hide it in alive mode
    1407         122 :             impl_adjustControlVisibilityToLayerVisibility_throw( false );
    1408             :         }
    1409           0 :         catch( const Exception& )
    1410             :         {
    1411             :             DBG_UNHANDLED_EXCEPTION();
    1412         122 :         }
    1413         122 :     }
    1414             : 
    1415             : 
    1416         144 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementInserted( const ContainerEvent& /*_Event*/ ) throw (RuntimeException, std::exception)
    1417             :     {
    1418             :         // not interested in
    1419         144 :     }
    1420             : 
    1421             : 
    1422         164 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementRemoved( const ContainerEvent& Event ) throw (RuntimeException, std::exception)
    1423             :     {
    1424         164 :         SolarMutexGuard aSolarGuard;
    1425             :             // some code below - in particular our disposal - might trigger actions which require the
    1426             :             // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
    1427             :             // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
    1428             :             // is the real bug. Toolkit really is infested with solar mutex usage ... :(
    1429             :             // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
    1430             :         DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementRemoved: where did this come from?" );
    1431             : 
    1432         164 :         if ( m_aControl == Event.Element )
    1433          26 :             impl_dispose_nothrow( false );
    1434         164 :     }
    1435             : 
    1436             : 
    1437           0 :     void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementReplaced( const ContainerEvent& Event ) throw (RuntimeException, std::exception)
    1438             :     {
    1439           0 :         SolarMutexGuard aSolarGuard;
    1440             :         DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementReplaced: where did this come from?" );
    1441             : 
    1442           0 :         if ( ! ( m_aControl == Event.ReplacedElement ) )
    1443           0 :             return;
    1444             : 
    1445           0 :         Reference< XControl > xNewControl( Event.Element, UNO_QUERY );
    1446             :         DBG_ASSERT( xNewControl.is(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: invalid new control!" );
    1447           0 :         if ( !xNewControl.is() )
    1448           0 :             return;
    1449             : 
    1450           0 :         ENSURE_OR_THROW( m_pOutputDeviceForWindow, "calling this without /me having an output device should be impossible." );
    1451             : 
    1452             :         DBG_ASSERT( xNewControl->getModel() == m_aControl.getModel(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: another model at the new control?" );
    1453             :         // another model should - in the drawing layer - also imply another SdrUnoObj, which
    1454             :         // should also result in new ViewContact, and thus in new ViewObjectContacts
    1455             : 
    1456           0 :         impl_switchControlListening_nothrow( false );
    1457             : 
    1458           0 :         ControlHolder aNewControl( xNewControl );
    1459           0 :         aNewControl.setZoom( m_aControl.getZoom() );
    1460           0 :         aNewControl.setPosSize( m_aControl.getPosSize() );
    1461           0 :         aNewControl.setDesignMode( impl_isControlDesignMode_nothrow() );
    1462             : 
    1463           0 :         m_aControl = xNewControl;
    1464           0 :         m_bControlIsVisible = m_aControl.isVisible();
    1465             : 
    1466           0 :         impl_switchControlListening_nothrow( true );
    1467             : 
    1468           0 :         m_pAntiImpl->onControlChangedOrModified( ViewObjectContactOfUnoControl::ImplAccess() );
    1469             :     }
    1470             : 
    1471             : 
    1472           6 :     void ViewObjectContactOfUnoControl_Impl::setControlDesignMode( bool _bDesignMode ) const
    1473             :     {
    1474           6 :         if ( ( m_eControlDesignMode != eUnknown ) && ( _bDesignMode == impl_isControlDesignMode_nothrow() ) )
    1475             :             // nothing to do
    1476           0 :             return;
    1477           6 :         m_eControlDesignMode = _bDesignMode ? eDesign : eAlive;
    1478             : 
    1479           6 :         if ( !m_aControl.is() )
    1480             :             // nothing to do, the setting will be respected as soon as the control
    1481             :             // is created
    1482           0 :             return;
    1483             : 
    1484             :         try
    1485             :         {
    1486           6 :             m_aControl.setDesignMode( _bDesignMode );
    1487             :         }
    1488           0 :         catch( const Exception& )
    1489             :         {
    1490             :             DBG_UNHANDLED_EXCEPTION();
    1491             :         }
    1492             :     }
    1493             : 
    1494             : 
    1495             :     //= LazyControlCreationPrimitive2D
    1496             : 
    1497             : 
    1498        5852 :     bool LazyControlCreationPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
    1499             :     {
    1500        5852 :         if ( !BufferedDecompositionPrimitive2D::operator==( rPrimitive ) )
    1501           0 :             return false;
    1502             : 
    1503        5852 :         const LazyControlCreationPrimitive2D* pRHS = dynamic_cast< const LazyControlCreationPrimitive2D* >( &rPrimitive );
    1504        5852 :         if ( !pRHS )
    1505           0 :             return false;
    1506             : 
    1507        5852 :         if ( m_pVOCImpl != pRHS->m_pVOCImpl )
    1508           0 :             return false;
    1509             : 
    1510        5852 :         if ( m_aTransformation != pRHS->m_aTransformation )
    1511         272 :             return false;
    1512             : 
    1513        5580 :         return true;
    1514             :     }
    1515             : 
    1516             : 
    1517       11887 :     void LazyControlCreationPrimitive2D::getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation )
    1518             :     {
    1519             :         // Do use model data directly to create the correct geometry. Do NOT
    1520             :         // use getBoundRect()/getSnapRect() here; tese will use the sequence of
    1521             :         // primitives themselves in the long run.
    1522       11887 :         Rectangle aSdrGeoData( _rVOC.GetSdrUnoObj().GetGeoRect() );
    1523       11887 :         Point aGridOffset = _rVOC.GetSdrUnoObj().GetGridOffset();
    1524             :         // Hack for calc, transform position of object according
    1525             :         // to current zoom so as objects relative position to grid
    1526             :         // appears stable
    1527       11887 :         aSdrGeoData += aGridOffset;
    1528             :         const basegfx::B2DRange aRange(
    1529       11887 :             aSdrGeoData.Left(),
    1530       11887 :             aSdrGeoData.Top(),
    1531       11887 :             aSdrGeoData.Right(),
    1532       11887 :             aSdrGeoData.Bottom()
    1533       47548 :         );
    1534             : 
    1535       11887 :         _out_Transformation.identity();
    1536       11887 :         _out_Transformation.set( 0, 0, aRange.getWidth() );
    1537       11887 :         _out_Transformation.set( 1, 1, aRange.getHeight() );
    1538       11887 :         _out_Transformation.set( 0, 2, aRange.getMinX() );
    1539       11887 :         _out_Transformation.set( 1, 2, aRange.getMinY() );
    1540       11887 :     }
    1541             : 
    1542             : 
    1543       27205 :     ::basegfx::B2DRange LazyControlCreationPrimitive2D::getB2DRange( const ::drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/ ) const
    1544             :     {
    1545       27205 :         ::basegfx::B2DRange aRange( 0.0, 0.0, 1.0, 1.0 );
    1546       27205 :         aRange.transform( m_aTransformation );
    1547       27205 :         return aRange;
    1548             :     }
    1549             : 
    1550             : 
    1551        4507 :     ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::get2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
    1552             :     {
    1553             :     #if OSL_DEBUG_LEVEL > 1
    1554             :         ::basegfx::B2DVector aScale, aTranslate;
    1555             :         double fRotate, fShearX;
    1556             :         _rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
    1557             :     #endif
    1558        4507 :         if ( m_pVOCImpl->hasControl() )
    1559        2548 :             impl_positionAndZoomControl( _rViewInformation );
    1560        4507 :         return BufferedDecompositionPrimitive2D::get2DDecomposition( _rViewInformation );
    1561             :     }
    1562             : 
    1563             : 
    1564        2290 :     ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::create2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
    1565             :     {
    1566             :     #if OSL_DEBUG_LEVEL > 1
    1567             :         ::basegfx::B2DVector aScale, aTranslate;
    1568             :         double fRotate, fShearX;
    1569             :         _rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
    1570             :     #endif
    1571        2290 :         const bool bHadControl = m_pVOCImpl->getExistentControl().is();
    1572             : 
    1573             :         // force control here to make it a VCL ChildWindow. Will be fetched
    1574             :         // and used below by getExistentControl()
    1575        2290 :         m_pVOCImpl->ensureControl( &_rViewInformation.getObjectToViewTransformation() );
    1576        2290 :         impl_positionAndZoomControl( _rViewInformation );
    1577             : 
    1578             :         // get needed data
    1579        2290 :         const ViewContactOfUnoControl& rViewContactOfUnoControl( m_pVOCImpl->getViewContact() );
    1580        2290 :         Reference< XControlModel > xControlModel( rViewContactOfUnoControl.GetSdrUnoObj().GetUnoControlModel() );
    1581        2290 :         const ControlHolder& rControl( m_pVOCImpl->getExistentControl() );
    1582             : 
    1583        2290 :         if ( !bHadControl && rControl.is() && rControl.isVisible() )
    1584         117 :             rControl.invalidate();
    1585             : 
    1586        2290 :         if ( !bHadControl && rControl.is() && rControl.isVisible() )
    1587         117 :             rControl.invalidate();
    1588             : 
    1589             :         // check if we already have an XControl.
    1590        2290 :         if ( !xControlModel.is() || !rControl.is() )
    1591             :             // use the default mechanism. This will create a ControlPrimitive2D without
    1592             :             // handing over a XControl. If not even a XControlModel exists, it will
    1593             :             // create the SdrObject fallback visualisation
    1594         149 :             return rViewContactOfUnoControl.getViewIndependentPrimitive2DSequence();
    1595             : 
    1596             :         // create a primitive and hand over the existing xControl. This will
    1597             :         // allow the primitive to not need to create another one on demand.
    1598             :         const drawinglayer::primitive2d::Primitive2DReference xRetval( new ::drawinglayer::primitive2d::ControlPrimitive2D(
    1599        4282 :             m_aTransformation, xControlModel, rControl.getControl() ) );
    1600             : 
    1601        4431 :         return drawinglayer::primitive2d::Primitive2DSequence(&xRetval, 1);
    1602             :     }
    1603             : 
    1604             : 
    1605       22518 :     ImplPrimitive2DIDBlock( LazyControlCreationPrimitive2D, PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D )
    1606             : 
    1607         592 :     ViewObjectContactOfUnoControl::ViewObjectContactOfUnoControl( ObjectContact& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
    1608             :         :ViewObjectContactOfSdrObj( _rObjectContact, _rViewContact )
    1609         592 :         ,m_pImpl( new ViewObjectContactOfUnoControl_Impl( this ) )
    1610             :     {
    1611         592 :     }
    1612             : 
    1613             : 
    1614        1776 :     ViewObjectContactOfUnoControl::~ViewObjectContactOfUnoControl()
    1615             :     {
    1616         592 :         m_pImpl->dispose();
    1617         592 :         m_pImpl = NULL;
    1618             : 
    1619        1184 :     }
    1620             : 
    1621             : 
    1622         192 :     Reference< XControl > ViewObjectContactOfUnoControl::getControl()
    1623             :     {
    1624         192 :         SolarMutexGuard aSolarGuard;
    1625         192 :         m_pImpl->ensureControl( NULL );
    1626         192 :         return m_pImpl->getExistentControl().getControl();
    1627             :     }
    1628             : 
    1629             : 
    1630           0 :     Reference< XControl > ViewObjectContactOfUnoControl::getTemporaryControlForWindow(
    1631             :         const vcl::Window& _rWindow, Reference< XControlContainer >& _inout_ControlContainer, const SdrUnoObj& _rUnoObject )
    1632             :     {
    1633           0 :         ControlHolder aControl;
    1634             : 
    1635           0 :         InvisibleControlViewAccess aSimulatePageView( _inout_ControlContainer );
    1636           0 :         OSL_VERIFY( ViewObjectContactOfUnoControl_Impl::createControlForDevice( aSimulatePageView, _rWindow, _rUnoObject,
    1637             :             _rWindow.GetViewTransformation(), _rWindow.GetInverseViewTransformation(), aControl ) );
    1638           0 :         return aControl.getControl();
    1639             :     }
    1640             : 
    1641             : 
    1642         484 :     void ViewObjectContactOfUnoControl::ensureControlVisibility( bool _bVisible ) const
    1643             :     {
    1644         484 :         SolarMutexGuard aSolarGuard;
    1645             : 
    1646             :         try
    1647             :         {
    1648         484 :             const ControlHolder& rControl( m_pImpl->getExistentControl() );
    1649         484 :             if ( !rControl.is() )
    1650         482 :                 return;
    1651             : 
    1652             :             // only need to care for alive mode
    1653           2 :             if ( rControl.isDesignMode() )
    1654           2 :                 return;
    1655             : 
    1656             :             // is the visibility correct?
    1657           0 :             if ( m_pImpl->isControlVisible() == _bVisible )
    1658           0 :                 return;
    1659             : 
    1660             :             // no -> adjust it
    1661           0 :             rControl.setVisible( _bVisible );
    1662             :             DBG_ASSERT( m_pImpl->isControlVisible() == _bVisible, "ViewObjectContactOfUnoControl::ensureControlVisibility: this didn't work!" );
    1663             :                 // now this would mean that either isControlVisible is not reliable,
    1664             :                 // or that showing/hiding the window did not work as intended.
    1665             :         }
    1666           0 :         catch( const Exception& )
    1667             :         {
    1668             :             DBG_UNHANDLED_EXCEPTION();
    1669           0 :         }
    1670             :     }
    1671             : 
    1672             : 
    1673           6 :     void ViewObjectContactOfUnoControl::setControlDesignMode( bool _bDesignMode ) const
    1674             :     {
    1675           6 :         SolarMutexGuard aSolarGuard;
    1676           6 :         m_pImpl->setControlDesignMode( _bDesignMode );
    1677             : 
    1678           6 :         if(!_bDesignMode)
    1679             :         {
    1680             :             // when live mode is switched on, a refresh is needed. The edit mode visualisation
    1681             :             // needs to be repainted and the now used VCL-Window needs to be positioned and
    1682             :             // sized. Both is done from the repant refresh.
    1683           6 :             const_cast< ViewObjectContactOfUnoControl* >(this)->ActionChanged();
    1684           6 :         }
    1685           6 :     }
    1686             : 
    1687             : 
    1688       11942 :     drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfUnoControl::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/) const
    1689             :     {
    1690       11942 :         if ( m_pImpl->isDisposed() )
    1691             :             // our control already died.
    1692             :             // TODO: Is it worth re-creating the control? Finally, this is a pathological situation, it means some instance
    1693             :             // disposed the control though it doesn't own it. So, /me thinks we should not bother here.
    1694          44 :             return drawinglayer::primitive2d::Primitive2DSequence();
    1695             : 
    1696       11898 :         if ( GetObjectContact().getViewInformation2D().getViewTransformation().isIdentity() )
    1697             :             // remove this when #i115754# is fixed
    1698          10 :             return drawinglayer::primitive2d::Primitive2DSequence();
    1699             : 
    1700             :         // ignore existing controls which are in alive mode and manually switched to "invisible"
    1701             :         // #102090# / 2009-06-05 / frank.schoenheit@sun.com
    1702       11888 :         const ControlHolder& rControl( m_pImpl->getExistentControl() );
    1703       11888 :         if ( rControl.is() && !rControl.isDesignMode() && !rControl.isVisible() )
    1704           1 :             return drawinglayer::primitive2d::Primitive2DSequence();
    1705             : 
    1706       11887 :         ::drawinglayer::primitive2d::Primitive2DReference xPrimitive( new LazyControlCreationPrimitive2D( m_pImpl ) );
    1707       11887 :         return ::drawinglayer::primitive2d::Primitive2DSequence( &xPrimitive, 1 );
    1708             :     }
    1709             : 
    1710             : 
    1711       17052 :     bool ViewObjectContactOfUnoControl::isPrimitiveVisible( const DisplayInfo& _rDisplayInfo ) const
    1712             :     {
    1713       17052 :         SolarMutexGuard aSolarGuard;
    1714             : 
    1715       17052 :         if ( m_pImpl->hasControl() )
    1716             :         {
    1717       10268 :             const ::drawinglayer::geometry::ViewInformation2D& rViewInformation( GetObjectContact().getViewInformation2D() );
    1718             :         #if OSL_DEBUG_LEVEL > 1
    1719             :             ::basegfx::B2DVector aScale, aTranslate;
    1720             :             double fRotate, fShearX;
    1721             :             rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
    1722             :         #endif
    1723             : 
    1724       10268 :             if ( !rViewInformation.getViewport().isEmpty() )
    1725       10268 :                 m_pImpl->positionAndZoomControl( rViewInformation.getObjectToViewTransformation() );
    1726             :         }
    1727             : 
    1728       17052 :         return ViewObjectContactOfSdrObj::isPrimitiveVisible( _rDisplayInfo );
    1729             :     }
    1730             : 
    1731             : 
    1732       10809 :     void ViewObjectContactOfUnoControl::propertyChange()
    1733             :     {
    1734       10809 :         impl_onControlChangedOrModified();
    1735       10809 :     }
    1736             : 
    1737             : 
    1738       13251 :     void ViewObjectContactOfUnoControl::ActionChanged()
    1739             :     {
    1740             :         // call parent
    1741       13251 :         ViewObjectContactOfSdrObj::ActionChanged();
    1742       13251 :         const ControlHolder& rControl(m_pImpl->getExistentControl());
    1743             : 
    1744       13251 :         if(rControl.is() && !rControl.isDesignMode())
    1745             :         {
    1746             :             // #i93180# if layer visibility has changed and control is in live mode, it is necessary
    1747             :             // to correct visibility to make those control vanish on SdrObject LayerID changes
    1748          28 :             const SdrPageView* pSdrPageView = GetObjectContact().TryToGetSdrPageView();
    1749             : 
    1750          28 :             if(pSdrPageView)
    1751             :             {
    1752          28 :                 const SdrObject& rObject = getSdrObject();
    1753          28 :                 const bool bIsLayerVisible( rObject.IsVisible() && pSdrPageView->GetVisibleLayers().IsSet(rObject.GetLayer()));
    1754             : 
    1755          28 :                 if(rControl.isVisible() != bIsLayerVisible)
    1756             :                 {
    1757           0 :                     rControl.setVisible(bIsLayerVisible);
    1758             :                 }
    1759             :             }
    1760             :         }
    1761       13251 :     }
    1762             : 
    1763             : 
    1764       10809 :     void ViewObjectContactOfUnoControl::impl_onControlChangedOrModified()
    1765             :     {
    1766             :         // graphical invalidate at all views
    1767       10809 :         ActionChanged();
    1768             : 
    1769             :         // #i93318# flush Primitive2DSequence to force recreation with updated XControlModel
    1770             :         // since e.g. background color has changed and existing decompositions are possibly no
    1771             :         // longer valid. Unfortunately this is not detected from ControlPrimitive2D::operator==
    1772             :         // since it only has a uno reference to the XControlModel
    1773       10809 :         flushPrimitive2DSequence();
    1774       10809 :     }
    1775             : 
    1776           0 :     UnoControlPrintOrPreviewContact::UnoControlPrintOrPreviewContact( ObjectContactOfPageView& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
    1777           0 :         :ViewObjectContactOfUnoControl( _rObjectContact, _rViewContact )
    1778             :     {
    1779           0 :     }
    1780             : 
    1781             : 
    1782           0 :     UnoControlPrintOrPreviewContact::~UnoControlPrintOrPreviewContact()
    1783             :     {
    1784           0 :     }
    1785             : 
    1786             : 
    1787           0 :     drawinglayer::primitive2d::Primitive2DSequence UnoControlPrintOrPreviewContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo ) const
    1788             :     {
    1789           0 :         if ( !m_pImpl->isPrintableControl() )
    1790           0 :             return drawinglayer::primitive2d::Primitive2DSequence();
    1791           0 :         return ViewObjectContactOfUnoControl::createPrimitive2DSequence( rDisplayInfo );
    1792             :     }
    1793             : 
    1794             : 
    1795         651 : } } // namespace sdr::contact
    1796             : 
    1797             : 
    1798             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10