bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / slidesorter / view / SlideSorterView.cxx
blob2616e93eee60d41414f0354b2b8abf3c21c9bd78
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 <DrawDocShell.hxx>
43 #include <PaneDockingWindow.hxx>
45 #include <drawdoc.hxx>
46 #include <sdpage.hxx>
47 #include <Window.hxx>
49 #include <sal/log.hxx>
50 #include <svl/itempool.hxx>
51 #include <svx/svdpagv.hxx>
52 #include <svx/svdopage.hxx>
53 #include <svx/xlndsit.hxx>
54 #include <svx/xlnclit.hxx>
55 #include <vcl/svapp.hxx>
56 #include <vcl/scrbar.hxx>
57 #include <vcl/settings.hxx>
59 #include <tools/poly.hxx>
60 #include <vcl/lineinfo.hxx>
61 #include <algorithm>
62 #include <svx/sdrpagewindow.hxx>
63 #include <basegfx/matrix/b2dhommatrix.hxx>
64 #include <basegfx/polygon/b2dpolygontools.hxx>
65 #include <basegfx/polygon/b2dpolygon.hxx>
66 #include <drawinglayer/geometry/viewinformation2d.hxx>
67 #include <canvas/elapsedtime.hxx>
69 //#define DEBUG_TIMING
70 #ifdef DEBUG_TIMING
71 #include <memory>
72 #include <vector>
73 #endif
75 using namespace std;
76 using namespace ::sd::slidesorter::model;
77 using namespace ::drawinglayer::primitive2d;
79 namespace sd { namespace slidesorter { namespace view {
81 namespace {
82 /** Wrapper around the SlideSorterView that supports the IPainter
83 interface and that allows the LayeredDevice to hold the
84 SlideSorterView (held as unique_ptr by the SlideSorter) as
85 shared_ptr.
87 class Painter : public ILayerPainter
89 public:
90 explicit Painter (SlideSorterView& rView) : mrView(rView) {}
92 virtual void Paint (OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) override
94 mrView.Paint(rDevice,rRepaintArea);
97 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) override {}
99 private:
100 SlideSorterView& mrView;
104 class BackgroundPainter
105 : public ILayerPainter
107 public:
108 explicit BackgroundPainter (const Color& rBackgroundColor) : maBackgroundColor(rBackgroundColor) {}
109 BackgroundPainter(const BackgroundPainter&) = delete;
110 BackgroundPainter& operator=(const BackgroundPainter&) = delete;
112 virtual void Paint (OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) override
114 rDevice.SetFillColor(maBackgroundColor);
115 rDevice.SetLineColor();
116 rDevice.DrawRect(rRepaintArea);
119 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) override {}
121 void SetColor (const Color& rColor) { maBackgroundColor = rColor; }
123 private:
124 Color maBackgroundColor;
128 SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
129 : ::sd::View (
130 *rSlideSorter.GetModel().GetDocument(),
131 rSlideSorter.GetContentWindow(),
132 rSlideSorter.GetViewShell()),
133 mrSlideSorter(rSlideSorter),
134 mrModel(rSlideSorter.GetModel()),
135 mbIsDisposed(false),
136 mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
137 mbPageObjectVisibilitiesValid (false),
138 mpPreviewCache(),
139 mpLayeredDevice(new LayeredDevice(rSlideSorter.GetContentWindow())),
140 maVisiblePageRange(-1,-1),
141 maPreviewSize(0,0),
142 mbPreciousFlagUpdatePending(true),
143 meOrientation(Layouter::GRID),
144 mpPageUnderMouse(),
145 mpPageObjectPainter(),
146 mpBackgroundPainter(
147 new BackgroundPainter(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
148 mpToolTip(new ToolTip(mrSlideSorter)),
149 mbIsRearrangePending(true),
150 maVisibilityChangeListeners()
152 // Hide the page that contains the page objects.
153 SetPageVisible (false);
155 // Register the background painter on level 1 to avoid the creation of a
156 // background buffer.
157 mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
159 // Wrap a shared_ptr-held-wrapper around this view and register it as
160 // painter at the layered device. There is no explicit destruction: in
161 // the SlideSorterView destructor the layered device is destroyed and
162 // with it the only reference to the wrapper which therefore is also
163 // destroyed.
164 SharedILayerPainter pPainter (new Painter(*this));
166 // The painter is placed on level 1 to avoid buffering. This should be
167 // a little faster during animations because the previews are painted
168 // directly into the window, not via the buffer.
169 mpLayeredDevice->RegisterPainter(pPainter, 1);
172 SlideSorterView::~SlideSorterView()
174 if ( ! mbIsDisposed)
176 OSL_ASSERT(mbIsDisposed);
177 Dispose();
181 void SlideSorterView::Init()
183 HandleModelChange();
186 void SlideSorterView::Dispose()
188 mpLayeredDevice->Dispose();
189 mpPreviewCache.reset();
191 SetPageUnderMouse(SharedPageDescriptor());
193 // Hide the page to avoid problems in the view when deleting
194 // visualized objects
195 HideSdrPage();
197 // Deletion of the objects and the page will be done in SdrModel
198 // destructor (as long as objects and pages are added)
200 OSL_ASSERT(mpLayeredDevice.use_count() == 1);
201 mpLayeredDevice.reset();
203 mbIsDisposed = true;
206 sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rWindowPosition) const
208 sal_Int32 nIndex (-1);
210 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
211 if (pWindow)
213 nIndex = mpLayouter->GetIndexAtPoint(pWindow->PixelToLogic(rWindowPosition), false, false);
215 // Clip the page index against the page count.
216 if (nIndex >= mrModel.GetPageCount())
217 nIndex = -1;
220 return nIndex;
223 Layouter& SlideSorterView::GetLayouter() { return *mpLayouter; }
225 void SlideSorterView::ModelHasChanged()
227 // Ignore this call. Rely on hints sent by the model to get informed of
228 // model changes.
231 void SlideSorterView::PreModelChange()
233 // Reset the slide under the mouse. It will be re-set in PostModelChange().
234 SetPageUnderMouse(SharedPageDescriptor());
237 void SlideSorterView::PostModelChange()
239 // In PreModelChange() the page objects have been released. Here we
240 // create new ones.
241 ::osl::MutexGuard aGuard (mrModel.GetMutex());
243 model::PageEnumeration aPageEnumeration (
244 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
246 // The new page objects have to be scaled and positioned.
247 RequestRearrange();
248 RequestRepaint();
251 /** At the moment for every model change all page objects are destroyed and
252 re-created again. This can be optimized by accepting hints that
253 describe the type of change so that existing page objects can be
254 reused.
256 void SlideSorterView::HandleModelChange()
258 PreModelChange ();
259 PostModelChange();
262 void SlideSorterView::HandleDrawModeChange()
264 // Replace the preview cache with a new and empty one. The
265 // PreviewRenderer that is used by the cache is replaced by this as
266 // well.
267 mpPreviewCache.reset();
268 GetPreviewCache()->InvalidateCache();
270 RequestRepaint();
273 void SlideSorterView::HandleDataChangeEvent()
275 GetPageObjectPainter()->SetTheme(mrSlideSorter.GetTheme());
277 // Update the color used by the background painter.
278 std::shared_ptr<BackgroundPainter> pPainter (
279 std::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter));
280 if (pPainter)
281 pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
283 RequestRepaint();
286 void SlideSorterView::Resize()
288 UpdateOrientation();
290 mpLayeredDevice->Resize();
291 RequestRearrange();
294 void SlideSorterView::RequestRearrange()
296 mbIsRearrangePending = true;
297 Rearrange();
300 void SlideSorterView::Rearrange()
302 if ( ! mbIsRearrangePending)
303 return;
304 if (mrModel.GetPageCount() <= 0)
305 return;
307 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
308 if ( ! pWindow)
309 return;
310 const Size aWindowSize (pWindow->GetSizePixel());
311 if (aWindowSize.Width()<=0 || aWindowSize.Height()<=0)
312 return;
314 const bool bRearrangeSuccess (
315 mpLayouter->Rearrange (
316 meOrientation,
317 aWindowSize,
318 mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
319 mrModel.GetPageCount()));
320 if (bRearrangeSuccess)
322 mbIsRearrangePending = false;
323 Layout();
324 UpdatePageUnderMouse();
325 // RequestRepaint();
329 void SlideSorterView::UpdateOrientation()
331 // The layout of slides depends on whether the slide sorter is
332 // displayed in the center or the side pane.
333 if (mrSlideSorter.GetViewShell()->IsMainViewShell())
334 SetOrientation(Layouter::GRID);
335 else
337 // Get access to the docking window.
338 vcl::Window* pWindow = mrSlideSorter.GetContentWindow();
339 PaneDockingWindow* pDockingWindow = nullptr;
340 while (pWindow!=nullptr && pDockingWindow==nullptr)
342 pDockingWindow = dynamic_cast<PaneDockingWindow*>(pWindow);
343 pWindow = pWindow->GetParent();
346 if (pDockingWindow != nullptr)
348 const long nScrollBarSize (
349 Application::GetSettings().GetStyleSettings().GetScrollBarSize());
350 switch (pDockingWindow->GetOrientation())
352 case PaneDockingWindow::HorizontalOrientation:
353 if (SetOrientation(Layouter::HORIZONTAL))
355 const Range aRange (mpLayouter->GetValidVerticalSizeRange());
356 pDockingWindow->SetValidSizeRange(Range(
357 aRange.Min() + nScrollBarSize,
358 aRange.Max() + nScrollBarSize));
360 break;
362 case PaneDockingWindow::VerticalOrientation:
363 if (SetOrientation(Layouter::VERTICAL))
365 const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
366 pDockingWindow->SetValidSizeRange(Range(
367 aRange.Min() + nScrollBarSize,
368 aRange.Max() + nScrollBarSize));
370 break;
372 case PaneDockingWindow::UnknownOrientation:
373 if (SetOrientation(Layouter::GRID))
375 const sal_Int32 nAdditionalSize (10);
376 pDockingWindow->SetMinOutputSizePixel(Size(
377 mpLayouter->GetValidHorizontalSizeRange().Min()
378 + nScrollBarSize
379 + nAdditionalSize,
380 mpLayouter->GetValidVerticalSizeRange().Min()
381 + nScrollBarSize
382 + nAdditionalSize));
384 return;
387 else
389 // We are not placed in a docking window. One possible reason
390 // is that the slide sorter is temporarily into a cache and was
391 // reparented to a non-docking window.
392 SetOrientation(Layouter::GRID);
397 void SlideSorterView::Layout ()
399 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
400 if (pWindow)
402 // Set the model area, i.e. the smallest rectangle that includes all
403 // page objects.
404 const ::tools::Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
405 pWindow->SetViewOrigin (aViewBox.TopLeft());
406 pWindow->SetViewSize (aViewBox.GetSize());
408 std::shared_ptr<PageObjectLayouter> pPageObjectLayouter(
409 mpLayouter->GetPageObjectLayouter());
410 if (pPageObjectLayouter)
412 const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetPreviewSize());
413 if (maPreviewSize != aNewPreviewSize && GetPreviewCache())
415 mpPreviewCache->ChangeSize(aNewPreviewSize, Bitmap::HasFastScale());
416 maPreviewSize = aNewPreviewSize;
420 // Iterate over all page objects and place them relative to the
421 // containing page.
422 model::PageEnumeration aPageEnumeration (
423 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
424 while (aPageEnumeration.HasMoreElements())
426 model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
427 pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex(), false));
431 InvalidatePageObjectVisibilities ();
434 void SlideSorterView::InvalidatePageObjectVisibilities()
436 mbPageObjectVisibilitiesValid = false;
439 void SlideSorterView::DeterminePageObjectVisibilities()
441 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
442 if (!pWindow)
443 return;
445 // Set this flag to true here so that an invalidate during the
446 // visibility calculation can correctly invalidate it again.
447 mbPageObjectVisibilitiesValid = true;
449 ::tools::Rectangle aViewArea (pWindow->PixelToLogic(::tools::Rectangle(Point(0,0),pWindow->GetSizePixel())));
450 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea));
451 const Range aUnion(
452 ::std::min(maVisiblePageRange.Min(), aRange.Min()),
453 ::std::max(maVisiblePageRange.Max(), aRange.Max()));
455 // For page objects that just dropped off the visible area we
456 // decrease the priority of pending requests for preview bitmaps.
457 if (maVisiblePageRange != aRange)
458 mbPreciousFlagUpdatePending |= true;
460 model::SharedPageDescriptor pDescriptor;
461 for (long nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
463 pDescriptor = mrModel.GetPageDescriptor(nIndex);
464 if (pDescriptor.get() != nullptr)
465 SetState(
466 pDescriptor,
467 PageDescriptor::ST_Visible,
468 aRange.IsInside(nIndex));
471 // Broadcast a change of the set of visible page objects.
472 if (maVisiblePageRange != aRange)
474 maVisiblePageRange = aRange;
476 // Tell the listeners that the visibility of some objects has
477 // changed.
478 ::std::vector<Link<LinkParamNone*,void>>& aChangeListeners (maVisibilityChangeListeners);
479 for (const auto& rLink : aChangeListeners)
481 rLink.Call(nullptr);
485 // Restore the mouse over state.
486 UpdatePageUnderMouse();
489 void SlideSorterView::UpdatePreciousFlags()
491 if (!mbPreciousFlagUpdatePending)
492 return;
494 mbPreciousFlagUpdatePending = false;
496 model::SharedPageDescriptor pDescriptor;
497 std::shared_ptr<cache::PageCache> pCache = GetPreviewCache();
498 sal_Int32 nPageCount (mrModel.GetPageCount());
500 for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
502 pDescriptor = mrModel.GetPageDescriptor(nIndex);
503 if (pDescriptor.get() != nullptr)
505 pCache->SetPreciousFlag(
506 pDescriptor->GetPage(),
507 maVisiblePageRange.IsInside(nIndex));
509 else
511 // At least one cache entry can not be updated. Remember to
512 // repeat the whole updating later and leave the loop now.
513 mbPreciousFlagUpdatePending = true;
514 break;
519 bool SlideSorterView::SetOrientation (const Layouter::Orientation eOrientation)
521 if (meOrientation != eOrientation)
523 meOrientation = eOrientation;
524 return true;
526 else
527 return false;
530 void SlideSorterView::RequestRepaint()
532 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
533 if (pWindow)
535 mpLayeredDevice->InvalidateAllLayers(
536 ::tools::Rectangle(
537 pWindow->PixelToLogic(Point(0,0)),
538 pWindow->PixelToLogic(pWindow->GetSizePixel())));
539 pWindow->Invalidate();
543 void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
545 if (rpDescriptor)
546 RequestRepaint(rpDescriptor->GetBoundingBox());
549 void SlideSorterView::RequestRepaint (const ::tools::Rectangle& rRepaintBox)
551 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
552 if (pWindow)
554 mpLayeredDevice->InvalidateAllLayers(rRepaintBox);
555 pWindow->Invalidate(rRepaintBox);
559 void SlideSorterView::RequestRepaint (const vcl::Region& rRepaintRegion)
561 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
562 if (pWindow)
564 mpLayeredDevice->InvalidateAllLayers(rRepaintRegion);
565 pWindow->Invalidate(rRepaintRegion);
569 ::tools::Rectangle SlideSorterView::GetModelArea()
571 return mpLayouter->GetTotalBoundingBox();
574 #ifdef DEBUG_TIMING
575 static ::canvas::tools::ElapsedTime gaTimer;
576 static const size_t gFrameTimeCount (10);
577 static size_t gFrameTimeIndex (0);
578 static ::std::vector<double> gFrameTimes (gFrameTimeCount, 0);
579 static double gFrameTimeSum (0);
580 static const Rectangle gFrameTimeBox (10,10,150,20);
581 static double gnLastFrameStart = 0;
582 #endif
584 void SlideSorterView::CompleteRedraw (
585 OutputDevice* pDevice,
586 const vcl::Region& rPaintArea,
587 sdr::contact::ViewObjectContactRedirector* pRedirector)
589 (void)pRedirector;
590 #ifdef DEBUG_TIMING
591 const double nStartTime (gaTimer.getElapsedTime());
592 SAL_INFO("sd",("SlideSorterView::CompleteRedraw start at %f, %s",
593 nStartTime,
594 mnLockRedrawSmph ? "locked" : "");
595 #endif
597 if (pDevice == nullptr || pDevice!=mrSlideSorter.GetContentWindow())
598 return;
600 // The parent implementation of CompleteRedraw is called only when
601 // painting is locked. We do all the painting ourself. When painting
602 // is locked the parent implementation keeps track of the repaint
603 // requests and later, when painting is unlocked, calls CompleteRedraw
604 // for all missed repaints.
606 if (mnLockRedrawSmph == 0)
608 if (mpLayeredDevice->HandleMapModeChange())
609 DeterminePageObjectVisibilities();
610 mpLayeredDevice->Repaint(rPaintArea);
612 else
614 maRedrawRegion.Union(rPaintArea);
617 #ifdef DEBUG_TIMING
618 const double nEndTime (gaTimer.getElapsedTime());
619 SAL_INFO("sd",("SlideSorterView::CompleteRedraw end at %f after %fms", nEndTime, (nEndTime-nStartTime)*1000);
620 gFrameTimeSum -= gFrameTimes[gFrameTimeIndex];
621 gFrameTimes[gFrameTimeIndex] = nStartTime - gnLastFrameStart;
622 gnLastFrameStart = nStartTime;
623 gFrameTimeSum += gFrameTimes[gFrameTimeIndex];
624 gFrameTimeIndex = (gFrameTimeIndex+1) % gFrameTimeCount;
626 mrSlideSorter.GetContentWindow()->SetFillCOL_BLUE);
627 mrSlideSorter.GetContentWindow()->DrawRect(gFrameTimeBox);
628 mrSlideSorter.GetContentWindow()->SetTextCOL_WHITE);
629 mrSlideSorter.GetContentWindow()->DrawText(
630 gFrameTimeBox,
631 OUString::number(1 / (gFrameTimeSum / gFrameTimeCount)),
632 DrawTextFlags::Right | DrawTextFlags::VCenter);
633 // mrSlideSorter.GetContentWindow()->Invalidate(gFrameTimeBox);
634 #endif
637 void SlideSorterView::Paint (
638 OutputDevice& rDevice,
639 const ::tools::Rectangle& rRepaintArea)
641 if ( ! mpPageObjectPainter)
642 if ( ! GetPageObjectPainter())
643 return;
645 // Update the page visibilities when they have been invalidated.
646 if ( ! mbPageObjectVisibilitiesValid)
647 DeterminePageObjectVisibilities();
649 if (mbPreciousFlagUpdatePending)
650 UpdatePreciousFlags();
652 if (mbIsRearrangePending)
653 Rearrange();
655 // Paint all page objects that are fully or partially inside the
656 // repaint region.
657 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
658 for (long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
660 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
661 if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
662 continue;
664 mpPageObjectPainter->PaintPageObject(rDevice, pDescriptor);
668 void SlideSorterView::ConfigurationChanged (
669 utl::ConfigurationBroadcaster* pBroadcaster,
670 ConfigurationHints nHint)
672 // Some changes of the configuration (some of the colors for example)
673 // may affect the previews. Throw away the old ones and create new ones.
674 cache::PageCacheManager::Instance()->InvalidateAllCaches();
676 ::sd::View::ConfigurationChanged(pBroadcaster, nHint);
677 RequestRepaint();
681 std::shared_ptr<cache::PageCache> const & SlideSorterView::GetPreviewCache()
683 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
684 if (pWindow && mpPreviewCache == nullptr)
686 mpPreviewCache.reset(
687 new cache::PageCache(
688 mpLayouter->GetPageObjectSize(),
689 Bitmap::HasFastScale(),
690 cache::SharedCacheContext(new ViewCacheContext(mrSlideSorter))));
693 return mpPreviewCache;
696 Range const & SlideSorterView::GetVisiblePageRange()
698 if ( ! mbPageObjectVisibilitiesValid)
699 DeterminePageObjectVisibilities();
700 return maVisiblePageRange;
703 void SlideSorterView::AddVisibilityChangeListener (const Link<LinkParamNone*,void>& rListener)
705 if (::std::find (
706 maVisibilityChangeListeners.begin(),
707 maVisibilityChangeListeners.end(),
708 rListener) == maVisibilityChangeListeners.end())
710 maVisibilityChangeListeners.push_back(rListener);
714 void SlideSorterView::RemoveVisibilityChangeListener(const Link<LinkParamNone*,void>&rListener)
716 maVisibilityChangeListeners.erase (
717 ::std::find (
718 maVisibilityChangeListeners.begin(),
719 maVisibilityChangeListeners.end(),
720 rListener));
723 ToolTip& SlideSorterView::GetToolTip() const
725 OSL_ASSERT(mpToolTip);
726 return *mpToolTip;
729 void SlideSorterView::DragFinished (sal_Int8 nDropAction)
731 mrSlideSorter.GetController().GetClipboard().DragFinished(nDropAction);
733 View::DragFinished(nDropAction);
736 void SlideSorterView::UpdatePageUnderMouse ()
738 VclPtr<ScrollBar> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
739 VclPtr<ScrollBar> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar());
740 if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->IsTracking())
741 || (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->IsTracking()))
743 // One of the scroll bars is tracking mouse movement. Do not
744 // highlight the slide under the mouse in this case.
745 SetPageUnderMouse(SharedPageDescriptor());
746 return;
749 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
750 if (pWindow && pWindow->IsVisible() && ! pWindow->IsMouseCaptured())
752 const Window::PointerState aPointerState (pWindow->GetPointerState());
753 const ::tools::Rectangle aWindowBox (pWindow->GetPosPixel(), pWindow->GetSizePixel());
754 if (aWindowBox.IsInside(aPointerState.maPos))
756 UpdatePageUnderMouse(aPointerState.maPos);
757 return;
761 SetPageUnderMouse(SharedPageDescriptor());
764 void SlideSorterView::UpdatePageUnderMouse (
765 const Point& rMousePosition)
767 SetPageUnderMouse(mrSlideSorter.GetController().GetPageAt(rMousePosition));
770 void SlideSorterView::SetPageUnderMouse (
771 const model::SharedPageDescriptor& rpDescriptor)
773 if (mpPageUnderMouse == rpDescriptor)
774 return;
776 if (mpPageUnderMouse)
777 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, false);
779 mpPageUnderMouse = rpDescriptor;
781 if (mpPageUnderMouse)
782 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, true);
784 // Change the quick help text to display the name of the page under
785 // the mouse.
786 mpToolTip->SetPage(rpDescriptor);
789 bool SlideSorterView::SetState (
790 const model::SharedPageDescriptor& rpDescriptor,
791 const PageDescriptor::State eState,
792 const bool bStateValue)
794 if ( ! rpDescriptor)
795 return false;
797 const bool bModified (rpDescriptor->SetState(eState, bStateValue));
798 if ( ! bModified)
799 return false;
801 // When the page object is not visible (i.e. not on the screen then
802 // nothing has to be painted.
803 if (rpDescriptor->HasState(PageDescriptor::ST_Visible))
805 // For most states a change of that state leads to visible
806 // difference and we have to request a repaint.
807 if (eState != PageDescriptor::ST_WasSelected)
808 RequestRepaint(rpDescriptor);
811 return bModified;
814 std::shared_ptr<PageObjectPainter> const & SlideSorterView::GetPageObjectPainter()
816 if ( ! mpPageObjectPainter)
817 mpPageObjectPainter.reset(new PageObjectPainter(mrSlideSorter));
818 return mpPageObjectPainter;
821 //===== SlideSorterView::DrawLock =============================================
823 SlideSorterView::DrawLock::DrawLock (SlideSorter const & rSlideSorter)
824 : mrView(rSlideSorter.GetView()),
825 mpWindow(rSlideSorter.GetContentWindow())
827 if (mrView.mnLockRedrawSmph == 0)
828 mrView.maRedrawRegion.SetEmpty();
829 ++mrView.mnLockRedrawSmph;
832 SlideSorterView::DrawLock::~DrawLock()
834 OSL_ASSERT(mrView.mnLockRedrawSmph>0);
835 --mrView.mnLockRedrawSmph;
836 if (mrView.mnLockRedrawSmph == 0)
837 if (mpWindow)
839 mpWindow->Invalidate(mrView.maRedrawRegion);
840 mpWindow->Update();
844 void SlideSorterView::DrawLock::Dispose()
846 mpWindow.reset();
849 } } } // end of namespace ::sd::slidesorter::view
851 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */