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