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