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