Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include "view/SlsInsertionIndicatorOverlay.hxx"
31 : :
32 : : #include "SlideSorter.hxx"
33 : : #include "model/SlsPageEnumeration.hxx"
34 : : #include "view/SlideSorterView.hxx"
35 : : #include "view/SlsLayouter.hxx"
36 : : #include "view/SlsPageObjectLayouter.hxx"
37 : : #include "view/SlsTheme.hxx"
38 : : #include "cache/SlsPageCache.hxx"
39 : : #include "SlsFramePainter.hxx"
40 : : #include "SlsLayeredDevice.hxx"
41 : : #include "DrawDocShell.hxx"
42 : : #include "drawdoc.hxx"
43 : : #include "sdpage.hxx"
44 : : #include "sdmod.hxx"
45 : :
46 : : #include <vcl/virdev.hxx>
47 : : #include <basegfx/range/b2drectangle.hxx>
48 : : #include <basegfx/tools/canvastools.hxx>
49 : : #include <basegfx/polygon/b2dpolygon.hxx>
50 : : #include <basegfx/polygon/b2dpolygontools.hxx>
51 : :
52 : :
53 : : namespace {
54 : :
55 : :
56 : : static const double gnPreviewOffsetScale = 1.0 / 8.0;
57 : :
58 : :
59 : :
60 : 0 : Rectangle GrowRectangle (const Rectangle& rBox, const sal_Int32 nOffset)
61 : : {
62 : : return Rectangle (
63 : 0 : rBox.Left() - nOffset,
64 : 0 : rBox.Top() - nOffset,
65 : 0 : rBox.Right() + nOffset,
66 : 0 : rBox.Bottom() + nOffset);
67 : : }
68 : :
69 : 0 : sal_Int32 RoundToInt (const double nValue) { return sal_Int32(::rtl::math::round(nValue)); }
70 : :
71 : : } // end of anonymous namespace
72 : :
73 : :
74 : : namespace sd { namespace slidesorter { namespace view {
75 : :
76 : :
77 : : //===== InsertionIndicatorOverlay ===========================================
78 : :
79 : : const static sal_Int32 gnShadowBorder = 3;
80 : : const static sal_Int32 gnSuperScaleFactor = 1;
81 : :
82 : 130 : InsertionIndicatorOverlay::InsertionIndicatorOverlay (SlideSorter& rSlideSorter)
83 : : : mrSlideSorter(rSlideSorter),
84 : : mbIsVisible(false),
85 : : mnLayerIndex(2),
86 : : mpLayerInvalidator(),
87 : : maLocation(),
88 : : maIcon(),
89 : : maIconOffset(),
90 : : mpShadowPainter(
91 [ + - ][ + - ]: 130 : new FramePainter(mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_RawInsertShadow)))
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
92 : : {
93 : 130 : }
94 : :
95 : :
96 : :
97 : :
98 [ + - ][ + - ]: 130 : InsertionIndicatorOverlay::~InsertionIndicatorOverlay (void)
[ + - ][ + - ]
99 : : {
100 [ + - ]: 130 : Hide();
101 [ - + ]: 260 : }
102 : :
103 : :
104 : :
105 : :
106 : 0 : void InsertionIndicatorOverlay::Create (const controller::Transferable* pTransferable)
107 : : {
108 [ # # ]: 0 : if (pTransferable == NULL)
109 : 0 : return;
110 : :
111 : 0 : sal_Int32 nSelectionCount (0);
112 [ # # ]: 0 : if (pTransferable->HasPageBookmarks())
113 : 0 : nSelectionCount = pTransferable->GetPageBookmarks().size();
114 : : else
115 : : {
116 [ # # ]: 0 : DrawDocShell* pDataDocShell = dynamic_cast<DrawDocShell*>(&pTransferable->GetDocShell());
117 [ # # ]: 0 : if (pDataDocShell != NULL)
118 : : {
119 : 0 : SdDrawDocument* pDataDocument = pDataDocShell->GetDoc();
120 [ # # ]: 0 : if (pDataDocument != NULL)
121 : 0 : nSelectionCount = pDataDocument->GetSdPageCount(PK_STANDARD);
122 : : }
123 : : }
124 : 0 : Create(pTransferable->GetRepresentatives(), nSelectionCount);
125 : : }
126 : :
127 : :
128 : :
129 : :
130 : 0 : void InsertionIndicatorOverlay::Create (
131 : : const ::std::vector<controller::Transferable::Representative>& rRepresentatives,
132 : : const sal_Int32 nSelectionCount)
133 : : {
134 [ # # ][ # # ]: 0 : view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
135 : : ::boost::shared_ptr<view::PageObjectLayouter> pPageObjectLayouter (
136 [ # # ]: 0 : rLayouter.GetPageObjectLayouter());
137 [ # # ]: 0 : ::boost::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
138 : : const Size aOriginalPreviewSize (pPageObjectLayouter->GetSize(
139 : : PageObjectLayouter::Preview,
140 [ # # ]: 0 : PageObjectLayouter::WindowCoordinateSystem));
141 : :
142 : 0 : const double nPreviewScale (0.5);
143 : : const Size aPreviewSize (
144 : 0 : RoundToInt(aOriginalPreviewSize.Width()*nPreviewScale),
145 : 0 : RoundToInt(aOriginalPreviewSize.Height()*nPreviewScale));
146 : : const sal_Int32 nOffset (
147 : 0 : RoundToInt(Min(aPreviewSize.Width(),aPreviewSize.Height()) * gnPreviewOffsetScale));
148 : :
149 : : // Determine size and offset depending on the number of previews.
150 : 0 : sal_Int32 nCount (rRepresentatives.size());
151 [ # # ]: 0 : if (nCount > 0)
152 : 0 : --nCount;
153 : : Size aIconSize(
154 : 0 : aPreviewSize.Width() + 2 * gnShadowBorder + nCount*nOffset,
155 : 0 : aPreviewSize.Height() + 2 * gnShadowBorder + nCount*nOffset);
156 : 0 : maIconOffset = Point(gnShadowBorder, gnShadowBorder);
157 : :
158 : : // Create virtual devices for bitmap and mask whose bitmaps later be
159 : : // combined to form the BitmapEx of the icon.
160 : : VirtualDevice aContent (
161 [ # # ][ # # ]: 0 : *mrSlideSorter.GetContentWindow(),
162 : : 0,
163 [ # # ]: 0 : 0);
164 [ # # ]: 0 : aContent.SetOutputSizePixel(aIconSize);
165 : :
166 [ # # ]: 0 : aContent.SetFillColor();
167 [ # # ][ # # ]: 0 : aContent.SetLineColor(pTheme->GetColor(Theme::Color_PreviewBorder));
168 [ # # ]: 0 : const Point aOffset = PaintRepresentatives(aContent, aPreviewSize, nOffset, rRepresentatives);
169 : :
170 [ # # ]: 0 : PaintPageCount(aContent, nSelectionCount, aPreviewSize, aOffset);
171 : :
172 [ # # ][ # # ]: 0 : maIcon = aContent.GetBitmapEx(Point(0,0), aIconSize);
[ # # ]
173 [ # # ][ # # ]: 0 : maIcon.Scale(aIconSize);
[ # # ][ # # ]
174 : 0 : }
175 : :
176 : :
177 : :
178 : :
179 : 0 : Point InsertionIndicatorOverlay::PaintRepresentatives (
180 : : OutputDevice& rContent,
181 : : const Size aPreviewSize,
182 : : const sal_Int32 nOffset,
183 : : const ::std::vector<controller::Transferable::Representative>& rRepresentatives) const
184 : : {
185 [ # # ]: 0 : const Point aOffset (0,rRepresentatives.size()==1 ? -nOffset : 0);
186 : :
187 : : // Paint the pages.
188 : 0 : Point aPageOffset (0,0);
189 : 0 : double nTransparency (0);
190 [ # # ][ # # ]: 0 : const BitmapEx aExclusionOverlay (mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_HideSlideOverlay));
[ # # ][ # # ]
191 [ # # ]: 0 : for (sal_Int32 nIndex=2; nIndex>=0; --nIndex)
192 : : {
193 [ # # ]: 0 : if (rRepresentatives.size() <= sal_uInt32(nIndex))
194 : 0 : continue;
195 [ # # # # ]: 0 : switch(nIndex)
196 : : {
197 : : case 0 :
198 : 0 : aPageOffset = Point(0, nOffset);
199 : 0 : nTransparency = 0.85;
200 : 0 : break;
201 : : case 1:
202 : 0 : aPageOffset = Point(nOffset, 0);
203 : 0 : nTransparency = 0.75;
204 : 0 : break;
205 : : case 2:
206 : 0 : aPageOffset = Point(2*nOffset, 2*nOffset);
207 : 0 : nTransparency = 0.65;
208 : 0 : break;
209 : : }
210 : 0 : aPageOffset += aOffset;
211 : 0 : aPageOffset.X() += gnShadowBorder;
212 : 0 : aPageOffset.Y() += gnShadowBorder;
213 : :
214 : : // Paint the preview.
215 [ # # ]: 0 : Bitmap aPreview (rRepresentatives[nIndex].maBitmap);
216 : : const Size aSuperSampleSize(
217 : : aPreviewSize.Width()*gnSuperScaleFactor,
218 : 0 : aPreviewSize.Height()*gnSuperScaleFactor);
219 [ # # ]: 0 : aPreview.Scale(aPreviewSize, BMP_SCALE_BEST);
220 [ # # ][ # # ]: 0 : rContent.DrawBitmapEx(aPageOffset, aPreview);
[ # # ]
221 : :
222 : : // When the page is marked as excluded from the slide show then
223 : : // paint an overlay that visualizes this.
224 [ # # ]: 0 : if (rRepresentatives[nIndex].mbIsExcluded)
225 : : {
226 [ # # ]: 0 : const Region aSavedClipRegion (rContent.GetClipRegion());
227 [ # # ][ # # ]: 0 : rContent.IntersectClipRegion(Rectangle(aPageOffset, aPreviewSize));
228 : : // Paint bitmap tiled over the preview to mark it as excluded.
229 : 0 : const sal_Int32 nIconWidth (aExclusionOverlay.GetSizePixel().Width());
230 : 0 : const sal_Int32 nIconHeight (aExclusionOverlay.GetSizePixel().Height());
231 [ # # ][ # # ]: 0 : if (nIconWidth>0 && nIconHeight>0)
232 : : {
233 [ # # ]: 0 : for (sal_Int32 nX=0; nX<aPreviewSize.Width(); nX+=nIconWidth)
234 [ # # ]: 0 : for (sal_Int32 nY=0; nY<aPreviewSize.Height(); nY+=nIconHeight)
235 [ # # ]: 0 : rContent.DrawBitmapEx(Point(nX,nY)+aPageOffset, aExclusionOverlay);
236 : : }
237 [ # # ][ # # ]: 0 : rContent.SetClipRegion(aSavedClipRegion);
238 : : }
239 : :
240 : : // Tone down the bitmap. The further back the darker it becomes.
241 : : Rectangle aBox (
242 : 0 : aPageOffset.X(),
243 : 0 : aPageOffset.Y(),
244 : 0 : aPageOffset.X()+aPreviewSize.Width()-1,
245 [ # # ]: 0 : aPageOffset.Y()+aPreviewSize.Height()-1);
246 [ # # ]: 0 : rContent.SetFillColor(COL_BLACK);
247 [ # # ]: 0 : rContent.SetLineColor();
248 : : rContent.DrawTransparent(
249 : : ::basegfx::B2DPolyPolygon(::basegfx::tools::createPolygonFromRect(
250 : 0 : ::basegfx::B2DRectangle(aBox.Left(), aBox.Top(), aBox.Right()+1, aBox.Bottom()+1),
251 : : 0,
252 : : 0)),
253 [ # # ][ # # ]: 0 : nTransparency);
[ # # ][ # # ]
[ # # ][ # # ]
254 : :
255 : : // Draw border around preview.
256 [ # # ]: 0 : Rectangle aBorderBox (GrowRectangle(aBox, 1));
257 [ # # ]: 0 : rContent.SetLineColor(COL_GRAY);
258 [ # # ]: 0 : rContent.SetFillColor();
259 [ # # ]: 0 : rContent.DrawRect(aBorderBox);
260 : :
261 : : // Draw shadow around preview.
262 [ # # ]: 0 : mpShadowPainter->PaintFrame(rContent, aBorderBox);
263 [ # # ]: 0 : }
264 : :
265 [ # # ]: 0 : return aPageOffset;
266 : : }
267 : :
268 : :
269 : :
270 : :
271 : 0 : void InsertionIndicatorOverlay::PaintPageCount (
272 : : OutputDevice& rDevice,
273 : : const sal_Int32 nSelectionCount,
274 : : const Size aPreviewSize,
275 : : const Point aFirstPageOffset) const
276 : : {
277 : : // Paint the number of slides.
278 [ # # ]: 0 : ::boost::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
279 [ # # ]: 0 : ::boost::shared_ptr<Font> pFont(Theme::GetFont(Theme::Font_PageCount, rDevice));
280 [ # # ]: 0 : if (pFont)
281 : : {
282 : 0 : ::rtl::OUString sNumber (::rtl::OUString::valueOf(nSelectionCount));
283 : :
284 : : // Determine the size of the (painted) text and create a bounding
285 : : // box that centers the text on the first preview.
286 [ # # ]: 0 : rDevice.SetFont(*pFont);
287 [ # # ]: 0 : Rectangle aTextBox;
288 [ # # ][ # # ]: 0 : rDevice.GetTextBoundRect(aTextBox, sNumber);
[ # # ]
289 : 0 : Point aTextOffset (aTextBox.TopLeft());
290 [ # # ]: 0 : Size aTextSize (aTextBox.GetSize());
291 : : // Place text inside the first page preview.
292 : 0 : Point aTextLocation(aFirstPageOffset);
293 : : // Center the text.
294 : : aTextLocation += Point(
295 [ # # ]: 0 : (aPreviewSize.Width()-aTextBox.GetWidth())/2,
296 [ # # ]: 0 : (aPreviewSize.Height()-aTextBox.GetHeight())/2);
297 [ # # ]: 0 : aTextBox = Rectangle(aTextLocation, aTextSize);
298 : :
299 : : // Paint background, border and text.
300 : : static const sal_Int32 nBorder = 5;
301 [ # # ][ # # ]: 0 : rDevice.SetFillColor(pTheme->GetColor(Theme::Color_Selection));
302 [ # # ][ # # ]: 0 : rDevice.SetLineColor(pTheme->GetColor(Theme::Color_Selection));
303 [ # # ][ # # ]: 0 : rDevice.DrawRect(GrowRectangle(aTextBox, nBorder));
304 : :
305 [ # # ]: 0 : rDevice.SetFillColor();
306 [ # # ][ # # ]: 0 : rDevice.SetLineColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
307 [ # # ][ # # ]: 0 : rDevice.DrawRect(GrowRectangle(aTextBox, nBorder-1));
308 : :
309 [ # # ][ # # ]: 0 : rDevice.SetTextColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
310 [ # # ][ # # ]: 0 : rDevice.DrawText(aTextBox.TopLeft()-aTextOffset, sNumber);
[ # # ]
311 [ # # ][ # # ]: 0 : }
312 : 0 : }
313 : :
314 : :
315 : :
316 : :
317 : 0 : void InsertionIndicatorOverlay::SetLocation (const Point& rLocation)
318 : : {
319 : : const Point aTopLeft (
320 : : rLocation - Point(
321 : 0 : maIcon.GetSizePixel().Width()/2,
322 : 0 : maIcon.GetSizePixel().Height()/2));
323 [ # # ]: 0 : if (maLocation != aTopLeft)
324 : : {
325 [ # # ]: 0 : const Rectangle aOldBoundingBox (GetBoundingBox());
326 : :
327 : 0 : maLocation = aTopLeft;
328 : :
329 [ # # ][ # # ]: 0 : if (mpLayerInvalidator && IsVisible())
[ # # ]
330 : : {
331 [ # # ]: 0 : mpLayerInvalidator->Invalidate(aOldBoundingBox);
332 [ # # ][ # # ]: 0 : mpLayerInvalidator->Invalidate(GetBoundingBox());
333 : : }
334 : : }
335 : 0 : }
336 : :
337 : :
338 : :
339 : :
340 : 0 : void InsertionIndicatorOverlay::Paint (
341 : : OutputDevice& rDevice,
342 : : const Rectangle& rRepaintArea)
343 : : {
344 : : (void)rRepaintArea;
345 : :
346 [ # # ]: 0 : if ( ! IsVisible())
347 : 0 : return;
348 : :
349 [ # # ]: 0 : rDevice.DrawImage(maLocation, maIcon);
350 : : }
351 : :
352 : :
353 : :
354 : :
355 : 0 : void InsertionIndicatorOverlay::SetLayerInvalidator (const SharedILayerInvalidator& rpInvalidator)
356 : : {
357 : 0 : mpLayerInvalidator = rpInvalidator;
358 : :
359 [ # # ][ # # ]: 0 : if (mbIsVisible && mpLayerInvalidator)
[ # # ]
360 [ # # ]: 0 : mpLayerInvalidator->Invalidate(GetBoundingBox());
361 : 0 : }
362 : :
363 : :
364 : :
365 : :
366 : 0 : bool InsertionIndicatorOverlay::IsVisible (void) const
367 : : {
368 : 0 : return mbIsVisible;
369 : : }
370 : :
371 : :
372 : :
373 : :
374 : 0 : void InsertionIndicatorOverlay::Show (void)
375 : : {
376 [ # # ]: 0 : if ( ! mbIsVisible)
377 : : {
378 : 0 : mbIsVisible = true;
379 : :
380 : : ::boost::shared_ptr<LayeredDevice> pLayeredDevice (
381 [ # # ][ # # ]: 0 : mrSlideSorter.GetView().GetLayeredDevice());
382 [ # # ]: 0 : if (pLayeredDevice)
383 : : {
384 [ # # ][ # # ]: 0 : pLayeredDevice->RegisterPainter(shared_from_this(), mnLayerIndex);
[ # # ][ # # ]
[ # # ]
385 [ # # ]: 0 : if (mpLayerInvalidator)
386 [ # # ][ # # ]: 0 : mpLayerInvalidator->Invalidate(GetBoundingBox());
387 [ # # ]: 0 : }
388 : : }
389 : 0 : }
390 : :
391 : :
392 : :
393 : :
394 : 130 : void InsertionIndicatorOverlay::Hide (void)
395 : : {
396 [ - + ]: 130 : if (mbIsVisible)
397 : : {
398 : 0 : mbIsVisible = false;
399 : :
400 : : ::boost::shared_ptr<LayeredDevice> pLayeredDevice (
401 [ # # ][ # # ]: 0 : mrSlideSorter.GetView().GetLayeredDevice());
402 [ # # ]: 0 : if (pLayeredDevice)
403 : : {
404 [ # # ]: 0 : if (mpLayerInvalidator)
405 [ # # ][ # # ]: 0 : mpLayerInvalidator->Invalidate(GetBoundingBox());
406 [ # # ][ # # ]: 0 : pLayeredDevice->RemovePainter(shared_from_this(), mnLayerIndex);
[ # # ][ # # ]
[ # # ]
407 [ # # ]: 0 : }
408 : : }
409 : 130 : }
410 : :
411 : :
412 : :
413 : :
414 : 0 : Rectangle InsertionIndicatorOverlay::GetBoundingBox (void) const
415 : : {
416 : 0 : return Rectangle(maLocation, maIcon.GetSizePixel());
417 : : }
418 : :
419 : :
420 : :
421 : :
422 : 0 : Size InsertionIndicatorOverlay::GetSize (void) const
423 : : {
424 : : return Size(
425 : 0 : maIcon.GetSizePixel().Width() + 10,
426 : 0 : maIcon.GetSizePixel().Height() + 10);
427 : : }
428 : :
429 : :
430 : :
431 : : } } } // end of namespace ::sd::slidesorter::view
432 : :
433 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|