android: Update app-specific/MIME type icons
[LibreOffice.git] / sd / source / ui / slidesorter / view / SlideSorterView.cxx
blobd15b2137451a583f29c5b3dc7032f4e317b904f2
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 <SlideSorter.hxx>
23 #include <ViewShell.hxx>
24 #include "SlsViewCacheContext.hxx"
25 #include "SlsLayeredDevice.hxx"
26 #include <view/SlsLayouter.hxx>
27 #include <view/SlsPageObjectLayouter.hxx>
28 #include <view/SlsPageObjectPainter.hxx>
29 #include <view/SlsILayerPainter.hxx>
30 #include <view/SlsToolTip.hxx>
31 #include <controller/SlideSorterController.hxx>
32 #include <controller/SlsClipboard.hxx>
33 #include <model/SlideSorterModel.hxx>
34 #include <model/SlsPageEnumerationProvider.hxx>
35 #include <model/SlsPageDescriptor.hxx>
36 #include <cache/SlsPageCache.hxx>
37 #include <cache/SlsPageCacheManager.hxx>
38 #include <titledockwin.hxx>
40 #include <sdpage.hxx>
41 #include <Window.hxx>
43 #include <comphelper/lok.hxx>
44 #include <osl/diagnose.h>
45 #include <vcl/svapp.hxx>
46 #include <vcl/settings.hxx>
47 #include <vcl/graphicfilter.hxx>
49 #include <algorithm>
51 //#define DEBUG_TIMING
52 #ifdef DEBUG_TIMING
53 #include <memory>
54 #include <vector>
55 #endif
57 using namespace ::sd::slidesorter::model;
58 using namespace ::drawinglayer::primitive2d;
60 namespace sd::slidesorter::view {
62 namespace {
63 /** Wrapper around the SlideSorterView that supports the IPainter
64 interface and that allows the LayeredDevice to hold the
65 SlideSorterView (held as unique_ptr by the SlideSorter) as
66 shared_ptr.
68 class Painter : public ILayerPainter
70 public:
71 explicit Painter (SlideSorterView& rView) : mrView(rView) {}
73 virtual void Paint (OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) override
75 mrView.Paint(rDevice,rRepaintArea);
78 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) override {}
80 private:
81 SlideSorterView& mrView;
85 namespace {
87 class BackgroundPainter
88 : public ILayerPainter
90 public:
91 explicit BackgroundPainter (const Color& rBackgroundColor) : maBackgroundColor(rBackgroundColor) {}
92 BackgroundPainter(const BackgroundPainter&) = delete;
93 BackgroundPainter& operator=(const BackgroundPainter&) = delete;
95 virtual void Paint (OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) override
97 rDevice.SetFillColor(maBackgroundColor);
98 rDevice.SetLineColor();
99 rDevice.DrawRect(rRepaintArea);
102 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) override {}
104 void SetColor (const Color& rColor) { maBackgroundColor = rColor; }
106 private:
107 Color maBackgroundColor;
112 SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
113 : ::sd::View (
114 *rSlideSorter.GetModel().GetDocument(),
115 rSlideSorter.GetContentWindow()->GetOutDev(),
116 rSlideSorter.GetViewShell()),
117 mrSlideSorter(rSlideSorter),
118 mrModel(rSlideSorter.GetModel()),
119 mbIsDisposed(false),
120 mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
121 mbPageObjectVisibilitiesValid (false),
122 mpLayeredDevice(std::make_shared<LayeredDevice>(rSlideSorter.GetContentWindow())),
123 maVisiblePageRange(-1,-1),
124 maPreviewSize(0,0),
125 mbPreciousFlagUpdatePending(true),
126 meOrientation(Layouter::GRID),
127 mpBackgroundPainter(
128 std::make_shared<BackgroundPainter>(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
129 mpToolTip(new ToolTip(mrSlideSorter)),
130 mbIsRearrangePending(true)
132 // Hide the page that contains the page objects.
133 SetPageVisible (false);
135 // Register the background painter on level 1 to avoid the creation of a
136 // background buffer.
137 mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
139 // Wrap a shared_ptr-held-wrapper around this view and register it as
140 // painter at the layered device. There is no explicit destruction: in
141 // the SlideSorterView destructor the layered device is destroyed and
142 // with it the only reference to the wrapper which therefore is also
143 // destroyed.
144 SharedILayerPainter pPainter = std::make_shared<Painter>(*this);
146 // The painter is placed on level 1 to avoid buffering. This should be
147 // a little faster during animations because the previews are painted
148 // directly into the window, not via the buffer.
149 mpLayeredDevice->RegisterPainter(pPainter, 1);
152 SlideSorterView::~SlideSorterView()
154 if ( ! mbIsDisposed)
156 OSL_ASSERT(mbIsDisposed);
157 Dispose();
161 void SlideSorterView::Init()
163 HandleModelChange();
166 void SlideSorterView::Dispose()
168 mpLayeredDevice->Dispose();
169 mpPreviewCache.reset();
171 SetPageUnderMouse(SharedPageDescriptor());
173 // Hide the page to avoid problems in the view when deleting
174 // visualized objects
175 HideSdrPage();
177 // Deletion of the objects and the page will be done in SdrModel
178 // destructor (as long as objects and pages are added)
180 OSL_ASSERT(mpLayeredDevice.use_count() == 1);
181 mpLayeredDevice.reset();
183 mbIsDisposed = true;
186 sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rWindowPosition) const
188 sal_Int32 nIndex (-1);
190 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
191 if (pWindow)
193 nIndex = mpLayouter->GetIndexAtPoint(pWindow->PixelToLogic(rWindowPosition), false, false);
195 // Clip the page index against the page count.
196 if (nIndex >= mrModel.GetPageCount())
197 nIndex = -1;
200 return nIndex;
203 Layouter& SlideSorterView::GetLayouter() { return *mpLayouter; }
205 void SlideSorterView::ModelHasChanged()
207 // Ignore this call. Rely on hints sent by the model to get informed of
208 // model changes.
211 void SlideSorterView::PreModelChange()
213 // Reset the slide under the mouse. It will be re-set in PostModelChange().
214 SetPageUnderMouse(SharedPageDescriptor());
217 void SlideSorterView::PostModelChange()
219 // In PreModelChange() the page objects have been released. Here we
220 // create new ones.
221 ::osl::MutexGuard aGuard (mrModel.GetMutex());
223 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel);
225 // The new page objects have to be scaled and positioned.
226 RequestRearrange();
227 RequestRepaint();
230 /** At the moment for every model change all page objects are destroyed and
231 re-created again. This can be optimized by accepting hints that
232 describe the type of change so that existing page objects can be
233 reused.
235 void SlideSorterView::HandleModelChange()
237 PreModelChange ();
238 PostModelChange();
241 void SlideSorterView::HandleDrawModeChange()
243 // Replace the preview cache with a new and empty one. The
244 // PreviewRenderer that is used by the cache is replaced by this as
245 // well.
246 mpPreviewCache.reset();
247 GetPreviewCache()->InvalidateCache();
249 RequestRepaint();
252 void SlideSorterView::HandleDataChangeEvent()
254 GetPageObjectPainter()->SetTheme(mrSlideSorter.GetTheme());
256 // Update the color used by the background painter.
257 std::shared_ptr<BackgroundPainter> pPainter (
258 std::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter));
259 if (pPainter)
260 pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
262 RequestRepaint();
265 void SlideSorterView::Resize()
267 UpdateOrientation();
269 mpLayeredDevice->Resize();
270 RequestRearrange();
273 void SlideSorterView::RequestRearrange()
275 mbIsRearrangePending = true;
276 Rearrange();
279 void SlideSorterView::Rearrange()
281 if ( ! mbIsRearrangePending)
282 return;
283 if (mrModel.GetPageCount() <= 0)
284 return;
286 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
287 if ( ! pWindow)
288 return;
289 const Size aWindowSize (pWindow->GetSizePixel());
290 if (aWindowSize.IsEmpty())
291 return;
293 const bool bRearrangeSuccess (
294 mpLayouter->Rearrange (
295 meOrientation,
296 aWindowSize,
297 mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
298 mrModel.GetPageCount()));
299 if (bRearrangeSuccess)
301 mbIsRearrangePending = false;
302 Layout();
303 UpdatePageUnderMouse();
304 // RequestRepaint();
308 void SlideSorterView::UpdateOrientation()
310 // The layout of slides depends on whether the slide sorter is
311 // displayed in the center or the side pane.
312 if (mrSlideSorter.GetViewShell()->IsMainViewShell())
313 SetOrientation(Layouter::GRID);
314 else
316 // Get access to the docking window.
317 vcl::Window* pWindow = mrSlideSorter.GetContentWindow();
318 TitledDockingWindow* pDockingWindow = nullptr;
319 while (pWindow!=nullptr && pDockingWindow==nullptr)
321 pDockingWindow = dynamic_cast<TitledDockingWindow*>(pWindow);
322 pWindow = pWindow->GetParent();
325 if (pDockingWindow != nullptr)
327 const ::tools::Long nScrollBarSize (
328 Application::GetSettings().GetStyleSettings().GetScrollBarSize());
329 switch (pDockingWindow->GetOrientation())
331 case TitledDockingWindow::HorizontalOrientation:
332 if (SetOrientation(Layouter::HORIZONTAL))
334 const Range aRange (mpLayouter->GetValidVerticalSizeRange());
335 pDockingWindow->SetValidSizeRange(Range(
336 aRange.Min() + nScrollBarSize,
337 aRange.Max() + nScrollBarSize));
339 break;
341 case TitledDockingWindow::VerticalOrientation:
342 if (SetOrientation(Layouter::VERTICAL))
344 const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
345 pDockingWindow->SetValidSizeRange(Range(
346 aRange.Min() + nScrollBarSize,
347 aRange.Max() + nScrollBarSize));
349 break;
351 case TitledDockingWindow::UnknownOrientation:
352 if (SetOrientation(Layouter::GRID))
354 const sal_Int32 nAdditionalSize (10);
355 pDockingWindow->SetMinOutputSizePixel(Size(
356 mpLayouter->GetValidHorizontalSizeRange().Min()
357 + nScrollBarSize
358 + nAdditionalSize,
359 mpLayouter->GetValidVerticalSizeRange().Min()
360 + nScrollBarSize
361 + nAdditionalSize));
363 return;
366 else
368 // We are not placed in a docking window. One possible reason
369 // is that the slide sorter is temporarily into a cache and was
370 // reparented to a non-docking window.
371 SetOrientation(Layouter::GRID);
376 void SlideSorterView::Layout ()
378 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
379 if (pWindow)
381 // Set the model area, i.e. the smallest rectangle that includes all
382 // page objects.
383 const ::tools::Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
384 pWindow->SetViewOrigin (aViewBox.TopLeft());
385 pWindow->SetViewSize (aViewBox.GetSize());
387 std::shared_ptr<PageObjectLayouter> pPageObjectLayouter(
388 mpLayouter->GetPageObjectLayouter());
389 if (pPageObjectLayouter)
391 const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetPreviewSize());
392 if (maPreviewSize != aNewPreviewSize && GetPreviewCache())
394 mpPreviewCache->ChangeSize(aNewPreviewSize, Bitmap::HasFastScale());
395 maPreviewSize = aNewPreviewSize;
399 // Iterate over all page objects and place them relative to the
400 // containing page.
401 model::PageEnumeration aPageEnumeration (
402 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
403 while (aPageEnumeration.HasMoreElements())
405 model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
406 pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex(), false));
410 InvalidatePageObjectVisibilities ();
413 void SlideSorterView::InvalidatePageObjectVisibilities()
415 mbPageObjectVisibilitiesValid = false;
418 void SlideSorterView::DeterminePageObjectVisibilities()
420 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
421 if (!pWindow)
422 return;
424 // Set this flag to true here so that an invalidate during the
425 // visibility calculation can correctly invalidate it again.
426 mbPageObjectVisibilitiesValid = true;
428 ::tools::Rectangle aViewArea (pWindow->PixelToLogic(::tools::Rectangle(Point(0,0),pWindow->GetSizePixel())));
429 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea));
430 const Range aUnion(
431 ::std::min(maVisiblePageRange.Min(), aRange.Min()),
432 ::std::max(maVisiblePageRange.Max(), aRange.Max()));
434 // For page objects that just dropped off the visible area we
435 // decrease the priority of pending requests for preview bitmaps.
436 if (maVisiblePageRange != aRange)
437 mbPreciousFlagUpdatePending |= true;
439 model::SharedPageDescriptor pDescriptor;
440 for (::tools::Long nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
442 pDescriptor = mrModel.GetPageDescriptor(nIndex);
443 if (pDescriptor)
444 SetState(
445 pDescriptor,
446 PageDescriptor::ST_Visible,
447 aRange.Contains(nIndex));
450 // Broadcast a change of the set of visible page objects.
451 if (maVisiblePageRange != aRange)
453 maVisiblePageRange = aRange;
455 // Tell the listeners that the visibility of some objects has
456 // changed.
457 ::std::vector<Link<LinkParamNone*,void>>& aChangeListeners (maVisibilityChangeListeners);
458 for (const auto& rLink : aChangeListeners)
460 rLink.Call(nullptr);
464 // Restore the mouse over state.
465 UpdatePageUnderMouse();
468 void SlideSorterView::UpdatePreciousFlags()
470 if (!mbPreciousFlagUpdatePending)
471 return;
473 mbPreciousFlagUpdatePending = false;
475 model::SharedPageDescriptor pDescriptor;
476 std::shared_ptr<cache::PageCache> pCache = GetPreviewCache();
477 sal_Int32 nPageCount (mrModel.GetPageCount());
479 for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
481 pDescriptor = mrModel.GetPageDescriptor(nIndex);
482 if (pDescriptor)
484 pCache->SetPreciousFlag(
485 pDescriptor->GetPage(),
486 maVisiblePageRange.Contains(nIndex));
488 else
490 // At least one cache entry can not be updated. Remember to
491 // repeat the whole updating later and leave the loop now.
492 mbPreciousFlagUpdatePending = true;
493 break;
498 bool SlideSorterView::SetOrientation (const Layouter::Orientation eOrientation)
500 if (meOrientation != eOrientation)
502 meOrientation = eOrientation;
503 return true;
505 else
506 return false;
509 void SlideSorterView::RequestRepaint()
511 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
512 if (pWindow)
514 mpLayeredDevice->InvalidateAllLayers(
515 ::tools::Rectangle(
516 pWindow->PixelToLogic(Point(0,0)),
517 pWindow->PixelToLogic(pWindow->GetSizePixel())));
518 pWindow->Invalidate();
522 void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
524 if (rpDescriptor)
525 RequestRepaint(rpDescriptor->GetBoundingBox());
528 void SlideSorterView::RequestRepaint (const ::tools::Rectangle& rRepaintBox)
530 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
531 if (pWindow)
533 mpLayeredDevice->InvalidateAllLayers(rRepaintBox);
534 pWindow->Invalidate(rRepaintBox);
538 void SlideSorterView::RequestRepaint (const vcl::Region& rRepaintRegion)
540 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
541 if (pWindow)
543 mpLayeredDevice->InvalidateAllLayers(rRepaintRegion);
544 pWindow->Invalidate(rRepaintRegion);
548 ::tools::Rectangle SlideSorterView::GetModelArea() const
550 return mpLayouter->GetTotalBoundingBox();
553 #ifdef DEBUG_TIMING
554 static ::canvas::tools::ElapsedTime gaTimer;
555 static const size_t gFrameTimeCount (10);
556 static size_t gFrameTimeIndex (0);
557 static ::std::vector<double> gFrameTimes (gFrameTimeCount, 0);
558 static double gFrameTimeSum (0);
559 static const ::tools::Rectangle gFrameTimeBox (10,10,150,20);
560 static double gnLastFrameStart = 0;
561 #endif
563 void SlideSorterView::CompleteRedraw (
564 OutputDevice* pDevice,
565 const vcl::Region& rPaintArea,
566 sdr::contact::ViewObjectContactRedirector* pRedirector)
568 (void)pRedirector;
570 if (comphelper::LibreOfficeKit::isActive())
571 return;
573 if (pDevice == nullptr || pDevice!=mrSlideSorter.GetContentWindow()->GetOutDev())
574 return;
576 #ifdef DEBUG_TIMING
577 const double nStartTime (gaTimer.getElapsedTime());
578 SAL_INFO("sd.timing", "SlideSorterView::CompleteRedraw start" << (mnLockRedrawSmph ? " locked" : ""));
579 #endif
581 // The parent implementation of CompleteRedraw is called only when
582 // painting is locked. We do all the painting ourself. When painting
583 // is locked the parent implementation keeps track of the repaint
584 // requests and later, when painting is unlocked, calls CompleteRedraw
585 // for all missed repaints.
587 if (mnLockRedrawSmph == 0)
589 if (mpLayeredDevice->HandleMapModeChange())
590 DeterminePageObjectVisibilities();
591 mpLayeredDevice->Repaint(rPaintArea);
593 else
595 maRedrawRegion.Union(rPaintArea);
598 #ifdef DEBUG_TIMING
599 const double nEndTime (gaTimer.getElapsedTime());
600 SAL_INFO("sd.timing", "SlideSorterView::CompleteRedraw end after " << (nEndTime-nStartTime)*1000 << " ms");
601 gFrameTimeSum -= gFrameTimes[gFrameTimeIndex];
602 gFrameTimes[gFrameTimeIndex] = nStartTime - gnLastFrameStart;
603 gnLastFrameStart = nStartTime;
604 gFrameTimeSum += gFrameTimes[gFrameTimeIndex];
605 gFrameTimeIndex = (gFrameTimeIndex+1) % gFrameTimeCount;
607 mrSlideSorter.GetContentWindow()->SetFillColor(COL_BLUE);
608 mrSlideSorter.GetContentWindow()->DrawRect(gFrameTimeBox);
609 mrSlideSorter.GetContentWindow()->SetTextColor(COL_WHITE);
610 mrSlideSorter.GetContentWindow()->DrawText(
611 gFrameTimeBox,
612 OUString::number(1 / (gFrameTimeSum / gFrameTimeCount)),
613 DrawTextFlags::Right | DrawTextFlags::VCenter);
614 // mrSlideSorter.GetContentWindow()->Invalidate(gFrameTimeBox);
615 #endif
618 void SlideSorterView::Paint (
619 OutputDevice& rDevice,
620 const ::tools::Rectangle& rRepaintArea)
622 if (rRepaintArea.IsEmpty())
623 return;
625 if ( ! mpPageObjectPainter)
626 if ( ! GetPageObjectPainter())
627 return;
629 // Update the page visibilities when they have been invalidated.
630 if ( ! mbPageObjectVisibilitiesValid)
631 DeterminePageObjectVisibilities();
633 if (mbPreciousFlagUpdatePending)
634 UpdatePreciousFlags();
636 if (mbIsRearrangePending)
637 Rearrange();
639 // Paint all page objects that are fully or partially inside the
640 // repaint region.
641 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
642 // Try to prefetch all graphics from the pages to paint. This will be done
643 // in threads to be more efficient than loading them on-demand one by one.
644 std::vector<Graphic*> graphics;
645 for (::tools::Long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
647 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
648 if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
649 continue;
650 pDescriptor->GetPage()->getGraphicsForPrefetch(graphics);
652 // Handle also one page before and after to have those in advance on scrolling.
653 for (::tools::Long nIndex : { aRange.Min() - 1, aRange.Max() + 1 })
655 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
656 if (!pDescriptor)
657 continue;
658 pDescriptor->GetPage()->getGraphicsForPrefetch(graphics);
660 if(graphics.size() > 1) // threading does not help with loading just one
661 GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded(graphics);
663 for (::tools::Long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
665 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
666 if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
667 continue;
669 mpPageObjectPainter->PaintPageObject(rDevice, pDescriptor);
673 void SlideSorterView::ConfigurationChanged (
674 utl::ConfigurationBroadcaster* pBroadcaster,
675 ConfigurationHints nHint)
677 // Some changes of the configuration (some of the colors for example)
678 // may affect the previews. Throw away the old ones and create new ones.
679 cache::PageCacheManager::Instance()->InvalidateAllCaches();
681 ::sd::View::ConfigurationChanged(pBroadcaster, nHint);
682 RequestRepaint();
686 std::shared_ptr<cache::PageCache> const & SlideSorterView::GetPreviewCache()
688 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
689 if (pWindow && mpPreviewCache == nullptr)
691 mpPreviewCache =
692 std::make_shared<cache::PageCache>(
693 mpLayouter->GetPageObjectSize(),
694 Bitmap::HasFastScale(),
695 std::make_shared<ViewCacheContext>(mrSlideSorter));
698 return mpPreviewCache;
701 Range const & SlideSorterView::GetVisiblePageRange()
703 if ( ! mbPageObjectVisibilitiesValid)
704 DeterminePageObjectVisibilities();
705 return maVisiblePageRange;
708 void SlideSorterView::AddVisibilityChangeListener (const Link<LinkParamNone*,void>& rListener)
710 if (::std::find (
711 maVisibilityChangeListeners.begin(),
712 maVisibilityChangeListeners.end(),
713 rListener) == maVisibilityChangeListeners.end())
715 maVisibilityChangeListeners.push_back(rListener);
719 void SlideSorterView::RemoveVisibilityChangeListener(const Link<LinkParamNone*,void>&rListener)
721 maVisibilityChangeListeners.erase (
722 ::std::find (
723 maVisibilityChangeListeners.begin(),
724 maVisibilityChangeListeners.end(),
725 rListener));
728 ToolTip& SlideSorterView::GetToolTip() const
730 OSL_ASSERT(mpToolTip);
731 return *mpToolTip;
734 void SlideSorterView::DragFinished (sal_Int8 nDropAction)
736 mrSlideSorter.GetController().GetClipboard().DragFinished(nDropAction);
738 View::DragFinished(nDropAction);
741 void SlideSorterView::UpdatePageUnderMouse ()
743 // Tracking TODO check
744 VclPtr<ScrollAdaptor> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
745 VclPtr<ScrollAdaptor> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar());
746 if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->HasGrab())
747 || (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->HasGrab()))
749 // One of the scroll bars is tracking mouse movement. Do not
750 // highlight the slide under the mouse in this case.
751 SetPageUnderMouse(SharedPageDescriptor());
752 return;
755 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
756 if (pWindow && pWindow->IsVisible() && ! pWindow->IsMouseCaptured())
758 const Window::PointerState aPointerState (pWindow->GetPointerState());
759 const ::tools::Rectangle aWindowBox (pWindow->GetPosPixel(), pWindow->GetSizePixel());
760 if (aWindowBox.Contains(aPointerState.maPos))
762 UpdatePageUnderMouse(aPointerState.maPos);
763 return;
767 SetPageUnderMouse(SharedPageDescriptor());
770 void SlideSorterView::UpdatePageUnderMouse (
771 const Point& rMousePosition)
773 SetPageUnderMouse(mrSlideSorter.GetController().GetPageAt(rMousePosition));
776 void SlideSorterView::SetPageUnderMouse (
777 const model::SharedPageDescriptor& rpDescriptor)
779 if (mpPageUnderMouse == rpDescriptor)
780 return;
782 if (mpPageUnderMouse)
783 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, false);
785 mpPageUnderMouse = rpDescriptor;
787 if (mpPageUnderMouse)
788 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, true);
790 // Change the quick help text to display the name of the page under
791 // the mouse.
792 mpToolTip->SetPage(rpDescriptor);
795 bool SlideSorterView::SetState (
796 const model::SharedPageDescriptor& rpDescriptor,
797 const PageDescriptor::State eState,
798 const bool bStateValue)
800 if ( ! rpDescriptor)
801 return false;
803 const bool bModified (rpDescriptor->SetState(eState, bStateValue));
804 if ( ! bModified)
805 return false;
807 // When the page object is not visible (i.e. not on the screen then
808 // nothing has to be painted.
809 if (rpDescriptor->HasState(PageDescriptor::ST_Visible))
811 // For most states a change of that state leads to visible
812 // difference and we have to request a repaint.
813 if (eState != PageDescriptor::ST_WasSelected)
814 RequestRepaint(rpDescriptor);
817 return bModified;
820 std::shared_ptr<PageObjectPainter> const & SlideSorterView::GetPageObjectPainter()
822 if ( ! mpPageObjectPainter)
823 mpPageObjectPainter = std::make_shared<PageObjectPainter>(mrSlideSorter);
824 return mpPageObjectPainter;
827 //===== SlideSorterView::DrawLock =============================================
829 SlideSorterView::DrawLock::DrawLock (SlideSorter const & rSlideSorter)
830 : mrView(rSlideSorter.GetView()),
831 mpWindow(rSlideSorter.GetContentWindow())
833 if (mrView.mnLockRedrawSmph == 0)
834 mrView.maRedrawRegion.SetEmpty();
835 ++mrView.mnLockRedrawSmph;
838 SlideSorterView::DrawLock::~DrawLock()
840 OSL_ASSERT(mrView.mnLockRedrawSmph>0);
841 --mrView.mnLockRedrawSmph;
842 if (mrView.mnLockRedrawSmph == 0)
843 if (mpWindow)
845 mpWindow->Invalidate(mrView.maRedrawRegion);
849 void SlideSorterView::DrawLock::Dispose()
851 mpWindow.reset();
854 } // end of namespace ::sd::slidesorter::view
856 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */