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