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