bump product version to 5.0.4.1
[LibreOffice.git] / sd / source / ui / slidesorter / view / SlideSorterView.cxx
blobc1428c874c59d520f8732a4cf9ca07f6d5a31ccc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "view/SlideSorterView.hxx"
22 #include "ViewShellBase.hxx"
23 #include "SlideSorter.hxx"
24 #include "SlideSorterViewShell.hxx"
25 #include "ViewShell.hxx"
26 #include "SlsViewCacheContext.hxx"
27 #include "SlsLayeredDevice.hxx"
28 #include "view/SlsLayouter.hxx"
29 #include "view/SlsPageObjectLayouter.hxx"
30 #include "view/SlsPageObjectPainter.hxx"
31 #include "view/SlsILayerPainter.hxx"
32 #include "view/SlsToolTip.hxx"
33 #include "controller/SlideSorterController.hxx"
34 #include "controller/SlsProperties.hxx"
35 #include "controller/SlsClipboard.hxx"
36 #include "model/SlideSorterModel.hxx"
37 #include "model/SlsPageEnumerationProvider.hxx"
38 #include "model/SlsPageDescriptor.hxx"
39 #include "cache/SlsPageCache.hxx"
40 #include "cache/SlsPageCacheManager.hxx"
41 #include "cache/SlsCacheContext.hxx"
42 #include "taskpane/SlideSorterCacheDisplay.hxx"
43 #include "DrawDocShell.hxx"
44 #include "PaneDockingWindow.hxx"
46 #include "drawdoc.hxx"
47 #include "sdpage.hxx"
48 #include "Window.hxx"
49 #include "sdresid.hxx"
50 #include "glob.hrc"
52 #include <svl/itempool.hxx>
53 #include <svx/svdpagv.hxx>
54 #include <svx/svdopage.hxx>
55 #include <svx/xlndsit.hxx>
56 #include <svx/xlnclit.hxx>
57 #include <vcl/svapp.hxx>
58 #include <vcl/scrbar.hxx>
59 #include <vcl/settings.hxx>
61 #include <tools/poly.hxx>
62 #include <vcl/lineinfo.hxx>
63 #include <algorithm>
64 #include <svx/sdrpagewindow.hxx>
65 #include <basegfx/matrix/b2dhommatrix.hxx>
66 #include <basegfx/polygon/b2dpolygontools.hxx>
67 #include <basegfx/polygon/b2dpolygon.hxx>
68 #include <drawinglayer/geometry/viewinformation2d.hxx>
69 #include <canvas/elapsedtime.hxx>
71 //#define DEBUG_TIMING
72 #ifdef DEBUG_TIMING
73 #include <vector>
74 #endif
76 using namespace std;
77 using namespace ::sd::slidesorter::model;
78 using namespace ::drawinglayer::primitive2d;
80 namespace sd { namespace slidesorter { namespace view {
82 namespace {
83 /** Wrapper around the SlideSorterView that supports the IPainter
84 interface and that allows the LayeredDevice to hold the
85 SlideSorterView (held as scoped_ptr by the SlideSorter) as
86 shared_ptr.
88 class Painter : public ILayerPainter
90 public:
91 Painter (SlideSorterView& rView) : mrView(rView) {}
92 virtual ~Painter() {}
94 virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea) SAL_OVERRIDE
96 mrView.Paint(rDevice,rRepaintArea);
99 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) SAL_OVERRIDE {}
101 private:
102 SlideSorterView& mrView;
106 class BackgroundPainter
107 : public ILayerPainter,
108 public ::boost::noncopyable
110 public:
111 BackgroundPainter (const Color& rBackgroundColor) : maBackgroundColor(rBackgroundColor) {}
112 virtual ~BackgroundPainter() {}
114 virtual void Paint (OutputDevice& rDevice, const Rectangle& rRepaintArea) SAL_OVERRIDE
116 rDevice.SetFillColor(maBackgroundColor);
117 rDevice.SetLineColor();
118 rDevice.DrawRect(rRepaintArea);
121 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) SAL_OVERRIDE {}
123 void SetColor (const Color& rColor) { maBackgroundColor = rColor; }
125 private:
126 Color maBackgroundColor;
129 TYPEINIT1(SlideSorterView, ::sd::View);
131 SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
132 : ::sd::View (
133 *rSlideSorter.GetModel().GetDocument(),
134 rSlideSorter.GetContentWindow(),
135 rSlideSorter.GetViewShell()),
136 mrSlideSorter(rSlideSorter),
137 mrModel(rSlideSorter.GetModel()),
138 mbIsDisposed(false),
139 mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
140 mbPageObjectVisibilitiesValid (false),
141 mpPreviewCache(),
142 mpLayeredDevice(new LayeredDevice(rSlideSorter.GetContentWindow())),
143 maVisiblePageRange(-1,-1),
144 mbModelChangedWhileModifyEnabled(true),
145 maPreviewSize(0,0),
146 mbPreciousFlagUpdatePending(true),
147 meOrientation(Layouter::GRID),
148 mpProperties(rSlideSorter.GetProperties()),
149 mpPageUnderMouse(),
150 mnButtonUnderMouse(-1),
151 mpPageObjectPainter(),
152 mpSelectionPainter(),
153 mpBackgroundPainter(
154 new BackgroundPainter(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
155 mpToolTip(new ToolTip(mrSlideSorter)),
156 mbIsRearrangePending(true),
157 maVisibilityChangeListeners()
159 // Hide the page that contains the page objects.
160 SetPageVisible (false);
162 // Register the background painter on level 1 to avoid the creation of a
163 // background buffer.
164 mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
166 // Wrap a shared_ptr-held-wrapper around this view and register it as
167 // painter at the layered device. There is no explicit destruction: in
168 // the SlideSorterView destructor the layered device is destroyed and
169 // with it the only reference to the wrapper which therefore is also
170 // destroyed.
171 SharedILayerPainter pPainter (new Painter(*this));
173 // The painter is placed on level 1 to avoid buffering. This should be
174 // a little faster during animations because the previews are painted
175 // directly into the window, not via the buffer.
176 mpLayeredDevice->RegisterPainter(pPainter, 1);
179 SlideSorterView::~SlideSorterView()
181 if ( ! mbIsDisposed)
183 OSL_ASSERT(mbIsDisposed);
184 Dispose();
188 void SlideSorterView::Init()
190 HandleModelChange();
193 void SlideSorterView::Dispose()
195 mpSelectionPainter.reset();
197 mpLayeredDevice->Dispose();
198 mpPreviewCache.reset();
200 SetPageUnderMouse(SharedPageDescriptor());
202 // Hide the page to avoid problems in the view when deleting
203 // visualized objects
204 HideSdrPage();
206 // Deletion of the objects and the page will be done in SdrModel
207 // destructor (as long as objects and pages are added)
209 OSL_ASSERT(mpLayeredDevice.unique());
210 mpLayeredDevice.reset();
212 mbIsDisposed = true;
215 sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rWindowPosition) const
217 sal_Int32 nIndex (-1);
219 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
220 if (pWindow)
222 nIndex = mpLayouter->GetIndexAtPoint(pWindow->PixelToLogic(rWindowPosition), false, false);
224 // Clip the page index against the page count.
225 if (nIndex >= mrModel.GetPageCount())
226 nIndex = -1;
229 return nIndex;
232 Layouter& SlideSorterView::GetLayouter()
234 return *mpLayouter.get();
237 void SlideSorterView::ModelHasChanged()
239 // Ignore this call. Rely on hints sent by the model to get informed of
240 // model changes.
243 void SlideSorterView::PreModelChange()
245 // Reset the slide under the mouse. It will be re-set in PostModelChange().
246 SetPageUnderMouse(SharedPageDescriptor());
249 void SlideSorterView::PostModelChange()
251 // In PreModelChange() the page objects have been released. Here we
252 // create new ones.
253 ::osl::MutexGuard aGuard (mrModel.GetMutex());
255 model::PageEnumeration aPageEnumeration (
256 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
258 // The new page objects have to be scaled and positioned.
259 RequestRearrange();
260 RequestRepaint();
263 /** At the moment for every model change all page objects are destroyed and
264 re-created again. This can be optimized by accepting hints that
265 describe the type of change so that existing page objects can be
266 reused.
268 void SlideSorterView::HandleModelChange()
270 PreModelChange ();
271 PostModelChange();
274 void SlideSorterView::HandleDrawModeChange()
276 // Replace the preview cache with a new and empty one. The
277 // PreviewRenderer that is used by the cache is replaced by this as
278 // well.
279 mpPreviewCache.reset();
280 GetPreviewCache()->InvalidateCache(true);
282 RequestRepaint();
285 void SlideSorterView::HandleDataChangeEvent()
287 GetPageObjectPainter()->SetTheme(mrSlideSorter.GetTheme());
289 // Update the color used by the background painter.
290 ::boost::shared_ptr<BackgroundPainter> pPainter (
291 ::boost::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter));
292 if (pPainter)
293 pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
295 RequestRepaint();
298 void SlideSorterView::Resize()
300 UpdateOrientation();
302 mpLayeredDevice->Resize();
303 RequestRearrange();
306 void SlideSorterView::RequestRearrange()
308 mbIsRearrangePending = true;
309 Rearrange();
312 void SlideSorterView::Rearrange()
314 if ( ! mbIsRearrangePending)
315 return;
316 if (mrModel.GetPageCount() <= 0)
317 return;
319 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
320 if ( ! pWindow)
321 return;
322 const Size aWindowSize (pWindow->GetSizePixel());
323 if (aWindowSize.Width()<=0 || aWindowSize.Height()<=0)
324 return;
326 const bool bRearrangeSuccess (
327 mpLayouter->Rearrange (
328 meOrientation,
329 aWindowSize,
330 mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
331 mrModel.GetPageCount()));
332 if (bRearrangeSuccess)
334 mbIsRearrangePending = false;
335 Layout();
336 UpdatePageUnderMouse();
337 // RequestRepaint();
341 void SlideSorterView::UpdateOrientation()
343 // The layout of slides depends on whether the slide sorter is
344 // displayed in the center or the side pane.
345 if (mrSlideSorter.GetViewShell()->IsMainViewShell())
346 SetOrientation(Layouter::GRID);
347 else
349 // Get access to the docking window.
350 vcl::Window* pWindow = mrSlideSorter.GetContentWindow();
351 PaneDockingWindow* pDockingWindow = NULL;
352 while (pWindow!=NULL && pDockingWindow==NULL)
354 pDockingWindow = dynamic_cast<PaneDockingWindow*>(pWindow);
355 pWindow = pWindow->GetParent();
358 if (pDockingWindow != NULL)
360 const long nScrollBarSize (
361 Application::GetSettings().GetStyleSettings().GetScrollBarSize());
362 switch (pDockingWindow->GetOrientation())
364 case PaneDockingWindow::HorizontalOrientation:
365 if (SetOrientation(Layouter::HORIZONTAL))
367 const Range aRange (mpLayouter->GetValidVerticalSizeRange());
368 pDockingWindow->SetValidSizeRange(Range(
369 aRange.Min() + nScrollBarSize,
370 aRange.Max() + nScrollBarSize));
372 break;
374 case PaneDockingWindow::VerticalOrientation:
375 if (SetOrientation(Layouter::VERTICAL))
377 const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
378 pDockingWindow->SetValidSizeRange(Range(
379 aRange.Min() + nScrollBarSize,
380 aRange.Max() + nScrollBarSize));
382 break;
384 case PaneDockingWindow::UnknownOrientation:
385 if (SetOrientation(Layouter::GRID))
387 const sal_Int32 nAdditionalSize (10);
388 pDockingWindow->SetMinOutputSizePixel(Size(
389 mpLayouter->GetValidHorizontalSizeRange().Min()
390 + nScrollBarSize
391 + nAdditionalSize,
392 mpLayouter->GetValidVerticalSizeRange().Min()
393 + nScrollBarSize
394 + nAdditionalSize));
396 return;
399 else
401 // We are not placed in a docking window. One possible reason
402 // is that the slide sorter is temporarily into a cache and was
403 // reparented to a non-docking window.
404 SetOrientation(Layouter::GRID);
409 void SlideSorterView::Layout ()
411 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
412 if (pWindow)
414 // Set the model area, i.e. the smallest rectangle that includes all
415 // page objects.
416 const Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
417 pWindow->SetViewOrigin (aViewBox.TopLeft());
418 pWindow->SetViewSize (aViewBox.GetSize());
420 ::boost::shared_ptr<PageObjectLayouter> pPageObjectLayouter(
421 mpLayouter->GetPageObjectLayouter());
422 if (pPageObjectLayouter)
424 const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetPreviewSize(PageObjectLayouter::WindowCoordinateSystem));
425 if (maPreviewSize != aNewPreviewSize && GetPreviewCache())
427 mpPreviewCache->ChangeSize(aNewPreviewSize, Bitmap::HasFastScale());
428 maPreviewSize = aNewPreviewSize;
432 // Iterate over all page objects and place them relative to the
433 // containing page.
434 model::PageEnumeration aPageEnumeration (
435 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
436 while (aPageEnumeration.HasMoreElements())
438 model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
439 pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex()));
443 InvalidatePageObjectVisibilities ();
446 void SlideSorterView::InvalidatePageObjectVisibilities()
448 mbPageObjectVisibilitiesValid = false;
451 void SlideSorterView::DeterminePageObjectVisibilities()
453 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
454 if (pWindow)
456 // Set this flag to true here so that an invalidate during the
457 // visibility calculation can correctly invalidate it again.
458 mbPageObjectVisibilitiesValid = true;
460 Rectangle aViewArea (pWindow->PixelToLogic(Rectangle(Point(0,0),pWindow->GetSizePixel())));
461 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea));
462 const Range aUnion(
463 ::std::min(maVisiblePageRange.Min(), aRange.Min()),
464 ::std::max(maVisiblePageRange.Max(), aRange.Max()));
466 // For page objects that just dropped off the visible area we
467 // decrease the priority of pending requests for preview bitmaps.
468 if (maVisiblePageRange != aRange)
469 mbPreciousFlagUpdatePending |= true;
471 model::SharedPageDescriptor pDescriptor;
472 for (int nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
474 pDescriptor = mrModel.GetPageDescriptor(nIndex);
475 if (pDescriptor.get() != NULL)
476 SetState(
477 pDescriptor,
478 PageDescriptor::ST_Visible,
479 aRange.IsInside(nIndex));
482 // Broadcast a change of the set of visible page objects.
483 if (maVisiblePageRange != aRange)
485 maVisiblePageRange = aRange;
487 // Tell the listeners that the visibility of some objects has
488 // changed.
489 ::std::vector<Link<>>& aChangeListeners (maVisibilityChangeListeners);
490 for (::std::vector<Link<>>::const_iterator
491 iLink(aChangeListeners.begin()),
492 iEnd(aChangeListeners.end());
493 iLink!=iEnd;
494 ++iLink)
496 iLink->Call(NULL);
500 // Restore the mouse over state.
501 UpdatePageUnderMouse();
505 void SlideSorterView::UpdatePreciousFlags()
507 if (mbPreciousFlagUpdatePending)
509 mbPreciousFlagUpdatePending = false;
511 model::SharedPageDescriptor pDescriptor;
512 ::boost::shared_ptr<cache::PageCache> pCache = GetPreviewCache();
513 sal_Int32 nPageCount (mrModel.GetPageCount());
515 for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
517 pDescriptor = mrModel.GetPageDescriptor(nIndex);
518 if (pDescriptor.get() != NULL)
520 pCache->SetPreciousFlag(
521 pDescriptor->GetPage(),
522 maVisiblePageRange.IsInside(nIndex));
523 SSCD_SET_VISIBILITY(mrModel.GetDocument(), nIndex,
524 maVisiblePageRange.IsInside(nIndex));
526 else
528 // At least one cache entry can not be updated. Remember to
529 // repeat the whole updating later and leave the loop now.
530 mbPreciousFlagUpdatePending = true;
531 break;
537 bool SlideSorterView::SetOrientation (const Layouter::Orientation eOrientation)
539 if (meOrientation != eOrientation)
541 meOrientation = eOrientation;
542 return true;
544 else
545 return false;
548 void SlideSorterView::RequestRepaint()
550 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
551 if (pWindow)
553 mpLayeredDevice->InvalidateAllLayers(
554 Rectangle(
555 pWindow->PixelToLogic(Point(0,0)),
556 pWindow->PixelToLogic(pWindow->GetSizePixel())));
557 pWindow->Invalidate();
561 void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
563 if (rpDescriptor)
564 RequestRepaint(rpDescriptor->GetBoundingBox());
567 void SlideSorterView::RequestRepaint (const Rectangle& rRepaintBox)
569 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
570 if (pWindow)
572 mpLayeredDevice->InvalidateAllLayers(rRepaintBox);
573 pWindow->Invalidate(rRepaintBox);
577 void SlideSorterView::RequestRepaint (const vcl::Region& rRepaintRegion)
579 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
580 if (pWindow)
582 mpLayeredDevice->InvalidateAllLayers(rRepaintRegion);
583 pWindow->Invalidate(rRepaintRegion);
587 Rectangle SlideSorterView::GetModelArea()
589 return mpLayouter->GetTotalBoundingBox();
592 #ifdef DEBUG_TIMING
593 static ::canvas::tools::ElapsedTime gaTimer;
594 static const size_t gFrameTimeCount (10);
595 static size_t gFrameTimeIndex (0);
596 static ::std::vector<double> gFrameTimes (gFrameTimeCount, 0);
597 static double gFrameTimeSum (0);
598 static const Rectangle gFrameTimeBox (10,10,150,20);
599 static double gnLastFrameStart = 0;
600 #endif
602 void SlideSorterView::CompleteRedraw (
603 OutputDevice* pDevice,
604 const vcl::Region& rPaintArea,
605 sdr::contact::ViewObjectContactRedirector* pRedirector)
607 (void)pRedirector;
608 #ifdef DEBUG_TIMING
609 const double nStartTime (gaTimer.getElapsedTime());
610 OSL_TRACE("SlideSorterView::CompleteRedraw start at %f, %s",
611 nStartTime,
612 mnLockRedrawSmph ? "locked" : "");
613 #endif
615 if (pDevice == NULL || pDevice!=mrSlideSorter.GetContentWindow())
616 return;
618 // The parent implementation of CompleteRedraw is called only when
619 // painting is locked. We do all the painting ourself. When painting
620 // is locked the parent implementation keeps track of the repaint
621 // requests and later, when painting is unlocked, calls CompleteRedraw
622 // for all missed repaints.
624 if (mnLockRedrawSmph == 0)
626 mrSlideSorter.GetContentWindow()->IncrementLockCount();
627 if (mpLayeredDevice->HandleMapModeChange())
628 DeterminePageObjectVisibilities();
629 mpLayeredDevice->Repaint(rPaintArea);
630 mrSlideSorter.GetContentWindow()->DecrementLockCount();
632 else
634 maRedrawRegion.Union(rPaintArea);
637 #ifdef DEBUG_TIMING
638 const double nEndTime (gaTimer.getElapsedTime());
639 OSL_TRACE("SlideSorterView::CompleteRedraw end at %f after %fms", nEndTime, (nEndTime-nStartTime)*1000);
640 gFrameTimeSum -= gFrameTimes[gFrameTimeIndex];
641 gFrameTimes[gFrameTimeIndex] = nStartTime - gnLastFrameStart;
642 gnLastFrameStart = nStartTime;
643 gFrameTimeSum += gFrameTimes[gFrameTimeIndex];
644 gFrameTimeIndex = (gFrameTimeIndex+1) % gFrameTimeCount;
646 mrSlideSorter.GetContentWindow()->SetFillColor(COL_BLUE);
647 mrSlideSorter.GetContentWindow()->DrawRect(gFrameTimeBox);
648 mrSlideSorter.GetContentWindow()->SetTextColor(COL_WHITE);
649 mrSlideSorter.GetContentWindow()->DrawText(
650 gFrameTimeBox,
651 OUString::number(1 / (gFrameTimeSum / gFrameTimeCount)),
652 DrawTextFlags::Right | DrawTextFlags::VCenter);
653 // mrSlideSorter.GetContentWindow()->Invalidate(gFrameTimeBox);
654 #endif
657 void SlideSorterView::Paint (
658 OutputDevice& rDevice,
659 const Rectangle& rRepaintArea)
661 if ( ! mpPageObjectPainter)
662 if ( ! GetPageObjectPainter())
663 return;
665 // Update the page visibilities when they have been invalidated.
666 if ( ! mbPageObjectVisibilitiesValid)
667 DeterminePageObjectVisibilities();
669 if (mbPreciousFlagUpdatePending)
670 UpdatePreciousFlags();
672 if (mbIsRearrangePending)
673 Rearrange();
675 // Paint all page objects that are fully or partially inside the
676 // repaint region.
677 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
678 for (sal_Int32 nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
680 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
681 if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
682 continue;
684 mpPageObjectPainter->PaintPageObject(rDevice, pDescriptor);
688 void SlideSorterView::ConfigurationChanged (
689 utl::ConfigurationBroadcaster* pBroadcaster,
690 sal_uInt32 nHint)
692 // Some changes of the configuration (some of the colors for example)
693 // may affect the previews. Throw away the old ones and create new ones.
694 cache::PageCacheManager::Instance()->InvalidateAllCaches();
696 ::sd::View::ConfigurationChanged(pBroadcaster, nHint);
697 RequestRepaint();
701 ::boost::shared_ptr<cache::PageCache> SlideSorterView::GetPreviewCache()
703 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
704 if (pWindow && mpPreviewCache.get() == NULL)
706 mpPreviewCache.reset(
707 new cache::PageCache(
708 mpLayouter->GetPageObjectSize(),
709 Bitmap::HasFastScale(),
710 cache::SharedCacheContext(new ViewCacheContext(mrSlideSorter))));
713 return mpPreviewCache;
716 Pair SlideSorterView::GetVisiblePageRange()
718 if ( ! mbPageObjectVisibilitiesValid)
719 DeterminePageObjectVisibilities();
720 return maVisiblePageRange;
723 void SlideSorterView::AddVisibilityChangeListener (const Link<>& rListener)
725 if (::std::find (
726 maVisibilityChangeListeners.begin(),
727 maVisibilityChangeListeners.end(),
728 rListener) == maVisibilityChangeListeners.end())
730 maVisibilityChangeListeners.push_back(rListener);
734 void SlideSorterView::RemoveVisibilityChangeListener(const Link<>&rListener)
736 maVisibilityChangeListeners.erase (
737 ::std::find (
738 maVisibilityChangeListeners.begin(),
739 maVisibilityChangeListeners.end(),
740 rListener));
743 ToolTip& SlideSorterView::GetToolTip() const
745 OSL_ASSERT(mpToolTip);
746 return *mpToolTip;
749 void SlideSorterView::DragFinished (sal_Int8 nDropAction)
751 mrSlideSorter.GetController().GetClipboard().DragFinished(nDropAction);
753 View::DragFinished(nDropAction);
756 void SlideSorterView::Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint)
758 ::sd::DrawDocShell* pDocShell = mrModel.GetDocument()->GetDocSh();
759 if (pDocShell!=NULL && pDocShell->IsEnableSetModified())
760 mbModelChangedWhileModifyEnabled = true;
762 ::sd::View::Notify(rBroadcaster, rHint);
765 void SlideSorterView::UpdatePageUnderMouse ()
767 VclPtr<ScrollBar> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
768 VclPtr<ScrollBar> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar());
769 if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->IsTracking())
770 || (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->IsTracking()))
772 // One of the scroll bars is tracking mouse movement. Do not
773 // highlight the slide under the mouse in this case.
774 SetPageUnderMouse(SharedPageDescriptor());
775 return;
778 sd::Window *pWindow (mrSlideSorter.GetContentWindow());
779 if (pWindow && pWindow->IsVisible() && ! pWindow->IsMouseCaptured())
781 const Window::PointerState aPointerState (pWindow->GetPointerState());
782 const Rectangle aWindowBox (pWindow->GetPosPixel(), pWindow->GetSizePixel());
783 if (aWindowBox.IsInside(aPointerState.maPos))
785 UpdatePageUnderMouse(aPointerState.maPos);
786 return;
790 SetPageUnderMouse(SharedPageDescriptor());
793 void SlideSorterView::UpdatePageUnderMouse (
794 const Point& rMousePosition)
796 SetPageUnderMouse(mrSlideSorter.GetController().GetPageAt(rMousePosition));
799 void SlideSorterView::SetPageUnderMouse (
800 const model::SharedPageDescriptor& rpDescriptor)
802 if (mpPageUnderMouse != rpDescriptor)
804 if (mpPageUnderMouse)
805 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, false);
807 mpPageUnderMouse = rpDescriptor;
809 if (mpPageUnderMouse)
810 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, true);
812 // Change the quick help text to display the name of the page under
813 // the mouse.
814 mpToolTip->SetPage(rpDescriptor);
818 bool SlideSorterView::SetState (
819 const model::SharedPageDescriptor& rpDescriptor,
820 const PageDescriptor::State eState,
821 const bool bStateValue)
823 model::SharedPageDescriptor pDescriptor (rpDescriptor);
824 if ( ! pDescriptor)
825 return false;
827 const bool bModified (pDescriptor->SetState(eState, bStateValue));
828 if ( ! bModified)
829 return false;
831 // When the page object is not visible (i.e. not on the screen then
832 // nothing has to be painted.
833 if (pDescriptor->HasState(PageDescriptor::ST_Visible))
835 // For most states a change of that state leads to visible
836 // difference and we have to request a repaint.
837 if (eState != PageDescriptor::ST_WasSelected)
838 RequestRepaint(pDescriptor);
841 return bModified;
844 ::boost::shared_ptr<PageObjectPainter> SlideSorterView::GetPageObjectPainter()
846 if ( ! mpPageObjectPainter)
847 mpPageObjectPainter.reset(new PageObjectPainter(mrSlideSorter));
848 return mpPageObjectPainter;
851 //===== SlideSorterView::DrawLock =============================================
853 SlideSorterView::DrawLock::DrawLock (SlideSorter& rSlideSorter)
854 : mrView(rSlideSorter.GetView()),
855 mpWindow(rSlideSorter.GetContentWindow())
857 if (mrView.mnLockRedrawSmph == 0)
858 mrView.maRedrawRegion.SetEmpty();
859 ++mrView.mnLockRedrawSmph;
862 SlideSorterView::DrawLock::~DrawLock()
864 OSL_ASSERT(mrView.mnLockRedrawSmph>0);
865 --mrView.mnLockRedrawSmph;
866 if (mrView.mnLockRedrawSmph == 0)
867 if (mpWindow)
869 mpWindow->Invalidate(mrView.maRedrawRegion);
870 mpWindow->Update();
874 void SlideSorterView::DrawLock::Dispose()
876 mpWindow.reset();
879 } } } // end of namespace ::sd::slidesorter::view
881 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */