summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx')
-rw-r--r--sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx448
1 files changed, 448 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx b/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx
new file mode 100644
index 000000000000..abaa5a43b215
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlsInsertionIndicatorOverlay.cxx
@@ -0,0 +1,448 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_sd.hxx"
+
+#include "view/SlsInsertionIndicatorOverlay.hxx"
+
+#include "SlideSorter.hxx"
+#include "model/SlsPageEnumeration.hxx"
+#include "view/SlideSorterView.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsTheme.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "SlsFramePainter.hxx"
+#include "SlsLayeredDevice.hxx"
+#include "DrawDocShell.hxx"
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include "sdmod.hxx"
+
+#include <vcl/virdev.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+#include <basegfx/tools/canvastools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
+
+namespace {
+
+
+static const double gnPreviewOffsetScale = 1.0 / 8.0;
+
+
+
+Rectangle GrowRectangle (const Rectangle& rBox, const sal_Int32 nOffset)
+{
+ return Rectangle (
+ rBox.Left() - nOffset,
+ rBox.Top() - nOffset,
+ rBox.Right() + nOffset,
+ rBox.Bottom() + nOffset);
+}
+
+sal_Int32 RoundToInt (const double nValue) { return sal_Int32(::rtl::math::round(nValue)); }
+
+} // end of anonymous namespace
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+
+//===== InsertionIndicatorOverlay ===========================================
+
+const static sal_Int32 gnShadowBorder = 3;
+const static sal_Int32 gnSuperScaleFactor = 1;
+
+InsertionIndicatorOverlay::InsertionIndicatorOverlay (SlideSorter& rSlideSorter)
+ : mrSlideSorter(rSlideSorter),
+ mbIsVisible(false),
+ mnLayerIndex(2),
+ mpLayerInvalidator(),
+ maLocation(),
+ maIcon(),
+ maIconOffset(),
+ mpShadowPainter(
+ new FramePainter(mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_RawInsertShadow)))
+{
+}
+
+
+
+
+InsertionIndicatorOverlay::~InsertionIndicatorOverlay (void)
+{
+ Hide();
+}
+
+
+
+
+void InsertionIndicatorOverlay::Create (const controller::Transferable* pTransferable)
+{
+ if (pTransferable == NULL)
+ return;
+
+ sal_Int32 nSelectionCount (0);
+ if (pTransferable->HasPageBookmarks())
+ nSelectionCount = pTransferable->GetPageBookmarks().Count();
+ else
+ {
+ DrawDocShell* pDataDocShell = dynamic_cast<DrawDocShell*>(&pTransferable->GetDocShell());
+ if (pDataDocShell != NULL)
+ {
+ SdDrawDocument* pDataDocument = pDataDocShell->GetDoc();
+ if (pDataDocument != NULL)
+ nSelectionCount = pDataDocument->GetSdPageCount(PK_STANDARD);
+ }
+ }
+ Create(pTransferable->GetRepresentatives(), nSelectionCount);
+}
+
+
+
+
+void InsertionIndicatorOverlay::Create (
+ const ::std::vector<controller::Transferable::Representative>& rRepresentatives,
+ const sal_Int32 nSelectionCount)
+{
+ view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
+ ::boost::shared_ptr<view::PageObjectLayouter> pPageObjectLayouter (
+ rLayouter.GetPageObjectLayouter());
+ ::boost::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
+ const Size aOriginalPreviewSize (pPageObjectLayouter->GetSize(
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::WindowCoordinateSystem));
+
+ const double nPreviewScale (0.5);
+ const Size aPreviewSize (
+ RoundToInt(aOriginalPreviewSize.Width()*nPreviewScale),
+ RoundToInt(aOriginalPreviewSize.Height()*nPreviewScale));
+ const sal_Int32 nOffset (
+ RoundToInt(Min(aPreviewSize.Width(),aPreviewSize.Height()) * gnPreviewOffsetScale));
+
+ // Determine size and offset depending on the number of previews.
+ sal_Int32 nCount (rRepresentatives.size());
+ if (nCount > 0)
+ --nCount;
+ Size aIconSize(
+ aPreviewSize.Width() + 2 * gnShadowBorder + nCount*nOffset,
+ aPreviewSize.Height() + 2 * gnShadowBorder + nCount*nOffset);
+ maIconOffset = Point(gnShadowBorder, gnShadowBorder);
+
+ // Create virtual devices for bitmap and mask whose bitmaps later be
+ // combined to form the BitmapEx of the icon.
+ VirtualDevice aContent (
+ *mrSlideSorter.GetContentWindow(),
+ 0,
+ 0);
+ aContent.SetOutputSizePixel(aIconSize);
+
+ aContent.SetFillColor();
+ aContent.SetLineColor(pTheme->GetColor(Theme::Color_PreviewBorder));
+ const Point aOffset = PaintRepresentatives(aContent, aPreviewSize, nOffset, rRepresentatives);
+
+ PaintPageCount(aContent, nSelectionCount, aPreviewSize, aOffset);
+
+ maIcon = aContent.GetBitmapEx(Point(0,0), aIconSize);
+ maIcon.Scale(aIconSize);
+}
+
+
+
+
+void InsertionIndicatorOverlay::SelectRepresentatives (
+ model::PageEnumeration& rSelection,
+ ::std::vector<model::SharedPageDescriptor>& rDescriptors) const
+{
+ sal_Int32 nCount (0);
+ while (rSelection.HasMoreElements())
+ {
+ if (nCount++ >= 3)
+ break;
+ rDescriptors.push_back(rSelection.GetNextElement());
+ }
+}
+
+
+
+
+Point InsertionIndicatorOverlay::PaintRepresentatives (
+ OutputDevice& rContent,
+ const Size aPreviewSize,
+ const sal_Int32 nOffset,
+ const ::std::vector<controller::Transferable::Representative>& rRepresentatives) const
+{
+ const Point aOffset (0,rRepresentatives.size()==1 ? -nOffset : 0);
+
+ // Paint the pages.
+ Point aPageOffset (0,0);
+ double nTransparency (0);
+ const BitmapEx aExclusionOverlay (mrSlideSorter.GetTheme()->GetIcon(Theme::Icon_HideSlideOverlay));
+ for (sal_Int32 nIndex=2; nIndex>=0; --nIndex)
+ {
+ if (rRepresentatives.size() <= sal_uInt32(nIndex))
+ continue;
+ switch(nIndex)
+ {
+ case 0 :
+ aPageOffset = Point(0, nOffset);
+ nTransparency = 0.85;
+ break;
+ case 1:
+ aPageOffset = Point(nOffset, 0);
+ nTransparency = 0.75;
+ break;
+ case 2:
+ aPageOffset = Point(2*nOffset, 2*nOffset);
+ nTransparency = 0.65;
+ break;
+ }
+ aPageOffset += aOffset;
+ aPageOffset.X() += gnShadowBorder;
+ aPageOffset.Y() += gnShadowBorder;
+
+ // Paint the preview.
+ Bitmap aPreview (rRepresentatives[nIndex].maBitmap);
+ const Size aSuperSampleSize(
+ aPreviewSize.Width()*gnSuperScaleFactor,
+ aPreviewSize.Height()*gnSuperScaleFactor);
+ aPreview.Scale(aPreviewSize, BMP_SCALE_INTERPOLATE);
+ rContent.DrawBitmapEx(aPageOffset, aPreview);
+
+ // When the page is marked as excluded from the slide show then
+ // paint an overlay that visualizes this.
+ if (rRepresentatives[nIndex].mbIsExcluded)
+ {
+ const Region aSavedClipRegion (rContent.GetClipRegion());
+ rContent.IntersectClipRegion(Rectangle(aPageOffset, aPreviewSize));
+ // Paint bitmap tiled over the preview to mark it as excluded.
+ const sal_Int32 nIconWidth (aExclusionOverlay.GetSizePixel().Width());
+ const sal_Int32 nIconHeight (aExclusionOverlay.GetSizePixel().Height());
+ if (nIconWidth>0 && nIconHeight>0)
+ {
+ for (sal_Int32 nX=0; nX<aPreviewSize.Width(); nX+=nIconWidth)
+ for (sal_Int32 nY=0; nY<aPreviewSize.Height(); nY+=nIconHeight)
+ rContent.DrawBitmapEx(Point(nX,nY)+aPageOffset, aExclusionOverlay);
+ }
+ rContent.SetClipRegion(aSavedClipRegion);
+ }
+
+ // Tone down the bitmap. The further back the darker it becomes.
+ Rectangle aBox (
+ aPageOffset.X(),
+ aPageOffset.Y(),
+ aPageOffset.X()+aPreviewSize.Width()-1,
+ aPageOffset.Y()+aPreviewSize.Height()-1);
+ rContent.SetFillColor(COL_BLACK);
+ rContent.SetLineColor();
+ rContent.DrawTransparent(
+ ::basegfx::B2DPolyPolygon(::basegfx::tools::createPolygonFromRect(
+ ::basegfx::B2DRectangle(aBox.Left(), aBox.Top(), aBox.Right()+1, aBox.Bottom()+1),
+ 0,
+ 0)),
+ nTransparency);
+
+ // Draw border around preview.
+ Rectangle aBorderBox (GrowRectangle(aBox, 1));
+ rContent.SetLineColor(COL_GRAY);
+ rContent.SetFillColor();
+ rContent.DrawRect(aBorderBox);
+
+ // Draw shadow around preview.
+ mpShadowPainter->PaintFrame(rContent, aBorderBox);
+ }
+
+ return aPageOffset;
+}
+
+
+
+
+void InsertionIndicatorOverlay::PaintPageCount (
+ OutputDevice& rDevice,
+ const sal_Int32 nSelectionCount,
+ const Size aPreviewSize,
+ const Point aFirstPageOffset) const
+{
+ // Paint the number of slides.
+ ::boost::shared_ptr<view::Theme> pTheme (mrSlideSorter.GetTheme());
+ ::boost::shared_ptr<Font> pFont(Theme::GetFont(Theme::Font_PageCount, rDevice));
+ if (pFont)
+ {
+ ::rtl::OUString sNumber (::rtl::OUString::valueOf(nSelectionCount));
+
+ // Determine the size of the (painted) text and create a bounding
+ // box that centers the text on the first preview.
+ rDevice.SetFont(*pFont);
+ Rectangle aTextBox;
+ rDevice.GetTextBoundRect(aTextBox, sNumber);
+ Point aTextOffset (aTextBox.TopLeft());
+ Size aTextSize (aTextBox.GetSize());
+ // Place text inside the first page preview.
+ Point aTextLocation(aFirstPageOffset);
+ // Center the text.
+ aTextLocation += Point(
+ (aPreviewSize.Width()-aTextBox.GetWidth())/2,
+ (aPreviewSize.Height()-aTextBox.GetHeight())/2);
+ aTextBox = Rectangle(aTextLocation, aTextSize);
+
+ // Paint background, border and text.
+ static const sal_Int32 nBorder = 5;
+ rDevice.SetFillColor(pTheme->GetColor(Theme::Color_Selection));
+ rDevice.SetLineColor(pTheme->GetColor(Theme::Color_Selection));
+ rDevice.DrawRect(GrowRectangle(aTextBox, nBorder));
+
+ rDevice.SetFillColor();
+ rDevice.SetLineColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
+ rDevice.DrawRect(GrowRectangle(aTextBox, nBorder-1));
+
+ rDevice.SetTextColor(pTheme->GetColor(Theme::Color_PageCountFontColor));
+ rDevice.DrawText(aTextBox.TopLeft()-aTextOffset, sNumber);
+ }
+}
+
+
+
+
+void InsertionIndicatorOverlay::SetLocation (const Point& rLocation)
+{
+ const Point aTopLeft (
+ rLocation - Point(
+ maIcon.GetSizePixel().Width()/2,
+ maIcon.GetSizePixel().Height()/2));
+ if (maLocation != aTopLeft)
+ {
+ const Rectangle aOldBoundingBox (GetBoundingBox());
+
+ maLocation = aTopLeft;
+
+ if (mpLayerInvalidator && IsVisible())
+ {
+ mpLayerInvalidator->Invalidate(aOldBoundingBox);
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+ }
+ }
+}
+
+
+
+
+void InsertionIndicatorOverlay::Paint (
+ OutputDevice& rDevice,
+ const Rectangle& rRepaintArea)
+{
+ (void)rRepaintArea;
+
+ if ( ! IsVisible())
+ return;
+
+ rDevice.DrawImage(maLocation, maIcon);
+}
+
+
+
+
+void InsertionIndicatorOverlay::SetLayerInvalidator (const SharedILayerInvalidator& rpInvalidator)
+{
+ mpLayerInvalidator = rpInvalidator;
+
+ if (mbIsVisible && mpLayerInvalidator)
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+}
+
+
+
+
+bool InsertionIndicatorOverlay::IsVisible (void) const
+{
+ return mbIsVisible;
+}
+
+
+
+
+void InsertionIndicatorOverlay::Show (void)
+{
+ if ( ! mbIsVisible)
+ {
+ mbIsVisible = true;
+
+ ::boost::shared_ptr<LayeredDevice> pLayeredDevice (
+ mrSlideSorter.GetView().GetLayeredDevice());
+ if (pLayeredDevice)
+ {
+ pLayeredDevice->RegisterPainter(shared_from_this(), mnLayerIndex);
+ if (mpLayerInvalidator)
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+ }
+ }
+}
+
+
+
+
+void InsertionIndicatorOverlay::Hide (void)
+{
+ if (mbIsVisible)
+ {
+ mbIsVisible = false;
+
+ ::boost::shared_ptr<LayeredDevice> pLayeredDevice (
+ mrSlideSorter.GetView().GetLayeredDevice());
+ if (pLayeredDevice)
+ {
+ if (mpLayerInvalidator)
+ mpLayerInvalidator->Invalidate(GetBoundingBox());
+ pLayeredDevice->RemovePainter(shared_from_this(), mnLayerIndex);
+ }
+ }
+}
+
+
+
+
+Rectangle InsertionIndicatorOverlay::GetBoundingBox (void) const
+{
+ return Rectangle(maLocation, maIcon.GetSizePixel());
+}
+
+
+
+
+Size InsertionIndicatorOverlay::GetSize (void) const
+{
+ return Size(
+ maIcon.GetSizePixel().Width() + 10,
+ maIcon.GetSizePixel().Height() + 10);
+}
+
+
+
+} } } // end of namespace ::sd::slidesorter::view
+