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 52 ::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 126 SdrPageWindow::SdrPageWindow(SdrPageView& rPageView, SdrPaintWindow& rPaintWindow) 127 : mpObjectContact(0L), 128 mrPageView(rPageView), 129 mpPaintWindow(&rPaintWindow), 130 mpOriginalPaintWindow(NULL) 131 { 132 } 133 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 155 sdr::contact::ObjectContact* SdrPageWindow::CreateViewSpecificObjectContact() 156 { 157 return new sdr::contact::ObjectContactOfPageView(*this); 158 } 159 160 // OVERLAYMANAGER 161 ::sdr::overlay::OverlayManager* SdrPageWindow::GetOverlayManager() const 162 { 163 return GetPaintWindow().GetOverlayManager(); 164 } 165 166 void SdrPageWindow::patchPaintWindow(SdrPaintWindow& rPaintWindow) 167 { 168 mpOriginalPaintWindow = mpPaintWindow; 169 mpPaintWindow = &rPaintWindow; 170 } 171 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 182 void SdrPageWindow::PrePaint() 183 { 184 // give OC the chance to do ProcessDisplay preparations 185 if(HasObjectContact()) 186 { 187 GetObjectContact().PrepareProcessDisplay(); 188 } 189 } 190 191 void SdrPageWindow::PostPaint() 192 { 193 } 194 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 { 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 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 298 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 350 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(...) 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 430 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 440 bool SdrPageWindow::HasObjectContact() const 441 { 442 return ( mpObjectContact != NULL ); 443 } 444 445 // #i26631# 446 void SdrPageWindow::ResetObjectContact() 447 { 448 if(mpObjectContact) 449 { 450 delete mpObjectContact; 451 mpObjectContact = 0L; 452 } 453 } 454 455 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