1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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();
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());
102 SvxViewChangedHint::SvxViewChangedHint() : SfxHint(SfxHintId::SvxViewChanged
)
107 BitmapEx
convertMetafileToBitmapEx(
108 const GDIMetaFile
& rMtf
,
109 const basegfx::B2DRange
& rTargetRange
,
110 const sal_uInt32 nMaximumQuadraticPixels
)
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()),
122 aBitmapEx
= drawinglayer::convertPrimitive2DContainerToBitmapEx(
123 drawinglayer::primitive2d::Primitive2DContainer
{ aMtf
},
125 nMaximumQuadraticPixels
);
131 SdrPaintView::SdrPaintView(SdrModel
& rSdrModel
, OutputDevice
* pOut
)
133 , mpActualOutDev(nullptr)
135 , mpDefaultStyleSheet(nullptr)
136 , maDefaultAttr(rSdrModel
.GetItemPool())
137 , maComeBackIdle( "svx::SdrPaintView aComeBackIdle" )
138 , meAnimationMode(SdrAnimationMode::Animate
)
143 , mbPageVisible(true)
144 , mbPageShadowVisible(true)
145 , mbPageBorderVisible(true)
146 , mbBordVisible(true)
147 , mbGridVisible(true)
149 , mbHlplVisible(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)
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);
178 AddDeviceToPaintView(*pOut
, nullptr);
180 maColorConfig
.AddListener(this);
181 onChangeColorConfig();
184 SdrPaintView::~SdrPaintView()
186 if (mpDefaultStyleSheet
)
187 EndListening(*mpDefaultStyleSheet
);
189 maColorConfig
.RemoveListener(this);
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;
207 if (rHint
.GetId() != SfxHintId::ThisIsAnSdrHint
)
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
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
)
234 void SdrPaintView::ConfigurationChanged( ::utl::ConfigurationBroadcaster
* , ConfigurationHints eHint
)
236 if (eHint
== ConfigurationHints::OnlyCurrentDocumentColorScheme
)
238 onChangeColorConfig();
242 IMPL_LINK_NOARG(SdrPaintView
, ImpComeBackHdl
, Timer
*, void)
244 if (mbSomeObjChgdFlag
) {
245 mbSomeObjChgdFlag
=false;
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())
267 // test mpPageView here again, HideSdrPage() may have invalidated it.
270 mpPageView
->ModelHasChanged();
275 bool SdrPaintView::IsAction() const
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
307 sal_uInt16
SdrPaintView::ImpGetMinMovLogic(short nMinMov
, const OutputDevice
* pOut
) const
309 if (nMinMov
>=0) return sal_uInt16(nMinMov
);
312 pOut
= GetFirstOutputDevice();
315 return short(-pOut
->PixelToLogic(Size(nMinMov
,0)).Width());
321 sal_uInt16
SdrPaintView::ImpGetHitTolLogic(short nHitTol
, const OutputDevice
* pOut
) const
323 if (nHitTol
>=0) return sal_uInt16(nHitTol
);
326 pOut
= GetFirstOutputDevice();
329 return short(-pOut
->PixelToLogic(Size(nHitTol
,0)).Width());
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());
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
);
358 void SdrPaintView::ClearPageView()
369 SdrPageView
* SdrPaintView::ShowSdrPage(SdrPage
* pPage
)
371 if(pPage
&& (!mpPageView
|| mpPageView
->GetPage() != pPage
))
379 if (SdrView
*pView
= dynamic_cast<SdrView
*>(this))
381 mpPageView
.reset(new SdrPageView(pPage
, *pView
));
386 return mpPageView
.get();
389 void SdrPaintView::HideSdrPage()
398 void SdrPaintView::AddDeviceToPaintView(OutputDevice
& rNewDev
, vcl::Window
*pWindow
)
400 SdrPaintWindow
* pNewPaintWindow
= new SdrPaintWindow(*this, rNewDev
, pWindow
);
401 maPaintWindows
.emplace_back(pNewPaintWindow
);
405 mpPageView
->AddPaintWindowToPageView(*pNewPaintWindow
);
409 void SdrPaintView::DeleteDeviceFromPaintView(OutputDevice
& rOldDev
)
411 SdrPaintWindow
* pCandidate
= FindPaintWindow(rOldDev
);
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
);
432 bool SdrPaintView::IsLayerVisible(const OUString
& rName
) const
434 return mpPageView
&& mpPageView
->IsLayerVisible(rName
);
437 void SdrPaintView::SetLayerLocked(const OUString
& rName
, bool bLock
)
441 mpPageView
->SetLayerLocked(rName
,bLock
);
445 bool SdrPaintView::IsLayerLocked(const OUString
& rName
) const
449 return mpPageView
->IsLayerLocked(rName
);
455 void SdrPaintView::SetLayerPrintable(const OUString
& rName
, bool bPrn
)
459 mpPageView
->SetLayerPrintable(rName
,bPrn
);
463 bool SdrPaintView::IsLayerPrintable(const OUString
& rName
) const
467 return mpPageView
->IsLayerPrintable(rName
);
473 void SdrPaintView::PrePaint()
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());
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
535 const sal_uInt64
nStopTime(tools::Time::GetSystemTicks());
536 const sal_uInt64
nNeededTime(nStopTime
- nStartTime
);
537 const double fTimePerPaint((double)nNeededTime
/ (double)nRepeatCount
);
541 for(a
= 0; a
< REMEMBERED_TIMES_COUNT
; a
++)
543 fLastTimes
[a
] = fTimePerPaint
;
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
586 SdrPaintWindow
* SdrPaintView::BeginCompleteRedraw(OutputDevice
* pOut
)
588 assert(pOut
&& "SdrPaintView::BeginCompleteRedraw: No OutDev (!)");
589 SdrPaintWindow
* pPaintWindow
= FindPaintWindow(*pOut
);
593 // draw preprocessing, only for known devices
594 // prepare PreRendering
595 pPaintWindow
->PreparePreRenderDevice();
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);
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
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
;
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
)
669 if (pView
->IsTextEdit() && pView
->GetSdrPageView())
671 pView
->TextEditDrawing(rPaintWindow
);
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 (!)");
693 SdrPageWindow
* pKnownTarget
= mpPageView
->FindPageWindow(*pPaintWindow
);
697 vcl::Region aOptimizedRepaintRegion
= OptimizeDrawLayersRegion( pOut
, rReg
, bDisableIntersect
);
700 pKnownTarget
->PrepareRedraw(aOptimizedRepaintRegion
);
702 // remember prepared SdrPageWindow
703 mpPageView
->setPreparedPageWindow(pKnownTarget
);
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
);
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 (!)");
730 SdrPageWindow
* pKnownTarget
= mpPageView
->FindPageWindow(*pPaintWindow
);
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
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
)
775 SdrPageWindow
* pKnownTarget
= mpPageView
->FindPageWindow(rPaintWindow
);
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(),
788 mpPageView
->setPreparedPageWindow(nullptr);
793 bool SdrPaintView::KeyInput(const KeyEvent
& /*rKEvt*/, vcl::Window
* /*pWin*/)
798 void SdrPaintView::GlueInvalidate() const
800 // Do not invalidate GluePoints in Online
801 // They are handled on front-end
802 if (comphelper::LibreOfficeKit::isActive())
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();
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
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()
891 mpPageView
->LeaveOneGroup();
895 void SdrPaintView::LeaveAllGroup()
899 mpPageView
->LeaveAllGroup();
903 bool SdrPaintView::IsGroupEntered() const
907 return (mpPageView
->GetEnteredLevel() != 0);
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
)
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
));
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();
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);
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())
1034 MapMode
aMap(rWin
.GetMapMode());
1035 Size
aActualSize(rWin
.GetOutDev()->GetOutputSize());
1037 if( aActualSize
.IsEmpty() )
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
)
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
));
1070 if (dx
!=0 || dy
!=0) {
1071 rWin
.Scroll(-dx
,-dy
);
1072 rWin
.SetMapMode(aMap
);
1073 rWin
.PaintImmediately();
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
)
1095 mbAnimationPause
= bSet
;
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
)
1125 SdrPageWindow
* pWindow
= mpPageView
->FindPageWindow(*const_cast<OutputDevice
*>(pOut
));
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
)
1156 mpPageView
->SetApplicationBackgroundColor(aBackgroundColor
);
1160 // Set document color for svx at SdrPageViews
1161 void SdrPaintView::SetApplicationDocumentColor(Color aDocumentColor
)
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
)
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: */