Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / svx / source / svdraw / svdpntv.cxx
blob4d2b7b636a370db0960f7d293c1f54126183b5b3
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 <svx/sdrpaintwindow.hxx>
24 #include <svx/svdmodel.hxx>
26 #include <svx/svdpage.hxx>
27 #include <svx/svdpagv.hxx>
28 #include <svl/hint.hxx>
30 #include <svx/svdview.hxx>
31 #include <svx/svdglue.hxx>
32 #include <svx/svdobj.hxx>
33 #include <sxlayitm.hxx>
34 #include <svl/itemiter.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <svl/whiter.hxx>
37 #include <svl/style.hxx>
38 #include <svx/sdrpagewindow.hxx>
39 #include <vcl/svapp.hxx>
40 #include <svx/sdr/contact/objectcontact.hxx>
41 #include <svx/sdr/animation/objectanimator.hxx>
42 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
43 #include <basegfx/matrix/b2dhommatrixtools.hxx>
44 #include <comphelper/lok.hxx>
45 #include <svx/svdviter.hxx>
47 using namespace ::com::sun::star;
49 // interface to SdrPaintWindow
51 SdrPaintWindow* SdrPaintView::FindPaintWindow(const OutputDevice& rOut) const
53 // back to loop - there is more to test than a std::find_if and a lambda can do
54 for(auto& candidate : maPaintWindows)
56 if(&(candidate->GetOutputDevice()) == &rOut)
58 return candidate.get();
61 // check for patched to allow finding in that state, too
62 if(nullptr != candidate->getPatched() && &(candidate->getPatched()->GetOutputDevice()) == &rOut)
64 return candidate->getPatched();
68 return nullptr;
71 SdrPaintWindow* SdrPaintView::GetPaintWindow(sal_uInt32 nIndex) const
73 return maPaintWindows[nIndex].get();
76 void SdrPaintView::DeletePaintWindow(SdrPaintWindow& rOld)
78 auto aFindResult = ::std::find_if(maPaintWindows.begin(), maPaintWindows.end(),
79 [&](const std::unique_ptr<SdrPaintWindow>& p) { return p.get() == &rOld; });
81 if(aFindResult != maPaintWindows.end())
83 maPaintWindows.erase(aFindResult);
87 OutputDevice* SdrPaintView::GetFirstOutputDevice() const
89 if(PaintWindowCount())
91 return &(GetPaintWindow(0)->GetOutputDevice());
94 return nullptr;
98 SvxViewChangedHint::SvxViewChangedHint()
103 BitmapEx convertMetafileToBitmapEx(
104 const GDIMetaFile& rMtf,
105 const basegfx::B2DRange& rTargetRange,
106 const sal_uInt32 nMaximumQuadraticPixels)
108 BitmapEx aBitmapEx;
110 if(rMtf.GetActionSize())
112 const drawinglayer::primitive2d::Primitive2DReference aMtf(
113 new drawinglayer::primitive2d::MetafilePrimitive2D(
114 basegfx::utils::createScaleTranslateB2DHomMatrix(
115 rTargetRange.getRange(),
116 rTargetRange.getMinimum()),
117 rMtf));
118 aBitmapEx = convertPrimitive2DSequenceToBitmapEx(
119 drawinglayer::primitive2d::Primitive2DContainer { aMtf },
120 rTargetRange,
121 nMaximumQuadraticPixels);
124 return aBitmapEx;
127 SdrPaintView::SdrPaintView(SdrModel& rSdrModel, OutputDevice* pOut)
128 : mrSdrModelFromSdrView(rSdrModel)
129 , mpModel(&rSdrModel)
130 , mpActualOutDev(nullptr)
131 , mpDragWin(nullptr)
132 , mpDefaultStyleSheet(nullptr)
133 , maDefaultAttr(rSdrModel.GetItemPool())
134 , meAnimationMode(SdrAnimationMode::Animate)
135 , mnHitTolPix(2)
136 , mnMinMovPix(3)
137 , mnHitTolLog(0)
138 , mnMinMovLog(0)
139 , mbPageVisible(true)
140 , mbPageShadowVisible(true)
141 , mbPageBorderVisible(true)
142 , mbBordVisible(true)
143 , mbGridVisible(true)
144 , mbGridFront(false)
145 , mbHlplVisible(true)
146 , mbHlplFront(true)
147 , mbGlueVisible(false)
148 , mbGlueVisible2(false)
149 , mbGlueVisible3(false)
150 , mbGlueVisible4(false)
151 , mbSomeObjChgdFlag(false)
152 , mbSwapAsynchron(false)
153 , mbPrintPreview(false)
154 , mbAnimationPause(false)
155 , mbBufferedOutputAllowed(false)
156 , mbBufferedOverlayAllowed(false)
157 , mbPagePaintingAllowed(true)
158 , mbPreviewRenderer(false)
159 , mbHideOle(false)
160 , mbHideChart(false)
161 , mbHideDraw(false)
162 , mbHideFormControl(false)
163 , maGridColor(COL_BLACK)
165 maComeBackIdle.SetPriority(TaskPriority::REPAINT);
166 maComeBackIdle.SetInvokeHandler(LINK(this,SdrPaintView,ImpComeBackHdl));
167 maComeBackIdle.SetDebugName( "svx::SdrPaintView aComeBackIdle" );
169 if (mpModel)
170 SetDefaultStyleSheet(mpModel->GetDefaultStyleSheet(), true);
172 if (pOut)
173 AddWindowToPaintView(pOut, nullptr);
175 maColorConfig.AddListener(this);
176 onChangeColorConfig();
179 SdrPaintView::~SdrPaintView()
181 if (mpDefaultStyleSheet)
182 EndListening(*mpDefaultStyleSheet);
184 maColorConfig.RemoveListener(this);
185 ClearPageView();
187 // delete existing SdrPaintWindows
188 maPaintWindows.clear();
192 void SdrPaintView::Notify(SfxBroadcaster& rBC, const SfxHint& rHint)
194 //If the stylesheet has been destroyed
195 if (&rBC == mpDefaultStyleSheet)
197 if (rHint.GetId() == SfxHintId::Dying)
198 mpDefaultStyleSheet = nullptr;
199 return;
202 if (rHint.GetId() != SfxHintId::ThisIsAnSdrHint)
203 return;
204 const SdrHint* pSdrHint = static_cast<const SdrHint*>(&rHint);
205 SdrHintKind eKind = pSdrHint->GetKind();
206 if (eKind==SdrHintKind::ObjectChange || eKind==SdrHintKind::ObjectInserted || eKind==SdrHintKind::ObjectRemoved)
208 bool bObjChg = !mbSomeObjChgdFlag; // if true, evaluate for ComeBack timer
209 if (bObjChg)
211 mbSomeObjChgdFlag=true;
212 maComeBackIdle.Start();
216 if (eKind==SdrHintKind::PageOrderChange)
218 const SdrPage* pPg=pSdrHint->GetPage();
219 if (pPg && !pPg->IsInserted())
221 if(mpPageView && mpPageView->GetPage() == pPg)
223 HideSdrPage();
229 void SdrPaintView::ConfigurationChanged( ::utl::ConfigurationBroadcaster* , ConfigurationHints )
231 onChangeColorConfig();
232 InvalidateAllWin();
235 IMPL_LINK_NOARG(SdrPaintView, ImpComeBackHdl, Timer *, void)
237 if (mbSomeObjChgdFlag) {
238 mbSomeObjChgdFlag=false;
239 ModelHasChanged();
243 void SdrPaintView::FlushComeBackTimer() const
245 if (mbSomeObjChgdFlag) {
246 // casting to nonconst
247 const_cast<SdrPaintView*>(this)->ImpComeBackHdl(&const_cast<SdrPaintView*>(this)->maComeBackIdle);
248 const_cast<SdrPaintView*>(this)->maComeBackIdle.Stop();
252 void SdrPaintView::ModelHasChanged()
254 // broadcast to all PageViews
255 if(mpPageView && !mpPageView->GetPage()->IsInserted())
257 HideSdrPage();
260 // test mpPageView here again, HideSdrPage() may have invalidated it.
261 if(mpPageView)
263 mpPageView->ModelHasChanged();
268 bool SdrPaintView::IsAction() const
270 return false;
273 void SdrPaintView::MovAction(const Point&)
277 void SdrPaintView::EndAction()
281 void SdrPaintView::BckAction()
285 void SdrPaintView::BrkAction()
289 void SdrPaintView::TakeActionRect(tools::Rectangle&) const
294 // info about TextEdit. Default is false.
295 bool SdrPaintView::IsTextEdit() const
297 return false;
300 sal_uInt16 SdrPaintView::ImpGetMinMovLogic(short nMinMov, const OutputDevice* pOut) const
302 if (nMinMov>=0) return sal_uInt16(nMinMov);
303 if (pOut==nullptr)
305 pOut = GetFirstOutputDevice();
307 if (pOut!=nullptr) {
308 return short(-pOut->PixelToLogic(Size(nMinMov,0)).Width());
309 } else {
310 return 0;
314 sal_uInt16 SdrPaintView::ImpGetHitTolLogic(short nHitTol, const OutputDevice* pOut) const
316 if (nHitTol>=0) return sal_uInt16(nHitTol);
317 if (pOut==nullptr)
319 pOut = GetFirstOutputDevice();
321 if (pOut!=nullptr) {
322 return short(-pOut->PixelToLogic(Size(nHitTol,0)).Width());
323 } else {
324 return 0;
328 void SdrPaintView::TheresNewMapMode()
330 if (mpActualOutDev) {
331 mnHitTolLog=static_cast<sal_uInt16>(mpActualOutDev->PixelToLogic(Size(mnHitTolPix,0)).Width());
332 mnMinMovLog=static_cast<sal_uInt16>(mpActualOutDev->PixelToLogic(Size(mnMinMovPix,0)).Width());
336 void SdrPaintView::SetActualWin(const OutputDevice* pWin)
338 mpActualOutDev = const_cast<OutputDevice *>(pWin);
339 TheresNewMapMode();
343 void SdrPaintView::ClearPageView()
345 BrkAction();
347 if(mpPageView)
349 InvalidateAllWin();
350 mpPageView.reset();
354 SdrPageView* SdrPaintView::ShowSdrPage(SdrPage* pPage)
356 if(pPage && (!mpPageView || mpPageView->GetPage() != pPage))
358 if(mpPageView)
360 InvalidateAllWin();
361 mpPageView.reset();
364 mpPageView.reset(new SdrPageView(pPage, *static_cast<SdrView*>(this)));
365 mpPageView->Show();
368 return mpPageView.get();
371 void SdrPaintView::HideSdrPage()
373 if(mpPageView)
375 mpPageView->Hide();
376 mpPageView.reset();
380 void SdrPaintView::AddWindowToPaintView(OutputDevice* pNewWin, vcl::Window *pWindow)
382 DBG_ASSERT(pNewWin, "SdrPaintView::AddWindowToPaintView: No OutputDevice(!)");
383 SdrPaintWindow* pNewPaintWindow = new SdrPaintWindow(*this, *pNewWin, pWindow);
384 maPaintWindows.emplace_back(pNewPaintWindow);
386 if(mpPageView)
388 mpPageView->AddPaintWindowToPageView(*pNewPaintWindow);
392 void SdrPaintView::DeleteWindowFromPaintView(OutputDevice* pOldWin)
394 assert(pOldWin && "SdrPaintView::DeleteWindowFromPaintView: No OutputDevice(!)");
395 SdrPaintWindow* pCandidate = FindPaintWindow(*pOldWin);
397 if(pCandidate)
399 if(mpPageView)
401 mpPageView->RemovePaintWindowFromPageView(*pCandidate);
404 DeletePaintWindow(*pCandidate);
408 void SdrPaintView::SetLayerVisible(const OUString& rName, bool bShow)
410 if(mpPageView)
412 mpPageView->SetLayerVisible(rName, bShow);
415 InvalidateAllWin();
418 bool SdrPaintView::IsLayerVisible(const OUString& rName) const
420 if(mpPageView)
422 return mpPageView->IsLayerVisible(rName);
425 return false;
428 void SdrPaintView::SetLayerLocked(const OUString& rName, bool bLock)
430 if(mpPageView)
432 mpPageView->SetLayerLocked(rName,bLock);
436 bool SdrPaintView::IsLayerLocked(const OUString& rName) const
438 if(mpPageView)
440 return mpPageView->IsLayerLocked(rName);
443 return false;
446 void SdrPaintView::SetLayerPrintable(const OUString& rName, bool bPrn)
448 if(mpPageView)
450 mpPageView->SetLayerPrintable(rName,bPrn);
454 bool SdrPaintView::IsLayerPrintable(const OUString& rName) const
456 if(mpPageView)
458 return mpPageView->IsLayerPrintable(rName);
461 return false;
464 void SdrPaintView::PrePaint()
466 if(mpPageView)
468 mpPageView->PrePaint();
473 // #define SVX_REPAINT_TIMER_TEST
475 void SdrPaintView::CompleteRedraw(OutputDevice* pOut, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector)
477 #ifdef SVX_REPAINT_TIMER_TEST
478 #define REMEMBERED_TIMES_COUNT (10)
479 static bool bDoTimerTest(false);
480 static bool bTimesInited(false);
481 static sal_uInt32 nRepeatCount(10);
482 static double fLastTimes[REMEMBERED_TIMES_COUNT];
483 const sal_uInt64 nStartTime(tools::Time::GetSystemTicks());
484 sal_uInt32 count(1);
485 sal_uInt32 a;
487 if(bDoTimerTest)
489 count = nRepeatCount;
492 for(a = 0; a < count; a++)
494 #endif // SVX_REPAINT_TIMER_TEST
496 // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region
497 // rReg may be made more granular (fine) with using it. Normally, rReg
498 // does come from Window::Paint() anyways and thus is based on a single
499 // rectangle which was derived from exactly that repaint region
500 vcl::Region aOptimizedRepaintRegion(rReg);
502 if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType())
504 vcl::Window* pWindow = static_cast<vcl::Window*>(pOut);
506 if(pWindow->IsInPaint())
508 if(!pWindow->GetPaintRegion().IsEmpty())
510 aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion());
515 SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut);
516 OSL_ENSURE(pPaintWindow, "SdrPaintView::CompleteRedraw: No OutDev (!)");
518 DoCompleteRedraw(*pPaintWindow, aOptimizedRepaintRegion, pRedirector);
519 EndCompleteRedraw(*pPaintWindow, true);
521 #ifdef SVX_REPAINT_TIMER_TEST
524 if(bDoTimerTest)
526 const sal_uInt64 nStopTime(tools::Time::GetSystemTicks());
527 const sal_uInt64 nNeededTime(nStopTime - nStartTime);
528 const double fTimePerPaint((double)nNeededTime / (double)nRepeatCount);
530 if(!bTimesInited)
532 for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
534 fLastTimes[a] = fTimePerPaint;
537 bTimesInited = true;
539 else
541 for(a = 1; a < REMEMBERED_TIMES_COUNT; a++)
543 fLastTimes[a - 1] = fLastTimes[a];
546 fLastTimes[REMEMBERED_TIMES_COUNT - 1] = fTimePerPaint;
549 double fAddedTimes(0.0);
551 for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
553 fAddedTimes += fLastTimes[a];
556 const double fAverageTimePerPaint(fAddedTimes / (double)REMEMBERED_TIMES_COUNT);
558 fprintf(stderr, "-----------(start result)----------\n");
559 fprintf(stderr, "StartTime : %" SAL_PRIuUINT64 ", StopTime: %" SAL_PRIuUINT64 ", NeededTime: %" SAL_PRIuUINT64 ", TimePerPaint: %f\n", nStartTime, nStopTime, nNeededTime, fTimePerPaint);
560 fprintf(stderr, "Remembered times: ");
562 for(a = 0; a < REMEMBERED_TIMES_COUNT; a++)
564 fprintf(stderr, "%d: %f ", a, fLastTimes[a]);
567 fprintf(stderr, "\n");
568 fprintf(stderr, "AverageTimePerPaint: %f\n", fAverageTimePerPaint);
569 fprintf(stderr, "-----------(stop result)----------\n");
571 #endif // SVX_REPAINT_TIMER_TEST
575 // #i72889#
577 SdrPaintWindow* SdrPaintView::BeginCompleteRedraw(OutputDevice* pOut)
579 OSL_ENSURE(pOut, "SdrPaintView::BeginCompleteRedraw: No OutDev (!)");
580 SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut);
582 if(pPaintWindow)
584 // draw preprocessing, only for known devices
585 // prepare PreRendering
586 pPaintWindow->PreparePreRenderDevice();
588 else
590 // None of the known OutputDevices is the target of this paint, use
591 // a temporary SdrPaintWindow for this Redraw.
592 pPaintWindow = new SdrPaintWindow(*this, *pOut);
593 pPaintWindow->setTemporaryTarget(true);
596 return pPaintWindow;
599 void SdrPaintView::DoCompleteRedraw(SdrPaintWindow& rPaintWindow, const vcl::Region& rReg, sdr::contact::ViewObjectContactRedirector* pRedirector)
601 // redraw all PageViews with the target. This may expand the RedrawRegion
602 // at the PaintWindow, plus taking care of FormLayer expansion
603 if(mpPageView)
605 mpPageView->CompleteRedraw(rPaintWindow, rReg, pRedirector);
609 void SdrPaintView::EndCompleteRedraw(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer)
611 std::unique_ptr<SdrPaintWindow> pPaintWindow;
612 if (comphelper::LibreOfficeKit::isActive() && rPaintWindow.getTemporaryTarget())
614 // Tiled rendering, we must paint the TextEdit to the output device.
615 pPaintWindow.reset(&rPaintWindow);
616 pPaintWindow->setTemporaryTarget(false);
619 if(rPaintWindow.getTemporaryTarget())
621 // get rid of temp target again
622 delete &rPaintWindow;
624 else
626 // draw postprocessing, only for known devices
627 // it is necessary to always paint FormLayer
628 if(bPaintFormLayer)
630 ImpFormLayerDrawing(rPaintWindow);
633 // look for active TextEdit. As long as this cannot be painted to a VDev,
634 // it cannot get part of buffering. In that case, output evtl. prerender
635 // early and paint text edit to window.
636 if(IsTextEdit() && GetSdrPageView())
638 static_cast< SdrView* >(this)->TextEditDrawing(rPaintWindow);
641 if (comphelper::LibreOfficeKit::isActive())
643 // Look for active text edits in other views showing the same page,
644 // and show them as well.
645 if (SdrPageView* pPageView = GetSdrPageView())
647 SdrViewIter aIter(pPageView->GetPage());
648 for (SdrView* pView = aIter.FirstView(); pView; pView = aIter.NextView())
650 if (pView == this)
651 continue;
653 if (pView->IsTextEdit() && pView->GetSdrPageView())
655 pView->TextEditDrawing(rPaintWindow);
661 // draw Overlay, also to PreRender device if exists
662 rPaintWindow.DrawOverlay(rPaintWindow.GetRedrawRegion());
664 // output PreRendering
665 rPaintWindow.OutputPreRenderDevice(rPaintWindow.GetRedrawRegion());
670 SdrPaintWindow* SdrPaintView::BeginDrawLayers(OutputDevice* pOut, const vcl::Region& rReg, bool bDisableIntersect)
672 // #i74769# use BeginCompleteRedraw() as common base
673 SdrPaintWindow* pPaintWindow = BeginCompleteRedraw(pOut);
674 OSL_ENSURE(pPaintWindow, "SdrPaintView::BeginDrawLayers: No SdrPaintWindow (!)");
676 if(mpPageView)
678 SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow);
680 if(pKnownTarget)
682 vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, bDisableIntersect );
684 // prepare redraw
685 pKnownTarget->PrepareRedraw(aOptimizedRepaintRegion);
687 // remember prepared SdrPageWindow
688 mpPageView->setPreparedPageWindow(pKnownTarget);
692 return pPaintWindow;
695 void SdrPaintView::EndDrawLayers(SdrPaintWindow& rPaintWindow, bool bPaintFormLayer)
697 // #i74769# use EndCompleteRedraw() as common base
698 EndCompleteRedraw(rPaintWindow, bPaintFormLayer);
700 if(mpPageView)
702 // forget prepared SdrPageWindow
703 mpPageView->setPreparedPageWindow(nullptr);
707 void SdrPaintView::UpdateDrawLayersRegion(OutputDevice* pOut, const vcl::Region& rReg)
709 SdrPaintWindow* pPaintWindow = FindPaintWindow(*pOut);
710 OSL_ENSURE(pPaintWindow, "SdrPaintView::UpdateDrawLayersRegion: No SdrPaintWindow (!)");
712 if(mpPageView)
714 SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(*pPaintWindow);
716 if(pKnownTarget)
718 vcl::Region aOptimizedRepaintRegion = OptimizeDrawLayersRegion( pOut, rReg, false/*bDisableIntersect*/ );
719 pKnownTarget->GetPaintWindow().SetRedrawRegion(aOptimizedRepaintRegion);
720 mpPageView->setPreparedPageWindow(pKnownTarget); // already set actually
725 vcl::Region SdrPaintView::OptimizeDrawLayersRegion(OutputDevice* pOut, const vcl::Region& rReg, bool bDisableIntersect)
727 // #i74769# check if pOut is a win and has a ClipRegion. If Yes, the Region
728 // rReg may be made more granular (fine) with using it. Normally, rReg
729 // does come from Window::Paint() anyways and thus is based on a single
730 // rectangle which was derived from exactly that repaint region
731 vcl::Region aOptimizedRepaintRegion(rReg);
733 // #i76114# Intersecting the region with the Window's paint region is disabled
734 // for print preview in Calc, because the intersection can be empty (if the paint
735 // region is outside of the table area of the page), and then no clip region
736 // would be set.
737 if(pOut && OUTDEV_WINDOW == pOut->GetOutDevType() && !bDisableIntersect)
739 vcl::Window* pWindow = static_cast<vcl::Window*>(pOut);
741 if(pWindow->IsInPaint())
743 if(!pWindow->GetPaintRegion().IsEmpty())
745 aOptimizedRepaintRegion.Intersect(pWindow->GetPaintRegion());
749 return aOptimizedRepaintRegion;
753 void SdrPaintView::ImpFormLayerDrawing( SdrPaintWindow& rPaintWindow )
755 if(!mpPageView)
756 return;
758 SdrPageWindow* pKnownTarget = mpPageView->FindPageWindow(rPaintWindow);
760 if(pKnownTarget)
762 const SdrModel& rModel = *(GetModel());
763 const SdrLayerAdmin& rLayerAdmin = rModel.GetLayerAdmin();
764 const SdrLayerID nControlLayerId = rLayerAdmin.GetLayerID(rLayerAdmin.GetControlLayerName());
766 // BUFFERED use GetTargetOutputDevice() now, it may be targeted to VDevs, too
767 // need to set PreparedPageWindow to make DrawLayer use the correct ObjectContact
768 mpPageView->setPreparedPageWindow(pKnownTarget);
769 mpPageView->DrawLayer(nControlLayerId, &rPaintWindow.GetTargetOutputDevice());
770 mpPageView->setPreparedPageWindow(nullptr);
775 bool SdrPaintView::KeyInput(const KeyEvent& /*rKEvt*/, vcl::Window* /*pWin*/)
777 return false;
780 void SdrPaintView::GlueInvalidate() const
782 const sal_uInt32 nWindowCount(PaintWindowCount());
784 for(sal_uInt32 nWinNum(0); nWinNum < nWindowCount; nWinNum++)
786 SdrPaintWindow* pPaintWindow = GetPaintWindow(nWinNum);
788 if(pPaintWindow->OutputToWindow())
790 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
792 if(mpPageView)
794 const SdrObjList* pOL=mpPageView->GetObjList();
795 const size_t nObjCount = pOL->GetObjCount();
796 for (size_t nObjNum=0; nObjNum<nObjCount; ++nObjNum) {
797 const SdrObject* pObj=pOL->GetObj(nObjNum);
798 const SdrGluePointList* pGPL=pObj->GetGluePointList();
799 if (pGPL!=nullptr && pGPL->GetCount()!=0) {
800 pGPL->Invalidate(static_cast<vcl::Window&>(rOutDev), pObj);
808 void SdrPaintView::InvalidateAllWin()
810 const sal_uInt32 nWindowCount(PaintWindowCount());
812 for(sal_uInt32 a(0); a < nWindowCount; a++)
814 SdrPaintWindow* pPaintWindow = GetPaintWindow(a);
816 if(pPaintWindow->OutputToWindow())
818 InvalidateOneWin(pPaintWindow->GetOutputDevice());
823 void SdrPaintView::InvalidateAllWin(const tools::Rectangle& rRect)
825 const sal_uInt32 nWindowCount(PaintWindowCount());
827 for(sal_uInt32 a(0); a < nWindowCount; a++)
829 SdrPaintWindow* pPaintWindow = GetPaintWindow(a);
831 if(pPaintWindow->OutputToWindow())
833 OutputDevice& rOutDev = pPaintWindow->GetOutputDevice();
834 tools::Rectangle aRect(rRect);
836 Point aOrg(rOutDev.GetMapMode().GetOrigin());
837 aOrg.setX(-aOrg.X() ); aOrg.setY(-aOrg.Y() );
838 tools::Rectangle aOutRect(aOrg, rOutDev.GetOutputSize());
840 // In case of tiled rendering we want to get all invalidations, so visual area is not interesting.
841 if (aRect.IsOver(aOutRect) || comphelper::LibreOfficeKit::isActive())
843 InvalidateOneWin(rOutDev, aRect);
849 void SdrPaintView::InvalidateOneWin(OutputDevice& rDevice)
851 vcl::Window& rWin(static_cast<vcl::Window&>(rDevice));
852 // do not erase background, that causes flicker (!)
853 rWin.Invalidate(InvalidateFlags::NoErase);
856 void SdrPaintView::InvalidateOneWin(OutputDevice& rDevice, const tools::Rectangle& rRect)
858 vcl::Window& rWin(static_cast<vcl::Window&>(rDevice));
859 // do not erase background, that causes flicker (!)
860 rWin.Invalidate(rRect, InvalidateFlags::NoErase);
863 void SdrPaintView::LeaveOneGroup()
865 if(mpPageView)
867 mpPageView->LeaveOneGroup();
871 void SdrPaintView::LeaveAllGroup()
873 if(mpPageView)
875 mpPageView->LeaveAllGroup();
879 bool SdrPaintView::IsGroupEntered() const
881 if(mpPageView)
883 return (mpPageView->GetEnteredLevel() != 0);
886 return false;
889 void SdrPaintView::SetNotPersistDefaultAttr(const SfxItemSet& rAttr)
891 // bReplaceAll has no effect here at all.
892 bool bMeasure= dynamic_cast<const SdrView*>(this) != nullptr && static_cast<SdrView*>(this)->IsMeasureTool();
893 const SfxPoolItem *pPoolItem=nullptr;
894 if (rAttr.GetItemState(SDRATTR_LAYERID,true,&pPoolItem)==SfxItemState::SET) {
895 SdrLayerID nLayerId=static_cast<const SdrLayerIdItem*>(pPoolItem)->GetValue();
896 const SdrLayer* pLayer=mpModel->GetLayerAdmin().GetLayerPerID(nLayerId);
897 if (pLayer!=nullptr) {
898 if (bMeasure) maMeasureLayer=pLayer->GetName();
899 else maActualLayer=pLayer->GetName();
902 if (rAttr.GetItemState(SDRATTR_LAYERNAME,true,&pPoolItem)==SfxItemState::SET) {
903 if (bMeasure) maMeasureLayer=static_cast<const SdrLayerNameItem*>(pPoolItem)->GetValue();
904 else maActualLayer=static_cast<const SdrLayerNameItem*>(pPoolItem)->GetValue();
908 void SdrPaintView::MergeNotPersistDefaultAttr(SfxItemSet& rAttr) const
910 // bOnlyHardAttr has no effect here at all.
911 bool bMeasure= dynamic_cast<const SdrView*>(this) != nullptr && static_cast<const SdrView*>(this)->IsMeasureTool();
912 const OUString& aNam = bMeasure ? maMeasureLayer : maActualLayer;
913 rAttr.Put(SdrLayerNameItem(aNam));
914 SdrLayerID nLayer=mpModel->GetLayerAdmin().GetLayerID(aNam);
915 if (nLayer!=SDRLAYER_NOTFOUND) {
916 rAttr.Put(SdrLayerIdItem(nLayer));
920 void SdrPaintView::SetDefaultAttr(const SfxItemSet& rAttr, bool bReplaceAll)
922 #ifdef DBG_UTIL
924 bool bHasEEFeatureItems=false;
925 SfxItemIter aIter(rAttr);
926 for (const SfxPoolItem* pItem = aIter.GetCurItem(); !bHasEEFeatureItems && pItem;
927 pItem = aIter.NextItem())
929 if (!IsInvalidItem(pItem)) {
930 sal_uInt16 nW=pItem->Which();
931 if (nW>=EE_FEATURE_START && nW<=EE_FEATURE_END) bHasEEFeatureItems=true;
935 if(bHasEEFeatureItems)
937 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr,
938 VclMessageType::Info, VclButtonsType::Ok,
939 "SdrPaintView::SetDefaultAttr(): Setting EE_FEATURE items at the SdrView does not make sense! It only leads to overhead and unreadable documents."));
940 xInfoBox->run();
943 #endif
944 if (bReplaceAll) maDefaultAttr.Set(rAttr);
945 else maDefaultAttr.Put(rAttr,false); // if FALSE, regard InvalidItems as "holes," not as Default
946 SetNotPersistDefaultAttr(rAttr);
949 void SdrPaintView::SetDefaultStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
951 if (mpDefaultStyleSheet)
952 EndListening(*mpDefaultStyleSheet);
953 mpDefaultStyleSheet=pStyleSheet;
954 if (mpDefaultStyleSheet)
955 StartListening(*mpDefaultStyleSheet);
957 if (pStyleSheet!=nullptr && !bDontRemoveHardAttr) {
958 SfxWhichIter aIter(pStyleSheet->GetItemSet());
959 sal_uInt16 nWhich=aIter.FirstWhich();
960 while (nWhich!=0) {
961 if (pStyleSheet->GetItemSet().GetItemState(nWhich)==SfxItemState::SET) {
962 maDefaultAttr.ClearItem(nWhich);
964 nWhich=aIter.NextWhich();
969 void SdrPaintView::GetAttributes(SfxItemSet& rTargetSet, bool bOnlyHardAttr) const
971 if(bOnlyHardAttr || !mpDefaultStyleSheet)
973 rTargetSet.Put(maDefaultAttr, false);
975 else
977 // else merge with DefStyleSheet
978 rTargetSet.Put(mpDefaultStyleSheet->GetItemSet(), false);
979 rTargetSet.Put(maDefaultAttr, false);
981 MergeNotPersistDefaultAttr(rTargetSet);
984 void SdrPaintView::SetAttributes(const SfxItemSet& rSet, bool bReplaceAll)
986 SetDefaultAttr(rSet,bReplaceAll);
989 SfxStyleSheet* SdrPaintView::GetStyleSheet() const
991 return mpDefaultStyleSheet;
994 void SdrPaintView::SetStyleSheet(SfxStyleSheet* pStyleSheet, bool bDontRemoveHardAttr)
996 SetDefaultStyleSheet(pStyleSheet,bDontRemoveHardAttr);
999 void SdrPaintView::MakeVisible(const tools::Rectangle& rRect, vcl::Window& rWin)
1001 // TODO: handle when the text cursor goes out of the chart area
1002 // However this hack avoids that the cursor gets misplaced wrt the text.
1003 if (comphelper::LibreOfficeKit::isActive() && rWin.IsChart())
1005 return;
1008 MapMode aMap(rWin.GetMapMode());
1009 Size aActualSize(rWin.GetOutputSize());
1011 if( aActualSize.IsEmpty() )
1012 return;
1014 Size aNewSize(rRect.GetSize());
1015 bool bNewScale=false;
1016 bool bNeedMoreX=aNewSize.Width()>aActualSize.Width();
1017 bool bNeedMoreY=aNewSize.Height()>aActualSize.Height();
1018 if (bNeedMoreX || bNeedMoreY)
1020 bNewScale=true;
1021 // set new MapMode (Size+Org) and invalidate everything
1022 Fraction aXFact(aNewSize.Width(),aActualSize.Width());
1023 Fraction aYFact(aNewSize.Height(),aActualSize.Height());
1024 if (aYFact>aXFact) aXFact=aYFact;
1025 aXFact*=aMap.GetScaleX();
1026 aXFact.ReduceInaccurate(10); // to avoid runovers and BigInt mapping
1027 aMap.SetScaleX(aXFact);
1028 aMap.SetScaleY(aYFact);
1029 rWin.SetMapMode(aMap);
1030 aActualSize=rWin.GetOutputSize();
1032 Point aOrg(aMap.GetOrigin());
1033 tools::Long dx=0,dy=0;
1034 tools::Long l=-aOrg.X();
1035 tools::Long r=-aOrg.X()+aActualSize.Width()-1;
1036 tools::Long o=-aOrg.Y();
1037 tools::Long u=-aOrg.Y()+aActualSize.Height()-1;
1038 if (l>rRect.Left()) dx=rRect.Left()-l;
1039 else if (r<rRect.Right()) dx=rRect.Right()-r;
1040 if (o>rRect.Top()) dy=rRect.Top()-o;
1041 else if (u<rRect.Bottom()) dy=rRect.Bottom()-u;
1042 aMap.SetOrigin(Point(aOrg.X()-dx,aOrg.Y()-dy));
1043 if (!bNewScale) {
1044 if (dx!=0 || dy!=0) {
1045 rWin.Scroll(-dx,-dy);
1046 rWin.SetMapMode(aMap);
1047 rWin.PaintImmediately();
1049 } else {
1050 rWin.SetMapMode(aMap);
1051 InvalidateOneWin(rWin);
1055 void SdrPaintView::DoConnect(SdrOle2Obj* /*pOleObj*/)
1059 void SdrPaintView::SetAnimationEnabled( bool bEnable )
1061 SetAnimationMode( bEnable ? SdrAnimationMode::Animate : SdrAnimationMode::Disable );
1064 void SdrPaintView::SetAnimationPause( bool bSet )
1066 if(mbAnimationPause == bSet)
1067 return;
1069 mbAnimationPause = bSet;
1071 if(!mpPageView)
1072 return;
1074 for(sal_uInt32 b(0); b < mpPageView->PageWindowCount(); b++)
1076 SdrPageWindow& rPageWindow = *(mpPageView->GetPageWindow(b));
1077 sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact();
1078 sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator();
1080 if(rAnimator.IsPaused() != bSet)
1082 rAnimator.SetPaused(bSet);
1087 void SdrPaintView::SetAnimationMode( const SdrAnimationMode eMode )
1089 meAnimationMode = eMode;
1092 void SdrPaintView::VisAreaChanged(const OutputDevice* pOut)
1094 if(!mpPageView)
1095 return;
1097 if (pOut)
1099 SdrPageWindow* pWindow = mpPageView->FindPageWindow(*const_cast<OutputDevice*>(pOut));
1101 if(pWindow)
1103 VisAreaChanged();
1106 else
1108 VisAreaChanged();
1112 void SdrPaintView::VisAreaChanged()
1114 // notify SfxListener
1115 Broadcast(SvxViewChangedHint());
1119 void SdrPaintView::onChangeColorConfig()
1121 maGridColor = maColorConfig.GetColorValue( svtools::DRAWGRID ).nColor;
1125 // Set background color for svx at SdrPageViews
1126 void SdrPaintView::SetApplicationBackgroundColor(Color aBackgroundColor)
1128 if(mpPageView)
1130 mpPageView->SetApplicationBackgroundColor(aBackgroundColor);
1134 // Set document color for svx at SdrPageViews
1135 void SdrPaintView::SetApplicationDocumentColor(Color aDocumentColor)
1137 if(mpPageView)
1139 mpPageView->SetApplicationDocumentColor(aDocumentColor);
1143 bool SdrPaintView::IsBufferedOutputAllowed() const
1145 return (mbBufferedOutputAllowed && maDrawinglayerOpt.IsPaintBuffer());
1148 void SdrPaintView::SetBufferedOutputAllowed(bool bNew)
1150 if(bNew != mbBufferedOutputAllowed)
1152 mbBufferedOutputAllowed = bNew;
1156 bool SdrPaintView::IsBufferedOverlayAllowed() const
1158 return (mbBufferedOverlayAllowed && maDrawinglayerOpt.IsOverlayBuffer());
1161 void SdrPaintView::SetBufferedOverlayAllowed(bool bNew)
1163 if(bNew != mbBufferedOverlayAllowed)
1165 mbBufferedOverlayAllowed = bNew;
1170 void SdrPaintView::SetPagePaintingAllowed(bool bNew)
1172 if(bNew != mbPagePaintingAllowed)
1174 mbPagePaintingAllowed = bNew;
1178 // #i38135# Sets the timer for Object animations and restarts.
1179 void SdrPaintView::SetAnimationTimer(sal_uInt32 nTime)
1181 if(mpPageView)
1183 // first, reset all timers at all windows to 0L
1184 for(sal_uInt32 a(0); a < mpPageView->PageWindowCount(); a++)
1186 SdrPageWindow& rPageWindow = *mpPageView->GetPageWindow(a);
1187 sdr::contact::ObjectContact& rObjectContact = rPageWindow.GetObjectContact();
1188 sdr::animation::primitiveAnimator& rAnimator = rObjectContact.getPrimitiveAnimator();
1189 rAnimator.SetTime(nTime);
1194 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */