1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_sd.hxx"
25 
26 #include "view/SlsPageObjectPainter.hxx"
27 
28 #include "model/SlsPageDescriptor.hxx"
29 #include "view/SlideSorterView.hxx"
30 #include "view/SlsPageObjectLayouter.hxx"
31 #include "view/SlsLayouter.hxx"
32 #include "view/SlsTheme.hxx"
33 #include "view/SlsButtonBar.hxx"
34 #include "SlsFramePainter.hxx"
35 #include "cache/SlsPageCache.hxx"
36 #include "controller/SlsProperties.hxx"
37 #include "Window.hxx"
38 #include "sdpage.hxx"
39 #include "sdresid.hxx"
40 #include <vcl/svapp.hxx>
41 #include <vcl/vclenum.hxx>
42 #include <vcl/virdev.hxx>
43 #include <boost/scoped_ptr.hpp>
44 
45 using namespace ::drawinglayer::primitive2d;
46 
47 namespace sd { namespace slidesorter { namespace view {
48 
49 namespace {
50 
Blend(const sal_uInt8 nValue1,const sal_uInt8 nValue2,const double nWeight)51 sal_uInt8 Blend (
52     const sal_uInt8 nValue1,
53     const sal_uInt8 nValue2,
54     const double nWeight)
55 {
56     const double nValue (nValue1*(1-nWeight) + nValue2 * nWeight);
57     if (nValue < 0)
58         return 0;
59     else if (nValue > 255)
60         return 255;
61     else
62         return (sal_uInt8)nValue;
63 }
64 
ClampColorChannel(const double nValue)65 sal_uInt8 ClampColorChannel (const double nValue)
66 {
67     if (nValue <= 0)
68         return 0;
69     else if (nValue >= 255)
70         return 255;
71     else
72         return sal_uInt8(nValue);
73 }
74 
CalculateColorChannel(const double nColor1,const double nColor2,const double nAlpha1,const double nAlpha2,const double nAlpha0)75 sal_uInt8 CalculateColorChannel(
76     const double nColor1,
77     const double nColor2,
78     const double nAlpha1,
79     const double nAlpha2,
80     const double nAlpha0)
81 {
82     if (nAlpha0 == 0)
83         return 0;
84 
85     const double nColor0 ((nAlpha1*nColor1 + nAlpha1*nAlpha2*nColor1 + nAlpha2*nColor2) / nAlpha0);
86     return ClampColorChannel(255 * nColor0);
87 }
88 
89 } // end of anonymous namespace
90 
91 
92 
93 
94 //===== PageObjectPainter =====================================================
95 
PageObjectPainter(const SlideSorter & rSlideSorter)96 PageObjectPainter::PageObjectPainter (
97     const SlideSorter& rSlideSorter)
98     : mrLayouter(rSlideSorter.GetView().GetLayouter()),
99       mpPageObjectLayouter(),
100       mpCache(rSlideSorter.GetView().GetPreviewCache()),
101       mpProperties(rSlideSorter.GetProperties()),
102       mpTheme(rSlideSorter.GetTheme()),
103       mpPageNumberFont(Theme::GetFont(Theme::Font_PageNumber, *rSlideSorter.GetContentWindow())),
104       mpShadowPainter(new FramePainter(mpTheme->GetIcon(Theme::Icon_RawShadow))),
105       mpFocusBorderPainter(new FramePainter(mpTheme->GetIcon(Theme::Icon_FocusBorder))),
106       maNormalBackground(),
107       maSelectionBackground(),
108       maFocusedSelectionBackground(),
109       maMouseOverBackground(),
110       maMouseOverFocusedBackground(),
111       msUnhideString(mpTheme->GetString(Theme::String_Unhide)),
112       mrButtonBar(rSlideSorter.GetView().GetButtonBar()),
113       maSize()
114 {
115     // Replace the color (not the alpha values) in the focus border with a
116     // color derived from the current selection color.
117     Color aColor (mpTheme->GetColor(Theme::Color_Selection));
118     sal_uInt16 nHue, nSat, nBri;
119     aColor.RGBtoHSB(nHue, nSat, nBri);
120     aColor = Color::HSBtoRGB(nHue, 28, 65);
121     mpFocusBorderPainter->AdaptColor(aColor, true);
122 }
123 
124 
125 
126 
~PageObjectPainter(void)127 PageObjectPainter::~PageObjectPainter (void)
128 {
129 }
130 
131 
132 
133 
PaintPageObject(OutputDevice & rDevice,const model::SharedPageDescriptor & rpDescriptor)134 void PageObjectPainter::PaintPageObject (
135     OutputDevice& rDevice,
136     const model::SharedPageDescriptor& rpDescriptor)
137 {
138     if (UpdatePageObjectLayouter())
139     {
140         // Turn off antialiasing to avoid the bitmaps from being
141         // shifted by fractions of a pixel and thus show blurry edges.
142         const sal_uInt16 nSavedAntialiasingMode (rDevice.GetAntialiasing());
143         rDevice.SetAntialiasing(nSavedAntialiasingMode & ~ANTIALIASING_ENABLE_B2DDRAW);
144 
145         PaintBackground(rDevice, rpDescriptor);
146         PaintPreview(rDevice, rpDescriptor);
147         PaintPageNumber(rDevice, rpDescriptor);
148         PaintTransitionEffect(rDevice, rpDescriptor);
149         mrButtonBar.Paint(rDevice, rpDescriptor);
150 
151         rDevice.SetAntialiasing(nSavedAntialiasingMode);
152     }
153 }
154 
155 
156 
157 
UpdatePageObjectLayouter(void)158 bool PageObjectPainter::UpdatePageObjectLayouter (void)
159 {
160     // The page object layouter is quite volatile. It may have been replaced
161     // since the last call.  Update it now.
162     mpPageObjectLayouter = mrLayouter.GetPageObjectLayouter();
163     if ( ! mpPageObjectLayouter)
164     {
165         OSL_ASSERT(mpPageObjectLayouter);
166         return false;
167     }
168     else
169         return true;
170 }
171 
172 
173 
174 
NotifyResize(const bool bForce)175 void PageObjectPainter::NotifyResize (const bool bForce)
176 {
177     if (bForce || ! mpPageObjectLayouter)
178         InvalidateBitmaps();
179     else if (UpdatePageObjectLayouter())
180     {
181         const Size aSize (mpPageObjectLayouter->GetSize(
182                 PageObjectLayouter::FocusIndicator,
183                 PageObjectLayouter::WindowCoordinateSystem));
184         if ( maSize!=aSize)
185         {
186             maSize = aSize;
187             InvalidateBitmaps();
188         }
189     }
190 }
191 
192 
193 
194 
InvalidateBitmaps(void)195 void PageObjectPainter::InvalidateBitmaps (void)
196 {
197     maNormalBackground.SetEmpty();
198     maSelectionBackground.SetEmpty();
199     maFocusedSelectionBackground.SetEmpty();
200     maFocusedBackground.SetEmpty();
201     maMouseOverBackground.SetEmpty();
202     maMouseOverFocusedBackground.SetEmpty();
203     maMouseOverSelectedAndFocusedBackground.SetEmpty();
204 }
205 
206 
207 
208 
SetTheme(const::boost::shared_ptr<view::Theme> & rpTheme)209 void PageObjectPainter::SetTheme (const ::boost::shared_ptr<view::Theme>& rpTheme)
210 {
211     mpTheme = rpTheme;
212     NotifyResize(true);
213 }
214 
215 
216 
217 
PaintBackground(OutputDevice & rDevice,const model::SharedPageDescriptor & rpDescriptor)218 void PageObjectPainter::PaintBackground (
219     OutputDevice& rDevice,
220     const model::SharedPageDescriptor& rpDescriptor)
221 {
222     const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
223         rpDescriptor,
224         PageObjectLayouter::FocusIndicator,
225         PageObjectLayouter::ModelCoordinateSystem));
226 
227     const Bitmap& rBackground (GetBackgroundForState(rpDescriptor, rDevice));
228     rDevice.DrawBitmap(aBox.TopLeft(), rBackground);
229 
230     // Fill the interior of the preview area with the default background
231     // color of the page.
232     SdPage* pPage = rpDescriptor->GetPage();
233     if (pPage != NULL)
234     {
235         rDevice.SetFillColor(pPage->GetPageBackgroundColor(NULL));
236         rDevice.SetLineColor(pPage->GetPageBackgroundColor(NULL));
237         const Rectangle aPreviewBox (mpPageObjectLayouter->GetBoundingBox(
238             rpDescriptor,
239             PageObjectLayouter::Preview,
240             PageObjectLayouter::ModelCoordinateSystem));
241         rDevice.DrawRect(aPreviewBox);
242     }
243 }
244 
245 
246 
247 
PaintPreview(OutputDevice & rDevice,const model::SharedPageDescriptor & rpDescriptor) const248 void PageObjectPainter::PaintPreview (
249     OutputDevice& rDevice,
250     const model::SharedPageDescriptor& rpDescriptor) const
251 {
252     const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
253         rpDescriptor,
254         PageObjectLayouter::Preview,
255         PageObjectLayouter::ModelCoordinateSystem));
256 
257     if( bool(mpCache))
258     {
259         const SdrPage* pPage = rpDescriptor->GetPage();
260         mpCache->SetPreciousFlag(pPage, true);
261 
262         const Bitmap aPreview (GetPreviewBitmap(rpDescriptor, &rDevice));
263         if ( ! aPreview.IsEmpty())
264         {
265             if (aPreview.GetSizePixel() != aBox.GetSize())
266                 rDevice.DrawBitmap(aBox.TopLeft(), aBox.GetSize(), aPreview);
267             else
268                 rDevice.DrawBitmap(aBox.TopLeft(), aPreview);
269         }
270     }
271 }
272 
273 
274 
275 
CreateMarkedPreview(const Size & rSize,const Bitmap & rPreview,const BitmapEx & rOverlay,const OutputDevice * pReferenceDevice) const276 Bitmap PageObjectPainter::CreateMarkedPreview (
277     const Size& rSize,
278     const Bitmap& rPreview,
279     const BitmapEx& rOverlay,
280     const OutputDevice* pReferenceDevice) const
281 {
282     ::boost::scoped_ptr<VirtualDevice> pDevice;
283     if (pReferenceDevice != NULL)
284         pDevice.reset(new VirtualDevice(*pReferenceDevice));
285     else
286         pDevice.reset(new VirtualDevice());
287     pDevice->SetOutputSizePixel(rSize);
288 
289     pDevice->DrawBitmap(Point(0,0), rSize, rPreview);
290 
291     // Paint bitmap tiled over the preview to mark it as excluded.
292     const sal_Int32 nIconWidth (rOverlay.GetSizePixel().Width());
293     const sal_Int32 nIconHeight (rOverlay.GetSizePixel().Height());
294     if (nIconWidth>0 && nIconHeight>0)
295     {
296         for (sal_Int32 nX=0; nX<rSize.Width(); nX+=nIconWidth)
297             for (sal_Int32 nY=0; nY<rSize.Height(); nY+=nIconHeight)
298                 pDevice->DrawBitmapEx(Point(nX,nY), rOverlay);
299     }
300     return pDevice->GetBitmap(Point(0,0), rSize);
301 }
302 
303 
304 
305 
GetPreviewBitmap(const model::SharedPageDescriptor & rpDescriptor,const OutputDevice * pReferenceDevice) const306 Bitmap PageObjectPainter::GetPreviewBitmap (
307     const model::SharedPageDescriptor& rpDescriptor,
308     const OutputDevice* pReferenceDevice) const
309 {
310     const SdrPage* pPage = rpDescriptor->GetPage();
311     const bool bIsExcluded (rpDescriptor->HasState(model::PageDescriptor::ST_Excluded));
312 
313     if (bIsExcluded)
314     {
315         Bitmap aMarkedPreview (mpCache->GetMarkedPreviewBitmap(pPage,false));
316         const Rectangle aPreviewBox (mpPageObjectLayouter->GetBoundingBox(
317             rpDescriptor,
318             PageObjectLayouter::Preview,
319             PageObjectLayouter::ModelCoordinateSystem));
320         if (aMarkedPreview.IsEmpty() || aMarkedPreview.GetSizePixel()!=aPreviewBox.GetSize())
321         {
322             aMarkedPreview = CreateMarkedPreview(
323                 aPreviewBox.GetSize(),
324                 mpCache->GetPreviewBitmap(pPage,true),
325                 mpTheme->GetIcon(Theme::Icon_HideSlideOverlay),
326                 pReferenceDevice);
327             mpCache->SetMarkedPreviewBitmap(pPage, aMarkedPreview);
328         }
329         return aMarkedPreview;
330     }
331     else
332     {
333         return mpCache->GetPreviewBitmap(pPage,false);
334     }
335 }
336 
337 
338 
339 
PaintPageNumber(OutputDevice & rDevice,const model::SharedPageDescriptor & rpDescriptor) const340 void PageObjectPainter::PaintPageNumber (
341     OutputDevice& rDevice,
342     const model::SharedPageDescriptor& rpDescriptor) const
343 {
344     const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
345         rpDescriptor,
346         PageObjectLayouter::PageNumber,
347         PageObjectLayouter::ModelCoordinateSystem));
348 
349     // Determine the color of the page number.
350     Color aPageNumberColor (mpTheme->GetColor(Theme::Color_PageNumberDefault));
351     if (rpDescriptor->HasState(model::PageDescriptor::ST_MouseOver) ||
352         rpDescriptor->HasState(model::PageDescriptor::ST_Selected))
353     {
354         // Page number is painted on background for hover or selection or
355         // both.  Each of these background colors has a predefined luminance
356         // which is compatible with the PageNumberHover color.
357         aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberHover));
358     }
359     else
360     {
361         const Color aBackgroundColor (mpTheme->GetColor(Theme::Color_Background));
362         const sal_Int32 nBackgroundLuminance (aBackgroundColor.GetLuminance());
363         // When the background color is black then this is interpreted as
364         // high contrast mode and the font color is set to white.
365         if (nBackgroundLuminance == 0)
366             aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberHighContrast));
367         else
368         {
369             // Compare luminance of default page number color and background
370             // color.  When the two are similar then use a darker
371             // (preferred) or brighter font color.
372             const sal_Int32 nFontLuminance (aPageNumberColor.GetLuminance());
373             if (abs(nBackgroundLuminance - nFontLuminance) < 60)
374             {
375                 if (nBackgroundLuminance > nFontLuminance-30)
376                     aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberBrightBackground));
377                 else
378                     aPageNumberColor = Color(mpTheme->GetColor(Theme::Color_PageNumberDarkBackground));
379             }
380         }
381     }
382 
383     // Paint the page number.
384     OSL_ASSERT(rpDescriptor->GetPage()!=NULL);
385     const sal_Int32 nPageNumber ((rpDescriptor->GetPage()->GetPageNum() - 1) / 2 + 1);
386     const String sPageNumber (String::CreateFromInt32(nPageNumber));
387     rDevice.SetFont(*mpPageNumberFont);
388     rDevice.SetTextColor(aPageNumberColor);
389     rDevice.DrawText(aBox, sPageNumber, TEXT_DRAW_RIGHT | TEXT_DRAW_VCENTER);
390 }
391 
392 
393 
394 
PaintTransitionEffect(OutputDevice & rDevice,const model::SharedPageDescriptor & rpDescriptor) const395 void PageObjectPainter::PaintTransitionEffect (
396     OutputDevice& rDevice,
397     const model::SharedPageDescriptor& rpDescriptor) const
398 {
399     const SdPage* pPage = rpDescriptor->GetPage();
400     if (pPage!=NULL && pPage->getTransitionType() > 0)
401     {
402         const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
403             rpDescriptor,
404             PageObjectLayouter::TransitionEffectIndicator,
405             PageObjectLayouter::ModelCoordinateSystem));
406 
407         rDevice.DrawBitmapEx(
408             aBox.TopLeft(),
409             mpPageObjectLayouter->GetTransitionEffectIcon().GetBitmapEx());
410     }
411 }
412 
413 
414 
415 
GetBackgroundForState(const model::SharedPageDescriptor & rpDescriptor,const OutputDevice & rReferenceDevice)416 Bitmap& PageObjectPainter::GetBackgroundForState (
417     const model::SharedPageDescriptor& rpDescriptor,
418     const OutputDevice& rReferenceDevice)
419 {
420     enum State { None = 0x00, Selected = 0x01, MouseOver = 0x02, Focused = 0x04 };
421     const int eState =
422           (rpDescriptor->HasState(model::PageDescriptor::ST_Selected) ? Selected : None)
423         | (rpDescriptor->HasState(model::PageDescriptor::ST_MouseOver) ? MouseOver : None)
424         | (rpDescriptor->HasState(model::PageDescriptor::ST_Focused) ? Focused : None);
425 
426     switch (eState)
427     {
428         case MouseOver | Selected | Focused:
429             return GetBackground(
430                 maMouseOverSelectedAndFocusedBackground,
431                 Theme::Gradient_MouseOverSelectedAndFocusedPage,
432                 rReferenceDevice,
433                 true);
434 
435         case MouseOver | Selected:
436         case MouseOver:
437             return GetBackground(
438                 maMouseOverBackground,
439                 Theme::Gradient_MouseOverPage,
440                 rReferenceDevice,
441                 false);
442 
443         case MouseOver | Focused:
444             return GetBackground(
445                 maMouseOverFocusedBackground,
446                 Theme::Gradient_MouseOverPage,
447                 rReferenceDevice,
448                 true);
449 
450         case Selected | Focused:
451             return GetBackground(
452                 maFocusedSelectionBackground,
453                 Theme::Gradient_SelectedAndFocusedPage,
454                 rReferenceDevice,
455                 true);
456 
457         case Selected:
458             return GetBackground(
459                 maSelectionBackground,
460                 Theme::Gradient_SelectedPage,
461                 rReferenceDevice,
462                 false);
463 
464         case Focused:
465             return GetBackground(
466                 maFocusedBackground,
467                 Theme::Gradient_FocusedPage,
468                 rReferenceDevice,
469                 true);
470 
471         case None:
472         default:
473             return GetBackground(
474                 maNormalBackground,
475                 Theme::Gradient_NormalPage,
476                 rReferenceDevice,
477                 false);
478     }
479 }
480 
481 
482 
483 
GetBackground(Bitmap & rBackground,Theme::GradientColorType eType,const OutputDevice & rReferenceDevice,const bool bHasFocusBorder)484 Bitmap& PageObjectPainter::GetBackground(
485     Bitmap& rBackground,
486     Theme::GradientColorType eType,
487     const OutputDevice& rReferenceDevice,
488     const bool bHasFocusBorder)
489 {
490     if (rBackground.IsEmpty())
491         rBackground = CreateBackgroundBitmap(rReferenceDevice, eType, bHasFocusBorder);
492     return rBackground;
493 }
494 
495 
496 
497 
CreateBackgroundBitmap(const OutputDevice & rReferenceDevice,const Theme::GradientColorType eColorType,const bool bHasFocusBorder) const498 Bitmap PageObjectPainter::CreateBackgroundBitmap(
499     const OutputDevice& rReferenceDevice,
500     const Theme::GradientColorType eColorType,
501     const bool bHasFocusBorder) const
502 {
503     const Size aSize (mpPageObjectLayouter->GetSize(
504         PageObjectLayouter::FocusIndicator,
505         PageObjectLayouter::WindowCoordinateSystem));
506     const Rectangle aPageObjectBox (mpPageObjectLayouter->GetBoundingBox(
507         Point(0,0),
508         PageObjectLayouter::PageObject,
509         PageObjectLayouter::ModelCoordinateSystem));
510     VirtualDevice aBitmapDevice (rReferenceDevice);
511     aBitmapDevice.SetOutputSizePixel(aSize);
512 
513     // Fill the background with the background color of the slide sorter.
514     const Color aBackgroundColor (mpTheme->GetColor(Theme::Color_Background));
515     aBitmapDevice.SetFillColor(aBackgroundColor);
516     aBitmapDevice.SetLineColor(aBackgroundColor);
517     aBitmapDevice.DrawRect(Rectangle(Point(0,0), aSize));
518 
519     // Paint the slide area with a linear gradient that starts some pixels
520     // below the top and ends some pixels above the bottom.
521     const Color aTopColor(mpTheme->GetGradientColor(eColorType, Theme::Fill1));
522     const Color aBottomColor(mpTheme->GetGradientColor(eColorType, Theme::Fill2));
523     if (aTopColor != aBottomColor)
524     {
525         const sal_Int32 nHeight (aPageObjectBox.GetHeight());
526         const sal_Int32 nDefaultConstantSize(nHeight/4);
527         const sal_Int32 nMinimalGradientSize(40);
528         const sal_Int32 nY1 (
529             ::std::max<sal_Int32>(
530                 0,
531                 ::std::min<sal_Int32>(
532                     nDefaultConstantSize,
533                     (nHeight - nMinimalGradientSize)/2)));
534         const sal_Int32 nY2 (nHeight-nY1);
535         const sal_Int32 nTop (aPageObjectBox.Top());
536         for (sal_Int32 nY=0; nY<nHeight; ++nY)
537         {
538             if (nY<=nY1)
539                 aBitmapDevice.SetLineColor(aTopColor);
540             else if (nY>=nY2)
541                 aBitmapDevice.SetLineColor(aBottomColor);
542             else
543             {
544                 Color aColor (aTopColor);
545                 aColor.Merge(aBottomColor, 255 * (nY2-nY) / (nY2-nY1));
546                 aBitmapDevice.SetLineColor(aColor);
547             }
548             aBitmapDevice.DrawLine(
549                 Point(aPageObjectBox.Left(), nY+nTop),
550                 Point(aPageObjectBox.Right(), nY+nTop));
551         }
552     }
553     else
554     {
555         aBitmapDevice.SetFillColor(aTopColor);
556         aBitmapDevice.DrawRect(aPageObjectBox);
557     }
558 
559     // Paint the simple border and, for some backgrounds, the focus border.
560     if (bHasFocusBorder)
561         mpFocusBorderPainter->PaintFrame(aBitmapDevice, aPageObjectBox);
562     else
563         PaintBorder(aBitmapDevice, eColorType, aPageObjectBox);
564 
565     // Get bounding box of the preview around which a shadow is painted.
566     // Compensate for the border around the preview.
567     const Rectangle aBox (mpPageObjectLayouter->GetBoundingBox(
568         Point(0,0),
569         PageObjectLayouter::Preview,
570         PageObjectLayouter::ModelCoordinateSystem));
571     Rectangle aFrameBox (aBox.Left()-1,aBox.Top()-1,aBox.Right()+1,aBox.Bottom()+1);
572     mpShadowPainter->PaintFrame(aBitmapDevice, aFrameBox);
573 
574     return aBitmapDevice.GetBitmap (Point(0,0),aSize);
575 }
576 
577 
578 
579 
PaintBorder(OutputDevice & rDevice,const Theme::GradientColorType eColorType,const Rectangle & rBox) const580 void PageObjectPainter::PaintBorder (
581     OutputDevice& rDevice,
582     const Theme::GradientColorType eColorType,
583     const Rectangle& rBox) const
584 {
585     rDevice.SetFillColor();
586     const sal_Int32 nBorderWidth (1);
587     for (int nIndex=0; nIndex<nBorderWidth; ++nIndex)
588     {
589         const int nDelta (nIndex);
590         rDevice.SetLineColor(mpTheme->GetGradientColor(eColorType, Theme::Border2));
591         rDevice.DrawLine(
592             Point(rBox.Left()-nDelta, rBox.Top()-nDelta),
593             Point(rBox.Left()-nDelta, rBox.Bottom()+nDelta));
594         rDevice.DrawLine(
595             Point(rBox.Left()-nDelta, rBox.Bottom()+nDelta),
596             Point(rBox.Right()+nDelta, rBox.Bottom()+nDelta));
597         rDevice.DrawLine(
598             Point(rBox.Right()+nDelta, rBox.Bottom()+nDelta),
599             Point(rBox.Right()+nDelta, rBox.Top()-nDelta));
600 
601         rDevice.SetLineColor(mpTheme->GetGradientColor(eColorType, Theme::Border1));
602         rDevice.DrawLine(
603             Point(rBox.Left()-nDelta, rBox.Top()-nDelta),
604             Point(rBox.Right()+nDelta, rBox.Top()-nDelta));
605     }
606 }
607 
608 
609 
610 } } } // end of namespace sd::slidesorter::view
611