Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <svx/sdrpagewindow.hxx>
30 : : #include <com/sun/star/awt/XWindow.hpp>
31 : : #include <com/sun/star/beans/XPropertySet.hpp>
32 : : #include <com/sun/star/awt/PosSize.hpp>
33 : : #include <com/sun/star/util/XModeChangeBroadcaster.hpp>
34 : : #include <comphelper/processfactory.hxx>
35 : : #include <vcl/svapp.hxx>
36 : : #include <toolkit/helper/vclunohelper.hxx>
37 : : #include <svx/svdouno.hxx>
38 : : #include <svx/svdpage.hxx>
39 : : #include <svx/svdview.hxx>
40 : : #include <svx/svdpagv.hxx>
41 : : #include <svx/sdrpaintwindow.hxx>
42 : : #include <svx/sdr/contact/objectcontactofpageview.hxx>
43 : : #include <svx/sdr/contact/displayinfo.hxx>
44 : : #include <osl/mutex.hxx>
45 : : #include <svx/fmview.hxx>
46 : : #include <basegfx/matrix/b2dhommatrix.hxx>
47 : :
48 : : ////////////////////////////////////////////////////////////////////////////////////////////////////
49 : :
50 : : using namespace ::rtl;
51 : : using namespace ::com::sun::star;
52 : :
53 : : ////////////////////////////////////////////////////////////////////////////////////////////////////
54 : :
55 : 1487 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlContainer > SdrPageWindow::GetControlContainer( bool _bCreateIfNecessary ) const
56 : : {
57 [ + + ][ + - ]: 1487 : if ( !mxControlContainer.is() && _bCreateIfNecessary )
[ + + ]
58 : : {
59 : 653 : SdrView& rView = GetPageView().GetView();
60 : :
61 [ + + ]: 653 : const SdrPaintWindow& rPaintWindow( GetOriginalPaintWindow() ? *GetOriginalPaintWindow() : GetPaintWindow() );
62 [ + + ][ + - ]: 653 : if ( rPaintWindow.OutputToWindow() && !rView.IsPrintPreview() )
[ + + ]
63 : : {
64 [ + - ]: 636 : Window& rWindow = dynamic_cast< Window& >( rPaintWindow.GetOutputDevice() );
65 [ + - ][ + - ]: 636 : const_cast< SdrPageWindow* >( this )->mxControlContainer = VCLUnoHelper::CreateControlContainer( &rWindow );
66 : :
67 : : // #100394# xC->setVisible triggers window->Show() and this has
68 : : // problems when the view is not completely constructed which may
69 : : // happen when loading. This leads to accessibility broadcasts which
70 : : // throw asserts due to the not finished view. All this chain can be avoided
71 : : // since xC->setVisible is here called only for the side effect in
72 : : // UnoControlContainer::setVisible(...) which calls createPeer(...).
73 : : // This will now be called directly from here.
74 : :
75 [ + - ]: 636 : uno::Reference< awt::XControl > xControl(mxControlContainer, uno::UNO_QUERY);
76 [ + - ]: 636 : if(xControl.is())
77 : : {
78 [ + - ][ + - ]: 636 : uno::Reference< uno::XInterface > xContext = xControl->getContext();
79 [ + - ]: 636 : if(!xContext.is())
80 : : {
81 [ + - ]: 636 : xControl->createPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > (),
82 [ + - ]: 636 : ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > () );
83 : 636 : }
84 : 636 : }
85 : : }
86 : : else
87 : : {
88 : : // Printer and VirtualDevice, or rather: no OutDev
89 [ + - ]: 17 : uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
90 [ + - ]: 17 : if( xFactory.is() )
91 : : {
92 [ + - ][ + - ]: 17 : const_cast< SdrPageWindow* >( this )->mxControlContainer = uno::Reference< awt::XControlContainer >(xFactory->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlContainer"))), uno::UNO_QUERY);
[ + - ][ + - ]
[ + - ]
93 [ + - ][ + - ]: 17 : uno::Reference< awt::XControlModel > xModel(xFactory->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.UnoControlContainerModel"))), uno::UNO_QUERY);
[ + - ][ + - ]
94 [ + - ]: 17 : uno::Reference< awt::XControl > xControl(mxControlContainer, uno::UNO_QUERY);
95 [ + - ]: 17 : if (xControl.is())
96 [ + - ][ + - ]: 17 : xControl->setModel(xModel);
97 : :
98 : 17 : OutputDevice& rOutDev = rPaintWindow.GetOutputDevice();
99 : 17 : Point aPosPix = rOutDev.GetMapMode().GetOrigin();
100 : 17 : Size aSizePix = rOutDev.GetOutputSizePixel();
101 : :
102 [ + - ]: 17 : uno::Reference< awt::XWindow > xContComp(mxControlContainer, uno::UNO_QUERY);
103 [ + - ]: 17 : if( xContComp.is() )
104 [ + - ][ + - ]: 17 : xContComp->setPosSize(aPosPix.X(), aPosPix.Y(), aSizePix.Width(), aSizePix.Height(), awt::PosSize::POSSIZE);
105 : 17 : }
106 : : }
107 : :
108 [ - + ]: 653 : FmFormView* pViewAsFormView = dynamic_cast< FmFormView* >( &rView );
109 [ + - ]: 653 : if ( pViewAsFormView )
110 : 653 : pViewAsFormView->InsertControlContainer(mxControlContainer);
111 : : }
112 : 1487 : return mxControlContainer;
113 : : }
114 : :
115 : 3204 : SdrPageWindow::SdrPageWindow(SdrPageView& rPageView, SdrPaintWindow& rPaintWindow)
116 : : : mpObjectContact(0L),
117 : : mrPageView(rPageView),
118 : : mpPaintWindow(&rPaintWindow),
119 : 3204 : mpOriginalPaintWindow(NULL)
120 : : {
121 : 3204 : }
122 : :
123 : 3113 : SdrPageWindow::~SdrPageWindow()
124 : : {
125 : : // #i26631#
126 [ + - ]: 3113 : ResetObjectContact();
127 : :
128 [ + + ]: 3113 : if (mxControlContainer.is())
129 : : {
130 : 642 : SdrView& rView = GetPageView().GetView();
131 : :
132 : : // notify derived views
133 [ - + ]: 642 : FmFormView* pViewAsFormView = dynamic_cast< FmFormView* >( &rView );
134 [ + - ]: 642 : if ( pViewAsFormView )
135 [ + - ]: 642 : pViewAsFormView->RemoveControlContainer(mxControlContainer);
136 : :
137 : : // dispose the control container
138 [ + - ]: 642 : uno::Reference< lang::XComponent > xComponent(mxControlContainer, uno::UNO_QUERY);
139 [ + - ][ + - ]: 642 : xComponent->dispose();
140 : : }
141 : 3113 : }
142 : :
143 : : // ObjectContact section
144 : 2381 : sdr::contact::ObjectContact* SdrPageWindow::CreateViewSpecificObjectContact()
145 : : {
146 [ + - ]: 2381 : return new sdr::contact::ObjectContactOfPageView(*this);
147 : : }
148 : :
149 : : // OVERLAY MANAGER
150 : 8764 : rtl::Reference< ::sdr::overlay::OverlayManager > SdrPageWindow::GetOverlayManager() const
151 : : {
152 : 8764 : return GetPaintWindow().GetOverlayManager();
153 : : }
154 : :
155 : 42819 : void SdrPageWindow::patchPaintWindow(SdrPaintWindow& rPaintWindow)
156 : : {
157 : 42819 : mpOriginalPaintWindow = mpPaintWindow;
158 : 42819 : mpPaintWindow = &rPaintWindow;
159 : 42819 : }
160 : :
161 : 42819 : void SdrPageWindow::unpatchPaintWindow()
162 : : {
163 : : DBG_ASSERT(mpOriginalPaintWindow, "SdrPageWindow::unpatchPaintWindow: paint window not patched!" );
164 [ + - ]: 42819 : if ( mpOriginalPaintWindow )
165 : : {
166 : 42819 : mpPaintWindow = mpOriginalPaintWindow;
167 : 42819 : mpOriginalPaintWindow = NULL;
168 : : }
169 : 42819 : }
170 : :
171 : 15547 : void SdrPageWindow::PrePaint()
172 : : {
173 : : // give OC the chance to do ProcessDisplay preparations
174 [ + + ]: 15547 : if(HasObjectContact())
175 : : {
176 : 12454 : GetObjectContact().PrepareProcessDisplay();
177 : : }
178 : 15547 : }
179 : :
180 : 15999 : void SdrPageWindow::PrepareRedraw(const Region& rReg)
181 : : {
182 : : // give OC the chance to do ProcessDisplay preparations
183 [ + + ]: 15999 : if(HasObjectContact())
184 : : {
185 : 13620 : GetObjectContact().PrepareProcessDisplay();
186 : : }
187 : :
188 : : // if necessary, remember changed RedrawArea at PaintWindow for usage with
189 : : // overlay and PreRenderDevice stuff
190 : 15999 : GetPaintWindow().SetRedrawRegion(rReg);
191 : 15999 : }
192 : :
193 : : //////////////////////////////////////////////////////////////////////////////
194 : : // clip test
195 : : #ifdef CLIPPER_TEST
196 : : #include <svx/svdopath.hxx>
197 : : #include <basegfx/polygon/b2dpolygon.hxx>
198 : : #include <tools/helpers.hxx>
199 : : #include <basegfx/polygon/b2dpolygoncutandtouch.hxx>
200 : : #include <basegfx/polygon/b2dpolypolygontools.hxx>
201 : : #include <basegfx/polygon/b2dpolygontools.hxx>
202 : : #include <basegfx/polygon/b2dpolygonclipper.hxx>
203 : :
204 : : // for ::std::sort
205 : : #include <algorithm>
206 : :
207 : : namespace
208 : : {
209 : : void impPaintStrokePolygon(const basegfx::B2DPolygon& rCandidate, OutputDevice& rOutDev, Color aColor)
210 : : {
211 : : basegfx::B2DPolygon aCandidate(rCandidate);
212 : :
213 : : if(aCandidate.areControlPointsUsed())
214 : : {
215 : : aCandidate = basegfx::tools::adaptiveSubdivideByAngle(rCandidate);
216 : : }
217 : :
218 : : if(aCandidate.count())
219 : : {
220 : : const sal_uInt32 nLoopCount(aCandidate.isClosed() ? aCandidate.count() : aCandidate.count() - 1L);
221 : : rOutDev.SetFillColor();
222 : : rOutDev.SetLineColor(aColor);
223 : :
224 : : for(sal_uInt32 a(0L); a < nLoopCount; a++)
225 : : {
226 : : const basegfx::B2DPoint aBStart(aCandidate.getB2DPoint(a));
227 : : const basegfx::B2DPoint aBEnd(aCandidate.getB2DPoint((a + 1) % aCandidate.count()));
228 : : const Point aStart(FRound(aBStart.getX()), FRound(aBStart.getY()));
229 : : const Point aEnd(FRound(aBEnd.getX()), FRound(aBEnd.getY()));
230 : : rOutDev.DrawLine(aStart, aEnd);
231 : : }
232 : : }
233 : : }
234 : :
235 : : void impTryTest(const SdrPageView& rPageView, OutputDevice& rOutDev)
236 : : {
237 : : if(rPageView.GetPage() && rPageView.GetPage()->GetObjCount() >= 2L)
238 : : {
239 : : SdrPage* pPage = rPageView.GetPage();
240 : : SdrObject* pObjA = pPage->GetObj(0L);
241 : :
242 : : if(pObjA && pObjA->ISA(SdrPathObj))
243 : : {
244 : : basegfx::B2DPolyPolygon aPolyA(((SdrPathObj*)pObjA)->GetPathPoly());
245 : : aPolyA = basegfx::tools::correctOrientations(aPolyA);
246 : :
247 : : basegfx::B2DPolyPolygon aPolyB;
248 : :
249 : : for(sal_uInt32 a(1L); a < rPageView.GetPage()->GetObjCount(); a++)
250 : : {
251 : : SdrObject* pObjB = pPage->GetObj(a);
252 : :
253 : : if(pObjB && pObjB->ISA(SdrPathObj))
254 : : {
255 : : basegfx::B2DPolyPolygon aCandidate(((SdrPathObj*)pObjB)->GetPathPoly());
256 : : aCandidate = basegfx::tools::correctOrientations(aCandidate);
257 : : aPolyB.append(aCandidate);
258 : : }
259 : : }
260 : :
261 : : if(aPolyA.count() && aPolyA.isClosed() && aPolyB.count())
262 : : {
263 : : // poly A is the clipregion, clip poly b against it. Algo depends on
264 : : // poly b being closed.
265 : : basegfx::B2DPolyPolygon aResult(basegfx::tools::clipPolyPolygonOnPolyPolygon(aPolyB, aPolyA));
266 : :
267 : : for(sal_uInt32 a(0L); a < aResult.count(); a++)
268 : : {
269 : : Color aColor(rand()%255, rand()%255, rand()%255);
270 : : impPaintStrokePolygon(aResult.getB2DPolygon(a), rOutDev, aColor);
271 : : }
272 : : }
273 : : }
274 : : }
275 : : }
276 : : } // end of anonymous namespace
277 : : #endif // CLIPPER_TEST
278 : :
279 : : //////////////////////////////////////////////////////////////////////////////
280 : :
281 : 2222 : void SdrPageWindow::RedrawAll(sdr::contact::ViewObjectContactRedirector* pRedirector) const
282 : : {
283 : : // set Redirector
284 [ + - ][ + - ]: 2222 : GetObjectContact().SetViewObjectContactRedirector(pRedirector);
285 : :
286 : : // set PaintingPageView
287 : 2222 : const SdrView& rView = mrPageView.GetView();
288 : 2222 : SdrModel& rModel = *((SdrModel*)rView.GetModel());
289 : :
290 : : // get to be processed layers
291 : 2222 : const sal_Bool bPrinter(GetPaintWindow().OutputToPrinter());
292 [ - + ]: 2222 : SetOfByte aProcessLayers = bPrinter ? mrPageView.GetPrintableLayers() : mrPageView.GetVisibleLayers();
293 : :
294 : : // create PaintInfoRec; use Rectangle only temporarily
295 [ + - ]: 2222 : const Region& rRegion = GetPaintWindow().GetRedrawRegion();
296 : :
297 : : // create processing data
298 [ + - ]: 2222 : sdr::contact::DisplayInfo aDisplayInfo;
299 : :
300 : : // Draw all layers. do NOT draw form layer from CompleteRedraw, this is done separately
301 : : // as a single layer paint
302 : 2222 : const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin();
303 [ + - ]: 2222 : const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName(), sal_False);
304 : 2222 : aProcessLayers.Clear(nControlLayerId);
305 : :
306 : : // still something to paint?
307 [ + - ][ + - ]: 2222 : if(!aProcessLayers.IsEmpty())
308 : : {
309 [ + - ]: 2222 : aDisplayInfo.SetProcessLayers(aProcessLayers);
310 : :
311 : : // Set region as redraw area
312 [ + - ]: 2222 : aDisplayInfo.SetRedrawArea(rRegion);
313 : :
314 : : // Draw/Impress
315 [ + - ][ + - ]: 2222 : aDisplayInfo.SetPageProcessingActive(rView.IsPagePaintingAllowed()); // #i72889#
316 : :
317 : : // paint page
318 [ + - ][ + - ]: 2222 : GetObjectContact().ProcessDisplay(aDisplayInfo);
319 : : }
320 : :
321 : : // reset redirector
322 [ + - ][ + - ]: 2222 : GetObjectContact().SetViewObjectContactRedirector(0L);
[ + - ]
323 : :
324 : : // LineClip test
325 : : #ifdef CLIPPER_TEST
326 : : if(true)
327 : : {
328 : : impTryTest(GetPageView(), GetPaintWindow().GetOutputDevice());
329 : : }
330 : : #endif // CLIPPER_TEST
331 : 2222 : }
332 : :
333 : 43512 : void SdrPageWindow::RedrawLayer(const SdrLayerID* pId, sdr::contact::ViewObjectContactRedirector* pRedirector) const
334 : : {
335 : : // set redirector
336 [ + - ][ + - ]: 43512 : GetObjectContact().SetViewObjectContactRedirector(pRedirector);
337 : :
338 : : // set PaintingPageView
339 : 43512 : const SdrView& rView = mrPageView.GetView();
340 : 43512 : SdrModel& rModel = *((SdrModel*)rView.GetModel());
341 : :
342 : : // get the layers to process
343 : 43512 : const sal_Bool bPrinter(GetPaintWindow().OutputToPrinter());
344 [ - + ]: 43512 : SetOfByte aProcessLayers = bPrinter ? mrPageView.GetPrintableLayers() : mrPageView.GetVisibleLayers();
345 : :
346 : : // is the given layer visible at all?
347 [ + - ]: 43512 : if(aProcessLayers.IsSet(*pId))
348 : : {
349 : : // find out if we are painting the ControlLayer
350 : 43512 : const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin();
351 [ + - ]: 43512 : const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName(), sal_False);
352 [ + - ][ + + ]: 43512 : const sal_Bool bControlLayerProcessingActive(pId && nControlLayerId == *pId);
353 : :
354 : : // create PaintInfoRec, use Rectangle only temporarily
355 [ + - ]: 43512 : const Region& rRegion = GetPaintWindow().GetRedrawRegion();
356 : :
357 : : // create processing data
358 [ + - ]: 43512 : sdr::contact::DisplayInfo aDisplayInfo;
359 : :
360 : : // is it the control layer? If Yes, set flag
361 [ + - ]: 43512 : aDisplayInfo.SetControlLayerProcessingActive(bControlLayerProcessingActive);
362 : :
363 : : // Draw just the one given layer
364 : 43512 : aProcessLayers.ClearAll();
365 : 43512 : aProcessLayers.Set(*pId);
366 : :
367 [ + - ]: 43512 : aDisplayInfo.SetProcessLayers(aProcessLayers);
368 : :
369 : : // Set region as redraw area
370 [ + - ]: 43512 : aDisplayInfo.SetRedrawArea(rRegion);
371 : :
372 : : // Writer or calc, coming from original RedrawOneLayer.
373 : : // #i72889# no page painting for layer painting
374 [ + - ]: 43512 : aDisplayInfo.SetPageProcessingActive(false);
375 : :
376 : : // paint page
377 [ + - ][ + - ]: 43512 : GetObjectContact().ProcessDisplay(aDisplayInfo);
[ + - ]
378 : : }
379 : :
380 : : // reset redirector
381 [ + - ][ + - ]: 43512 : GetObjectContact().SetViewObjectContactRedirector(0L);
382 : 43512 : }
383 : :
384 : : // Invalidate call, used from ObjectContact(OfPageView) in InvalidatePartOfView(...)
385 : 20858 : void SdrPageWindow::InvalidatePageWindow(const basegfx::B2DRange& rRange)
386 : : {
387 [ + + ][ + - ]: 20858 : if(GetPageView().IsVisible() && GetPaintWindow().OutputToWindow())
[ + + ]
388 : : {
389 [ + - ]: 20710 : const SvtOptionsDrawinglayer aDrawinglayerOpt;
390 : 20710 : Window& rWindow(static_cast< Window& >(GetPaintWindow().GetOutputDevice()));
391 : 20710 : basegfx::B2DRange aDiscreteRange(rRange);
392 [ + - ][ + - ]: 20710 : aDiscreteRange.transform(rWindow.GetViewTransformation());
[ + - ]
393 : :
394 [ + - ][ - + ]: 20710 : if(aDrawinglayerOpt.IsAntiAliasing())
395 : : {
396 : : // invalidate one discrete unit more under the assumption that AA
397 : : // needs one pixel more
398 [ # # ]: 0 : aDiscreteRange.grow(1.0);
399 : : }
400 : :
401 : : const Rectangle aVCLDiscreteRectangle(
402 [ + - ][ + - ]: 20710 : (sal_Int32)floor(aDiscreteRange.getMinX()), (sal_Int32)floor(aDiscreteRange.getMinY()),
403 [ + - ][ + - ]: 41420 : (sal_Int32)ceil(aDiscreteRange.getMaxX()), (sal_Int32)ceil(aDiscreteRange.getMaxY()));
[ + - ]
404 : 20710 : const bool bWasMapModeEnabled(rWindow.IsMapModeEnabled());
405 : :
406 [ + - ]: 20710 : rWindow.EnableMapMode(false);
407 [ + - ]: 20710 : rWindow.Invalidate(aVCLDiscreteRectangle, INVALIDATE_NOERASE);
408 [ + - ][ + - ]: 20710 : rWindow.EnableMapMode(bWasMapModeEnabled);
409 : : }
410 : 20858 : }
411 : :
412 : : // ObjectContact section
413 : 164350 : sdr::contact::ObjectContact& SdrPageWindow::GetObjectContact() const
414 : : {
415 [ + + ]: 164350 : if(!mpObjectContact)
416 : : {
417 : 2381 : ((SdrPageWindow*)this)->mpObjectContact = ((SdrPageWindow*)this)->CreateViewSpecificObjectContact();
418 : : }
419 : :
420 : 164350 : return *mpObjectContact;
421 : : }
422 : :
423 : 32466 : bool SdrPageWindow::HasObjectContact() const
424 : : {
425 : 32466 : return ( mpObjectContact != NULL );
426 : : }
427 : :
428 : : // #i26631#
429 : 3113 : void SdrPageWindow::ResetObjectContact()
430 : : {
431 [ + + ]: 3113 : if(mpObjectContact)
432 : : {
433 [ + - ]: 2294 : delete mpObjectContact;
434 : 2294 : mpObjectContact = 0L;
435 : : }
436 : 3113 : }
437 : :
438 : 4 : void SdrPageWindow::SetDesignMode( bool _bDesignMode ) const
439 : : {
440 [ - + ]: 4 : const ::sdr::contact::ObjectContactOfPageView* pOC = dynamic_cast< const ::sdr::contact::ObjectContactOfPageView* >( &GetObjectContact() );
441 : : DBG_ASSERT( pOC, "SdrPageWindow::SetDesignMode: invalid object contact!" );
442 [ + - ]: 4 : if ( pOC )
443 : 4 : pOC->SetUNOControlsDesignMode( _bDesignMode );
444 : 4 : }
445 : :
446 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|