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