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 803 : class ControlHolder
146 : {
147 : private:
148 : Reference< XControl > m_xControl;
149 : Reference< XWindow2 > m_xControlWindow;
150 : Reference< XView > m_xControlView;
151 :
152 : public:
153 586 : ControlHolder()
154 : :m_xControl()
155 : ,m_xControlWindow()
156 586 : ,m_xControlView()
157 : {
158 586 : }
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 217 : ControlHolder& operator=( const Reference< XControl >& _rxControl )
169 : {
170 217 : clear();
171 :
172 217 : m_xControl = _rxControl;
173 217 : if ( m_xControl.is() )
174 : {
175 217 : m_xControlWindow.set( m_xControl, UNO_QUERY );
176 217 : m_xControlView.set( m_xControl, UNO_QUERY );
177 217 : 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 217 : return *this;
185 : }
186 :
187 : public:
188 127576 : inline bool is() const { return m_xControl.is() && m_xControlWindow.is() && m_xControlView.is(); }
189 1145 : 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 15712 : inline bool isDesignMode() const { return m_xControl->isDesignMode(); }
194 220 : inline void setDesignMode( const bool _bDesign ) const { m_xControl->setDesignMode( _bDesign ); }
195 2068 : inline bool isVisible() const { return m_xControlWindow->isVisible(); }
196 55 : inline void setVisible( const bool _bVisible ) const { m_xControlWindow->setVisible( _bVisible ); }
197 : inline Reference< XControlModel >
198 395 : getModel() const { return m_xControl->getModel(); }
199 217 : inline void setModel( const Reference< XControlModel >& _m ) const { m_xControl->setModel( _m ); }
200 :
201 217 : inline void addWindowListener( const Reference< XWindowListener >& _l ) const { m_xControlWindow->addWindowListener( _l ); }
202 217 : 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 4928 : inline const Reference< XControl >& getControl() const { return m_xControl; }
214 : };
215 :
216 :
217 112 : bool operator==( const ControlHolder& _rControl, const Reference< XInterface >& _rxCompare )
218 : {
219 112 : return _rControl.getControl() == _rxCompare;
220 : }
221 :
222 98 : bool operator==( const ControlHolder& _rControl, const Any& _rxCompare )
223 : {
224 98 : return _rControl == Reference< XInterface >( _rxCompare, UNO_QUERY );
225 : }
226 :
227 26438 : 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 26438 : ::Rectangle aCurrentRect( getPosSize() );
234 26438 : if ( aCurrentRect != _rPosSize )
235 : {
236 257 : m_xControlWindow->setPosSize(
237 1028 : _rPosSize.Left(), _rPosSize.Top(), _rPosSize.GetWidth(), _rPosSize.GetHeight(),
238 : POSSIZE
239 1285 : );
240 : }
241 26438 : }
242 :
243 :
244 26438 : ::Rectangle ControlHolder::getPosSize() const
245 : {
246 : // no check whether we're valid, this is the responsibility of the caller
247 26438 : return VCLUnoHelper::ConvertToVCLRect( m_xControlWindow->getPosSize() );
248 : }
249 :
250 :
251 26438 : void ControlHolder::setZoom( const ::basegfx::B2DVector& _rScale ) const
252 : {
253 : // no check whether we're valid, this is the responsibility of the caller
254 26438 : m_xControlView->setZoom( (float)_rScale.getX(), (float)_rScale.getY() );
255 26438 : }
256 :
257 :
258 140 : void ControlHolder::invalidate() const
259 : {
260 140 : Reference< XWindowPeer > xPeer( m_xControl->getPeer() );
261 140 : if ( xPeer.is() )
262 : {
263 130 : vcl::Window* pWindow = VCLUnoHelper::GetWindow( xPeer );
264 : OSL_ENSURE( pWindow, "ControlHolder::invalidate: no implementation access!" );
265 130 : if ( pWindow )
266 130 : pWindow->Invalidate();
267 140 : }
268 140 : }
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 26438 : 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 26438 : if ( !_rControl.is() )
298 26438 : 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 26438 : ::basegfx::B2DPoint aTopLeft( _rLogicBoundingRect.Left(), _rLogicBoundingRect.Top() );
312 26438 : aTopLeft *= _rViewTransformation;
313 52876 : ::basegfx::B2DPoint aBottomRight( _rLogicBoundingRect.Right(), _rLogicBoundingRect.Bottom() );
314 26438 : aBottomRight *= _rViewTransformation;
315 :
316 26438 : const Rectangle aPaintRectPixel( (long)aTopLeft.getX(), (long)aTopLeft.getY(), (long)aBottomRight.getX(), (long)aBottomRight.getY() );
317 26438 : _rControl.setPosSize( aPaintRectPixel );
318 :
319 : // determine the scale from the current view transformation, and the normalization matrix
320 52876 : ::basegfx::B2DHomMatrix aObtainResolutionDependentScale( _rViewTransformation * _rZoomLevelNormalization );
321 52876 : ::basegfx::B2DVector aScale, aTranslate;
322 : double fRotate, fShearX;
323 26438 : aObtainResolutionDependentScale.decompose( aScale, aTranslate, fRotate, fShearX );
324 52876 : _rControl.setZoom( aScale );
325 : }
326 :
327 : /** disposes the given control
328 : */
329 342 : void disposeAndClearControl_nothrow( ControlHolder& _rControl )
330 : {
331 : try
332 : {
333 342 : Reference< XComponent > xControlComp( _rControl.getControl(), UNO_QUERY );
334 342 : if ( xControlComp.is() )
335 190 : xControlComp->dispose();
336 : }
337 0 : catch( const Exception& )
338 : {
339 : DBG_UNHANDLED_EXCEPTION();
340 : }
341 342 : _rControl.clear();
342 342 : }
343 :
344 : }
345 :
346 : /** interface encapsulating access to an SdrPageView, stripped down to the methods we really need
347 : */
348 3956 : 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 3956 : ~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 3955 : explicit SdrPageViewAccess( const SdrPageView& _rPageView ) : m_rPageView( _rPageView ) { }
375 :
376 3955 : 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 216 : bool SdrPageViewAccess::isDesignMode() const
386 : {
387 216 : return m_rPageView.GetView().IsDesignMode();
388 : }
389 :
390 :
391 432 : Reference< XControlContainer > SdrPageViewAccess::getControlContainer( const OutputDevice& _rDevice ) const
392 : {
393 432 : Reference< XControlContainer > xControlContainer = m_rPageView.GetControlContainer( _rDevice );
394 : DBG_ASSERT( xControlContainer.is() || NULL == m_rPageView.FindPageWindow( _rDevice ),
395 : "SdrPageViewAccess::getControlContainer: the output device is known, but there is no control container for it?" );
396 432 : return xControlContainer;
397 : }
398 :
399 :
400 87 : bool SdrPageViewAccess::isLayerVisible( SdrLayerID _nLayerID ) const
401 : {
402 87 : 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 1 : DummyPageViewAccess()
465 1 : {
466 1 : }
467 :
468 1 : 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 1 : bool DummyPageViewAccess::isDesignMode() const
478 : {
479 1 : return true;
480 : }
481 :
482 :
483 2 : Reference< XControlContainer > DummyPageViewAccess::getControlContainer( const OutputDevice& /*_rDevice*/ ) const
484 : {
485 2 : 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 : VclPtr<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 13559 : 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 28941 : getExistentControl() const { return m_aControl; }
579 :
580 : inline bool
581 34771 : 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 17348 : getViewContact() const
621 : {
622 17348 : ENSURE_OR_THROW( !impl_isDisposed_nofail(), "already disposed" );
623 17348 : 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 67196 : bool impl_isDisposed_nofail() const { return m_pAntiImpl == NULL; }
761 :
762 : /** determines whether our control is currently visible
763 : @nofail
764 : */
765 61 : 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 495 : 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 5637 : inline bool impl_isControlDesignMode_nothrow() const
780 : {
781 : DBG_ASSERT( m_eControlDesignMode != eUnknown, "ViewObjectContactOfUnoControl_Impl::impl_isControlDesignMode_nothrow: mode is still unknown!" );
782 5637 : 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 27098 : 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 13549 : explicit LazyControlCreationPrimitive2D( const ::rtl::Reference< ViewObjectContactOfUnoControl_Impl >& _pVOCImpl )
819 13549 : :m_pVOCImpl( _pVOCImpl )
820 : {
821 13549 : ENSURE_OR_THROW( m_pVOCImpl.is(), "Illegal argument." );
822 13549 : getTransformation( m_pVOCImpl->getViewContact(), m_aTransformation );
823 13549 : }
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 8434 : void impl_positionAndZoomControl( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
834 : {
835 8434 : if ( !_rViewInformation.getViewport().isEmpty() )
836 8433 : m_pVOCImpl->positionAndZoomControl( _rViewInformation.getObjectToViewTransformation() );
837 8434 : }
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 299 : 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 299 : ,m_aZoomLevelNormalization()
856 : {
857 : DBG_ASSERT( m_pAntiImpl, "ViewObjectContactOfUnoControl_Impl::ViewObjectContactOfUnoControl_Impl: invalid AntiImpl!" );
858 :
859 299 : const OutputDevice& rPageViewDevice( impl_getOutputDevice_throw() );
860 299 : 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 299 : ::basegfx::B2DHomMatrix aScaleNormalization;
869 598 : MapMode aCurrentDeviceMapMode( rPageViewDevice.GetMapMode() );
870 299 : aScaleNormalization.set( 0, 0, (double)aCurrentDeviceMapMode.GetScaleX() );
871 299 : aScaleNormalization.set( 1, 1, (double)aCurrentDeviceMapMode.GetScaleY() );
872 598 : m_aZoomLevelNormalization *= aScaleNormalization;
873 :
874 : #if OSL_DEBUG_LEVEL > 1
875 : m_aZoomLevelNormalization.decompose( aScale, aTranslate, fRotate, fShearX );
876 : #endif
877 299 : }
878 :
879 :
880 897 : ViewObjectContactOfUnoControl_Impl::~ViewObjectContactOfUnoControl_Impl()
881 : {
882 299 : if ( !impl_isDisposed_nofail() )
883 : {
884 0 : acquire();
885 0 : dispose();
886 : }
887 :
888 598 : }
889 :
890 :
891 326 : void ViewObjectContactOfUnoControl_Impl::impl_dispose_nothrow( bool _bAlsoDisposeControl )
892 : {
893 326 : if ( impl_isDisposed_nofail() )
894 353 : return;
895 :
896 299 : if ( m_aControl.is() )
897 217 : impl_switchControlListening_nothrow( false );
898 :
899 299 : if ( m_xContainer.is() )
900 216 : impl_switchContainerListening_nothrow( false );
901 :
902 : // dispose the control
903 299 : if ( _bAlsoDisposeControl )
904 272 : UnoControlContactHelper::disposeAndClearControl_nothrow( m_aControl );
905 :
906 299 : m_aControl.clear();
907 299 : m_xContainer.clear();
908 299 : m_pOutputDeviceForWindow = NULL;
909 299 : m_bControlIsVisible = false;
910 :
911 299 : m_pAntiImpl = NULL;
912 : }
913 :
914 :
915 299 : void ViewObjectContactOfUnoControl_Impl::dispose()
916 : {
917 299 : SolarMutexGuard aSolarGuard;
918 299 : impl_dispose_nothrow( true );
919 299 : }
920 :
921 :
922 26569 : bool ViewObjectContactOfUnoControl_Impl::getUnoObject( SdrUnoObj*& _out_rpObject ) const
923 : {
924 : OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::getUnoObject: already disposed()" );
925 26569 : if ( impl_isDisposed_nofail() )
926 0 : _out_rpObject = NULL;
927 : else
928 : {
929 26569 : _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 26569 : return ( _out_rpObject != NULL );
934 : }
935 :
936 :
937 26291 : 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 26291 : if ( !m_aControl.is() )
941 26361 : return;
942 :
943 : try
944 : {
945 26221 : SdrUnoObj* pUnoObject( NULL );
946 26221 : if ( getUnoObject( pUnoObject ) )
947 : {
948 26221 : Point aGridOffset = pUnoObject->GetGridOffset();
949 26221 : 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 26221 : aRect += aGridOffset;
954 26221 : 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 3895 : bool ViewObjectContactOfUnoControl_Impl::ensureControl( const basegfx::B2DHomMatrix* _pInitialViewTransformationOrNULL )
967 : {
968 : OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::ensureControl: already disposed()" );
969 3895 : if ( impl_isDisposed_nofail() )
970 0 : return false;
971 :
972 3895 : ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
973 3895 : if ( pPageViewContact )
974 : {
975 3894 : SdrPageViewAccess aPVAccess( pPageViewContact->GetPageWindow().GetPageView() );
976 3894 : const OutputDevice& rDevice( m_pAntiImpl->getPageViewOutputDevice().get() );
977 : return impl_ensureControl_nothrow(
978 : aPVAccess,
979 : rDevice,
980 : _pInitialViewTransformationOrNULL ? *_pInitialViewTransformationOrNULL : rDevice.GetViewTransformation()
981 3894 : );
982 : }
983 :
984 1 : DummyPageViewAccess aNoPageView;
985 1 : const OutputDevice& rDevice( impl_getOutputDevice_throw() );
986 : return impl_ensureControl_nothrow(
987 : aNoPageView,
988 : rDevice,
989 : _pInitialViewTransformationOrNULL ? *_pInitialViewTransformationOrNULL : rDevice.GetViewTransformation()
990 1 : );
991 : }
992 :
993 :
994 300 : 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 300 : boost::optional<const OutputDevice&> oPageOutputDev = m_pAntiImpl->getPageViewOutputDevice();
999 300 : if( oPageOutputDev )
1000 298 : return oPageOutputDev.get();
1001 :
1002 2 : const OutputDevice* pDevice = m_pAntiImpl->GetObjectContact().TryToGetOutputDevice();
1003 2 : ENSURE_OR_THROW( pDevice, "no output device -> no control" );
1004 2 : return *pDevice;
1005 : }
1006 :
1007 :
1008 : namespace
1009 : {
1010 3895 : static void lcl_resetFlag( bool& rbFlag )
1011 : {
1012 3895 : rbFlag = false;
1013 3895 : }
1014 : }
1015 :
1016 :
1017 3895 : bool ViewObjectContactOfUnoControl_Impl::impl_ensureControl_nothrow( IPageViewAccess& _rPageView, const OutputDevice& _rDevice,
1018 : const basegfx::B2DHomMatrix& _rInitialViewTransformation )
1019 : {
1020 3895 : 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 3895 : m_bCreatingControl = true;
1037 3895 : ::comphelper::ScopeGuard aGuard( ::boost::bind( lcl_resetFlag, ::boost::ref( m_bCreatingControl ) ) );
1038 :
1039 3895 : if ( m_aControl.is() )
1040 : {
1041 3608 : if ( m_pOutputDeviceForWindow.get() == &_rDevice )
1042 3608 : 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 (doesn'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 287 : SdrUnoObj* pUnoObject( NULL );
1058 287 : if ( !getUnoObject( pUnoObject ) )
1059 0 : return false;
1060 :
1061 574 : ControlHolder aControl;
1062 287 : if ( !createControlForDevice( _rPageView, _rDevice, *pUnoObject, _rInitialViewTransformation, m_aZoomLevelNormalization, aControl ) )
1063 70 : return false;
1064 :
1065 217 : m_pOutputDeviceForWindow = const_cast< OutputDevice * >( &_rDevice );
1066 217 : m_aControl = aControl;
1067 217 : 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 217 : m_eControlDesignMode = m_aControl.isDesignMode() ? eDesign : eAlive;
1078 217 : 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 217 : impl_switchControlListening_nothrow( true );
1087 :
1088 : // start listening at the control container, in case somebody tampers with our control
1089 217 : if ( m_xContainer.is() )
1090 216 : impl_switchContainerListening_nothrow( true );
1091 :
1092 4112 : return m_aControl.is();
1093 : }
1094 :
1095 :
1096 287 : 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 287 : _out_rControl.clear();
1101 :
1102 287 : Reference< XControlModel > xControlModel( _rUnoObject.GetUnoControlModel() );
1103 : DBG_ASSERT( xControlModel.is(), "ViewObjectContactOfUnoControl_Impl::createControlForDevice: no control model at the SdrUnoObject!?" );
1104 287 : if ( !xControlModel.is() )
1105 0 : return false;
1106 :
1107 287 : bool bSuccess = false;
1108 : try
1109 : {
1110 287 : const OUString sControlServiceName( _rUnoObject.GetUnoControlTypeName() );
1111 :
1112 574 : Reference< css::uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
1113 287 : _out_rControl = Reference<XControl>( xContext->getServiceManager()->createInstanceWithContext(sControlServiceName, xContext), UNO_QUERY_THROW );
1114 :
1115 : // knit the model and the control
1116 217 : _out_rControl.setModel( xControlModel );
1117 217 : Point aGridOffset = _rUnoObject.GetGridOffset();
1118 217 : 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 217 : aRect += aGridOffset;
1123 :
1124 : // proper geometry
1125 : UnoControlContactHelper::adjustControlGeometry_throw(
1126 : _out_rControl,
1127 : aRect,
1128 : _rInitialViewTransformation,
1129 : _rInitialZoomNormalization
1130 217 : );
1131 :
1132 : // set design mode before peer is created,
1133 : // this is also needed for accessibility
1134 217 : _out_rControl.setDesignMode( _rPageView.isDesignMode() );
1135 :
1136 : // adjust the initial visibility according to the visibility of the layer
1137 217 : impl_adjustControlVisibilityToLayerVisibility_throw( _out_rControl, _rUnoObject, _rPageView, false, true );
1138 :
1139 : // add the control to the respective control container
1140 : // do this last
1141 434 : Reference< XControlContainer > xControlContainer( _rPageView.getControlContainer( _rDevice ) );
1142 217 : if ( xControlContainer.is() )
1143 216 : xControlContainer->addControl( sControlServiceName, _out_rControl.getControl() );
1144 :
1145 504 : bSuccess = true;
1146 : }
1147 70 : catch( const Exception& )
1148 : {
1149 : DBG_UNHANDLED_EXCEPTION();
1150 : }
1151 :
1152 287 : if ( !bSuccess )
1153 : {
1154 : // delete the control which might have been created already
1155 70 : UnoControlContactHelper::disposeAndClearControl_nothrow( _out_rControl );
1156 : }
1157 :
1158 287 : return _out_rControl.is();
1159 : }
1160 :
1161 :
1162 61 : 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 61 : _out_rpPageView = NULL;
1167 61 : if ( impl_isDisposed_nofail() )
1168 0 : return false;
1169 :
1170 61 : ObjectContactOfPageView* pPageViewContact = dynamic_cast< ObjectContactOfPageView* >( &m_pAntiImpl->GetObjectContact() );
1171 61 : if ( pPageViewContact )
1172 61 : _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 61 : return ( _out_rpPageView != NULL );
1176 : }
1177 :
1178 :
1179 61 : 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 61 : SdrPageView* pPageView( NULL );
1185 61 : if ( !impl_getPageView_nothrow( pPageView ) )
1186 0 : return;
1187 :
1188 61 : SdrUnoObj* pUnoObject( NULL );
1189 61 : if ( !getUnoObject( pUnoObject ) )
1190 0 : return;
1191 :
1192 61 : SdrPageViewAccess aPVAccess( *pPageView );
1193 61 : impl_adjustControlVisibilityToLayerVisibility_throw( m_aControl, *pUnoObject, aPVAccess, impl_isControlVisible_nofail(), _bForce );
1194 : }
1195 :
1196 :
1197 278 : 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 278 : if ( !_rControl.isDesignMode() )
1204 : {
1205 : // the layer of our object
1206 87 : SdrLayerID nObjectLayer = _rUnoObject.GetLayer();
1207 : // is the object we're residing in visible in this view?
1208 87 : bool bIsObjectVisible = _rUnoObject.IsVisible() && _rPageView.isLayerVisible( nObjectLayer );
1209 :
1210 87 : if ( _bForce || ( bIsObjectVisible != _bIsCurrentlyVisible ) )
1211 : {
1212 55 : _rControl.setVisible( bIsObjectVisible );
1213 : }
1214 : }
1215 278 : }
1216 :
1217 :
1218 432 : void ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow( bool _bStart )
1219 : {
1220 : OSL_PRECOND( m_xContainer.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchContainerListening_nothrow: no control container!" );
1221 432 : if ( !m_xContainer.is() )
1222 432 : return;
1223 :
1224 : try
1225 : {
1226 432 : if ( _bStart )
1227 216 : m_xContainer->addContainerListener( this );
1228 : else
1229 216 : m_xContainer->removeContainerListener( this );
1230 : }
1231 0 : catch( const Exception& )
1232 : {
1233 : DBG_UNHANDLED_EXCEPTION();
1234 : }
1235 : }
1236 :
1237 :
1238 434 : void ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow( bool _bStart )
1239 : {
1240 : OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchControlListening_nothrow: invalid control!" );
1241 434 : if ( !m_aControl.is() )
1242 434 : return;
1243 :
1244 : try
1245 : {
1246 : // listen for visibility changes
1247 434 : if ( _bStart )
1248 217 : m_aControl.addWindowListener( this );
1249 : else
1250 217 : m_aControl.removeWindowListener( this );
1251 :
1252 : // in design mode, listen for some more aspects
1253 434 : impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() && _bStart );
1254 :
1255 : // listen for design mode changes
1256 434 : Reference< XModeChangeBroadcaster > xDesignModeChanges( m_aControl.getControl(), UNO_QUERY_THROW );
1257 434 : if ( _bStart )
1258 217 : xDesignModeChanges->addModeChangeListener( this );
1259 : else
1260 217 : xDesignModeChanges->removeModeChangeListener( this );
1261 : }
1262 0 : catch( const Exception& )
1263 : {
1264 : DBG_UNHANDLED_EXCEPTION();
1265 : }
1266 : }
1267 :
1268 :
1269 495 : void ViewObjectContactOfUnoControl_Impl::impl_switchDesignModeListening_nothrow( bool _bStart )
1270 : {
1271 495 : if ( impl_isDesignModeListening_nofail() != _bStart )
1272 : {
1273 382 : m_bIsDesignModeListening = _bStart;
1274 382 : impl_switchPropertyListening_nothrow( _bStart );
1275 : }
1276 495 : }
1277 :
1278 :
1279 382 : void ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow( bool _bStart )
1280 : {
1281 : OSL_PRECOND( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::impl_switchPropertyListening_nothrow: no control!" );
1282 382 : if ( !m_aControl.is() )
1283 382 : return;
1284 :
1285 : try
1286 : {
1287 382 : Reference< XPropertySet > xModelProperties( m_aControl.getModel(), UNO_QUERY_THROW );
1288 382 : if ( _bStart )
1289 191 : xModelProperties->addPropertyChangeListener( OUString(), this );
1290 : else
1291 191 : 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 : OSL_VERIFY( xModelProperties->getPropertyValue( "Printable" ) >>= bIsPrintable );
1311 : }
1312 0 : catch( const Exception& )
1313 : {
1314 : DBG_UNHANDLED_EXCEPTION();
1315 : }
1316 0 : return bIsPrintable;
1317 : }
1318 :
1319 :
1320 14 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::disposing( const EventObject& Source ) throw(RuntimeException, std::exception)
1321 : {
1322 14 : SolarMutexGuard aSolarGuard;
1323 : // some code below - in particular our disposal - might trigger actions which require the
1324 : // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
1325 : // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
1326 : // is the real bug. Toolkit really is infested with solar mutex usage ... :(
1327 : // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
1328 :
1329 14 : if ( !m_aControl.is() )
1330 0 : return;
1331 :
1332 43 : if ( ( m_aControl == Source.Source )
1333 55 : || ( m_aControl.getModel() == Source.Source )
1334 : )
1335 : {
1336 : // the model or the control is dying ... hmm, not much sense in that we ourself continue
1337 : // living
1338 14 : impl_dispose_nothrow( false );
1339 14 : return;
1340 : }
1341 :
1342 0 : DBG_ASSERT( Source.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::disposing: Who's this?" );
1343 : }
1344 :
1345 :
1346 286 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowResized( const WindowEvent& /*e*/ ) throw(RuntimeException, std::exception)
1347 : {
1348 : // not interested in
1349 286 : }
1350 :
1351 :
1352 550 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowMoved( const WindowEvent& /*e*/ ) throw(RuntimeException, std::exception)
1353 : {
1354 : // not interested in
1355 550 : }
1356 :
1357 :
1358 3813 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowShown( const EventObject& /*e*/ ) throw(RuntimeException, std::exception)
1359 : {
1360 3813 : SolarMutexGuard aSolarGuard;
1361 3813 : m_bControlIsVisible = true;
1362 3813 : }
1363 :
1364 :
1365 3846 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::windowHidden( const EventObject& /*e*/ ) throw(RuntimeException, std::exception)
1366 : {
1367 3846 : SolarMutexGuard aSolarGuard;
1368 3846 : m_bControlIsVisible = false;
1369 3846 : }
1370 :
1371 :
1372 5139 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::propertyChange( const PropertyChangeEvent& /*_rEvent*/ ) throw(RuntimeException, std::exception)
1373 : {
1374 5139 : SolarMutexGuard aSolarGuard;
1375 : // (re)painting might require VCL operations, which need the SolarMutex
1376 :
1377 : OSL_PRECOND( !impl_isDisposed_nofail(), "ViewObjectContactOfUnoControl_Impl::propertyChange: already disposed()" );
1378 5139 : if ( impl_isDisposed_nofail() )
1379 0 : return;
1380 :
1381 : DBG_ASSERT( m_aControl.is(), "ViewObjectContactOfUnoControl_Impl::propertyChange: " );
1382 5139 : if ( !m_aControl.is() )
1383 0 : return;
1384 :
1385 : // a generic property changed. If we're in design mode, we need to repaint the control
1386 5139 : if ( impl_isControlDesignMode_nothrow() )
1387 : {
1388 5139 : m_pAntiImpl->propertyChange();
1389 5139 : }
1390 : }
1391 :
1392 :
1393 61 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::modeChanged( const ModeChangeEvent& _rSource ) throw (RuntimeException, std::exception)
1394 : {
1395 61 : SolarMutexGuard aSolarGuard;
1396 :
1397 : DBG_ASSERT( _rSource.NewMode == "design" || _rSource.NewMode == "alive", "ViewObjectContactOfUnoControl_Impl::modeChanged: unexpected mode!" );
1398 :
1399 61 : m_eControlDesignMode = _rSource.NewMode == "design" ? eDesign : eAlive;
1400 :
1401 61 : impl_switchDesignModeListening_nothrow( impl_isControlDesignMode_nothrow() );
1402 :
1403 : try
1404 : {
1405 : // if the control is part of a invisible layer, we need to explicitly hide it in alive mode
1406 61 : impl_adjustControlVisibilityToLayerVisibility_throw( false );
1407 : }
1408 0 : catch( const Exception& )
1409 : {
1410 : DBG_UNHANDLED_EXCEPTION();
1411 61 : }
1412 61 : }
1413 :
1414 :
1415 88 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementInserted( const ContainerEvent& /*_Event*/ ) throw (RuntimeException, std::exception)
1416 : {
1417 : // not interested in
1418 88 : }
1419 :
1420 :
1421 98 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementRemoved( const ContainerEvent& Event ) throw (RuntimeException, std::exception)
1422 : {
1423 98 : SolarMutexGuard aSolarGuard;
1424 : // some code below - in particular our disposal - might trigger actions which require the
1425 : // SolarMutex. In particular, in our disposal, we remove ourself as listener from the control,
1426 : // which alone needs the SolarMutex. Of course this - a removeFooListener needed the SolarMutex -
1427 : // is the real bug. Toolkit really is infested with solar mutex usage ... :(
1428 : // #i82169# / 2007-11-14 / frank.schoenheit@sun.com
1429 : DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementRemoved: where did this come from?" );
1430 :
1431 98 : if ( m_aControl == Event.Element )
1432 13 : impl_dispose_nothrow( false );
1433 98 : }
1434 :
1435 :
1436 0 : void SAL_CALL ViewObjectContactOfUnoControl_Impl::elementReplaced( const ContainerEvent& Event ) throw (RuntimeException, std::exception)
1437 : {
1438 0 : SolarMutexGuard aSolarGuard;
1439 : DBG_ASSERT( Event.Source == m_xContainer, "ViewObjectContactOfUnoControl_Impl::elementReplaced: where did this come from?" );
1440 :
1441 0 : if ( ! ( m_aControl == Event.ReplacedElement ) )
1442 0 : return;
1443 :
1444 0 : Reference< XControl > xNewControl( Event.Element, UNO_QUERY );
1445 : DBG_ASSERT( xNewControl.is(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: invalid new control!" );
1446 0 : if ( !xNewControl.is() )
1447 0 : return;
1448 :
1449 0 : ENSURE_OR_THROW( m_pOutputDeviceForWindow, "calling this without /me having an output device should be impossible." );
1450 :
1451 : DBG_ASSERT( xNewControl->getModel() == m_aControl.getModel(), "ViewObjectContactOfUnoControl_Impl::elementReplaced: another model at the new control?" );
1452 : // another model should - in the drawing layer - also imply another SdrUnoObj, which
1453 : // should also result in new ViewContact, and thus in new ViewObjectContacts
1454 :
1455 0 : impl_switchControlListening_nothrow( false );
1456 :
1457 0 : ControlHolder aNewControl( xNewControl );
1458 0 : aNewControl.setZoom( m_aControl.getZoom() );
1459 0 : aNewControl.setPosSize( m_aControl.getPosSize() );
1460 0 : aNewControl.setDesignMode( impl_isControlDesignMode_nothrow() );
1461 :
1462 0 : m_aControl = xNewControl;
1463 0 : m_bControlIsVisible = m_aControl.isVisible();
1464 :
1465 0 : impl_switchControlListening_nothrow( true );
1466 :
1467 0 : m_pAntiImpl->onControlChangedOrModified( ViewObjectContactOfUnoControl::ImplAccess() );
1468 : }
1469 :
1470 :
1471 3 : void ViewObjectContactOfUnoControl_Impl::setControlDesignMode( bool _bDesignMode ) const
1472 : {
1473 3 : if ( ( m_eControlDesignMode != eUnknown ) && ( _bDesignMode == impl_isControlDesignMode_nothrow() ) )
1474 : // nothing to do
1475 0 : return;
1476 3 : m_eControlDesignMode = _bDesignMode ? eDesign : eAlive;
1477 :
1478 3 : if ( !m_aControl.is() )
1479 : // nothing to do, the setting will be respected as soon as the control
1480 : // is created
1481 0 : return;
1482 :
1483 : try
1484 : {
1485 3 : m_aControl.setDesignMode( _bDesignMode );
1486 : }
1487 0 : catch( const Exception& )
1488 : {
1489 : DBG_UNHANDLED_EXCEPTION();
1490 : }
1491 : }
1492 :
1493 :
1494 : //= LazyControlCreationPrimitive2D
1495 :
1496 :
1497 9421 : bool LazyControlCreationPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
1498 : {
1499 9421 : if ( !BufferedDecompositionPrimitive2D::operator==( rPrimitive ) )
1500 0 : return false;
1501 :
1502 9421 : const LazyControlCreationPrimitive2D* pRHS = dynamic_cast< const LazyControlCreationPrimitive2D* >( &rPrimitive );
1503 9421 : if ( !pRHS )
1504 0 : return false;
1505 :
1506 9421 : if ( m_pVOCImpl != pRHS->m_pVOCImpl )
1507 0 : return false;
1508 :
1509 9421 : if ( m_aTransformation != pRHS->m_aTransformation )
1510 238 : return false;
1511 :
1512 9183 : return true;
1513 : }
1514 :
1515 :
1516 13549 : void LazyControlCreationPrimitive2D::getTransformation( const ViewContactOfUnoControl& _rVOC, ::basegfx::B2DHomMatrix& _out_Transformation )
1517 : {
1518 : // Do use model data directly to create the correct geometry. Do NOT
1519 : // use getBoundRect()/getSnapRect() here; tese will use the sequence of
1520 : // primitives themselves in the long run.
1521 13549 : Rectangle aSdrGeoData( _rVOC.GetSdrUnoObj().GetGeoRect() );
1522 13549 : Point aGridOffset = _rVOC.GetSdrUnoObj().GetGridOffset();
1523 : // Hack for calc, transform position of object according
1524 : // to current zoom so as objects relative position to grid
1525 : // appears stable
1526 13549 : aSdrGeoData += aGridOffset;
1527 : const basegfx::B2DRange aRange(
1528 13549 : aSdrGeoData.Left(),
1529 13549 : aSdrGeoData.Top(),
1530 13549 : aSdrGeoData.Right(),
1531 13549 : aSdrGeoData.Bottom()
1532 54196 : );
1533 :
1534 13549 : _out_Transformation.identity();
1535 13549 : _out_Transformation.set( 0, 0, aRange.getWidth() );
1536 13549 : _out_Transformation.set( 1, 1, aRange.getHeight() );
1537 13549 : _out_Transformation.set( 0, 2, aRange.getMinX() );
1538 13549 : _out_Transformation.set( 1, 2, aRange.getMinY() );
1539 13549 : }
1540 :
1541 :
1542 33071 : ::basegfx::B2DRange LazyControlCreationPrimitive2D::getB2DRange( const ::drawinglayer::geometry::ViewInformation2D& /*rViewInformation*/ ) const
1543 : {
1544 33071 : ::basegfx::B2DRange aRange( 0.0, 0.0, 1.0, 1.0 );
1545 33071 : aRange.transform( m_aTransformation );
1546 33071 : return aRange;
1547 : }
1548 :
1549 :
1550 7578 : ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::get2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
1551 : {
1552 : #if OSL_DEBUG_LEVEL > 1
1553 : ::basegfx::B2DVector aScale, aTranslate;
1554 : double fRotate, fShearX;
1555 : _rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
1556 : #endif
1557 7578 : if ( m_pVOCImpl->hasControl() )
1558 4635 : impl_positionAndZoomControl( _rViewInformation );
1559 7578 : return BufferedDecompositionPrimitive2D::get2DDecomposition( _rViewInformation );
1560 : }
1561 :
1562 :
1563 3799 : ::drawinglayer::primitive2d::Primitive2DSequence LazyControlCreationPrimitive2D::create2DDecomposition( const ::drawinglayer::geometry::ViewInformation2D& _rViewInformation ) const
1564 : {
1565 : #if OSL_DEBUG_LEVEL > 1
1566 : ::basegfx::B2DVector aScale, aTranslate;
1567 : double fRotate, fShearX;
1568 : _rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
1569 : #endif
1570 3799 : const bool bHadControl = m_pVOCImpl->getExistentControl().is();
1571 :
1572 : // force control here to make it a VCL ChildWindow. Will be fetched
1573 : // and used below by getExistentControl()
1574 3799 : m_pVOCImpl->ensureControl( &_rViewInformation.getObjectToViewTransformation() );
1575 3799 : impl_positionAndZoomControl( _rViewInformation );
1576 :
1577 : // get needed data
1578 3799 : const ViewContactOfUnoControl& rViewContactOfUnoControl( m_pVOCImpl->getViewContact() );
1579 3799 : Reference< XControlModel > xControlModel( rViewContactOfUnoControl.GetSdrUnoObj().GetUnoControlModel() );
1580 3799 : const ControlHolder& rControl( m_pVOCImpl->getExistentControl() );
1581 :
1582 3799 : if ( !bHadControl && rControl.is() && rControl.isVisible() )
1583 70 : rControl.invalidate();
1584 :
1585 3799 : if ( !bHadControl && rControl.is() && rControl.isVisible() )
1586 70 : rControl.invalidate();
1587 :
1588 : // check if we already have an XControl.
1589 3799 : if ( !xControlModel.is() || !rControl.is() )
1590 : // use the default mechanism. This will create a ControlPrimitive2D without
1591 : // handing over a XControl. If not even a XControlModel exists, it will
1592 : // create the SdrObject fallback visualisation
1593 71 : return rViewContactOfUnoControl.getViewIndependentPrimitive2DSequence();
1594 :
1595 : // create a primitive and hand over the existing xControl. This will
1596 : // allow the primitive to not need to create another one on demand.
1597 : const drawinglayer::primitive2d::Primitive2DReference xRetval( new ::drawinglayer::primitive2d::ControlPrimitive2D(
1598 7456 : m_aTransformation, xControlModel, rControl.getControl() ) );
1599 :
1600 7527 : return drawinglayer::primitive2d::Primitive2DSequence(&xRetval, 1);
1601 : }
1602 :
1603 :
1604 30786 : ImplPrimitive2DIDBlock( LazyControlCreationPrimitive2D, PRIMITIVE2D_ID_SDRCONTROLPRIMITIVE2D )
1605 :
1606 299 : ViewObjectContactOfUnoControl::ViewObjectContactOfUnoControl( ObjectContact& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1607 : :ViewObjectContactOfSdrObj( _rObjectContact, _rViewContact )
1608 299 : ,m_pImpl( new ViewObjectContactOfUnoControl_Impl( this ) )
1609 : {
1610 299 : }
1611 :
1612 :
1613 897 : ViewObjectContactOfUnoControl::~ViewObjectContactOfUnoControl()
1614 : {
1615 299 : m_pImpl->dispose();
1616 299 : m_pImpl = NULL;
1617 :
1618 598 : }
1619 :
1620 :
1621 96 : Reference< XControl > ViewObjectContactOfUnoControl::getControl()
1622 : {
1623 96 : SolarMutexGuard aSolarGuard;
1624 96 : m_pImpl->ensureControl( NULL );
1625 96 : return m_pImpl->getExistentControl().getControl();
1626 : }
1627 :
1628 :
1629 0 : Reference< XControl > ViewObjectContactOfUnoControl::getTemporaryControlForWindow(
1630 : const vcl::Window& _rWindow, Reference< XControlContainer >& _inout_ControlContainer, const SdrUnoObj& _rUnoObject )
1631 : {
1632 0 : ControlHolder aControl;
1633 :
1634 0 : InvisibleControlViewAccess aSimulatePageView( _inout_ControlContainer );
1635 0 : OSL_VERIFY( ViewObjectContactOfUnoControl_Impl::createControlForDevice( aSimulatePageView, _rWindow, _rUnoObject,
1636 : _rWindow.GetViewTransformation(), _rWindow.GetInverseViewTransformation(), aControl ) );
1637 0 : return aControl.getControl();
1638 : }
1639 :
1640 :
1641 437 : void ViewObjectContactOfUnoControl::ensureControlVisibility( bool _bVisible ) const
1642 : {
1643 437 : SolarMutexGuard aSolarGuard;
1644 :
1645 : try
1646 : {
1647 437 : const ControlHolder& rControl( m_pImpl->getExistentControl() );
1648 437 : if ( !rControl.is() )
1649 436 : return;
1650 :
1651 : // only need to care for alive mode
1652 1 : if ( rControl.isDesignMode() )
1653 1 : return;
1654 :
1655 : // is the visibility correct?
1656 0 : if ( m_pImpl->isControlVisible() == _bVisible )
1657 0 : return;
1658 :
1659 : // no -> adjust it
1660 0 : rControl.setVisible( _bVisible );
1661 : DBG_ASSERT( m_pImpl->isControlVisible() == _bVisible, "ViewObjectContactOfUnoControl::ensureControlVisibility: this didn't work!" );
1662 : // now this would mean that either isControlVisible is not reliable,
1663 : // or that showing/hiding the window did not work as intended.
1664 : }
1665 0 : catch( const Exception& )
1666 : {
1667 : DBG_UNHANDLED_EXCEPTION();
1668 0 : }
1669 : }
1670 :
1671 :
1672 3 : void ViewObjectContactOfUnoControl::setControlDesignMode( bool _bDesignMode ) const
1673 : {
1674 3 : SolarMutexGuard aSolarGuard;
1675 3 : m_pImpl->setControlDesignMode( _bDesignMode );
1676 :
1677 3 : if(!_bDesignMode)
1678 : {
1679 : // when live mode is switched on, a refresh is needed. The edit mode visualisation
1680 : // needs to be repainted and the now used VCL-Window needs to be positioned and
1681 : // sized. Both is done from the repant refresh.
1682 3 : const_cast< ViewObjectContactOfUnoControl* >(this)->ActionChanged();
1683 3 : }
1684 3 : }
1685 :
1686 :
1687 13559 : drawinglayer::primitive2d::Primitive2DSequence ViewObjectContactOfUnoControl::createPrimitive2DSequence(const DisplayInfo& /*rDisplayInfo*/) const
1688 : {
1689 13559 : if ( m_pImpl->isDisposed() )
1690 : // our control already died.
1691 : // TODO: Is it worth re-creating the control? Finally, this is a pathological situation, it means some instance
1692 : // disposed the control though it doesn't own it. So, /me thinks we should not bother here.
1693 4 : return drawinglayer::primitive2d::Primitive2DSequence();
1694 :
1695 13555 : if ( GetObjectContact().getViewInformation2D().getViewTransformation().isIdentity() )
1696 : // remove this when #i115754# is fixed
1697 5 : return drawinglayer::primitive2d::Primitive2DSequence();
1698 :
1699 : // ignore existing controls which are in alive mode and manually switched to "invisible"
1700 : // #102090# / 2009-06-05 / frank.schoenheit@sun.com
1701 13550 : const ControlHolder& rControl( m_pImpl->getExistentControl() );
1702 13550 : if ( rControl.is() && !rControl.isDesignMode() && !rControl.isVisible() )
1703 1 : return drawinglayer::primitive2d::Primitive2DSequence();
1704 :
1705 13549 : ::drawinglayer::primitive2d::Primitive2DReference xPrimitive( new LazyControlCreationPrimitive2D( m_pImpl ) );
1706 13549 : return ::drawinglayer::primitive2d::Primitive2DSequence( &xPrimitive, 1 );
1707 : }
1708 :
1709 :
1710 27193 : bool ViewObjectContactOfUnoControl::isPrimitiveVisible( const DisplayInfo& _rDisplayInfo ) const
1711 : {
1712 27193 : SolarMutexGuard aSolarGuard;
1713 :
1714 27193 : if ( m_pImpl->hasControl() )
1715 : {
1716 17858 : const ::drawinglayer::geometry::ViewInformation2D& rViewInformation( GetObjectContact().getViewInformation2D() );
1717 : #if OSL_DEBUG_LEVEL > 1
1718 : ::basegfx::B2DVector aScale, aTranslate;
1719 : double fRotate, fShearX;
1720 : rViewInformation.getObjectToViewTransformation().decompose( aScale, aTranslate, fRotate, fShearX );
1721 : #endif
1722 :
1723 17858 : if ( !rViewInformation.getViewport().isEmpty() )
1724 17858 : m_pImpl->positionAndZoomControl( rViewInformation.getObjectToViewTransformation() );
1725 : }
1726 :
1727 27193 : return ViewObjectContactOfSdrObj::isPrimitiveVisible( _rDisplayInfo );
1728 : }
1729 :
1730 :
1731 5139 : void ViewObjectContactOfUnoControl::propertyChange()
1732 : {
1733 5139 : impl_onControlChangedOrModified();
1734 5139 : }
1735 :
1736 :
1737 7260 : void ViewObjectContactOfUnoControl::ActionChanged()
1738 : {
1739 : // call parent
1740 7260 : ViewObjectContactOfSdrObj::ActionChanged();
1741 7260 : const ControlHolder& rControl(m_pImpl->getExistentControl());
1742 :
1743 7260 : if(rControl.is() && !rControl.isDesignMode())
1744 : {
1745 : // #i93180# if layer visibility has changed and control is in live mode, it is necessary
1746 : // to correct visibility to make those control vanish on SdrObject LayerID changes
1747 13 : const SdrPageView* pSdrPageView = GetObjectContact().TryToGetSdrPageView();
1748 :
1749 13 : if(pSdrPageView)
1750 : {
1751 13 : const SdrObject& rObject = getSdrObject();
1752 13 : const bool bIsLayerVisible( rObject.IsVisible() && pSdrPageView->GetVisibleLayers().IsSet(rObject.GetLayer()));
1753 :
1754 13 : if(rControl.isVisible() != bIsLayerVisible)
1755 : {
1756 0 : rControl.setVisible(bIsLayerVisible);
1757 : }
1758 : }
1759 : }
1760 7260 : }
1761 :
1762 :
1763 5139 : void ViewObjectContactOfUnoControl::impl_onControlChangedOrModified()
1764 : {
1765 : // graphical invalidate at all views
1766 5139 : ActionChanged();
1767 :
1768 : // #i93318# flush Primitive2DSequence to force recreation with updated XControlModel
1769 : // since e.g. background color has changed and existing decompositions are possibly no
1770 : // longer valid. Unfortunately this is not detected from ControlPrimitive2D::operator==
1771 : // since it only has a uno reference to the XControlModel
1772 5139 : flushPrimitive2DSequence();
1773 5139 : }
1774 :
1775 0 : UnoControlPrintOrPreviewContact::UnoControlPrintOrPreviewContact( ObjectContactOfPageView& _rObjectContact, ViewContactOfUnoControl& _rViewContact )
1776 0 : :ViewObjectContactOfUnoControl( _rObjectContact, _rViewContact )
1777 : {
1778 0 : }
1779 :
1780 :
1781 0 : UnoControlPrintOrPreviewContact::~UnoControlPrintOrPreviewContact()
1782 : {
1783 0 : }
1784 :
1785 :
1786 0 : drawinglayer::primitive2d::Primitive2DSequence UnoControlPrintOrPreviewContact::createPrimitive2DSequence(const DisplayInfo& rDisplayInfo ) const
1787 : {
1788 0 : if ( !m_pImpl->isPrintableControl() )
1789 0 : return drawinglayer::primitive2d::Primitive2DSequence();
1790 0 : return ViewObjectContactOfUnoControl::createPrimitive2DSequence( rDisplayInfo );
1791 : }
1792 :
1793 :
1794 435 : } } // namespace sdr::contact
1795 :
1796 :
1797 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|