LibreOffice Module sd (master) 1
SlsInsertionIndicatorOverlay.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21
22#include <SlideSorter.hxx>
24#include <view/SlsLayouter.hxx>
26#include <view/SlsTheme.hxx>
27#include "SlsFramePainter.hxx"
28#include "SlsLayeredDevice.hxx"
29#include <DrawDocShell.hxx>
30#include <drawdoc.hxx>
31#include <Window.hxx>
32
33#include <o3tl/safeint.hxx>
34#include <rtl/math.hxx>
35#include <vcl/virdev.hxx>
39
40namespace {
41
42const double gnPreviewOffsetScale = 1.0 / 8.0;
43
44::tools::Rectangle GrowRectangle (const ::tools::Rectangle& rBox, const sal_Int32 nOffset)
45{
46 return ::tools::Rectangle (
47 rBox.Left() - nOffset,
48 rBox.Top() - nOffset,
49 rBox.Right() + nOffset,
50 rBox.Bottom() + nOffset);
51}
52
53sal_Int32 RoundToInt (const double nValue) { return sal_Int32(::rtl::math::round(nValue)); }
54
55} // end of anonymous namespace
56
57namespace sd::slidesorter::view {
58
59//===== InsertionIndicatorOverlay ===========================================
60
61const sal_Int32 gnShadowBorder = 3;
62const sal_Int32 gnLayerIndex = 2;
63
65 : mrSlideSorter(rSlideSorter),
66 mbIsVisible(false),
67 mpShadowPainter(
68 new FramePainter(mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_RawInsertShadow)))
69{
70}
71
73{
74 // cid#1491947 silence Uncaught exception
76}
77
79{
80 if (pTransferable == nullptr)
81 return;
82
83 std::shared_ptr<controller::TransferableData> pData (
85 if ( ! pData)
86 return;
87 sal_Int32 nSelectionCount (0);
88 if (pTransferable->HasPageBookmarks())
89 nSelectionCount = pTransferable->GetPageBookmarks().size();
90 else
91 {
92 DrawDocShell* pDataDocShell = dynamic_cast<DrawDocShell*>(pTransferable->GetDocShell().get());
93 if (pDataDocShell != nullptr)
94 {
95 SdDrawDocument* pDataDocument = pDataDocShell->GetDoc();
96 if (pDataDocument != nullptr)
97 nSelectionCount = pDataDocument->GetSdPageCount(PageKind::Standard);
98 }
99 }
100 Create(pData->GetRepresentatives(), nSelectionCount);
101}
102
104 const ::std::vector<controller::TransferableData::Representative>& rRepresentatives,
105 const sal_Int32 nSelectionCount)
106{
108 const std::shared_ptr<view::PageObjectLayouter>& pPageObjectLayouter (
109 rLayouter.GetPageObjectLayouter());
110 std::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
111 const Size aOriginalPreviewSize (pPageObjectLayouter->GetPreviewSize());
112
113 const double nPreviewScale (0.5);
114 const Size aPreviewSize (
115 RoundToInt(aOriginalPreviewSize.Width()*nPreviewScale),
116 RoundToInt(aOriginalPreviewSize.Height()*nPreviewScale));
117 const sal_Int32 nOffset (
118 RoundToInt(std::min(aPreviewSize.Width(),aPreviewSize.Height()) * gnPreviewOffsetScale));
119
120 // Determine size and offset depending on the number of previews.
121 sal_Int32 nCount (rRepresentatives.size());
122 if (nCount > 0)
123 --nCount;
124 Size aIconSize(
125 aPreviewSize.Width() + 2 * gnShadowBorder + nCount*nOffset,
126 aPreviewSize.Height() + 2 * gnShadowBorder + nCount*nOffset);
127
128 // Create virtual devices for bitmap and mask whose bitmaps later be
129 // combined to form the BitmapEx of the icon.
131 *mrSlideSorter.GetContentWindow()->GetOutDev(), DeviceFormat::WITH_ALPHA);
132 pContent->SetOutputSizePixel(aIconSize);
133
134 pContent->SetFillColor();
135 pContent->SetLineColor(pTheme->GetColor(Theme::Color_PreviewBorder));
136 const Point aOffset = PaintRepresentatives(*pContent, aPreviewSize, nOffset, rRepresentatives);
137
138 PaintPageCount(*pContent, nSelectionCount, aPreviewSize, aOffset);
139
140 maIcon = pContent->GetBitmapEx(Point(0,0), aIconSize);
141 maIcon.Scale(aIconSize);
142}
143
145 OutputDevice& rContent,
146 const Size& rPreviewSize,
147 const sal_Int32 nOffset,
148 const ::std::vector<controller::TransferableData::Representative>& rRepresentatives) const
149{
150 const Point aOffset (0,rRepresentatives.size()==1 ? -nOffset : 0);
151
152 // Paint the pages.
153 Point aPageOffset (0,0);
154 double nTransparency (0);
155 const BitmapEx aExclusionOverlay (mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_HideSlideOverlay));
156 for (sal_Int32 nIndex=2; nIndex>=0; --nIndex)
157 {
158 if (rRepresentatives.size() <= o3tl::make_unsigned(nIndex))
159 continue;
160 switch(nIndex)
161 {
162 case 0 :
163 aPageOffset = Point(0, nOffset);
164 nTransparency = 0.85;
165 break;
166 case 1:
167 aPageOffset = Point(nOffset, 0);
168 nTransparency = 0.75;
169 break;
170 case 2:
171 aPageOffset = Point(2*nOffset, 2*nOffset);
172 nTransparency = 0.65;
173 break;
174 }
175 aPageOffset += aOffset;
176 aPageOffset.AdjustX(gnShadowBorder );
177 aPageOffset.AdjustY(gnShadowBorder );
178
179 // Paint the preview.
180 BitmapEx aPreview (rRepresentatives[nIndex].maBitmap);
181 aPreview.Scale(rPreviewSize, BmpScaleFlag::BestQuality);
182 rContent.DrawBitmapEx(aPageOffset, aPreview);
183
184 // When the page is marked as excluded from the slide show then
185 // paint an overlay that visualizes this.
186 if (rRepresentatives[nIndex].mbIsExcluded)
187 {
188 const vcl::Region aSavedClipRegion (rContent.GetClipRegion());
189 rContent.IntersectClipRegion(::tools::Rectangle(aPageOffset, rPreviewSize));
190 // Paint bitmap tiled over the preview to mark it as excluded.
191 const sal_Int32 nIconWidth (aExclusionOverlay.GetSizePixel().Width());
192 const sal_Int32 nIconHeight (aExclusionOverlay.GetSizePixel().Height());
193 if (nIconWidth>0 && nIconHeight>0)
194 {
195 for (::tools::Long nX=0; nX<rPreviewSize.Width(); nX+=nIconWidth)
196 for (::tools::Long nY=0; nY<rPreviewSize.Height(); nY+=nIconHeight)
197 rContent.DrawBitmapEx(Point(nX,nY)+aPageOffset, aExclusionOverlay);
198 }
199 rContent.SetClipRegion(aSavedClipRegion);
200 }
201
202 // Tone down the bitmap. The further back the darker it becomes.
203 ::tools::Rectangle aBox (
204 aPageOffset.X(),
205 aPageOffset.Y(),
206 aPageOffset.X()+rPreviewSize.Width()-1,
207 aPageOffset.Y()+rPreviewSize.Height()-1);
208 rContent.SetFillColor(COL_BLACK);
209 rContent.SetLineColor();
210 rContent.DrawTransparent(
212 ::basegfx::B2DPolyPolygon(::basegfx::utils::createPolygonFromRect(
213 ::basegfx::B2DRectangle(aBox.Left(), aBox.Top(), aBox.Right()+1, aBox.Bottom()+1),
214 0,
215 0)),
216 nTransparency);
217
218 // Draw border around preview.
219 ::tools::Rectangle aBorderBox (GrowRectangle(aBox, 1));
220 rContent.SetLineColor(COL_GRAY);
221 rContent.SetFillColor();
222 rContent.DrawRect(aBorderBox);
223
224 // Draw shadow around preview.
225 mpShadowPainter->PaintFrame(rContent, aBorderBox);
226 }
227
228 return aPageOffset;
229}
230
232 OutputDevice& rDevice,
233 const sal_Int32 nSelectionCount,
234 const Size& rPreviewSize,
235 const Point& rFirstPageOffset) const
236{
237 // Paint the number of slides.
238 std::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
239 std::shared_ptr<vcl::Font> pFont(Theme::GetFont(Theme::Font_PageCount, rDevice));
240 if (!pFont)
241 return;
242
243 OUString sNumber (OUString::number(nSelectionCount));
244
245 // Determine the size of the (painted) text and create a bounding
246 // box that centers the text on the first preview.
247 rDevice.SetFont(*pFont);
248 ::tools::Rectangle aTextBox;
249 rDevice.GetTextBoundRect(aTextBox, sNumber);
250 Point aTextOffset (aTextBox.TopLeft());
251 Size aTextSize (aTextBox.GetSize());
252 // Place text inside the first page preview.
253 Point aTextLocation(rFirstPageOffset);
254 // Center the text.
255 aTextLocation += Point(
256 (rPreviewSize.Width()-aTextBox.GetWidth())/2,
257 (rPreviewSize.Height()-aTextBox.GetHeight())/2);
258 aTextBox = ::tools::Rectangle(aTextLocation, aTextSize);
259
260 // Paint background, border and text.
261 static const sal_Int32 nBorder = 5;
262 rDevice.SetFillColor(pTheme->GetColor(Theme::Color_Selection));
263 rDevice.SetLineColor(pTheme->GetColor(Theme::Color_Selection));
264 rDevice.DrawRect(GrowRectangle(aTextBox, nBorder));
265
266 rDevice.SetFillColor();
267 rDevice.SetLineColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
268 rDevice.DrawRect(GrowRectangle(aTextBox, nBorder-1));
269
270 rDevice.SetTextColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
271 rDevice.DrawText(aTextBox.TopLeft()-aTextOffset, sNumber);
272}
273
275{
276 const Point aTopLeft (
277 rLocation - Point(
279 maIcon.GetSizePixel().Height()/2));
280 if (maLocation != aTopLeft)
281 {
282 const ::tools::Rectangle aOldBoundingBox (GetBoundingBox());
283
284 maLocation = aTopLeft;
285
287 {
288 mpLayerInvalidator->Invalidate(aOldBoundingBox);
289 mpLayerInvalidator->Invalidate(GetBoundingBox());
290 }
291 }
292}
293
295 OutputDevice& rDevice,
296 const ::tools::Rectangle&)
297{
298 if ( ! IsVisible())
299 return;
300
301 rDevice.DrawImage(maLocation, Image(maIcon));
302}
303
305{
306 mpLayerInvalidator = rpInvalidator;
307
309 mpLayerInvalidator->Invalidate(GetBoundingBox());
310}
311
313{
314 if ( mbIsVisible)
315 return;
316
317 mbIsVisible = true;
318
319 std::shared_ptr<LayeredDevice> pLayeredDevice (
321 if (pLayeredDevice)
322 {
323 pLayeredDevice->RegisterPainter(shared_from_this(), gnLayerIndex);
325 mpLayerInvalidator->Invalidate(GetBoundingBox());
326 }
327}
328
330{
331 if (!mbIsVisible)
332 return;
333
334 mbIsVisible = false;
335
336 std::shared_ptr<LayeredDevice> pLayeredDevice (
338 if (pLayeredDevice)
339 {
341 mpLayerInvalidator->Invalidate(GetBoundingBox());
342 pLayeredDevice->RemovePainter(shared_from_this(), gnLayerIndex);
343 }
344}
345
347{
348 return ::tools::Rectangle(maLocation, maIcon.GetSizePixel());
349}
350
352{
353 return Size(
354 maIcon.GetSizePixel().Width() + 10,
355 maIcon.GetSizePixel().Height() + 10);
356}
357
358} // end of namespace ::sd::slidesorter::view
359
360/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SlideSorter & mrSlideSorter
bool Scale(const Size &rNewSize, BmpScaleFlag nScaleFlag=BmpScaleFlag::Default)
const Size & GetSizePixel() const
vcl::Region GetClipRegion() const
void DrawBitmapEx(const Point &rDestPt, const BitmapEx &rBitmapEx)
void SetFont(const vcl::Font &rNewFont)
void DrawRect(const tools::Rectangle &rRect)
bool GetTextBoundRect(tools::Rectangle &rRect, const OUString &rStr, sal_Int32 nBase=0, sal_Int32 nIndex=0, sal_Int32 nLen=-1, sal_uLong nLayoutWidth=0, KernArraySpan aDXArray=KernArraySpan(), o3tl::span< const sal_Bool > pKashidaArray={}, const SalLayoutGlyphs *pGlyphs=nullptr) const
void SetLineColor()
void SetTextColor(const Color &rColor)
void SetClipRegion()
void DrawImage(const Point &rPos, const Image &rImage, DrawImageFlags nStyle=DrawImageFlags::NONE)
void SetFillColor()
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
void DrawTransparent(const tools::PolyPolygon &rPolyPoly, sal_uInt16 nTransparencePercent)
void IntersectClipRegion(const tools::Rectangle &rRect)
constexpr tools::Long Y() const
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
sal_uInt16 GetSdPageCount(PageKind ePgKind) const
Definition: drawdoc2.cxx:212
const SfxObjectShellRef & GetDocShell() const
Definition: sdxfer.hxx:48
bool HasPageBookmarks() const
Definition: sdxfer.hxx:68
const std::vector< OUString > & GetPageBookmarks() const
Definition: sdxfer.hxx:69
constexpr tools::Long Height() const
constexpr tools::Long Width() const
SdDrawDocument * GetDoc()
Show previews for all the slides in a document and allow the user to insert or delete slides and modi...
Definition: SlideSorter.hxx:62
std::shared_ptr< view::Theme > const & GetTheme() const
Return the active theme which gives access to colors and fonts.
const VclPtr< sd::Window > & GetContentWindow() const
Return the content window.
Definition: SlideSorter.hxx:99
view::SlideSorterView & GetView() const
static std::shared_ptr< TransferableData > GetFromTransferable(const SdTransferable *pTransferable)
Point PaintRepresentatives(OutputDevice &rContent, const Size &rPreviewSize, const sal_Int32 nOffset, const ::std::vector< controller::TransferableData::Representative > &rPages) const
virtual void SetLayerInvalidator(const SharedILayerInvalidator &rpInvalidator) override
void SetLocation(const Point &rPosition)
Given a position in model coordinates this method calculates the insertion marker both as an index in...
virtual void Paint(OutputDevice &rDevice, const ::tools::Rectangle &rRepaintArea) override
void PaintPageCount(OutputDevice &rDevice, const sal_Int32 nSelectionCount, const Size &rPreviewSize, const Point &rFirstPageOffset) const
Calculate the size and position of page objects displayed by a slide sorter.
Definition: SlsLayouter.hxx:60
std::shared_ptr< PageObjectLayouter > const & GetPageObjectLayouter() const
const std::shared_ptr< LayeredDevice > & GetLayeredDevice() const
Collection of colors and styles that are used to paint the slide sorter view.
Definition: SlsTheme.hxx:39
static std::shared_ptr< vcl::Font > GetFont(const FontType eType, const OutputDevice &rDevice)
Definition: SlsTheme.cxx:118
constexpr tools::Long GetWidth() const
constexpr tools::Long Top() const
constexpr Point TopLeft() const
constexpr Size GetSize() const
constexpr tools::Long Right() const
constexpr tools::Long GetHeight() const
constexpr tools::Long Left() const
constexpr tools::Long Bottom() const
T * get() const
constexpr ::Color COL_GRAY(0x80, 0x80, 0x80)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
int nCount
#define suppress_fun_call_w_exception(expr)
sal_Int32 nIndex
std::unique_ptr< sal_Int32[]> pData
tools::Long const nBorder
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
std::shared_ptr< ILayerInvalidator > SharedILayerInvalidator
long Long