/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //////////////////////////////////////////////////////////////////////////////////////////////////// using namespace ::rtl; using namespace ::com::sun::star; //////////////////////////////////////////////////////////////////////////////////////////////////// ::com::sun::star::uno::Reference< ::com::sun::star::awt::XControlContainer > SdrPageWindow::GetControlContainer( bool _bCreateIfNecessary ) const { if ( !mxControlContainer.is() && _bCreateIfNecessary ) { SdrView& rView = GetPageView().GetView(); const SdrPaintWindow& rPaintWindow( GetOriginalPaintWindow() ? *GetOriginalPaintWindow() : GetPaintWindow() ); if ( rPaintWindow.OutputToWindow() && !rView.IsPrintPreview() ) { Window& rWindow = dynamic_cast< Window& >( rPaintWindow.GetOutputDevice() ); const_cast< SdrPageWindow* >( this )->mxControlContainer = VCLUnoHelper::CreateControlContainer( &rWindow ); // #100394# xC->setVisible triggers window->Show() and this has // problems when the view is not completely constructed which may // happen when loading. This leads to accessibility broadcasts which // throw asserts due to the not finished view. All this chain can be avoided // since xC->setVisible is here called only for the side effect in // UnoControlContainer::setVisible(...) which calls createPeer(...). // This will now be called directly from here. uno::Reference< awt::XControl > xControl(mxControlContainer, uno::UNO_QUERY); if(xControl.is()) { uno::Reference< uno::XInterface > xContext = xControl->getContext(); if(!xContext.is()) { xControl->createPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > (), ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > () ); } } } else { // Printer and VirtualDevice, or rather: no OutDev uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); const_cast< SdrPageWindow* >( this )->mxControlContainer = uno::Reference< awt::XControlContainer >(xFactory->createInstance("com.sun.star.awt.UnoControlContainer"), uno::UNO_QUERY); uno::Reference< awt::XControlModel > xModel(xFactory->createInstance("com.sun.star.awt.UnoControlContainerModel"), uno::UNO_QUERY); uno::Reference< awt::XControl > xControl(mxControlContainer, uno::UNO_QUERY); if (xControl.is()) xControl->setModel(xModel); OutputDevice& rOutDev = rPaintWindow.GetOutputDevice(); Point aPosPix = rOutDev.GetMapMode().GetOrigin(); Size aSizePix = rOutDev.GetOutputSizePixel(); uno::Reference< awt::XWindow > xContComp(mxControlContainer, uno::UNO_QUERY); if( xContComp.is() ) xContComp->setPosSize(aPosPix.X(), aPosPix.Y(), aSizePix.Width(), aSizePix.Height(), awt::PosSize::POSSIZE); } FmFormView* pViewAsFormView = dynamic_cast< FmFormView* >( &rView ); if ( pViewAsFormView ) pViewAsFormView->InsertControlContainer(mxControlContainer); } return mxControlContainer; } SdrPageWindow::SdrPageWindow(SdrPageView& rPageView, SdrPaintWindow& rPaintWindow) : mpObjectContact(0L), mrPageView(rPageView), mpPaintWindow(&rPaintWindow), mpOriginalPaintWindow(NULL) { } SdrPageWindow::~SdrPageWindow() { // #i26631# ResetObjectContact(); if (mxControlContainer.is()) { SdrView& rView = GetPageView().GetView(); // notify derived views FmFormView* pViewAsFormView = dynamic_cast< FmFormView* >( &rView ); if ( pViewAsFormView ) pViewAsFormView->RemoveControlContainer(mxControlContainer); // dispose the control container uno::Reference< lang::XComponent > xComponent(mxControlContainer, uno::UNO_QUERY); xComponent->dispose(); } } // ObjectContact section sdr::contact::ObjectContact* SdrPageWindow::CreateViewSpecificObjectContact() { return new sdr::contact::ObjectContactOfPageView(*this); } // OVERLAY MANAGER rtl::Reference< ::sdr::overlay::OverlayManager > SdrPageWindow::GetOverlayManager() const { return GetPaintWindow().GetOverlayManager(); } void SdrPageWindow::patchPaintWindow(SdrPaintWindow& rPaintWindow) { mpOriginalPaintWindow = mpPaintWindow; mpPaintWindow = &rPaintWindow; } void SdrPageWindow::unpatchPaintWindow() { DBG_ASSERT(mpOriginalPaintWindow, "SdrPageWindow::unpatchPaintWindow: paint window not patched!" ); if ( mpOriginalPaintWindow ) { mpPaintWindow = mpOriginalPaintWindow; mpOriginalPaintWindow = NULL; } } void SdrPageWindow::PrePaint() { // give OC the chance to do ProcessDisplay preparations if(HasObjectContact()) { GetObjectContact().PrepareProcessDisplay(); } } void SdrPageWindow::PrepareRedraw(const Region& rReg) { // give OC the chance to do ProcessDisplay preparations if(HasObjectContact()) { GetObjectContact().PrepareProcessDisplay(); } // if necessary, remember changed RedrawArea at PaintWindow for usage with // overlay and PreRenderDevice stuff GetPaintWindow().SetRedrawRegion(rReg); } ////////////////////////////////////////////////////////////////////////////// // clip test #ifdef CLIPPER_TEST #include #include #include #include #include #include #include // for ::std::sort #include namespace { void impPaintStrokePolygon(const basegfx::B2DPolygon& rCandidate, OutputDevice& rOutDev, Color aColor) { basegfx::B2DPolygon aCandidate(rCandidate); if(aCandidate.areControlPointsUsed()) { aCandidate = basegfx::tools::adaptiveSubdivideByAngle(rCandidate); } if(aCandidate.count()) { const sal_uInt32 nLoopCount(aCandidate.isClosed() ? aCandidate.count() : aCandidate.count() - 1L); rOutDev.SetFillColor(); rOutDev.SetLineColor(aColor); for(sal_uInt32 a(0L); a < nLoopCount; a++) { const basegfx::B2DPoint aBStart(aCandidate.getB2DPoint(a)); const basegfx::B2DPoint aBEnd(aCandidate.getB2DPoint((a + 1) % aCandidate.count())); const Point aStart(FRound(aBStart.getX()), FRound(aBStart.getY())); const Point aEnd(FRound(aBEnd.getX()), FRound(aBEnd.getY())); rOutDev.DrawLine(aStart, aEnd); } } } void impTryTest(const SdrPageView& rPageView, OutputDevice& rOutDev) { if(rPageView.GetPage() && rPageView.GetPage()->GetObjCount() >= 2L) { SdrPage* pPage = rPageView.GetPage(); SdrObject* pObjA = pPage->GetObj(0L); if(pObjA && pObjA->ISA(SdrPathObj)) { basegfx::B2DPolyPolygon aPolyA(((SdrPathObj*)pObjA)->GetPathPoly()); aPolyA = basegfx::tools::correctOrientations(aPolyA); basegfx::B2DPolyPolygon aPolyB; for(sal_uInt32 a(1L); a < rPageView.GetPage()->GetObjCount(); a++) { SdrObject* pObjB = pPage->GetObj(a); if(pObjB && pObjB->ISA(SdrPathObj)) { basegfx::B2DPolyPolygon aCandidate(((SdrPathObj*)pObjB)->GetPathPoly()); aCandidate = basegfx::tools::correctOrientations(aCandidate); aPolyB.append(aCandidate); } } if(aPolyA.count() && aPolyA.isClosed() && aPolyB.count()) { // poly A is the clipregion, clip poly b against it. Algo depends on // poly b being closed. basegfx::B2DPolyPolygon aResult(basegfx::tools::clipPolyPolygonOnPolyPolygon(aPolyB, aPolyA)); for(sal_uInt32 a(0L); a < aResult.count(); a++) { Color aColor(rand()%255, rand()%255, rand()%255); impPaintStrokePolygon(aResult.getB2DPolygon(a), rOutDev, aColor); } } } } } } // end of anonymous namespace #endif // CLIPPER_TEST ////////////////////////////////////////////////////////////////////////////// void SdrPageWindow::RedrawAll(sdr::contact::ViewObjectContactRedirector* pRedirector) const { // set Redirector GetObjectContact().SetViewObjectContactRedirector(pRedirector); // set PaintingPageView const SdrView& rView = mrPageView.GetView(); SdrModel& rModel = *((SdrModel*)rView.GetModel()); // get to be processed layers const bool bPrinter(GetPaintWindow().OutputToPrinter()); SetOfByte aProcessLayers = bPrinter ? mrPageView.GetPrintableLayers() : mrPageView.GetVisibleLayers(); // create PaintInfoRec; use Rectangle only temporarily const Region& rRegion = GetPaintWindow().GetRedrawRegion(); // create processing data sdr::contact::DisplayInfo aDisplayInfo; // Draw all layers. do NOT draw form layer from CompleteRedraw, this is done separately // as a single layer paint const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin(); const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName(), sal_False); aProcessLayers.Clear(nControlLayerId); // still something to paint? if(!aProcessLayers.IsEmpty()) { aDisplayInfo.SetProcessLayers(aProcessLayers); // Set region as redraw area aDisplayInfo.SetRedrawArea(rRegion); // Draw/Impress aDisplayInfo.SetPageProcessingActive(rView.IsPagePaintingAllowed()); // #i72889# // paint page GetObjectContact().ProcessDisplay(aDisplayInfo); } // reset redirector GetObjectContact().SetViewObjectContactRedirector(0L); // LineClip test #ifdef CLIPPER_TEST if(true) { impTryTest(GetPageView(), GetPaintWindow().GetOutputDevice()); } #endif // CLIPPER_TEST } void SdrPageWindow::RedrawLayer(const SdrLayerID* pId, sdr::contact::ViewObjectContactRedirector* pRedirector) const { // set redirector GetObjectContact().SetViewObjectContactRedirector(pRedirector); // set PaintingPageView const SdrView& rView = mrPageView.GetView(); SdrModel& rModel = *((SdrModel*)rView.GetModel()); // get the layers to process const bool bPrinter(GetPaintWindow().OutputToPrinter()); SetOfByte aProcessLayers = bPrinter ? mrPageView.GetPrintableLayers() : mrPageView.GetVisibleLayers(); // is the given layer visible at all? if(aProcessLayers.IsSet(*pId)) { // find out if we are painting the ControlLayer const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin(); const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName(), sal_False); const bool bControlLayerProcessingActive(pId && nControlLayerId == *pId); // create PaintInfoRec, use Rectangle only temporarily const Region& rRegion = GetPaintWindow().GetRedrawRegion(); // create processing data sdr::contact::DisplayInfo aDisplayInfo; // is it the control layer? If Yes, set flag aDisplayInfo.SetControlLayerProcessingActive(bControlLayerProcessingActive); // Draw just the one given layer aProcessLayers.ClearAll(); aProcessLayers.Set(*pId); aDisplayInfo.SetProcessLayers(aProcessLayers); // Set region as redraw area aDisplayInfo.SetRedrawArea(rRegion); // Writer or calc, coming from original RedrawOneLayer. // #i72889# no page painting for layer painting aDisplayInfo.SetPageProcessingActive(false); // paint page GetObjectContact().ProcessDisplay(aDisplayInfo); } // reset redirector GetObjectContact().SetViewObjectContactRedirector(0L); } // Invalidate call, used from ObjectContact(OfPageView) in InvalidatePartOfView(...) void SdrPageWindow::InvalidatePageWindow(const basegfx::B2DRange& rRange) { if(GetPageView().IsVisible() && GetPaintWindow().OutputToWindow()) { const SvtOptionsDrawinglayer aDrawinglayerOpt; Window& rWindow(static_cast< Window& >(GetPaintWindow().GetOutputDevice())); basegfx::B2DRange aDiscreteRange(rRange); aDiscreteRange.transform(rWindow.GetViewTransformation()); if(aDrawinglayerOpt.IsAntiAliasing()) { // invalidate one discrete unit more under the assumption that AA // needs one pixel more aDiscreteRange.grow(1.0); } const Rectangle aVCLDiscreteRectangle( (sal_Int32)floor(aDiscreteRange.getMinX()), (sal_Int32)floor(aDiscreteRange.getMinY()), (sal_Int32)ceil(aDiscreteRange.getMaxX()), (sal_Int32)ceil(aDiscreteRange.getMaxY())); const bool bWasMapModeEnabled(rWindow.IsMapModeEnabled()); rWindow.EnableMapMode(false); rWindow.Invalidate(aVCLDiscreteRectangle, INVALIDATE_NOERASE); rWindow.EnableMapMode(bWasMapModeEnabled); } } // ObjectContact section sdr::contact::ObjectContact& SdrPageWindow::GetObjectContact() const { if(!mpObjectContact) { ((SdrPageWindow*)this)->mpObjectContact = ((SdrPageWindow*)this)->CreateViewSpecificObjectContact(); } return *mpObjectContact; } bool SdrPageWindow::HasObjectContact() const { return ( mpObjectContact != NULL ); } // #i26631# void SdrPageWindow::ResetObjectContact() { if(mpObjectContact) { delete mpObjectContact; mpObjectContact = 0L; } } void SdrPageWindow::SetDesignMode( bool _bDesignMode ) const { const ::sdr::contact::ObjectContactOfPageView* pOC = dynamic_cast< const ::sdr::contact::ObjectContactOfPageView* >( &GetObjectContact() ); DBG_ASSERT( pOC, "SdrPageWindow::SetDesignMode: invalid object contact!" ); if ( pOC ) pOC->SetUNOControlsDesignMode( _bDesignMode ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */