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