| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_svx.hxx" |
| #include <svx/sdrpagewindow.hxx> |
| #include <com/sun/star/awt/XWindow.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/awt/PosSize.hpp> |
| #include <com/sun/star/util/XModeChangeBroadcaster.hpp> |
| #include <comphelper/processfactory.hxx> |
| #include <vcl/svapp.hxx> |
| #include <toolkit/helper/vclunohelper.hxx> |
| #include <svx/svdouno.hxx> |
| #include <svx/svdpage.hxx> |
| #include <svx/svdview.hxx> |
| #include <svx/svdpagv.hxx> |
| #include <svx/sdrpaintwindow.hxx> |
| #include <svx/sdr/contact/objectcontactofpageview.hxx> |
| #include <svx/sdr/contact/displayinfo.hxx> |
| #include <vos/mutex.hxx> |
| #include <svx/fmview.hxx> |
| #include <basegfx/matrix/b2dhommatrix.hxx> |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| |
| 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 chan 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. |
| |
| // UnoContainerModel erzeugen |
| // uno::Reference< awt::XWindow > xC(mxControlContainer, uno::UNO_QUERY); |
| // CreateControlContainer() is only used from |
| // , thus it seems not necessary to make |
| // it visible her at all. |
| // #58917# Das Show darf nicht am VCL-Fenster landen, weil dann Assertion vom SFX |
| // sal_Bool bVis = pWindow->IsVisible(); |
| // xC->setVisible(sal_True); |
| // if ( !bVis ) |
| // pWindow->Hide(); |
| // if( !mxContext.is() && bVisible ) |
| // // Es ist ein TopWindow, also automatisch anzeigen |
| // createPeer( ::com::sun::star::uno::Reference< ::com::sun::star::awt::XToolkit > (), ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindowPeer > () ); |
| |
| 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 und VirtualDevice, bzw. kein OutDev |
| uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); |
| if( xFactory.is() ) |
| { |
| const_cast< SdrPageWindow* >( this )->mxControlContainer = uno::Reference< awt::XControlContainer >(xFactory->createInstance(rtl::OUString::createFromAscii("com.sun.star.awt.UnoControlContainer")), uno::UNO_QUERY); |
| uno::Reference< awt::XControlModel > xModel(xFactory->createInstance(rtl::OUString::createFromAscii("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() |
| { |
| // #110094#, #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(); |
| } |
| } |
| |
| // #110094# ObjectContact section |
| sdr::contact::ObjectContact* SdrPageWindow::CreateViewSpecificObjectContact() |
| { |
| return new sdr::contact::ObjectContactOfPageView(*this); |
| } |
| |
| // OVERLAYMANAGER |
| ::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::PostPaint() |
| { |
| } |
| |
| void SdrPageWindow::PrepareRedraw(const Region& rReg) |
| { |
| // evtl. give OC the chance to do ProcessDisplay preparations |
| if(HasObjectContact()) |
| { |
| GetObjectContact().PrepareProcessDisplay(); |
| } |
| |
| // remember eventually changed RedrawArea at PaintWindow for usage with |
| // overlay and PreRenderDevice stuff |
| GetPaintWindow().SetRedrawRegion(rReg); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // clip test |
| #ifdef CLIPPER_TEST |
| #include <svx/svdopath.hxx> |
| #include <basegfx/polygon/b2dpolygon.hxx> |
| #include <vcl/salbtype.hxx> // FRound |
| #include <basegfx/polygon/b2dpolygoncutandtouch.hxx> |
| #include <basegfx/polygon/b2dpolypolygontools.hxx> |
| #include <basegfx/polygon/b2dpolygontools.hxx> |
| #include <basegfx/polygon/b2dpolygonclipper.hxx> |
| |
| // for ::std::sort |
| #include <algorithm> |
| |
| 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); |
| } |
| |
| bool bBla = true; |
| } |
| } |
| } |
| } |
| } // 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 sal_Bool bPrinter(GetPaintWindow().OutputToPrinter()); |
| SetOfByte aProcessLayers = bPrinter ? mrPageView.GetPrintableLayers() : mrPageView.GetVisibleLayers(); |
| |
| // create PaintInfoRec, #114359# 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 separate |
| // 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 sal_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 sal_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); |
| } |
| } |
| |
| // #110094# 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 ); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////////////////////////// |
| // eof |