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