summaryrefslogtreecommitdiff
path: root/sd/source/ui/slidesorter/view/SlideSorterView.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sd/source/ui/slidesorter/view/SlideSorterView.cxx')
-rw-r--r--sd/source/ui/slidesorter/view/SlideSorterView.cxx1132
1 files changed, 1132 insertions, 0 deletions
diff --git a/sd/source/ui/slidesorter/view/SlideSorterView.cxx b/sd/source/ui/slidesorter/view/SlideSorterView.cxx
new file mode 100644
index 000000000000..728eff5ee384
--- /dev/null
+++ b/sd/source/ui/slidesorter/view/SlideSorterView.cxx
@@ -0,0 +1,1132 @@
+/*************************************************************************
+ *
+ * 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/SlideSorterView.hxx"
+
+#include "ViewShellBase.hxx"
+#include "SlideSorter.hxx"
+#include "SlideSorterViewShell.hxx"
+#include "ViewShell.hxx"
+#include "SlsViewCacheContext.hxx"
+#include "SlsLayeredDevice.hxx"
+#include "view/SlsLayouter.hxx"
+#include "view/SlsPageObjectLayouter.hxx"
+#include "view/SlsPageObjectPainter.hxx"
+#include "view/SlsILayerPainter.hxx"
+#include "view/SlsButtonBar.hxx"
+#include "view/SlsToolTip.hxx"
+#include "controller/SlideSorterController.hxx"
+#include "controller/SlsProperties.hxx"
+#include "model/SlideSorterModel.hxx"
+#include "model/SlsPageEnumerationProvider.hxx"
+#include "model/SlsPageDescriptor.hxx"
+#include "cache/SlsPageCache.hxx"
+#include "cache/SlsPageCacheManager.hxx"
+#include "cache/SlsCacheContext.hxx"
+#include "taskpane/SlideSorterCacheDisplay.hxx"
+#include "DrawDocShell.hxx"
+#include "PaneDockingWindow.hxx"
+
+#include "drawdoc.hxx"
+#include "sdpage.hxx"
+#include "Window.hxx"
+#include "sdresid.hxx"
+#include "glob.hrc"
+
+#include <svl/itempool.hxx>
+#include <svx/svdpagv.hxx>
+#include <svx/svdopage.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnclit.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/scrbar.hxx>
+#include <tools/poly.hxx>
+#include <vcl/lineinfo.hxx>
+#include <algorithm>
+#include <svx/sdrpagewindow.hxx>
+#include <svl/itempool.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <canvas/elapsedtime.hxx>
+
+//#define DEBUG_TIMING
+#include <svl/itempool.hxx>
+#ifdef DEBUG_TIMING
+#include <vector>
+#endif
+#include <boost/foreach.hpp>
+
+
+using namespace std;
+using namespace ::sd::slidesorter::model;
+using namespace ::drawinglayer::primitive2d;
+
+
+namespace sd { namespace slidesorter { namespace view {
+
+namespace {
+ /** Wrapper around the SlideSorterView that supports the IPainter
+ interface and that allows the LayeredDevice to hold the
+ SlideSorterView (held as scoped_ptr by the SlideSorter) as
+ shared_ptr.
+ */
+ class Painter : public ILayerPainter
+ {
+ public:
+ Painter (SlideSorterView& rView) : mrView(rView) {}
+ virtual ~Painter (void) {}
+
+ virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea)
+ {
+ mrView.Paint(rDevice,rRepaintArea);
+ }
+
+ virtual void SetLayerInvalidator (const SharedILayerInvalidator&) {}
+
+ private:
+ SlideSorterView& mrView;
+ };
+}
+
+
+
+class BackgroundPainter
+ : public ILayerPainter,
+ public ::boost::noncopyable
+{
+public:
+ BackgroundPainter (const Color aBackgroundColor) : maBackgroundColor(aBackgroundColor) {}
+ virtual ~BackgroundPainter (void) {}
+
+ virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea)
+ {
+ rDevice.SetFillColor(maBackgroundColor);
+ rDevice.SetLineColor();
+ rDevice.DrawRect(rRepaintArea);
+ }
+
+ virtual void SetLayerInvalidator (const SharedILayerInvalidator&) {}
+
+ void SetColor (const Color aColor) { maBackgroundColor = aColor; }
+
+private:
+ Color maBackgroundColor;
+};
+
+
+
+TYPEINIT1(SlideSorterView, ::sd::View);
+
+SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
+ : ::sd::View (
+ rSlideSorter.GetModel().GetDocument(),
+ rSlideSorter.GetContentWindow().get(),
+ rSlideSorter.GetViewShell()),
+ mrSlideSorter(rSlideSorter),
+ mrModel(rSlideSorter.GetModel()),
+ mbIsDisposed(false),
+ mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
+ mbPageObjectVisibilitiesValid (false),
+ mpPreviewCache(),
+ mpLayeredDevice(new LayeredDevice(rSlideSorter.GetContentWindow())),
+ maVisiblePageRange(-1,-1),
+ mbModelChangedWhileModifyEnabled(true),
+ maPreviewSize(0,0),
+ mbPreciousFlagUpdatePending(true),
+ meOrientation(Layouter::GRID),
+ mpProperties(rSlideSorter.GetProperties()),
+ mpPageUnderMouse(),
+ mnButtonUnderMouse(-1),
+ mpPageObjectPainter(),
+ mpSelectionPainter(),
+ mpBackgroundPainter(
+ new BackgroundPainter(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
+ mpButtonBar(new ButtonBar(mrSlideSorter)),
+ mpToolTip(new ToolTip(mrSlideSorter)),
+ mbIsRearrangePending(true),
+ maVisibilityChangeListeners()
+{
+ // Hide the page that contains the page objects.
+ SetPageVisible (sal_False);
+
+
+ // Register the background painter on level 1 to avoid the creation of a
+ // background buffer.
+ mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
+
+ // Wrap a shared_ptr-held-wrapper around this view and register it as
+ // painter at the layered device. There is no explicit destruction: in
+ // the SlideSorterView destructor the layered device is destroyed and
+ // with it the only reference to the wrapper which therefore is also
+ // destroyed.
+ SharedILayerPainter pPainter (new Painter(*this));
+
+ // The painter is placed on level 1 to avoid buffering. This should be
+ // a little faster during animations because the previews are painted
+ // directly into the window, not via the buffer.
+ mpLayeredDevice->RegisterPainter(pPainter, 1);
+}
+
+
+
+
+SlideSorterView::~SlideSorterView (void)
+{
+ if ( ! mbIsDisposed)
+ {
+ OSL_ASSERT(mbIsDisposed);
+ Dispose();
+ }
+}
+
+
+
+
+void SlideSorterView::Init (void)
+{
+ HandleModelChange();
+}
+
+
+
+
+void SlideSorterView::Dispose (void)
+{
+ mpSelectionPainter.reset();
+
+ mpLayeredDevice->Dispose();
+ mpPreviewCache.reset();
+
+ SetPageUnderMouse(SharedPageDescriptor(),false);
+
+ // Hide the page to avoid problems in the view when deleting
+ // visualized objects
+ HideSdrPage();
+
+ // Deletion of the objects and the page will be done in SdrModel
+ // destructor (as long as objects and pages are added)
+
+ OSL_ASSERT(mpLayeredDevice.unique());
+ mpLayeredDevice.reset();
+
+ mbIsDisposed = true;
+}
+
+
+
+
+sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rWindowPosition) const
+{
+ sal_Int32 nIndex (-1);
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ nIndex = mpLayouter->GetIndexAtPoint(pWindow->PixelToLogic(rWindowPosition), false, false);
+
+ // Clip the page index against the page count.
+ if (nIndex >= mrModel.GetPageCount())
+ nIndex = -1;
+ }
+
+ return nIndex;
+}
+
+
+
+
+Layouter& SlideSorterView::GetLayouter (void)
+{
+ return *mpLayouter.get();
+}
+
+
+
+
+void SlideSorterView::ModelHasChanged (void)
+{
+ // Ignore this call. Rely on hints sent by the model to get informed of
+ // model changes.
+}
+
+
+
+
+void SlideSorterView::LocalModelHasChanged(void)
+{
+ mbModelChangedWhileModifyEnabled = false;
+
+ // First call our base class.
+ View::ModelHasChanged ();
+}
+
+
+
+
+void SlideSorterView::PreModelChange (void)
+{
+ // Reset the slide under the mouse. It will be re-set in PostModelChange().
+ SetPageUnderMouse(SharedPageDescriptor());
+}
+
+
+
+
+void SlideSorterView::PostModelChange (void)
+{
+ // In PreModelChange() the page objects have been released. Here we
+ // create new ones.
+ ::osl::MutexGuard aGuard (mrModel.GetMutex());
+
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+
+ // The new page objects have to be scaled and positioned.
+ RequestRearrange();
+ RequestRepaint();
+}
+
+
+
+
+/** At the moment for every model change all page objects are destroyed and
+ re-created again. This can be optimized by accepting hints that
+ describe the type of change so that existing page objects can be
+ reused.
+*/
+void SlideSorterView::HandleModelChange (void)
+{
+ PreModelChange ();
+ PostModelChange();
+}
+
+
+
+
+void SlideSorterView::HandleDrawModeChange (void)
+{
+ // Replace the preview cache with a new and empty one. The
+ // PreviewRenderer that is used by the cache is replaced by this as
+ // well.
+ mpPreviewCache.reset();
+ GetPreviewCache()->InvalidateCache(true);
+
+ RequestRepaint();
+}
+
+
+
+
+void SlideSorterView::HandleDataChangeEvent (void)
+{
+ GetPageObjectPainter()->SetTheme(mrSlideSorter.GetTheme());
+
+ // Update the color used by the background painter.
+ ::boost::shared_ptr<BackgroundPainter> pPainter (
+ ::boost::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter));
+ if (pPainter)
+ pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
+
+ if (mpButtonBar)
+ mpButtonBar->HandleDataChangeEvent();
+
+ RequestRepaint();
+}
+
+
+
+
+void SlideSorterView::Resize (void)
+{
+ UpdateOrientation();
+
+ mpLayeredDevice->Resize();
+ RequestRearrange();
+}
+
+
+
+
+void SlideSorterView::RequestRearrange (void)
+{
+ mbIsRearrangePending = true;
+ Rearrange();
+}
+
+
+
+
+void SlideSorterView::Rearrange (void)
+{
+ if ( ! mbIsRearrangePending)
+ return;
+ if (mrModel.GetPageCount() <= 0)
+ return;
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if ( ! pWindow)
+ return;
+ const Size aWindowSize (pWindow->GetSizePixel());
+ if (aWindowSize.Width()<=0 || aWindowSize.Height()<=0)
+ return;
+
+ const bool bRearrangeSuccess (
+ mpLayouter->Rearrange (
+ meOrientation,
+ aWindowSize,
+ mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
+ mrModel.GetPageCount()));
+ if (bRearrangeSuccess)
+ {
+ mbIsRearrangePending = false;
+ Layout();
+ UpdatePageUnderMouse(false);
+ // RequestRepaint();
+ }
+}
+
+
+
+
+void SlideSorterView::UpdateOrientation (void)
+{
+ // The layout of slides depends on whether the slide sorter is
+ // displayed in the center or the side pane.
+ if (mrSlideSorter.GetViewShell()->IsMainViewShell())
+ SetOrientation(Layouter::GRID);
+ else
+ {
+ // Get access to the docking window.
+ ::Window* pWindow = mrSlideSorter.GetContentWindow().get();
+ PaneDockingWindow* pDockingWindow = NULL;
+ while (pWindow!=NULL && pDockingWindow==NULL)
+ {
+ pDockingWindow = dynamic_cast<PaneDockingWindow*>(pWindow);
+ pWindow = pWindow->GetParent();
+ }
+
+ if (pDockingWindow != NULL)
+ {
+ const long nScrollBarSize (
+ Application::GetSettings().GetStyleSettings().GetScrollBarSize());
+ switch (pDockingWindow->GetOrientation())
+ {
+ case PaneDockingWindow::HorizontalOrientation:
+ if (SetOrientation(Layouter::HORIZONTAL))
+ {
+ const Range aRange (mpLayouter->GetValidVerticalSizeRange());
+ pDockingWindow->SetValidSizeRange(Range(
+ aRange.Min() + nScrollBarSize,
+ aRange.Max() + nScrollBarSize));
+ }
+ break;
+
+ case PaneDockingWindow::VerticalOrientation:
+ if (SetOrientation(Layouter::VERTICAL))
+ {
+ const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
+ pDockingWindow->SetValidSizeRange(Range(
+ aRange.Min() + nScrollBarSize,
+ aRange.Max() + nScrollBarSize));
+ }
+ break;
+
+ case PaneDockingWindow::UnknownOrientation:
+ if (SetOrientation(Layouter::GRID))
+ {
+ const sal_Int32 nAdditionalSize (10);
+ pDockingWindow->SetMinOutputSizePixel(Size(
+ mpLayouter->GetValidHorizontalSizeRange().Min()
+ + nScrollBarSize
+ + nAdditionalSize,
+ mpLayouter->GetValidVerticalSizeRange().Min()
+ + nScrollBarSize
+ + nAdditionalSize));
+ }
+ return;
+ }
+ }
+ else
+ {
+ // We are not placed in a docking window. One possible reason
+ // is that the slide sorter is temporarily into a cache and was
+ // reparented to a non-docking window.
+ SetOrientation(Layouter::GRID);
+ }
+ }
+}
+
+
+
+
+void SlideSorterView::Layout ()
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ // Set the model area, i.e. the smallest rectangle that includes all
+ // page objects.
+ const Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
+ pWindow->SetViewOrigin (aViewBox.TopLeft());
+ pWindow->SetViewSize (aViewBox.GetSize());
+
+ ::boost::shared_ptr<PageObjectLayouter> pPageObjectLayouter(
+ mpLayouter->GetPageObjectLayouter());
+ if (pPageObjectLayouter)
+ {
+ const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetSize(
+ PageObjectLayouter::Preview,
+ PageObjectLayouter::WindowCoordinateSystem));
+ if (maPreviewSize != aNewPreviewSize && GetPreviewCache())
+ {
+ mpPreviewCache->ChangeSize(aNewPreviewSize, true);
+ maPreviewSize = aNewPreviewSize;
+ }
+ }
+
+ // Iterate over all page objects and place them relative to the
+ // containing page.
+ model::PageEnumeration aPageEnumeration (
+ model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
+ while (aPageEnumeration.HasMoreElements())
+ {
+ model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
+ pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex()));
+ }
+
+ GetPageObjectPainter()->NotifyResize();
+ }
+
+ InvalidatePageObjectVisibilities ();
+}
+
+
+
+
+void SlideSorterView::InvalidatePageObjectVisibilities (void)
+{
+ mbPageObjectVisibilitiesValid = false;
+}
+
+
+
+
+void SlideSorterView::DeterminePageObjectVisibilities (void)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ // Set this flag to true here so that an invalidate during the
+ // visibility calculation can correctly invalidate it again.
+ mbPageObjectVisibilitiesValid = true;
+
+ Rectangle aViewArea (pWindow->PixelToLogic(Rectangle(Point(0,0),pWindow->GetSizePixel())));
+ const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea));
+ const Range aUnion(
+ ::std::min(maVisiblePageRange.Min(), aRange.Min()),
+ ::std::max(maVisiblePageRange.Max(), aRange.Max()));
+
+ // For page objects that just dropped off the visible area we
+ // decrease the priority of pending requests for preview bitmaps.
+ if (maVisiblePageRange != aRange)
+ mbPreciousFlagUpdatePending |= true;
+
+ model::SharedPageDescriptor pDescriptor;
+ for (int nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
+ {
+ pDescriptor = mrModel.GetPageDescriptor(nIndex);
+ if (pDescriptor.get() != NULL)
+ SetState(
+ pDescriptor,
+ PageDescriptor::ST_Visible,
+ aRange.IsInside(nIndex));
+ }
+
+ // Broadcast a change of the set of visible page objects.
+ if (maVisiblePageRange != aRange)
+ {
+ maVisiblePageRange = aRange;
+
+ // Tell the listeners that the visibility of some objects has
+ // changed.
+ ::std::vector<Link>& aChangeListeners (maVisibilityChangeListeners);
+ for (::std::vector<Link>::const_iterator
+ iLink(aChangeListeners.begin()),
+ iEnd(aChangeListeners.end());
+ iLink!=iEnd;
+ ++iLink)
+ {
+ iLink->Call(NULL);
+ }
+ }
+
+
+ // Restore the mouse over state.
+ UpdatePageUnderMouse(true);
+ }
+}
+
+
+
+
+void SlideSorterView::UpdatePreciousFlags (void)
+{
+ if (mbPreciousFlagUpdatePending)
+ {
+ mbPreciousFlagUpdatePending = false;
+
+ model::SharedPageDescriptor pDescriptor;
+ ::boost::shared_ptr<cache::PageCache> pCache = GetPreviewCache();
+ sal_Int32 nPageCount (mrModel.GetPageCount());
+
+ for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
+ {
+ pDescriptor = mrModel.GetPageDescriptor(nIndex);
+ if (pDescriptor.get() != NULL)
+ {
+ pCache->SetPreciousFlag(
+ pDescriptor->GetPage(),
+ maVisiblePageRange.IsInside(nIndex));
+ SSCD_SET_VISIBILITY(mrModel.GetDocument(), nIndex,
+ maVisiblePageRange.IsInside(nIndex));
+ }
+ else
+ {
+ // At least one cache entry can not be updated. Remember to
+ // repeat the whole updating later and leave the loop now.
+ mbPreciousFlagUpdatePending = true;
+ break;
+ }
+ }
+ }
+}
+
+
+
+
+bool SlideSorterView::SetOrientation (const Layouter::Orientation eOrientation)
+{
+ if (meOrientation != eOrientation)
+ {
+ meOrientation = eOrientation;
+ return true;
+ }
+ else
+ return false;
+}
+
+
+
+
+Layouter::Orientation SlideSorterView::GetOrientation (void) const
+{
+ return meOrientation;
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (void)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ mpLayeredDevice->InvalidateAllLayers(
+ Rectangle(
+ pWindow->PixelToLogic(Point(0,0)),
+ pWindow->PixelToLogic(pWindow->GetSizePixel())));
+ pWindow->Invalidate();
+ }
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
+{
+ if (rpDescriptor)
+ RequestRepaint(rpDescriptor->GetBoundingBox());
+}
+
+
+
+
+void SlideSorterView::RequestRepaint (const Rectangle& rRepaintBox)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ mpLayeredDevice->InvalidateAllLayers(rRepaintBox);
+ pWindow->Invalidate(rRepaintBox);
+ }
+}
+
+
+
+void SlideSorterView::RequestRepaint (const Region& rRepaintRegion)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow)
+ {
+ mpLayeredDevice->InvalidateAllLayers(rRepaintRegion);
+ pWindow->Invalidate(rRepaintRegion);
+ }
+}
+
+
+
+
+Rectangle SlideSorterView::GetModelArea (void)
+{
+ return mpLayouter->GetTotalBoundingBox();
+}
+
+
+#ifdef DEBUG_TIMING
+static ::canvas::tools::ElapsedTime gaTimer;
+static const size_t gFrameTimeCount (10);
+static size_t gFrameTimeIndex (0);
+static ::std::vector<double> gFrameTimes (gFrameTimeCount, 0);
+static double gFrameTimeSum (0);
+static const Rectangle gFrameTimeBox (10,10,150,20);
+static double gnLastFrameStart = 0;
+#endif
+
+void SlideSorterView::CompleteRedraw (
+ OutputDevice* pDevice,
+ const Region& rPaintArea,
+ sdr::contact::ViewObjectContactRedirector* pRedirector)
+{
+ (void)pRedirector;
+#ifdef DEBUG_TIMING
+ const double nStartTime (gaTimer.getElapsedTime());
+ OSL_TRACE("SlideSorterView::CompleteRedraw start at %f, %s",
+ nStartTime,
+ mnLockRedrawSmph ? "locked" : "");
+#endif
+
+ if (pDevice == NULL || pDevice!=mrSlideSorter.GetContentWindow().get())
+ return;
+
+ // The parent implementation of CompleteRedraw is called only when
+ // painting is locked. We do all the painting ourself. When painting
+ // is locked the parent implementation keeps track of the repaint
+ // requests and later, when painting is unlocked, calls CompleteRedraw
+ // for all missed repaints.
+
+ if (mnLockRedrawSmph == 0)
+ {
+ mrSlideSorter.GetContentWindow()->IncrementLockCount();
+ if (mpLayeredDevice->HandleMapModeChange())
+ DeterminePageObjectVisibilities();
+ mpLayeredDevice->Repaint(rPaintArea);
+ mrSlideSorter.GetContentWindow()->DecrementLockCount();
+ }
+ else
+ {
+ maRedrawRegion.Union(rPaintArea);
+ }
+
+#ifdef DEBUG_TIMING
+ const double nEndTime (gaTimer.getElapsedTime());
+ OSL_TRACE("SlideSorterView::CompleteRedraw end at %f after %fms", nEndTime, (nEndTime-nStartTime)*1000);
+ gFrameTimeSum -= gFrameTimes[gFrameTimeIndex];
+ gFrameTimes[gFrameTimeIndex] = nStartTime - gnLastFrameStart;
+ gnLastFrameStart = nStartTime;
+ gFrameTimeSum += gFrameTimes[gFrameTimeIndex];
+ gFrameTimeIndex = (gFrameTimeIndex+1) % gFrameTimeCount;
+
+
+ mrSlideSorter.GetContentWindow()->SetFillColor(COL_BLUE);
+ mrSlideSorter.GetContentWindow()->DrawRect(gFrameTimeBox);
+ mrSlideSorter.GetContentWindow()->SetTextColor(COL_WHITE);
+ mrSlideSorter.GetContentWindow()->DrawText(
+ gFrameTimeBox,
+ ::rtl::OUString::valueOf(1 / (gFrameTimeSum / gFrameTimeCount)),
+ TEXT_DRAW_RIGHT | TEXT_DRAW_VCENTER);
+ // mrSlideSorter.GetContentWindow()->Invalidate(gFrameTimeBox);
+#endif
+}
+
+
+
+
+void SlideSorterView::Paint (
+ OutputDevice& rDevice,
+ const Rectangle& rRepaintArea)
+{
+ if ( ! mpPageObjectPainter)
+ if ( ! GetPageObjectPainter())
+ return;
+
+ // Update the page visibilities when they have been invalidated.
+ if ( ! mbPageObjectVisibilitiesValid)
+ DeterminePageObjectVisibilities();
+
+ if (mbPreciousFlagUpdatePending)
+ UpdatePreciousFlags();
+
+ if (mbIsRearrangePending)
+ Rearrange();
+
+ // Paint all page objects that are fully or partially inside the
+ // repaint region.
+ const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
+ for (sal_Int32 nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
+ {
+ model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
+ if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
+ continue;
+
+ mpPageObjectPainter->PaintPageObject(rDevice, pDescriptor);
+ }
+}
+
+
+
+
+void SlideSorterView::ConfigurationChanged (
+ utl::ConfigurationBroadcaster* pBroadcaster,
+ sal_uInt32 nHint)
+{
+ // Some changes of the configuration (some of the colors for example)
+ // may affect the previews. Throw away the old ones and create new ones.
+ cache::PageCacheManager::Instance()->InvalidateAllCaches();
+
+ ::sd::View::ConfigurationChanged(pBroadcaster, nHint);
+ RequestRepaint();
+
+}
+
+
+
+
+::boost::shared_ptr<cache::PageCache> SlideSorterView::GetPreviewCache (void)
+{
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow && mpPreviewCache.get() == NULL)
+ {
+ mpPreviewCache.reset(
+ new cache::PageCache(
+ mpLayouter->GetPageObjectSize(),
+ false,
+ cache::SharedCacheContext(new ViewCacheContext(mrSlideSorter))));
+ }
+
+ return mpPreviewCache;
+}
+
+
+
+
+Pair SlideSorterView::GetVisiblePageRange (void)
+{
+ if ( ! mbPageObjectVisibilitiesValid)
+ DeterminePageObjectVisibilities();
+ return maVisiblePageRange;
+}
+
+
+
+
+void SlideSorterView::AddVisibilityChangeListener (const Link& rListener)
+{
+ if (::std::find (
+ maVisibilityChangeListeners.begin(),
+ maVisibilityChangeListeners.end(),
+ rListener) == maVisibilityChangeListeners.end())
+ {
+ maVisibilityChangeListeners.push_back(rListener);
+ }
+}
+
+
+
+
+void SlideSorterView::RemoveVisibilityChangeListener(const Link&rListener)
+{
+ maVisibilityChangeListeners.erase (
+ ::std::find (
+ maVisibilityChangeListeners.begin(),
+ maVisibilityChangeListeners.end(),
+ rListener));
+}
+
+
+
+
+ButtonBar& SlideSorterView::GetButtonBar (void) const
+{
+ OSL_ASSERT(mpButtonBar);
+ return *mpButtonBar;
+}
+
+
+
+
+ToolTip& SlideSorterView::GetToolTip (void) const
+{
+ OSL_ASSERT(mpToolTip);
+ return *mpToolTip;
+}
+
+
+
+
+void SlideSorterView::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
+{
+ ::sd::DrawDocShell* pDocShell = mrModel.GetDocument()->GetDocSh();
+ if (pDocShell!=NULL && pDocShell->IsEnableSetModified())
+ mbModelChangedWhileModifyEnabled = true;
+
+ ::sd::View::Notify(rBroadcaster, rHint);
+}
+
+
+
+
+void SlideSorterView::UpdatePageUnderMouse (bool bAnimate)
+{
+ ::boost::shared_ptr<ScrollBar> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
+ ::boost::shared_ptr<ScrollBar> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar());
+ if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->IsTracking())
+ || (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->IsTracking()))
+ {
+ // One of the scroll bars is tracking mouse movement. Do not
+ // highlight the slide under the mouse in this case.
+ SetPageUnderMouse(SharedPageDescriptor(),false);
+ return;
+ }
+
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ if (pWindow && pWindow->IsVisible() && ! pWindow->IsMouseCaptured())
+ {
+ const Window::PointerState aPointerState (pWindow->GetPointerState());
+ const Rectangle aWindowBox (pWindow->GetPosPixel(), pWindow->GetSizePixel());
+ if (aWindowBox.IsInside(aPointerState.maPos))
+ {
+ UpdatePageUnderMouse (
+ aPointerState.maPos,
+ (aPointerState.mnState & MOUSE_LEFT)!=0,
+ bAnimate);
+ return;
+ }
+ }
+
+ SetPageUnderMouse(SharedPageDescriptor(),false);
+}
+
+
+
+
+void SlideSorterView::UpdatePageUnderMouse (
+ const Point& rMousePosition,
+ const bool bIsMouseButtonDown,
+ const bool bAnimate)
+{
+ UpdatePageUnderMouse(
+ mrSlideSorter.GetController().GetPageAt(rMousePosition),
+ rMousePosition,
+ bIsMouseButtonDown,
+ bAnimate);
+}
+
+
+
+
+void SlideSorterView::UpdatePageUnderMouse (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const Point& rMousePosition,
+ const bool bIsMouseButtonDown,
+ const bool bAnimate)
+{
+ // Update the page under the mouse.
+ SetPageUnderMouse(rpDescriptor, bAnimate);
+
+ // Tell the button bar about the new mouse position.
+ SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
+ const Point aMouseModelPosition (pWindow->PixelToLogic(rMousePosition));
+
+ ::boost::shared_ptr<ViewShell> pMainViewShell (mrSlideSorter.GetViewShellBase()->GetMainViewShell());
+ if (pMainViewShell
+ && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW)
+ {
+ const bool bIsMouseOverButtonBar (GetButtonBar().IsMouseOverBar());
+ GetButtonBar().ProcessMouseMotionEvent(rpDescriptor, aMouseModelPosition, bIsMouseButtonDown);
+ // Set the help text of the slide when the mouse was moved from the
+ // button bar back over the preview.
+ if (rpDescriptor
+ && GetButtonBar().IsMouseOverBar() != bIsMouseOverButtonBar
+ && bIsMouseOverButtonBar)
+ {
+ mpToolTip->ShowDefaultHelpText();
+ }
+ }
+}
+
+
+
+
+void SlideSorterView::SetPageUnderMouse (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const bool bAnimate)
+{
+ if (mpPageUnderMouse != rpDescriptor)
+ {
+ if (mpPageUnderMouse)
+ SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, false, bAnimate);
+
+ mpPageUnderMouse = rpDescriptor;
+
+ if (mpPageUnderMouse)
+ SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, true, bAnimate);
+
+ // Change the quick help text to display the name of the page under
+ // the mouse.
+ mpToolTip->SetPage(rpDescriptor);
+ }
+}
+
+
+
+
+bool SlideSorterView::SetState (
+ const model::SharedPageDescriptor& rpDescriptor,
+ const PageDescriptor::State eState,
+ const bool bStateValue,
+ const bool bAnimate)
+{
+ model::SharedPageDescriptor pDescriptor (rpDescriptor);
+ if ( ! pDescriptor)
+ return false;
+
+ const bool bModified (pDescriptor->SetState(eState, bStateValue));
+ if ( ! bModified)
+ return false;
+
+ // When the page object is not visible (i.e. not on the screen then
+ // nothing has to be painted.
+ if (pDescriptor->HasState(PageDescriptor::ST_Visible))
+ {
+ // For most states a change of that state leads to visible
+ // difference and we have to request a repaint.
+ if (eState != PageDescriptor::ST_WasSelected)
+ RequestRepaint(pDescriptor);
+ }
+
+ ::boost::shared_ptr<ViewShell> pMainViewShell(mrSlideSorter.GetViewShellBase()->GetMainViewShell());
+ if (pMainViewShell
+ && pMainViewShell->GetShellType()!=ViewShell::ST_DRAW)
+ {
+ // Fade in or out the buttons.
+ if (eState == PageDescriptor::ST_MouseOver)
+ {
+ if (bStateValue)
+ GetButtonBar().RequestFadeIn(rpDescriptor, bAnimate);
+ else
+ GetButtonBar().RequestFadeOut(rpDescriptor, bAnimate);
+ }
+ }
+
+ return bModified;
+}
+
+
+
+
+::boost::shared_ptr<PageObjectPainter> SlideSorterView::GetPageObjectPainter (void)
+{
+ if ( ! mpPageObjectPainter)
+ mpPageObjectPainter.reset(new PageObjectPainter(mrSlideSorter));
+ return mpPageObjectPainter;
+}
+
+
+
+
+::boost::shared_ptr<LayeredDevice> SlideSorterView::GetLayeredDevice (void) const
+{
+ return mpLayeredDevice;
+}
+
+
+
+
+//===== SlideSorterView::DrawLock =============================================
+
+SlideSorterView::DrawLock::DrawLock (
+ view::SlideSorterView& rView,
+ const SharedSdWindow& rpWindow)
+ : mrView(rView),
+ mpWindow(rpWindow)
+{
+ if (mrView.mnLockRedrawSmph == 0)
+ mrView.maRedrawRegion.SetEmpty();
+ ++mrView.mnLockRedrawSmph;
+}
+
+
+
+
+SlideSorterView::DrawLock::DrawLock (SlideSorter& rSlideSorter)
+ : mrView(rSlideSorter.GetView()),
+ mpWindow(rSlideSorter.GetContentWindow())
+{
+ if (mrView.mnLockRedrawSmph == 0)
+ mrView.maRedrawRegion.SetEmpty();
+ ++mrView.mnLockRedrawSmph;
+}
+
+
+
+
+SlideSorterView::DrawLock::~DrawLock (void)
+{
+ OSL_ASSERT(mrView.mnLockRedrawSmph>0);
+ --mrView.mnLockRedrawSmph;
+ if (mrView.mnLockRedrawSmph == 0)
+ if (mpWindow)
+ {
+ mpWindow->Invalidate(mrView.maRedrawRegion);
+ mpWindow->Update();
+ }
+}
+
+
+
+
+void SlideSorterView::DrawLock::Dispose (void)
+{
+ mpWindow.reset();
+}
+
+
+} } } // end of namespace ::sd::slidesorter::view