/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; // interface to SdrPaintWindow SdrPaintWindow* SdrPaintView::FindPaintWindow(const OutputDevice& rOut) const { for(SdrPaintWindowVector::const_iterator a = maPaintWindows.begin(); a != maPaintWindows.end(); ++a) { if(&((*a)->GetOutputDevice()) == &rOut) { return *a; } } return nullptr; } SdrPaintWindow* SdrPaintView::GetPaintWindow(sal_uInt32 nIndex) const { if(nIndex < maPaintWindows.size()) { return maPaintWindows[nIndex]; } return nullptr; } void SdrPaintView::RemovePaintWindow(SdrPaintWindow& rOld) { const SdrPaintWindowVector::iterator aFindResult = ::std::find(maPaintWindows.begin(), maPaintWindows.end(), &rOld); if(aFindResult != maPaintWindows.end()) { maPaintWindows.erase(aFindResult); } } OutputDevice* SdrPaintView::GetFirstOutputDevice() const { if(PaintWindowCount()) { return &(GetPaintWindow(0)->GetOutputDevice()); } return nullptr; } SvxViewChangedHint::SvxViewChangedHint() { } BitmapEx convertMetafileToBitmapEx( const GDIMetaFile& rMtf, const basegfx::B2DRange& rTargetRange, const sal_uInt32 nMaximumQuadraticPixels) { BitmapEx aBitmapEx; if(rMtf.GetActionSize()) { const drawinglayer::primitive2d::Primitive2DReference aMtf( new drawinglayer::primitive2d::MetafilePrimitive2D( basegfx::utils::createScaleTranslateB2DHomMatrix( rTargetRange.getRange(), rTargetRange.getMinimum()), rMtf)); aBitmapEx = convertPrimitive2DSequenceToBitmapEx( drawinglayer::primitive2d::Primitive2DContainer { aMtf }, rTargetRange, nMaximumQuadraticPixels); } return aBitmapEx; } void SdrPaintView::ImpClearVars() { #ifdef DBG_UTIL mpItemBrowser=nullptr; #endif mbPageVisible=true; mbPageShadowVisible=true; mbPageBorderVisible=true; mbBordVisible=true; mbGridVisible=true; mbGridFront =false; mbHlplVisible=true; mbHlplFront =true; mbGlueVisible=false; mbGlueVisible2=false; mbGlueVisible3=false; mbGlueVisible4=false; mbSwapAsynchron=false; mbPrintPreview=false; mbPreviewRenderer=false; meAnimationMode = SdrAnimationMode::Animate; mbAnimationPause = false; mnHitTolPix=2; mnMinMovPix=3; mnHitTolLog=0; mnMinMovLog=0; mpActualOutDev=nullptr; mpDragWin=nullptr; mpDefaultStyleSheet=nullptr; mbSomeObjChgdFlag=false; maComeBackIdle.SetPriority(TaskPriority::REPAINT); maComeBackIdle.SetInvokeHandler(LINK(this,SdrPaintView,ImpComeBackHdl)); maComeBackIdle.SetDebugName( "svx::SdrPaintView aComeBackIdle" ); if (mpModel) SetDefaultStyleSheet(mpModel->GetDefaultStyleSheet(), true); maGridColor = COL_BLACK; } SdrPaintView::SdrPaintView( SdrModel& rSdrModel, OutputDevice* pOut) : mrSdrModelFromSdrView(rSdrModel), mpPageView(nullptr), maDefaultAttr(rSdrModel.GetItemPool()), mbBufferedOutputAllowed(false), mbBufferedOverlayAllowed(false), mbPagePaintingAllowed(true), mbHideOle(false), mbHideChart(false), mbHideDraw(false), mbHideFormControl(false) { mpModel=&rSdrModel; ImpClearVars(); if(pOut) { AddWindowToPaintView(pOut, nullptr); } maColorConfig.AddListener(this); onChangeColorConfig(); } SdrPaintView::~SdrPaintView() { if (mpDefaultStyleSheet) EndListening(*mpDefaultStyleSheet); maColorConfig.RemoveListener(this); ClearPageView(); #ifdef DBG_UTIL mpItemBrowser.disposeAndClear(); #endif // delete existing SdrPaintWindows while(!maPaintWindows.empty()) { delete maPaintWindows.back(); maPaintWindows.pop_back(); } } void SdrPaintView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint) { //If the stylesheet has been destroyed if (&rBC == mpDefaultStyleSheet) { if (rHint.GetId() == SfxHintId::Dying) mpDefaultStyleSheet = nullptr; return; } const SdrHint* pSdrHint = dynamic_cast(&rHint); if (!pSdrHint) return; SdrHintKind eKind = pSdrHint->GetKind(); if (eKind==SdrHintKind::ObjectChange || eKind==SdrHintKind::ObjectInserted || eKind==SdrHintKind::ObjectRemoved) { bool bObjChg = !mbSomeObjChgdFlag; // if true, evaluate for ComeBack timer if (bObjChg) { mbSomeObjChgdFlag=true; maComeBackIdle.Start(); } } if (eKind==SdrHintKind::PageOrderChange) { const SdrPage* pPg=pSdrHint->GetPage(); if (pPg && !pPg->IsInserted()) { if(mpPageView && mpPageView->GetPage() == pPg) { HideSdrPage(); } } } } void SdrPaintView::ConfigurationChanged( ::utl::ConfigurationBroadcaster* , ConfigurationHints ) { onChangeColorConfig(); InvalidateAllWin(); } IMPL_LINK_NOARG(SdrPaintView, ImpComeBackHdl, Timer *, void) { if (mbSomeObjChgdFlag) { mbSomeObjChgdFlag=false; ModelHasChanged(); } } void SdrPaintView::FlushComeBackTimer() const { if (mbSomeObjChgdFlag) { // casting to nonconst const_cast(this)->ImpComeBackHdl(&const_cast(this)->maComeBackIdle); const_cast(this)->maComeBackIdle.Stop(); } } void SdrPaintView::ModelHasChanged() { // broadcast to all PageViews if(mpPageView && !mpPageView->GetPage()->IsInserted()) { HideSdrPage(); } // test mpPageView here again, HideSdrPage() may have invalidated it. if(mpPageView) { mpPageView->ModelHasChanged(); } #ifdef DBG_UTIL if(mpItemBrowser) { mpItemBrowser->SetDirty(); } #endif } bool SdrPaintView::IsAction() const { return false; } void SdrPaintView::MovAction(const Point&) { } void SdrPaintView::EndAction() { } void SdrPaintView::BckAction() { } void SdrPaintView::BrkAction() { } void SdrPaintView::TakeActionRect(tools::Rectangle&) const { } // info about TextEdit. Default is false. bool SdrPaintView::IsTextEdit() const { return false; } sal_uInt16 SdrPaintView::ImpGetMinMovLogic(short nMinMov, const OutputDevice* pOut) const { if (nMinMov>=0) return sal_uInt16(nMinMov); if (pOut==nullptr) { pOut = GetFirstOutputDevice(); } if (pOut!=nullptr) { return short(-pOut->PixelToLogic(Size(nMinMov,0)).Width()); } else { return 0; } } sal_uInt16 SdrPaintView::ImpGetHitTolLogic(short nHitTol, const OutputDevice* pOut) const { if (nHitTol>=0) return sal_uInt16(nHitTol); if (pOut==nullptr) { pOut = GetFirstOutputDevice(); } if (pOut!=nullptr) { return short(-pOut->PixelToLogic(Size(nHitTol,0)).Width()); } else { return 0; } } void SdrPaintView::TheresNewMapMode() { if (mpActualOutDev) { mnHitTolLog=static_cast(mpActualOutDev->PixelToLogic(Size(mnHitTolPix,0)).Width()); mnMinMovLog=static_cast(mpActualOutDev->PixelToLogic(Size(mnMinMovPix,0)).Width()); } } void SdrPaintView::SetActualWin(const OutputDevice* pWin) { mpActualOutDev = const_cast(pWin); TheresNewMapMode(); } void SdrPaintView::ClearPageView() { BrkAction(); if(mpPageView) { InvalidateAllWin(); delete mpPageView; mpPageView = nullptr; } } SdrPageView* SdrPaintView::ShowSdrPage(SdrPage* pPage) { if(pPage && (!mpPageView || mpPageView->GetPage() != pPage)) { if(mpPageView) { InvalidateAllWin(); delete mpPageView; } mpPageView = new SdrPageView(pPage, *static_cast(this)); mpPageView->Show(); } return mpPageView; } void SdrPaintView::HideSdrPage() { if(mpPageView) { mpPageView->Hide(); delete mpPageView; mpPageView = nullptr; } } void SdrPaintView::AddWindowToPaintView(OutputDevice* pNewWin, vcl::Window *pWindow) { DBG_ASSERT(pNewWin, "SdrPaintView::AddWindowToPaintView: No OutputDevice(!)"); SdrPaintWindow* pNewPaintWindow = new SdrPaintWindow(*this, *pNewWin, pWindow); maPaintWindows.push_back(pNewPaintWindow); if(mpPageView) { mpPageView->AddPaintWindowToPageView(*pNewPaintWindow); } #ifdef DBG_UTIL if (mpItemBrowser!=nullptr) mpItemBrowser->ForceParent(); #endif } void SdrPaintView::DeleteWindowFromPaintView(OutputDevice* pOldWin) { assert(pOldWin && "SdrPaintView::DeleteWindowFromPaintView: No OutputDevice(!)"); SdrPaintWindow* pCandidate = FindPaintWindow(*pOldWin); if(pCandidate) { if(mpPageView) { mpPageView->RemovePaintWindowFromPageView(*pCandidate); } RemovePaintWindow(*pCandidate); delete pCandidate; } #ifdef DBG_UTIL if (mpItemBrowser!=nullptr) mpItemBrowser->ForceParent(); #endif } void SdrPaintView::SetLayerVisible(const OUString& rName, bool bShow) { if(mpPageView) { mpPageView->SetLayerVisible(rName, bShow); } InvalidateAllWin(); } bool SdrPaintView::IsLayerVisible(const OUString& rName) const { if(mpPageView) { return mpPageView->IsLayerVisible(rName); } return false; } void SdrPaintView::SetLayerLocked(const OUString& rName, bool bLock) { if(mpPageView) { mpPageView->SetLayerLocked(rName,bLock); } } bool SdrPaintView::IsLayerLocked(const OUString& rName) const { if(mpPageView) { return mpPageView->IsLayerLocked(rName); } return false; } void SdrPaintView::SetLayerPrintable(const OUString& rName, bool bPrn) { if(mpPageView) { mpPageView->SetLayerPrintable(rName,bPrn); } } bool SdrPaintView::IsLayerPrintable(const OUString& rName) const { if(mpPageView) { return mpPageView->IsLayerPrintable(rName); } return false; } void SdrPaintView::PrePaint() { if(mpPageView) { mpPageView->PrePaint(); } } // #define SVX_REPAINT_TIMER_TEST void SdrPaintView::CompleteRedraw(OutputDevice* pOut, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector) { #ifdef SVX_REPAINT_TIMER_TEST #define REMEMBERED_TIMES_COUNT (10) static bool bDoTimerTest(false); static bool bTimesInited(false); static sal_uInt32 nRepeatCount(10); static double fLastTimes[REMEMBERED_TIMES_COUNT]; const sal_uInt64 nStartTime(tools::Time::GetSystemTicks()); sal_uInt32 count(1); sal_uInt32 a; if(bDoTimerTest) { count = nRepeatCount; } for(a = 0; a < count; a++) { #endif // SVX_REPAINT_TIMER_TEST // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region // rReg may be made more granular (fine) with using it. Normally, rReg // does come from Window::Paint() anyways and thus is based on a single // rectangle which was derived from exactly that repaint region vcl::Region aOptimizedRepaintRegion(rReg); if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType()) { vcl::Window* pWindow = static_cast(pOut); if(pWindow->IsInPaint()) { if(!pWindow->GetPaintRegion().IsEmpty()) { aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion()); #ifdef DBG_UTIL // #i74769# test-paint repaint region static bool bDoPaintForVisualControl(false); if(bDoPaintForVisualControl) { RectangleVector aRectangles; aOptimizedRepaintRegion.GetRegionRectangles(aRectangles); pWindow->SetLineColor(COL_LIGHTGREEN); pWindow->SetFillColor(); for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); ++aRectIter) { pWindow->DrawRect(*aRectIter); } //RegionHandle aRegionHandle(aOptimizedRepaintRegion.BeginEnumRects()); //Rectangle aRegionRectangle; //while(aOptimizedRepaintRegion.GetEnumRects(aRegionHandle, aRegionRectangle)) //{ // pWindow->SetLineCOL_LIGHTGREEN); // pWindow->SetFillColor(); // pWindow->DrawRect(aRegionRectangle); //} //aOptimizedRepaintRegion.EndEnumRects(aRegionHandle); } #endif } } } SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut); OSL_ENSURE(pPaintWindow, "SdrPaintView::CompleteRedraw: No OutDev (!)"); DoCompleteRedraw(*pPaintWindow, aOptimizedRepaintRegion, pRedirector); EndCompleteRedraw(*pPaintWindow, true); #ifdef SVX_REPAINT_TIMER_TEST } if(bDoTimerTest) { const sal_uInt64 nStopTime(tools::Time::GetSystemTicks()); const sal_uInt64 nNeededTime(nStopTime - nStartTime); const double fTimePerPaint((double)nNeededTime / (double)nRepeatCount); if(!bTimesInited) { for(a = 0; a < REMEMBERED_TIMES_COUNT; a++) { fLastTimes[a] = fTimePerPaint; } bTimesInited = true; } else { for(a = 1; a < REMEMBERED_TIMES_COUNT; a++) { fLastTimes[a - 1] = fLastTimes[a]; } fLastTimes[REMEMBERED_TIMES_COUNT - 1] = fTimePerPaint; } double fAddedTimes(0.0); for(a = 0; a < REMEMBERED_TIMES_COUNT; a++) { fAddedTimes += fLastTimes[a]; } const double fAverageTimePerPaint(fAddedTimes / (double)REMEMBERED_TIMES_COUNT); fprintf(stderr, "-----------(start result)----------\n"); fprintf(stderr, "StartTime : %" SAL_PRIuUINT64 ", StopTime: %" SAL_PRIuUINT64 ", NeededTime: %" SAL_PRIuUINT64 ", TimePerPaint: %f\n", nStartTime, nStopTime, nNeededTime, fTimePerPaint); fprintf(stderr, "Remembered times: "); for(a = 0; a < REMEMBERED_TIMES_COUNT; a++) { fprintf(stderr, "%d: %f ", a, fLastTimes[a]); } fprintf(stderr, "\n"); fprintf(stderr, "AverageTimePerPaint: %f\n", fAverageTimePerPaint); fprintf(stderr, "-----------(stop result)----------\n"); } #endif // SVX_REPAINT_TIMER_TEST } // #i72889# SdrPaintWindow* SdrPaintView::BeginCompleteRedraw(OutputDevice* pOut) { OSL_ENSURE(pOut, "SdrPaintView::BeginCompleteRedraw: No OutDev (!)"); SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut); if(pPaintWindow) { // draw preprocessing, only for known devices // prepare PreRendering pPaintWindow->PreparePreRenderDevice(); } else { // None of the known OutputDevices is the target of this paint, use // a temporary SdrPaintWindow for this Redraw. pPaintWindow = new SdrPaintWindow(*this, *pOut); pPaintWindow->setTemporaryTarget(true); } return pPaintWindow; } void SdrPaintView::DoCompleteRedraw(SdrPaintWindow& rPaintWindow, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector) { // redraw all PageViews with the target. This may expand the RedrawRegion // at the PaintWindow, plus taking care of FormLayer expansion if(mpPageView) { mpPageView->CompleteRedraw(rPaintWindow, rReg, pRedirector); } } void SdrPaintView::EndCompleteRedraw(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer) { std::unique_ptr pPaintWindow; if (comphelper::LibreOfficeKit::isActive() && rPaintWindow.getTemporaryTarget()) { // Tiled rendering, we must paint the TextEdit to the output device. pPaintWindow.reset(&rPaintWindow); pPaintWindow->setTemporaryTarget(false); } if(rPaintWindow.getTemporaryTarget()) { // get rid of temp target again delete &rPaintWindow; } else { // draw postprocessing, only for known devices // it is necessary to always paint FormLayer if(bPaintFormLayer) { ImpFormLayerDrawing(rPaintWindow); } // look for active TextEdit. As long as this cannot be painted to a VDev, // it cannot get part of buffering. In that case, output evtl. prerender // early and paint text edit to window. if(IsTextEdit() && GetSdrPageView()) { static_cast< SdrView* >(this)->TextEditDrawing(rPaintWindow); } if (comphelper::LibreOfficeKit::isActive()) { // Look for active text edits in other views showing the same page, // and show them as well. if (SdrPageView* pPageView = GetSdrPageView()) { SdrViewIter aIter(pPageView->GetPage()); for (SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView()) { if (pView == this) continue; if (pView->IsTextEdit() && pView->GetSdrPageView()) { pView->TextEditDrawing(rPaintWindow); } } } } // draw Overlay, also to PreRender device if exists rPaintWindow.DrawOverlay(rPaintWindow.GetRedrawRegion()); // output PreRendering rPaintWindow.OutputPreRenderDevice(rPaintWindow.GetRedrawRegion()); } } SdrPaintWindow* SdrPaintView::BeginDrawLayers(OutputDevice* pOut, const vcl::Region& rReg, bool bDisableIntersect) { // #i74769# use BeginCompleteRedraw() as common base SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut); OSL_ENSURE(pPaintWindow, "SdrPaintView::BeginDrawLayers: No SdrPaintWindow (!)"); if(mpPageView) { SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow); if(pKnownTarget) { vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, bDisableIntersect ); // prepare redraw pKnownTarget->PrepareRedraw(aOptimizedRepaintRegion); // remember prepared SdrPageWindow mpPageView->setPreparedPageWindow(pKnownTarget); } } return pPaintWindow; } void SdrPaintView::EndDrawLayers(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer) { // #i74769# use EndCompleteRedraw() as common base EndCompleteRedraw(rPaintWindow, bPaintFormLayer); if(mpPageView) { // forget prepared SdrPageWindow mpPageView->setPreparedPageWindow(nullptr); } } void SdrPaintView::UpdateDrawLayersRegion(OutputDevice* pOut, const vcl::Region& rReg) { SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut); OSL_ENSURE(pPaintWindow, "SdrPaintView::UpdateDrawLayersRegion: No SdrPaintWindow (!)"); if(mpPageView) { SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow); if(pKnownTarget) { vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, false/*bDisableIntersect*/ ); pKnownTarget->GetPaintWindow().SetRedrawRegion(aOptimizedRepaintRegion); mpPageView->setPreparedPageWindow(pKnownTarget); // already set actually } } } vcl::Region SdrPaintView::OptimizeDrawLayersRegion(OutputDevice* pOut, const vcl::Region& rReg, bool bDisableIntersect) { // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region // rReg may be made more granular (fine) with using it. Normally, rReg // does come from Window::Paint() anyways and thus is based on a single // rectangle which was derived from exactly that repaint region vcl::Region aOptimizedRepaintRegion(rReg); // #i76114# Intersecting the region with the Window's paint region is disabled // for print preview in Calc, because the intersection can be empty (if the paint // region is outside of the table area of the page), and then no clip region // would be set. if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType() && !bDisableIntersect) { vcl::Window* pWindow = static_cast(pOut); if(pWindow->IsInPaint()) { if(!pWindow->GetPaintRegion().IsEmpty()) { aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion()); } } } return aOptimizedRepaintRegion; } void SdrPaintView::ImpFormLayerDrawing( SdrPaintWindow& rPaintWindow ) { if(mpPageView) { SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(rPaintWindow); if(pKnownTarget) { const SdrModel& rModel = *(GetModel()); const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin(); const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName()); // BUFFERED use GetTargetOutputDevice() now, it may be targeted to VDevs, too // need to set PreparedPageWindow to make DrawLayer use the correct ObjectContact mpPageView->setPreparedPageWindow(pKnownTarget); mpPageView->DrawLayer(nControlLayerId, &rPaintWindow.GetTargetOutputDevice()); mpPageView->setPreparedPageWindow(nullptr); } } } bool SdrPaintView::KeyInput(const KeyEvent& /*rKEvt*/, vcl::Window* /*pWin*/) { return false; } void SdrPaintView::GlueInvalidate() const { const sal_uInt32 nWindowCount(PaintWindowCount()); for(sal_uInt32 nWinNum(0); nWinNum < nWindowCount; nWinNum++) { SdrPaintWindow* pPaintWindow = GetPaintWindow(nWinNum); if(pPaintWindow->OutputToWindow()) { OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); if(mpPageView) { const SdrObjList* pOL=mpPageView->GetObjList(); const size_t nObjCount = pOL->GetObjCount(); for (size_t nObjNum=0; nObjNumGetObj(nObjNum); const SdrGluePointList* pGPL=pObj->GetGluePointList(); if (pGPL!=nullptr && pGPL->GetCount()!=0) { pGPL->Invalidate(static_cast(rOutDev), pObj); } } } } } } void SdrPaintView::InvalidateAllWin() { const sal_uInt32 nWindowCount(PaintWindowCount()); for(sal_uInt32 a(0); a < nWindowCount; a++) { SdrPaintWindow* pPaintWindow = GetPaintWindow(a); if(pPaintWindow->OutputToWindow()) { InvalidateOneWin(static_cast(pPaintWindow->GetOutputDevice())); } } } void SdrPaintView::InvalidateAllWin(const tools::Rectangle& rRect) { const sal_uInt32 nWindowCount(PaintWindowCount()); for(sal_uInt32 a(0); a < nWindowCount; a++) { SdrPaintWindow* pPaintWindow = GetPaintWindow(a); if(pPaintWindow->OutputToWindow()) { OutputDevice& rOutDev = pPaintWindow->GetOutputDevice(); tools::Rectangle aRect(rRect); Point aOrg(rOutDev.GetMapMode().GetOrigin()); aOrg.setX(-aOrg.X() ); aOrg.setY(-aOrg.Y() ); tools::Rectangle aOutRect(aOrg, rOutDev.GetOutputSize()); // In case of tiled rendering we want to get all invalidations, so visual area is not interesting. if (aRect.IsOver(aOutRect) || comphelper::LibreOfficeKit::isActive()) { InvalidateOneWin(static_cast(rOutDev), aRect); } } } } void SdrPaintView::InvalidateOneWin(vcl::Window& rWin) { // do not erase background, that causes flicker (!) rWin.Invalidate(InvalidateFlags::NoErase); } void SdrPaintView::InvalidateOneWin(vcl::Window& rWin, const tools::Rectangle& rRect) { // do not erase background, that causes flicker (!) rWin.Invalidate(rRect, InvalidateFlags::NoErase); } void SdrPaintView::LeaveOneGroup() { if(mpPageView) { mpPageView->LeaveOneGroup(); } } void SdrPaintView::LeaveAllGroup() { if(mpPageView) { mpPageView->LeaveAllGroup(); } } bool SdrPaintView::IsGroupEntered() const { if(mpPageView) { return (mpPageView->GetEnteredLevel() != 0); } return false; } void SdrPaintView::SetNotPersistDefaultAttr(const SfxItemSet& rAttr) { // bReplaceAll has no effect here at all. bool bMeasure= dynamic_cast(this) != nullptr && static_cast(this)->IsMeasureTool(); const SfxPoolItem *pPoolItem=nullptr; if (rAttr.GetItemState(SDRATTR_LAYERID,true,&pPoolItem)==SfxItemState::SET) { SdrLayerID nLayerId=static_cast(pPoolItem)->GetValue(); const SdrLayer* pLayer=mpModel->GetLayerAdmin().GetLayerPerID(nLayerId); if (pLayer!=nullptr) { if (bMeasure) maMeasureLayer=pLayer->GetName(); else maActualLayer=pLayer->GetName(); } } if (rAttr.GetItemState(SDRATTR_LAYERNAME,true,&pPoolItem)==SfxItemState::SET) { if (bMeasure) maMeasureLayer=static_cast(pPoolItem)->GetValue(); else maActualLayer=static_cast(pPoolItem)->GetValue(); } } void SdrPaintView::MergeNotPersistDefaultAttr(SfxItemSet& rAttr) const { // bOnlyHardAttr has no effect here at all. bool bMeasure= dynamic_cast(this) != nullptr && static_cast(this)->IsMeasureTool(); const OUString& aNam = bMeasure ? maMeasureLayer : maActualLayer; rAttr.Put(SdrLayerNameItem(aNam)); SdrLayerID nLayer=mpModel->GetLayerAdmin().GetLayerID(aNam); if (nLayer!=SDRLAYER_NOTFOUND) { rAttr.Put(SdrLayerIdItem(nLayer)); } } void SdrPaintView::SetDefaultAttr(const SfxItemSet& rAttr, bool bReplaceAll) { #ifdef DBG_UTIL { bool bHasEEFeatureItems=false; SfxItemIter aIter(rAttr); const SfxPoolItem* pItem=aIter.FirstItem(); while (!bHasEEFeatureItems && pItem!=nullptr) { if (!IsInvalidItem(pItem)) { sal_uInt16 nW=pItem->Which(); if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true; } pItem=aIter.NextItem(); } if(bHasEEFeatureItems) { OUString aMessage("SdrPaintView::SetDefaultAttr(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents."); std::unique_ptr xInfoBox(Application::CreateMessageDialog(nullptr, VclMessageType::Info, VclButtonsType::Ok, aMessage)); xInfoBox->run(); } } #endif if (bReplaceAll) maDefaultAttr.Set(rAttr); else maDefaultAttr.Put(rAttr,false); // if FALSE, regard InvalidItems as "holes," not as Default SetNotPersistDefaultAttr(rAttr); #ifdef DBG_UTIL if (mpItemBrowser!=nullptr) mpItemBrowser->SetDirty(); #endif } void SdrPaintView::SetDefaultStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr) { if (mpDefaultStyleSheet) EndListening(*mpDefaultStyleSheet); mpDefaultStyleSheet=pStyleSheet; if (mpDefaultStyleSheet) StartListening(*mpDefaultStyleSheet); if (pStyleSheet!=nullptr && !bDontRemoveHardAttr) { SfxWhichIter aIter(pStyleSheet->GetItemSet()); sal_uInt16 nWhich=aIter.FirstWhich(); while (nWhich!=0) { if (pStyleSheet->GetItemSet().GetItemState(nWhich)==SfxItemState::SET) { maDefaultAttr.ClearItem(nWhich); } nWhich=aIter.NextWhich(); } } #ifdef DBG_UTIL if (mpItemBrowser!=nullptr) mpItemBrowser->SetDirty(); #endif } bool SdrPaintView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const { if(bOnlyHardAttr || !mpDefaultStyleSheet) { rTargetSet.Put(maDefaultAttr, false); } else { // else merge with DefStyleSheet rTargetSet.Put(mpDefaultStyleSheet->GetItemSet(), false); rTargetSet.Put(maDefaultAttr, false); } MergeNotPersistDefaultAttr(rTargetSet); return true; } bool SdrPaintView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll) { SetDefaultAttr(rSet,bReplaceAll); return true; } SfxStyleSheet* SdrPaintView::GetStyleSheet() const { return mpDefaultStyleSheet; } bool SdrPaintView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr) { SetDefaultStyleSheet(pStyleSheet,bDontRemoveHardAttr); return true; } #ifdef DBG_UTIL void SdrPaintView::ShowItemBrowser(bool bShow) { if (bShow) { if (mpItemBrowser==nullptr) { mpItemBrowser=VclPtr::Create(*static_cast(this)); } mpItemBrowser->Show(); mpItemBrowser->GrabFocus(); } else { if (mpItemBrowser!=nullptr) { mpItemBrowser->Hide(); mpItemBrowser.disposeAndClear(); } } } #endif void SdrPaintView::MakeVisible(const tools::Rectangle& rRect, vcl::Window& rWin) { // TODO: handle when the text cursor goes out of the chart area // However this hack avoids that the cursor gets misplaced wrt the text. if (comphelper::LibreOfficeKit::isActive() && rWin.IsChart()) { return; } MapMode aMap(rWin.GetMapMode()); Size aActualSize(rWin.GetOutputSize()); if( aActualSize.Height() <= 0 || aActualSize.Width() <= 0 ) return; Size aNewSize(rRect.GetSize()); bool bNewScale=false; bool bNeedMoreX=aNewSize.Width()>aActualSize.Width(); bool bNeedMoreY=aNewSize.Height()>aActualSize.Height(); if (bNeedMoreX || bNeedMoreY) { bNewScale=true; // set new MapMode (Size+Org) and invalidate everything Fraction aXFact(aNewSize.Width(),aActualSize.Width()); Fraction aYFact(aNewSize.Height(),aActualSize.Height()); if (aYFact>aXFact) aXFact=aYFact; aXFact*=aMap.GetScaleX(); aXFact.ReduceInaccurate(10); // to avoid runovers and BigInt mapping aMap.SetScaleX(aXFact); aMap.SetScaleY(aYFact); rWin.SetMapMode(aMap); aActualSize=rWin.GetOutputSize(); } Point aOrg(aMap.GetOrigin()); long dx=0,dy=0; long l=-aOrg.X(); long r=-aOrg.X()+aActualSize.Width()-1; long o=-aOrg.Y(); long u=-aOrg.Y()+aActualSize.Height()-1; if (l>rRect.Left()) dx=rRect.Left()-l; else if (rrRect.Top()) dy=rRect.Top()-o; else if (uPageWindowCount(); b++) { SdrPageWindow& rPageWindow = *(mpPageView->GetPageWindow(b)); sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact(); sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator(); if(rAnimator.IsPaused() != bSet) { rAnimator.SetPaused(bSet); } } } } } void SdrPaintView::SetAnimationMode( const SdrAnimationMode eMode ) { meAnimationMode = eMode; } void SdrPaintView::VisAreaChanged(const OutputDevice* pOut) { if(mpPageView) { if (pOut) { SdrPageWindow* pWindow = mpPageView->FindPageWindow(*const_cast(pOut)); if(pWindow) { VisAreaChanged(); } } else { VisAreaChanged(); } } } void SdrPaintView::VisAreaChanged() { // notify SfxListener Broadcast(SvxViewChangedHint()); } void SdrPaintView::onChangeColorConfig() { maGridColor = maColorConfig.GetColorValue( svtools::DRAWGRID ).nColor; } // Set background color for svx at SdrPageViews void SdrPaintView::SetApplicationBackgroundColor(Color aBackgroundColor) { if(mpPageView) { mpPageView->SetApplicationBackgroundColor(aBackgroundColor); } } // Set document color for svx at SdrPageViews void SdrPaintView::SetApplicationDocumentColor(Color aDocumentColor) { if(mpPageView) { mpPageView->SetApplicationDocumentColor(aDocumentColor); } } bool SdrPaintView::IsBufferedOutputAllowed() const { return (mbBufferedOutputAllowed && maDrawinglayerOpt.IsPaintBuffer()); } void SdrPaintView::SetBufferedOutputAllowed(bool bNew) { if(bNew != mbBufferedOutputAllowed) { mbBufferedOutputAllowed = bNew; } } bool SdrPaintView::IsBufferedOverlayAllowed() const { return (mbBufferedOverlayAllowed && maDrawinglayerOpt.IsOverlayBuffer()); } void SdrPaintView::SetBufferedOverlayAllowed(bool bNew) { if(bNew != mbBufferedOverlayAllowed) { mbBufferedOverlayAllowed = bNew; } } void SdrPaintView::SetPagePaintingAllowed(bool bNew) { if(bNew != mbPagePaintingAllowed) { mbPagePaintingAllowed = bNew; } } // #i38135# Sets the timer for Object animations and restarts. void SdrPaintView::SetAnimationTimer(sal_uInt32 nTime) { if(mpPageView) { // first, reset all timers at all windows to 0L for(sal_uInt32 a(0); a < mpPageView->PageWindowCount(); a++) { SdrPageWindow& rPageWindow = *mpPageView->GetPageWindow(a); sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact(); sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator(); rAnimator.SetTime(nTime); } } } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */