tdf#130857 qt weld: Implement QtInstanceWidget::get_text_height
[LibreOffice.git] / svx / source / svdraw / svdpntv.cxx
blob5cee983a0b7333b33a8506fe3112ca694313e067
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <memory>
21 #include <svx/svdpntv.hxx>
22 #include <vcl/weld.hxx>
23 #include <vcl/window.hxx>
24 #include <svx/sdrpaintwindow.hxx>
25 #include <svx/svdmodel.hxx>
27 #include <svx/svdpage.hxx>
28 #include <svx/svdpagv.hxx>
29 #include <svl/hint.hxx>
31 #include <svx/svdview.hxx>
32 #include <svx/svdglue.hxx>
33 #include <svx/svdobj.hxx>
34 #include <sxlayitm.hxx>
35 #include <svl/itemiter.hxx>
36 #include <editeng/eeitem.hxx>
37 #include <svl/whiter.hxx>
38 #include <svl/style.hxx>
39 #include <svx/sdrpagewindow.hxx>
40 #include <vcl/svapp.hxx>
41 #include <svx/sdr/contact/objectcontact.hxx>
42 #include <svx/sdr/animation/objectanimator.hxx>
43 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
44 #include <drawinglayer/converters.hxx>
45 #include <basegfx/matrix/b2dhommatrixtools.hxx>
46 #include <comphelper/lok.hxx>
47 #include <svx/svdviter.hxx>
48 #include <osl/diagnose.h>
49 #include <officecfg/Office/Common.hxx>
51 using namespace ::com::sun::star;
53 // interface to SdrPaintWindow
55 SdrPaintWindow* SdrPaintView::FindPaintWindow(const OutputDevice& rOut) const
57 // back to loop - there is more to test than a std::find_if and a lambda can do
58 for(auto& candidate : maPaintWindows)
60 if(&(candidate->GetOutputDevice()) == &rOut)
62 return candidate.get();
65 // check for patched to allow finding in that state, too
66 if(nullptr != candidate->getPatched() && &(candidate->getPatched()->GetOutputDevice()) == &rOut)
68 return candidate->getPatched();
72 return nullptr;
75 SdrPaintWindow* SdrPaintView::GetPaintWindow(sal_uInt32 nIndex) const
77 return maPaintWindows[nIndex].get();
80 void SdrPaintView::DeletePaintWindow(const SdrPaintWindow& rOld)
82 auto aFindResult = ::std::find_if(maPaintWindows.begin(), maPaintWindows.end(),
83 [&](const std::unique_ptr<SdrPaintWindow>& p) { return p.get() == &rOld; });
85 if(aFindResult != maPaintWindows.end())
87 maPaintWindows.erase(aFindResult);
91 OutputDevice* SdrPaintView::GetFirstOutputDevice() const
93 if(PaintWindowCount())
95 return &(GetPaintWindow(0)->GetOutputDevice());
98 return nullptr;
102 SvxViewChangedHint::SvxViewChangedHint() : SfxHint(SfxHintId::SvxViewChanged)
107 BitmapEx convertMetafileToBitmapEx(
108 const GDIMetaFile& rMtf,
109 const basegfx::B2DRange& rTargetRange,
110 const sal_uInt32 nMaximumQuadraticPixels)
112 BitmapEx aBitmapEx;
114 if(rMtf.GetActionSize())
116 const drawinglayer::primitive2d::Primitive2DReference aMtf(
117 new drawinglayer::primitive2d::MetafilePrimitive2D(
118 basegfx::utils::createScaleTranslateB2DHomMatrix(
119 rTargetRange.getRange(),
120 rTargetRange.getMinimum()),
121 rMtf));
122 aBitmapEx = drawinglayer::convertPrimitive2DContainerToBitmapEx(
123 drawinglayer::primitive2d::Primitive2DContainer { aMtf },
124 rTargetRange,
125 nMaximumQuadraticPixels);
128 return aBitmapEx;
131 SdrPaintView::SdrPaintView(SdrModel& rSdrModel, OutputDevice* pOut)
132 : mrModel(rSdrModel)
133 , mpActualOutDev(nullptr)
134 , mpDragWin(nullptr)
135 , mpDefaultStyleSheet(nullptr)
136 , maDefaultAttr(rSdrModel.GetItemPool())
137 , maComeBackIdle( "svx::SdrPaintView aComeBackIdle" )
138 , meAnimationMode(SdrAnimationMode::Animate)
139 , mnHitTolPix(2)
140 , mnMinMovPix(3)
141 , mnHitTolLog(0)
142 , mnMinMovLog(0)
143 , mbPageVisible(true)
144 , mbPageShadowVisible(true)
145 , mbPageBorderVisible(true)
146 , mbBordVisible(true)
147 , mbGridVisible(true)
148 , mbGridFront(false)
149 , mbHlplVisible(true)
150 , mbHlplFront(true)
151 , mbGlueVisible(false)
152 , mbGlueVisible2(false)
153 , mbGlueVisible3(false)
154 , mbGlueVisible4(false)
155 , mbSomeObjChgdFlag(false)
156 , mbSwapAsynchron(false)
157 , mbPrintPreview(false)
158 , mbAnimationPause(false)
159 , mbBufferedOutputAllowed(false)
160 , mbBufferedOverlayAllowed(false)
161 , mbPageDecorationAllowed(true)
162 , mbMasterPageVisualizationAllowed(true)
163 , mbPreviewRenderer(false)
164 , mbHideOle(false)
165 , mbHideChart(false)
166 , mbHideDraw(false)
167 , mbHideFormControl(false)
168 , mbHideBackground(false)
169 , mbPaintTextEdit(true)
170 , maGridColor(COL_BLACK)
172 maComeBackIdle.SetPriority(TaskPriority::REPAINT);
173 maComeBackIdle.SetInvokeHandler(LINK(this,SdrPaintView,ImpComeBackHdl));
175 SetDefaultStyleSheet(GetModel().GetDefaultStyleSheet(), true);
177 if (pOut)
178 AddDeviceToPaintView(*pOut, nullptr);
180 maColorConfig.AddListener(this);
181 onChangeColorConfig();
184 SdrPaintView::~SdrPaintView()
186 if (mpDefaultStyleSheet)
187 EndListening(*mpDefaultStyleSheet);
189 maColorConfig.RemoveListener(this);
190 ClearPageView();
192 // delete existing SdrPaintWindows
193 maPaintWindows.clear();
197 void SdrPaintView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
199 //If the stylesheet has been destroyed
200 if (&rBC == mpDefaultStyleSheet)
202 if (rHint.GetId() == SfxHintId::Dying)
203 mpDefaultStyleSheet = nullptr;
204 return;
207 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
208 return;
209 const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
210 SdrHintKind eKind = pSdrHint->GetKind();
211 if (eKind==SdrHintKind::ObjectChange || eKind==SdrHintKind::ObjectInserted || eKind==SdrHintKind::ObjectRemoved)
213 bool bObjChg = !mbSomeObjChgdFlag; // if true, evaluate for ComeBack timer
214 if (bObjChg)
216 mbSomeObjChgdFlag=true;
217 maComeBackIdle.Start();
221 if (eKind==SdrHintKind::PageOrderChange)
223 const SdrPage* pPg=pSdrHint->GetPage();
224 if (pPg && !pPg->IsInserted())
226 if(mpPageView && mpPageView->GetPage() == pPg)
228 HideSdrPage();
234 void SdrPaintView::ConfigurationChanged( ::utl::ConfigurationBroadcaster* , ConfigurationHints eHint)
236 if (eHint == ConfigurationHints::OnlyCurrentDocumentColorScheme)
237 return;
238 onChangeColorConfig();
239 InvalidateAllWin();
242 IMPL_LINK_NOARG(SdrPaintView, ImpComeBackHdl, Timer *, void)
244 if (mbSomeObjChgdFlag) {
245 mbSomeObjChgdFlag=false;
246 ModelHasChanged();
250 void SdrPaintView::FlushComeBackTimer() const
252 if (mbSomeObjChgdFlag) {
253 // casting to nonconst
254 const_cast<SdrPaintView*>(this)->ImpComeBackHdl(&const_cast<SdrPaintView*>(this)->maComeBackIdle);
255 const_cast<SdrPaintView*>(this)->maComeBackIdle.Stop();
259 void SdrPaintView::ModelHasChanged()
261 // broadcast to all PageViews
262 if(mpPageView && !mpPageView->GetPage()->IsInserted())
264 HideSdrPage();
267 // test mpPageView here again, HideSdrPage() may have invalidated it.
268 if(mpPageView)
270 mpPageView->ModelHasChanged();
275 bool SdrPaintView::IsAction() const
277 return false;
280 void SdrPaintView::MovAction(const Point&)
284 void SdrPaintView::EndAction()
288 void SdrPaintView::BckAction()
292 void SdrPaintView::BrkAction()
296 void SdrPaintView::TakeActionRect(tools::Rectangle&) const
301 // info about TextEdit. Default is false.
302 bool SdrPaintView::IsTextEdit() const
304 return false;
307 sal_uInt16 SdrPaintView::ImpGetMinMovLogic(short nMinMov, const OutputDevice* pOut) const
309 if (nMinMov>=0) return sal_uInt16(nMinMov);
310 if (pOut==nullptr)
312 pOut = GetFirstOutputDevice();
314 if (pOut!=nullptr) {
315 return short(-pOut->PixelToLogic(Size(nMinMov,0)).Width());
316 } else {
317 return 0;
321 sal_uInt16 SdrPaintView::ImpGetHitTolLogic(short nHitTol, const OutputDevice* pOut) const
323 if (nHitTol>=0) return sal_uInt16(nHitTol);
324 if (pOut==nullptr)
326 pOut = GetFirstOutputDevice();
328 if (pOut!=nullptr) {
329 return short(-pOut->PixelToLogic(Size(nHitTol,0)).Width());
330 } else {
331 return 0;
335 void SdrPaintView::TheresNewMapMode()
337 if (mpActualOutDev) {
338 if (comphelper::LibreOfficeKit::isActive())
340 mnHitTolLog=static_cast<sal_uInt16>(OutputDevice::LogicToLogic(Size(mnHitTolPix,0), MapMode(MapUnit::MapPixel), mpActualOutDev->GetMapMode()).Width());
341 mnMinMovLog=static_cast<sal_uInt16>(OutputDevice::LogicToLogic(Size(mnMinMovPix,0), MapMode(MapUnit::MapPixel), mpActualOutDev->GetMapMode()).Width());
343 else
345 mnHitTolLog=static_cast<sal_uInt16>(mpActualOutDev->PixelToLogic(Size(mnHitTolPix,0)).Width());
346 mnMinMovLog=static_cast<sal_uInt16>(mpActualOutDev->PixelToLogic(Size(mnMinMovPix,0)).Width());
351 void SdrPaintView::SetActualWin(const OutputDevice* pWin)
353 mpActualOutDev = const_cast<OutputDevice *>(pWin);
354 TheresNewMapMode();
358 void SdrPaintView::ClearPageView()
360 BrkAction();
362 if(mpPageView)
364 InvalidateAllWin();
365 mpPageView.reset();
369 SdrPageView* SdrPaintView::ShowSdrPage(SdrPage* pPage)
371 if(pPage && (!mpPageView || mpPageView->GetPage() != pPage))
373 if(mpPageView)
375 InvalidateAllWin();
376 mpPageView.reset();
379 if (SdrView *pView = dynamic_cast<SdrView*>(this))
381 mpPageView.reset(new SdrPageView(pPage, *pView));
382 mpPageView->Show();
386 return mpPageView.get();
389 void SdrPaintView::HideSdrPage()
391 if(mpPageView)
393 mpPageView->Hide();
394 mpPageView.reset();
398 void SdrPaintView::AddDeviceToPaintView(OutputDevice& rNewDev, vcl::Window *pWindow)
400 SdrPaintWindow* pNewPaintWindow = new SdrPaintWindow(*this, rNewDev, pWindow);
401 maPaintWindows.emplace_back(pNewPaintWindow);
403 if(mpPageView)
405 mpPageView->AddPaintWindowToPageView(*pNewPaintWindow);
409 void SdrPaintView::DeleteDeviceFromPaintView(OutputDevice& rOldDev)
411 SdrPaintWindow* pCandidate = FindPaintWindow(rOldDev);
413 if(pCandidate)
415 if(mpPageView)
417 mpPageView->RemovePaintWindowFromPageView(*pCandidate);
420 DeletePaintWindow(*pCandidate);
424 void SdrPaintView::SetLayerVisible(const OUString& rName, bool bShow)
426 const bool bChanged = mpPageView && mpPageView->SetLayerVisible(rName, bShow);
427 if (!bChanged)
428 return;
429 InvalidateAllWin();
432 bool SdrPaintView::IsLayerVisible(const OUString& rName) const
434 return mpPageView && mpPageView->IsLayerVisible(rName);
437 void SdrPaintView::SetLayerLocked(const OUString& rName, bool bLock)
439 if(mpPageView)
441 mpPageView->SetLayerLocked(rName,bLock);
445 bool SdrPaintView::IsLayerLocked(const OUString& rName) const
447 if(mpPageView)
449 return mpPageView->IsLayerLocked(rName);
452 return false;
455 void SdrPaintView::SetLayerPrintable(const OUString& rName, bool bPrn)
457 if(mpPageView)
459 mpPageView->SetLayerPrintable(rName,bPrn);
463 bool SdrPaintView::IsLayerPrintable(const OUString& rName) const
465 if(mpPageView)
467 return mpPageView->IsLayerPrintable(rName);
470 return false;
473 void SdrPaintView::PrePaint()
475 if(mpPageView)
477 mpPageView->PrePaint();
482 // #define SVX_REPAINT_TIMER_TEST
484 void SdrPaintView::CompleteRedraw(OutputDevice* pOut, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector)
486 #ifdef SVX_REPAINT_TIMER_TEST
487 #define REMEMBERED_TIMES_COUNT (10)
488 static bool bDoTimerTest(false);
489 static bool bTimesInited(false);
490 static sal_uInt32 nRepeatCount(10);
491 static double fLastTimes[REMEMBERED_TIMES_COUNT];
492 const sal_uInt64 nStartTime(tools::Time::GetSystemTicks());
493 sal_uInt32 count(1);
494 sal_uInt32 a;
496 if(bDoTimerTest)
498 count = nRepeatCount;
501 for(a = 0; a < count; a++)
503 #endif // SVX_REPAINT_TIMER_TEST
505 // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region
506 // rReg may be made more granular (fine) with using it. Normally, rReg
507 // does come from Window::Paint() anyways and thus is based on a single
508 // rectangle which was derived from exactly that repaint region
509 vcl::Region aOptimizedRepaintRegion(rReg);
511 if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType())
513 vcl::Window* pWindow = pOut->GetOwnerWindow();
515 if(pWindow->IsInPaint())
517 if(!pWindow->GetPaintRegion().IsEmpty())
519 aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion());
524 SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut);
525 assert(pPaintWindow && "SdrPaintView::CompleteRedraw: No OutDev (!)");
527 DoCompleteRedraw(*pPaintWindow, aOptimizedRepaintRegion, pRedirector);
528 EndCompleteRedraw(*pPaintWindow, true);
530 #ifdef SVX_REPAINT_TIMER_TEST
533 if(bDoTimerTest)
535 const sal_uInt64 nStopTime(tools::Time::GetSystemTicks());
536 const sal_uInt64 nNeededTime(nStopTime - nStartTime);
537 const double fTimePerPaint((double)nNeededTime / (double)nRepeatCount);
539 if(!bTimesInited)
541 for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
543 fLastTimes[a] = fTimePerPaint;
546 bTimesInited = true;
548 else
550 for(a = 1; a < REMEMBERED_TIMES_COUNT; a++)
552 fLastTimes[a - 1] = fLastTimes[a];
555 fLastTimes[REMEMBERED_TIMES_COUNT - 1] = fTimePerPaint;
558 double fAddedTimes(0.0);
560 for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
562 fAddedTimes += fLastTimes[a];
565 const double fAverageTimePerPaint(fAddedTimes / (double)REMEMBERED_TIMES_COUNT);
567 fprintf(stderr, "-----------(start result)----------\n");
568 fprintf(stderr, "StartTime : %" SAL_PRIuUINT64 ", StopTime: %" SAL_PRIuUINT64 ", NeededTime: %" SAL_PRIuUINT64 ", TimePerPaint: %f\n", nStartTime, nStopTime, nNeededTime, fTimePerPaint);
569 fprintf(stderr, "Remembered times: ");
571 for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
573 fprintf(stderr, "%d: %f ", a, fLastTimes[a]);
576 fprintf(stderr, "\n");
577 fprintf(stderr, "AverageTimePerPaint: %f\n", fAverageTimePerPaint);
578 fprintf(stderr, "-----------(stop result)----------\n");
580 #endif // SVX_REPAINT_TIMER_TEST
584 // #i72889#
586 SdrPaintWindow* SdrPaintView::BeginCompleteRedraw(OutputDevice* pOut)
588 assert(pOut && "SdrPaintView::BeginCompleteRedraw: No OutDev (!)");
589 SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut);
591 if(pPaintWindow)
593 // draw preprocessing, only for known devices
594 // prepare PreRendering
595 pPaintWindow->PreparePreRenderDevice();
597 else
599 // None of the known OutputDevices is the target of this paint, use
600 // a temporary SdrPaintWindow for this Redraw.
601 pPaintWindow = new SdrPaintWindow(*this, *pOut);
602 pPaintWindow->setTemporaryTarget(true);
605 return pPaintWindow;
608 void SdrPaintView::DoCompleteRedraw(SdrPaintWindow& rPaintWindow, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector)
610 // redraw all PageViews with the target. This may expand the RedrawRegion
611 // at the PaintWindow, plus taking care of FormLayer expansion
612 if(mpPageView)
614 mpPageView->CompleteRedraw(rPaintWindow, rReg, pRedirector);
618 void SdrPaintView::EndCompleteRedraw(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer,
619 sdr::contact::ViewObjectContactRedirector* pRedirector)
621 std::unique_ptr<SdrPaintWindow> pPaintWindow;
622 if (comphelper::LibreOfficeKit::isActive() && rPaintWindow.getTemporaryTarget())
624 // Tiled rendering, we must paint the TextEdit to the output device.
625 pPaintWindow.reset(&rPaintWindow);
626 pPaintWindow->setTemporaryTarget(false);
629 if(rPaintWindow.getTemporaryTarget())
631 // get rid of temp target again
632 delete &rPaintWindow;
634 else
636 // draw postprocessing, only for known devices
637 // it is necessary to always paint FormLayer
638 // In the LOK case control rendering is performed through LokControlHandler
639 if(!comphelper::LibreOfficeKit::isActive() && bPaintFormLayer)
641 ImpFormLayerDrawing(rPaintWindow, pRedirector);
644 // look for active TextEdit. As long as this cannot be painted to a VDev,
645 // it cannot get part of buffering. In that case, output evtl. prerender
646 // early and paint text edit to window.
647 SdrPageView* pPageView = GetSdrPageView();
648 if(IsTextEdit() && pPageView)
650 if (!comphelper::LibreOfficeKit::isActive() || mbPaintTextEdit)
651 static_cast< SdrView* >(this)->TextEditDrawing(rPaintWindow);
654 if (comphelper::LibreOfficeKit::isActive() && pPageView)
656 // Look for active text edits in other views showing the same page,
657 // and show them as well. Show only if Page/MasterPage mode is matching.
658 bool bRequireMasterPage = pPageView->GetPage() ? pPageView->GetPage()->IsMasterPage() : false;
659 SdrViewIter::ForAllViews(pPageView->GetPage(),
660 [this, &bRequireMasterPage, &rPaintWindow] (SdrView* pView)
662 SdrPageView* pCurrentPageView = pView->GetSdrPageView();
663 bool bIsCurrentMasterPage = (pCurrentPageView && pCurrentPageView->GetPage()) ?
664 pCurrentPageView->GetPage()->IsMasterPage() : false;
666 if (pView == this || bRequireMasterPage != bIsCurrentMasterPage)
667 return false;
669 if (pView->IsTextEdit() && pView->GetSdrPageView())
671 pView->TextEditDrawing(rPaintWindow);
673 return false;
677 // draw Overlay, also to PreRender device if exists
678 rPaintWindow.DrawOverlay(rPaintWindow.GetRedrawRegion());
680 // output PreRendering
681 rPaintWindow.OutputPreRenderDevice(rPaintWindow.GetRedrawRegion());
685 SdrPaintWindow* SdrPaintView::BeginDrawLayers(OutputDevice* pOut, const vcl::Region& rReg, bool bDisableIntersect)
687 // #i74769# use BeginCompleteRedraw() as common base
688 SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut);
689 assert(pPaintWindow && "SdrPaintView::BeginDrawLayers: No SdrPaintWindow (!)");
691 if(mpPageView)
693 SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow);
695 if(pKnownTarget)
697 vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, bDisableIntersect );
699 // prepare redraw
700 pKnownTarget->PrepareRedraw(aOptimizedRepaintRegion);
702 // remember prepared SdrPageWindow
703 mpPageView->setPreparedPageWindow(pKnownTarget);
707 return pPaintWindow;
710 void SdrPaintView::EndDrawLayers(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer,
711 sdr::contact::ViewObjectContactRedirector* pRedirector)
713 // #i74769# use EndCompleteRedraw() as common base
714 EndCompleteRedraw(rPaintWindow, bPaintFormLayer, pRedirector);
716 if(mpPageView)
718 // forget prepared SdrPageWindow
719 mpPageView->setPreparedPageWindow(nullptr);
723 void SdrPaintView::UpdateDrawLayersRegion(const OutputDevice* pOut, const vcl::Region& rReg)
725 SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut);
726 assert(pPaintWindow && "SdrPaintView::UpdateDrawLayersRegion: No SdrPaintWindow (!)");
728 if(mpPageView)
730 SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow);
732 if(pKnownTarget)
734 vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, false/*bDisableIntersect*/ );
735 pKnownTarget->GetPaintWindow().SetRedrawRegion(aOptimizedRepaintRegion);
736 mpPageView->setPreparedPageWindow(pKnownTarget); // already set actually
741 vcl::Region SdrPaintView::OptimizeDrawLayersRegion(const OutputDevice* pOut, const vcl::Region& rReg, bool bDisableIntersect)
743 // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region
744 // rReg may be made more granular (fine) with using it. Normally, rReg
745 // does come from Window::Paint() anyways and thus is based on a single
746 // rectangle which was derived from exactly that repaint region
747 vcl::Region aOptimizedRepaintRegion(rReg);
749 // #i76114# Intersecting the region with the Window's paint region is disabled
750 // for print preview in Calc, because the intersection can be empty (if the paint
751 // region is outside of the table area of the page), and then no clip region
752 // would be set.
753 if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType() && !bDisableIntersect)
755 vcl::Window* pWindow = pOut->GetOwnerWindow();
757 if(pWindow->IsInPaint())
759 if(!pWindow->GetPaintRegion().IsEmpty())
761 aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion());
765 return aOptimizedRepaintRegion;
769 void SdrPaintView::ImpFormLayerDrawing( SdrPaintWindow& rPaintWindow,
770 sdr::contact::ViewObjectContactRedirector* pRedirector )
772 if(!mpPageView)
773 return;
775 SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(rPaintWindow);
777 if(pKnownTarget)
779 const SdrModel& rModel = GetModel();
780 const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin();
781 const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName());
783 // BUFFERED use GetTargetOutputDevice() now, it may be targeted to VDevs, too
784 // need to set PreparedPageWindow to make DrawLayer use the correct ObjectContact
785 mpPageView->setPreparedPageWindow(pKnownTarget);
786 mpPageView->DrawLayer(nControlLayerId, &rPaintWindow.GetTargetOutputDevice(),
787 pRedirector);
788 mpPageView->setPreparedPageWindow(nullptr);
793 bool SdrPaintView::KeyInput(const KeyEvent& /*rKEvt*/, vcl::Window* /*pWin*/)
795 return false;
798 void SdrPaintView::GlueInvalidate() const
800 // Do not invalidate GluePoints in Online
801 // They are handled on front-end
802 if (comphelper::LibreOfficeKit::isActive())
803 return;
805 const sal_uInt32 nWindowCount(PaintWindowCount());
807 for(sal_uInt32 nWinNum(0); nWinNum < nWindowCount; nWinNum++)
809 SdrPaintWindow* pPaintWindow = GetPaintWindow(nWinNum);
811 if(pPaintWindow->OutputToWindow())
813 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
815 if(mpPageView)
817 const SdrObjList* pOL=mpPageView->GetObjList();
818 for (const rtl::Reference<SdrObject>& pObj : *pOL) {
819 const SdrGluePointList* pGPL=pObj->GetGluePointList();
820 if (pGPL!=nullptr && pGPL->GetCount()!=0) {
821 pGPL->Invalidate(*rOutDev.GetOwnerWindow(), pObj.get());
829 void SdrPaintView::InvalidateAllWin()
831 const sal_uInt32 nWindowCount(PaintWindowCount());
833 for(sal_uInt32 a(0); a < nWindowCount; a++)
835 SdrPaintWindow* pPaintWindow = GetPaintWindow(a);
837 if(pPaintWindow->OutputToWindow())
839 InvalidateOneWin(pPaintWindow->GetOutputDevice());
844 void SdrPaintView::InvalidateAllWin(const tools::Rectangle& rRect)
846 const sal_uInt32 nWindowCount(PaintWindowCount());
848 for(sal_uInt32 a(0); a < nWindowCount; a++)
850 SdrPaintWindow* pPaintWindow = GetPaintWindow(a);
852 if(pPaintWindow->OutputToWindow())
854 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
855 tools::Rectangle aRect(rRect);
857 Point aOrg(rOutDev.GetMapMode().GetOrigin());
858 aOrg.setX(-aOrg.X() ); aOrg.setY(-aOrg.Y() );
859 tools::Rectangle aOutRect(aOrg, rOutDev.GetOutputSize());
861 // In case of tiled rendering we want to get all invalidations, so visual area is not interesting.
862 if (aRect.Overlaps(aOutRect) || comphelper::LibreOfficeKit::isActive())
864 InvalidateOneWin(rOutDev, aRect);
870 void SdrPaintView::InvalidateOneWin(OutputDevice& rDevice)
872 // do not erase background, that causes flicker (!)
873 // tdf#160444 check device's owner window is a nullptr
874 // Since commit 563f7077f1dbce31ff95ee8d2e8d17b629693db1, the
875 // device's owner window gets deleted before this object is
876 // deleted.
877 if (rDevice.GetOwnerWindow())
878 rDevice.GetOwnerWindow()->Invalidate(InvalidateFlags::NoErase);
881 void SdrPaintView::InvalidateOneWin(OutputDevice& rDevice, const tools::Rectangle& rRect)
883 // do not erase background, that causes flicker (!)
884 rDevice.GetOwnerWindow()->Invalidate(rRect, InvalidateFlags::NoErase);
887 void SdrPaintView::LeaveOneGroup()
889 if(mpPageView)
891 mpPageView->LeaveOneGroup();
895 void SdrPaintView::LeaveAllGroup()
897 if(mpPageView)
899 mpPageView->LeaveAllGroup();
903 bool SdrPaintView::IsGroupEntered() const
905 if(mpPageView)
907 return (mpPageView->GetEnteredLevel() != 0);
910 return false;
913 void SdrPaintView::SetNotPersistDefaultAttr(const SfxItemSet& rAttr)
915 // bReplaceAll has no effect here at all.
916 bool bMeasure= dynamic_cast<const SdrView*>(this) != nullptr && static_cast<SdrView*>(this)->IsMeasureTool();
918 if (const SdrLayerIdItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERID))
920 SdrLayerID nLayerId = pPoolItem->GetValue();
921 const SdrLayer* pLayer = GetModel().GetLayerAdmin().GetLayerPerID(nLayerId);
922 if (pLayer!=nullptr) {
923 if (bMeasure) maMeasureLayer=pLayer->GetName();
924 else maActualLayer=pLayer->GetName();
927 if (const SdrLayerNameItem *pPoolItem = rAttr.GetItemIfSet(SDRATTR_LAYERNAME))
929 if (bMeasure) maMeasureLayer = pPoolItem->GetValue();
930 else maActualLayer = pPoolItem->GetValue();
934 void SdrPaintView::MergeNotPersistDefaultAttr(SfxItemSet& rAttr) const
936 // bOnlyHardAttr has no effect here at all.
937 bool bMeasure= dynamic_cast<const SdrView*>(this) != nullptr && static_cast<const SdrView*>(this)->IsMeasureTool();
938 const OUString& aNam = bMeasure ? maMeasureLayer : maActualLayer;
939 rAttr.Put(SdrLayerNameItem(aNam));
940 SdrLayerID nLayer = GetModel().GetLayerAdmin().GetLayerID(aNam);
941 if (nLayer!=SDRLAYER_NOTFOUND) {
942 rAttr.Put(SdrLayerIdItem(nLayer));
946 void SdrPaintView::SetDefaultAttr(const SfxItemSet& rAttr, bool bReplaceAll)
948 #ifdef DBG_UTIL
950 bool bHasEEFeatureItems=false;
951 SfxItemIter aIter(rAttr);
952 for (const SfxPoolItem* pItem = aIter.GetCurItem(); !bHasEEFeatureItems && pItem;
953 pItem = aIter.NextItem())
955 if (!IsInvalidItem(pItem)) {
956 sal_uInt16 nW=pItem->Which();
957 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
961 if(bHasEEFeatureItems)
963 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
964 VclMessageType::Info, VclButtonsType::Ok,
965 u"SdrPaintView::SetDefaultAttr(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents."_ustr));
966 xInfoBox->run();
969 #endif
970 if (bReplaceAll) maDefaultAttr.Set(rAttr);
971 else maDefaultAttr.Put(rAttr,false); // if FALSE, regard InvalidItems as "holes," not as Default
972 SetNotPersistDefaultAttr(rAttr);
975 void SdrPaintView::SetDefaultStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
977 if (mpDefaultStyleSheet)
978 EndListening(*mpDefaultStyleSheet);
979 mpDefaultStyleSheet=pStyleSheet;
980 if (mpDefaultStyleSheet)
981 StartListening(*mpDefaultStyleSheet);
983 if (pStyleSheet!=nullptr && !bDontRemoveHardAttr) {
984 SfxWhichIter aIter(pStyleSheet->GetItemSet());
985 sal_uInt16 nWhich=aIter.FirstWhich();
986 while (nWhich!=0) {
987 if (aIter.GetItemState()==SfxItemState::SET) {
988 maDefaultAttr.ClearItem(nWhich);
990 nWhich=aIter.NextWhich();
995 void SdrPaintView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
997 if(bOnlyHardAttr || !mpDefaultStyleSheet)
999 rTargetSet.Put(maDefaultAttr, false);
1001 else
1003 // else merge with DefStyleSheet
1004 rTargetSet.Put(mpDefaultStyleSheet->GetItemSet(), false);
1005 rTargetSet.Put(maDefaultAttr, false);
1007 MergeNotPersistDefaultAttr(rTargetSet);
1010 void SdrPaintView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
1012 SetDefaultAttr(rSet,bReplaceAll);
1015 SfxStyleSheet* SdrPaintView::GetStyleSheet() const
1017 return mpDefaultStyleSheet;
1020 void SdrPaintView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
1022 SetDefaultStyleSheet(pStyleSheet,bDontRemoveHardAttr);
1025 void SdrPaintView::MakeVisible(const tools::Rectangle& rRect, vcl::Window& rWin)
1027 // TODO: handle when the text cursor goes out of the chart area
1028 // However this hack avoids that the cursor gets misplaced wrt the text.
1029 if (comphelper::LibreOfficeKit::isActive() && rWin.IsChart())
1031 return;
1034 MapMode aMap(rWin.GetMapMode());
1035 Size aActualSize(rWin.GetOutDev()->GetOutputSize());
1037 if( aActualSize.IsEmpty() )
1038 return;
1040 Size aNewSize(rRect.GetSize());
1041 bool bNewScale=false;
1042 bool bNeedMoreX=aNewSize.Width()>aActualSize.Width();
1043 bool bNeedMoreY=aNewSize.Height()>aActualSize.Height();
1044 if (bNeedMoreX || bNeedMoreY)
1046 bNewScale=true;
1047 // set new MapMode (Size+Org) and invalidate everything
1048 Fraction aXFact(aNewSize.Width(),aActualSize.Width());
1049 Fraction aYFact(aNewSize.Height(),aActualSize.Height());
1050 if (aYFact>aXFact) aXFact=aYFact;
1051 aXFact*=aMap.GetScaleX();
1052 aXFact.ReduceInaccurate(10); // to avoid runovers and BigInt mapping
1053 aMap.SetScaleX(aXFact);
1054 aMap.SetScaleY(aYFact);
1055 rWin.SetMapMode(aMap);
1056 aActualSize=rWin.GetOutDev()->GetOutputSize();
1058 Point aOrg(aMap.GetOrigin());
1059 tools::Long dx=0,dy=0;
1060 tools::Long l=-aOrg.X();
1061 tools::Long r=-aOrg.X()+aActualSize.Width()-1;
1062 tools::Long o=-aOrg.Y();
1063 tools::Long u=-aOrg.Y()+aActualSize.Height()-1;
1064 if (l>rRect.Left()) dx=rRect.Left()-l;
1065 else if (r<rRect.Right()) dx=rRect.Right()-r;
1066 if (o>rRect.Top()) dy=rRect.Top()-o;
1067 else if (u<rRect.Bottom()) dy=rRect.Bottom()-u;
1068 aMap.SetOrigin(Point(aOrg.X()-dx,aOrg.Y()-dy));
1069 if (!bNewScale) {
1070 if (dx!=0 || dy!=0) {
1071 rWin.Scroll(-dx,-dy);
1072 rWin.SetMapMode(aMap);
1073 rWin.PaintImmediately();
1075 } else {
1076 rWin.SetMapMode(aMap);
1077 InvalidateOneWin(*rWin.GetOutDev());
1081 void SdrPaintView::DoConnect(SdrOle2Obj* /*pOleObj*/)
1085 void SdrPaintView::SetAnimationEnabled( bool bEnable )
1087 SetAnimationMode( bEnable ? SdrAnimationMode::Animate : SdrAnimationMode::Disable );
1090 void SdrPaintView::SetAnimationPause( bool bSet )
1092 if(mbAnimationPause == bSet)
1093 return;
1095 mbAnimationPause = bSet;
1097 if(!mpPageView)
1098 return;
1100 for(sal_uInt32 b(0); b < mpPageView->PageWindowCount(); b++)
1102 SdrPageWindow& rPageWindow = *(mpPageView->GetPageWindow(b));
1103 sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact();
1104 sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator();
1106 if(rAnimator.IsPaused() != bSet)
1108 rAnimator.SetPaused(bSet);
1113 void SdrPaintView::SetAnimationMode( const SdrAnimationMode eMode )
1115 meAnimationMode = eMode;
1118 void SdrPaintView::VisAreaChanged(const OutputDevice* pOut)
1120 if(!mpPageView)
1121 return;
1123 if (pOut)
1125 SdrPageWindow* pWindow = mpPageView->FindPageWindow(*const_cast<OutputDevice*>(pOut));
1127 if(pWindow)
1129 VisAreaChanged();
1132 else
1134 VisAreaChanged();
1138 void SdrPaintView::VisAreaChanged()
1140 // notify SfxListener
1141 Broadcast(SvxViewChangedHint());
1145 void SdrPaintView::onChangeColorConfig()
1147 maGridColor = maColorConfig.GetColorValue( svtools::DRAWGRID ).nColor;
1151 // Set background color for svx at SdrPageViews
1152 void SdrPaintView::SetApplicationBackgroundColor(Color aBackgroundColor)
1154 if(mpPageView)
1156 mpPageView->SetApplicationBackgroundColor(aBackgroundColor);
1160 // Set document color for svx at SdrPageViews
1161 void SdrPaintView::SetApplicationDocumentColor(Color aDocumentColor)
1163 if(mpPageView)
1165 mpPageView->SetApplicationDocumentColor(aDocumentColor);
1169 bool SdrPaintView::IsBufferedOutputAllowed() const
1171 return (mbBufferedOutputAllowed && officecfg::Office::Common::Drawinglayer::PaintBuffer::get());
1174 void SdrPaintView::SetBufferedOutputAllowed(bool bNew)
1176 if(bNew != mbBufferedOutputAllowed)
1178 mbBufferedOutputAllowed = bNew;
1182 bool SdrPaintView::IsBufferedOverlayAllowed() const
1184 return (mbBufferedOverlayAllowed && officecfg::Office::Common::Drawinglayer::OverlayBuffer::get());
1187 void SdrPaintView::SetBufferedOverlayAllowed(bool bNew)
1189 if(bNew != mbBufferedOverlayAllowed)
1191 mbBufferedOverlayAllowed = bNew;
1196 void SdrPaintView::SetPageDecorationAllowed(bool bNew)
1198 if(bNew != mbPageDecorationAllowed)
1200 mbPageDecorationAllowed = bNew;
1204 void SdrPaintView::SetMasterPageVisualizationAllowed(bool bNew)
1206 if(bNew != mbMasterPageVisualizationAllowed)
1208 mbMasterPageVisualizationAllowed = bNew;
1212 // #i38135# Sets the timer for Object animations and restarts.
1213 void SdrPaintView::SetAnimationTimer(sal_uInt32 nTime)
1215 if(mpPageView)
1217 // first, reset all timers at all windows to 0L
1218 for(sal_uInt32 a(0); a < mpPageView->PageWindowCount(); a++)
1220 SdrPageWindow& rPageWindow = *mpPageView->GetPageWindow(a);
1221 sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact();
1222 sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator();
1223 rAnimator.SetTime(nTime);
1228 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */