tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sd / source / ui / slidesorter / view / SlideSorterView.cxx
blob051d375b43c770493fb6e52da3ecacc06537878a
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;
59 namespace sd::slidesorter::view {
61 namespace {
62 /** Wrapper around the SlideSorterView that supports the IPainter
63 interface and that allows the LayeredDevice to hold the
64 SlideSorterView (held as unique_ptr by the SlideSorter) as
65 shared_ptr.
67 class Painter : public ILayerPainter
69 public:
70 explicit Painter (SlideSorterView& rView) : mrView(rView) {}
72 virtual void Paint (OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) override
74 mrView.Paint(rDevice,rRepaintArea);
77 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) override {}
79 private:
80 SlideSorterView& mrView;
84 namespace {
86 class BackgroundPainter
87 : public ILayerPainter
89 public:
90 explicit BackgroundPainter (const Color& rBackgroundColor) : maBackgroundColor(rBackgroundColor) {}
91 BackgroundPainter(const BackgroundPainter&) = delete;
92 BackgroundPainter& operator=(const BackgroundPainter&) = delete;
94 virtual void Paint (OutputDevice& rDevice, const ::tools::Rectangle& rRepaintArea) override
96 rDevice.SetFillColor(maBackgroundColor);
97 rDevice.SetLineColor();
98 rDevice.DrawRect(rRepaintArea);
101 virtual void SetLayerInvalidator (const SharedILayerInvalidator&) override {}
103 void SetColor (const Color& rColor) { maBackgroundColor = rColor; }
105 private:
106 Color maBackgroundColor;
111 SlideSorterView::SlideSorterView (SlideSorter& rSlideSorter)
112 : ::sd::View (
113 *rSlideSorter.GetModel().GetDocument(),
114 rSlideSorter.GetContentWindow()->GetOutDev(),
115 rSlideSorter.GetViewShell()),
116 mrSlideSorter(rSlideSorter),
117 mrModel(rSlideSorter.GetModel()),
118 mbIsDisposed(false),
119 mpLayouter (new Layouter(rSlideSorter.GetContentWindow(), rSlideSorter.GetTheme())),
120 mbPageObjectVisibilitiesValid (false),
121 mpLayeredDevice(std::make_shared<LayeredDevice>(rSlideSorter.GetContentWindow())),
122 maVisiblePageRange(-1,-1),
123 maPreviewSize(0,0),
124 mbPreciousFlagUpdatePending(true),
125 meOrientation(Layouter::GRID),
126 mpBackgroundPainter(
127 std::make_shared<BackgroundPainter>(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background))),
128 mpToolTip(new ToolTip(mrSlideSorter)),
129 mbIsRearrangePending(true)
131 // Hide the page that contains the page objects.
132 SetPageVisible (false);
134 // Register the background painter on level 1 to avoid the creation of a
135 // background buffer.
136 mpLayeredDevice->RegisterPainter(mpBackgroundPainter, 1);
138 // Wrap a shared_ptr-held-wrapper around this view and register it as
139 // painter at the layered device. There is no explicit destruction: in
140 // the SlideSorterView destructor the layered device is destroyed and
141 // with it the only reference to the wrapper which therefore is also
142 // destroyed.
143 SharedILayerPainter pPainter = std::make_shared<Painter>(*this);
145 // The painter is placed on level 1 to avoid buffering. This should be
146 // a little faster during animations because the previews are painted
147 // directly into the window, not via the buffer.
148 mpLayeredDevice->RegisterPainter(pPainter, 1);
151 SlideSorterView::~SlideSorterView()
153 if ( ! mbIsDisposed)
155 OSL_ASSERT(mbIsDisposed);
156 Dispose();
160 void SlideSorterView::Init()
162 HandleModelChange();
165 void SlideSorterView::Dispose()
167 mpLayeredDevice->Dispose();
168 mpPreviewCache.reset();
170 SetPageUnderMouse(SharedPageDescriptor());
172 // Hide the page to avoid problems in the view when deleting
173 // visualized objects
174 HideSdrPage();
176 // Deletion of the objects and the page will be done in SdrModel
177 // destructor (as long as objects and pages are added)
179 OSL_ASSERT(mpLayeredDevice.use_count() == 1);
180 mpLayeredDevice.reset();
182 mbIsDisposed = true;
185 sal_Int32 SlideSorterView::GetPageIndexAtPoint (const Point& rWindowPosition) const
187 sal_Int32 nIndex (-1);
189 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
190 if (pWindow)
192 nIndex = mpLayouter->GetIndexAtPoint(pWindow->PixelToLogic(rWindowPosition), false, false);
194 // Clip the page index against the page count.
195 if (nIndex >= mrModel.GetPageCount())
196 nIndex = -1;
199 return nIndex;
202 Layouter& SlideSorterView::GetLayouter() { return *mpLayouter; }
204 void SlideSorterView::ModelHasChanged()
206 // Ignore this call. Rely on hints sent by the model to get informed of
207 // model changes.
210 void SlideSorterView::PreModelChange()
212 // Reset the slide under the mouse. It will be re-set in PostModelChange().
213 SetPageUnderMouse(SharedPageDescriptor());
216 void SlideSorterView::PostModelChange()
218 // In PreModelChange() the page objects have been released. Here we
219 // create new ones.
220 ::osl::MutexGuard aGuard (mrModel.GetMutex());
222 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel);
224 // The new page objects have to be scaled and positioned.
225 RequestRearrange();
226 RequestRepaint();
229 /** At the moment for every model change all page objects are destroyed and
230 re-created again. This can be optimized by accepting hints that
231 describe the type of change so that existing page objects can be
232 reused.
234 void SlideSorterView::HandleModelChange()
236 PreModelChange ();
237 PostModelChange();
240 void SlideSorterView::HandleDrawModeChange()
242 // Replace the preview cache with a new and empty one. The
243 // PreviewRenderer that is used by the cache is replaced by this as
244 // well.
245 mpPreviewCache.reset();
246 GetPreviewCache()->InvalidateCache();
248 RequestRepaint();
251 void SlideSorterView::HandleDataChangeEvent()
253 GetPageObjectPainter()->SetTheme(mrSlideSorter.GetTheme());
255 // Update the color used by the background painter.
256 std::shared_ptr<BackgroundPainter> pPainter (
257 std::dynamic_pointer_cast<BackgroundPainter>(mpBackgroundPainter));
258 if (pPainter)
259 pPainter->SetColor(mrSlideSorter.GetTheme()->GetColor(Theme::Color_Background));
261 RequestRepaint();
264 void SlideSorterView::Resize()
266 UpdateOrientation();
268 mpLayeredDevice->Resize();
269 RequestRearrange();
272 void SlideSorterView::RequestRearrange()
274 mbIsRearrangePending = true;
275 Rearrange();
278 void SlideSorterView::Rearrange()
280 if ( ! mbIsRearrangePending)
281 return;
282 if (mrModel.GetPageCount() <= 0)
283 return;
285 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
286 if ( ! pWindow)
287 return;
288 const Size aWindowSize (pWindow->GetSizePixel());
289 if (aWindowSize.IsEmpty())
290 return;
292 const bool bRearrangeSuccess (
293 mpLayouter->Rearrange (
294 meOrientation,
295 aWindowSize,
296 mrModel.GetPageDescriptor(0)->GetPage()->GetSize(),
297 mrModel.GetPageCount()));
298 if (bRearrangeSuccess)
300 mbIsRearrangePending = false;
301 Layout();
302 UpdatePageUnderMouse();
303 // RequestRepaint();
307 void SlideSorterView::UpdateOrientation()
309 // The layout of slides depends on whether the slide sorter is
310 // displayed in the center or the side pane.
311 if (mrSlideSorter.GetViewShell()->IsMainViewShell())
312 SetOrientation(Layouter::GRID);
313 else
315 // Get access to the docking window.
316 vcl::Window* pWindow = mrSlideSorter.GetContentWindow();
317 TitledDockingWindow* pDockingWindow = nullptr;
318 while (pWindow!=nullptr && pDockingWindow==nullptr)
320 pDockingWindow = dynamic_cast<TitledDockingWindow*>(pWindow);
321 pWindow = pWindow->GetParent();
324 if (pDockingWindow != nullptr)
326 const ::tools::Long nScrollBarSize (
327 Application::GetSettings().GetStyleSettings().GetScrollBarSize());
328 switch (pDockingWindow->GetOrientation())
330 case TitledDockingWindow::HorizontalOrientation:
331 if (SetOrientation(Layouter::HORIZONTAL))
333 const Range aRange (mpLayouter->GetValidVerticalSizeRange());
334 pDockingWindow->SetValidSizeRange(Range(
335 aRange.Min() + nScrollBarSize,
336 aRange.Max() + nScrollBarSize));
338 break;
340 case TitledDockingWindow::VerticalOrientation:
341 if (SetOrientation(Layouter::VERTICAL))
343 const Range aRange (mpLayouter->GetValidHorizontalSizeRange());
344 pDockingWindow->SetValidSizeRange(Range(
345 aRange.Min() + nScrollBarSize,
346 aRange.Max() + nScrollBarSize));
348 break;
350 case TitledDockingWindow::UnknownOrientation:
351 if (SetOrientation(Layouter::GRID))
353 const sal_Int32 nAdditionalSize (10);
354 pDockingWindow->SetMinOutputSizePixel(Size(
355 mpLayouter->GetValidHorizontalSizeRange().Min()
356 + nScrollBarSize
357 + nAdditionalSize,
358 mpLayouter->GetValidVerticalSizeRange().Min()
359 + nScrollBarSize
360 + nAdditionalSize));
362 return;
365 else
367 // We are not placed in a docking window. One possible reason
368 // is that the slide sorter is temporarily into a cache and was
369 // reparented to a non-docking window.
370 SetOrientation(Layouter::GRID);
375 void SlideSorterView::Layout ()
377 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
378 if (pWindow)
380 // Set the model area, i.e. the smallest rectangle that includes all
381 // page objects.
382 const ::tools::Rectangle aViewBox (mpLayouter->GetTotalBoundingBox());
383 pWindow->SetViewOrigin (aViewBox.TopLeft());
384 pWindow->SetViewSize (aViewBox.GetSize());
386 std::shared_ptr<PageObjectLayouter> pPageObjectLayouter(
387 mpLayouter->GetPageObjectLayouter());
388 if (pPageObjectLayouter)
390 const Size aNewPreviewSize (mpLayouter->GetPageObjectLayouter()->GetPreviewSize());
391 if (maPreviewSize != aNewPreviewSize && GetPreviewCache())
393 mpPreviewCache->ChangeSize(aNewPreviewSize, Bitmap::HasFastScale());
394 maPreviewSize = aNewPreviewSize;
398 // Iterate over all page objects and place them relative to the
399 // containing page.
400 model::PageEnumeration aPageEnumeration (
401 model::PageEnumerationProvider::CreateAllPagesEnumeration(mrModel));
402 while (aPageEnumeration.HasMoreElements())
404 model::SharedPageDescriptor pDescriptor (aPageEnumeration.GetNextElement());
405 pDescriptor->SetBoundingBox(mpLayouter->GetPageObjectBox(pDescriptor->GetPageIndex(), false));
409 InvalidatePageObjectVisibilities ();
412 void SlideSorterView::InvalidatePageObjectVisibilities()
414 mbPageObjectVisibilitiesValid = false;
417 void SlideSorterView::DeterminePageObjectVisibilities()
419 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
420 if (!pWindow)
421 return;
423 // Set this flag to true here so that an invalidate during the
424 // visibility calculation can correctly invalidate it again.
425 mbPageObjectVisibilitiesValid = true;
427 ::tools::Rectangle aViewArea (pWindow->PixelToLogic(::tools::Rectangle(Point(0,0),pWindow->GetSizePixel())));
428 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(aViewArea));
429 const Range aUnion(
430 ::std::min(maVisiblePageRange.Min(), aRange.Min()),
431 ::std::max(maVisiblePageRange.Max(), aRange.Max()));
433 // For page objects that just dropped off the visible area we
434 // decrease the priority of pending requests for preview bitmaps.
435 if (maVisiblePageRange != aRange)
436 mbPreciousFlagUpdatePending |= true;
438 model::SharedPageDescriptor pDescriptor;
439 for (::tools::Long nIndex=aUnion.Min(); nIndex<=aUnion.Max(); nIndex++)
441 pDescriptor = mrModel.GetPageDescriptor(nIndex);
442 if (pDescriptor)
443 SetState(
444 pDescriptor,
445 PageDescriptor::ST_Visible,
446 aRange.Contains(nIndex));
449 // Broadcast a change of the set of visible page objects.
450 if (maVisiblePageRange != aRange)
452 maVisiblePageRange = aRange;
454 // Tell the listeners that the visibility of some objects has
455 // changed.
456 ::std::vector<Link<LinkParamNone*,void>>& aChangeListeners (maVisibilityChangeListeners);
457 for (const auto& rLink : aChangeListeners)
459 rLink.Call(nullptr);
463 // Restore the mouse over state.
464 UpdatePageUnderMouse();
467 void SlideSorterView::UpdatePreciousFlags()
469 if (!mbPreciousFlagUpdatePending)
470 return;
472 mbPreciousFlagUpdatePending = false;
474 model::SharedPageDescriptor pDescriptor;
475 std::shared_ptr<cache::PageCache> pCache = GetPreviewCache();
476 sal_Int32 nPageCount (mrModel.GetPageCount());
478 for (int nIndex=0; nIndex<=nPageCount; ++nIndex)
480 pDescriptor = mrModel.GetPageDescriptor(nIndex);
481 if (pDescriptor)
483 pCache->SetPreciousFlag(
484 pDescriptor->GetPage(),
485 maVisiblePageRange.Contains(nIndex));
487 else
489 // At least one cache entry can not be updated. Remember to
490 // repeat the whole updating later and leave the loop now.
491 mbPreciousFlagUpdatePending = true;
492 break;
497 bool SlideSorterView::SetOrientation (const Layouter::Orientation eOrientation)
499 if (meOrientation != eOrientation)
501 meOrientation = eOrientation;
502 return true;
504 else
505 return false;
508 void SlideSorterView::RequestRepaint()
510 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
511 if (pWindow)
513 mpLayeredDevice->InvalidateAllLayers(
514 ::tools::Rectangle(
515 pWindow->PixelToLogic(Point(0,0)),
516 pWindow->PixelToLogic(pWindow->GetSizePixel())));
517 pWindow->Invalidate();
521 void SlideSorterView::RequestRepaint (const model::SharedPageDescriptor& rpDescriptor)
523 if (rpDescriptor)
524 RequestRepaint(rpDescriptor->GetBoundingBox());
527 void SlideSorterView::RequestRepaint (const ::tools::Rectangle& rRepaintBox)
529 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
530 if (pWindow)
532 mpLayeredDevice->InvalidateAllLayers(rRepaintBox);
533 pWindow->Invalidate(rRepaintBox);
537 void SlideSorterView::RequestRepaint (const vcl::Region& rRepaintRegion)
539 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
540 if (pWindow)
542 mpLayeredDevice->InvalidateAllLayers(rRepaintRegion);
543 pWindow->Invalidate(rRepaintRegion);
547 ::tools::Rectangle SlideSorterView::GetModelArea() const
549 return mpLayouter->GetTotalBoundingBox();
552 #ifdef DEBUG_TIMING
553 static ::canvas::tools::ElapsedTime gaTimer;
554 static const size_t gFrameTimeCount (10);
555 static size_t gFrameTimeIndex (0);
556 static ::std::vector<double> gFrameTimes (gFrameTimeCount, 0);
557 static double gFrameTimeSum (0);
558 static const ::tools::Rectangle gFrameTimeBox (10,10,150,20);
559 static double gnLastFrameStart = 0;
560 #endif
562 void SlideSorterView::CompleteRedraw (
563 OutputDevice* pDevice,
564 const vcl::Region& rPaintArea,
565 sdr::contact::ViewObjectContactRedirector* pRedirector)
567 (void)pRedirector;
569 if (comphelper::LibreOfficeKit::isActive())
570 return;
572 if (pDevice == nullptr || pDevice!=mrSlideSorter.GetContentWindow()->GetOutDev())
573 return;
575 #ifdef DEBUG_TIMING
576 const double nStartTime (gaTimer.getElapsedTime());
577 SAL_INFO("sd.timing", "SlideSorterView::CompleteRedraw start" << (mnLockRedrawSmph ? " locked" : ""));
578 #endif
580 // The parent implementation of CompleteRedraw is called only when
581 // painting is locked. We do all the painting ourself. When painting
582 // is locked the parent implementation keeps track of the repaint
583 // requests and later, when painting is unlocked, calls CompleteRedraw
584 // for all missed repaints.
586 if (mnLockRedrawSmph == 0)
588 if (mpLayeredDevice->HandleMapModeChange())
589 DeterminePageObjectVisibilities();
590 mpLayeredDevice->Repaint(rPaintArea);
592 else
594 maRedrawRegion.Union(rPaintArea);
597 #ifdef DEBUG_TIMING
598 const double nEndTime (gaTimer.getElapsedTime());
599 SAL_INFO("sd.timing", "SlideSorterView::CompleteRedraw end after " << (nEndTime-nStartTime)*1000 << " ms");
600 gFrameTimeSum -= gFrameTimes[gFrameTimeIndex];
601 gFrameTimes[gFrameTimeIndex] = nStartTime - gnLastFrameStart;
602 gnLastFrameStart = nStartTime;
603 gFrameTimeSum += gFrameTimes[gFrameTimeIndex];
604 gFrameTimeIndex = (gFrameTimeIndex+1) % gFrameTimeCount;
606 mrSlideSorter.GetContentWindow()->SetFillColor(COL_BLUE);
607 mrSlideSorter.GetContentWindow()->DrawRect(gFrameTimeBox);
608 mrSlideSorter.GetContentWindow()->SetTextColor(COL_WHITE);
609 mrSlideSorter.GetContentWindow()->DrawText(
610 gFrameTimeBox,
611 OUString::number(1 / (gFrameTimeSum / gFrameTimeCount)),
612 DrawTextFlags::Right | DrawTextFlags::VCenter);
613 // mrSlideSorter.GetContentWindow()->Invalidate(gFrameTimeBox);
614 #endif
617 void SlideSorterView::Paint (
618 OutputDevice& rDevice,
619 const ::tools::Rectangle& rRepaintArea)
621 if (rRepaintArea.IsEmpty())
622 return;
624 if ( ! mpPageObjectPainter)
625 if ( ! GetPageObjectPainter())
626 return;
628 // Update the page visibilities when they have been invalidated.
629 if ( ! mbPageObjectVisibilitiesValid)
630 DeterminePageObjectVisibilities();
632 if (mbPreciousFlagUpdatePending)
633 UpdatePreciousFlags();
635 if (mbIsRearrangePending)
636 Rearrange();
638 // Paint all page objects that are fully or partially inside the
639 // repaint region.
640 const Range aRange (mpLayouter->GetRangeOfVisiblePageObjects(rRepaintArea));
641 // Try to prefetch all graphics from the pages to paint. This will be done
642 // in threads to be more efficient than loading them on-demand one by one.
643 std::vector<Graphic*> graphics;
644 for (::tools::Long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
646 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
647 if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
648 continue;
649 pDescriptor->GetPage()->getGraphicsForPrefetch(graphics);
651 // Handle also one page before and after to have those in advance on scrolling.
652 for (::tools::Long nIndex : { aRange.Min() - 1, aRange.Max() + 1 })
654 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
655 if (!pDescriptor)
656 continue;
657 pDescriptor->GetPage()->getGraphicsForPrefetch(graphics);
659 if(graphics.size() > 1) // threading does not help with loading just one
660 GraphicFilter::GetGraphicFilter().MakeGraphicsAvailableThreaded(graphics);
662 for (::tools::Long nIndex=aRange.Min(); nIndex<=aRange.Max(); ++nIndex)
664 model::SharedPageDescriptor pDescriptor (mrModel.GetPageDescriptor(nIndex));
665 if (!pDescriptor || ! pDescriptor->HasState(PageDescriptor::ST_Visible))
666 continue;
668 mpPageObjectPainter->PaintPageObject(rDevice, pDescriptor);
672 void SlideSorterView::ConfigurationChanged (
673 utl::ConfigurationBroadcaster* pBroadcaster,
674 ConfigurationHints nHint)
676 // Some changes of the configuration (some of the colors for example)
677 // may affect the previews. Throw away the old ones and create new ones.
678 cache::PageCacheManager::Instance()->InvalidateAllCaches();
680 ::sd::View::ConfigurationChanged(pBroadcaster, nHint);
681 RequestRepaint();
685 std::shared_ptr<cache::PageCache> const & SlideSorterView::GetPreviewCache()
687 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
688 if (pWindow && mpPreviewCache == nullptr)
690 mpPreviewCache =
691 std::make_shared<cache::PageCache>(
692 mpLayouter->GetPageObjectSize(),
693 Bitmap::HasFastScale(),
694 std::make_shared<ViewCacheContext>(mrSlideSorter));
697 return mpPreviewCache;
700 Range const & SlideSorterView::GetVisiblePageRange()
702 if ( ! mbPageObjectVisibilitiesValid)
703 DeterminePageObjectVisibilities();
704 return maVisiblePageRange;
707 void SlideSorterView::AddVisibilityChangeListener (const Link<LinkParamNone*,void>& rListener)
709 if (::std::find (
710 maVisibilityChangeListeners.begin(),
711 maVisibilityChangeListeners.end(),
712 rListener) == maVisibilityChangeListeners.end())
714 maVisibilityChangeListeners.push_back(rListener);
718 void SlideSorterView::RemoveVisibilityChangeListener(const Link<LinkParamNone*,void>&rListener)
720 maVisibilityChangeListeners.erase (
721 ::std::find (
722 maVisibilityChangeListeners.begin(),
723 maVisibilityChangeListeners.end(),
724 rListener));
727 ToolTip& SlideSorterView::GetToolTip() const
729 OSL_ASSERT(mpToolTip);
730 return *mpToolTip;
733 void SlideSorterView::DragFinished (sal_Int8 nDropAction)
735 mrSlideSorter.GetController().GetClipboard().DragFinished(nDropAction);
737 View::DragFinished(nDropAction);
740 void SlideSorterView::UpdatePageUnderMouse ()
742 // Tracking TODO check
743 VclPtr<ScrollAdaptor> pVScrollBar (mrSlideSorter.GetVerticalScrollBar());
744 VclPtr<ScrollAdaptor> pHScrollBar (mrSlideSorter.GetHorizontalScrollBar());
745 if ((pVScrollBar && pVScrollBar->IsVisible() && pVScrollBar->HasGrab())
746 || (pHScrollBar && pHScrollBar->IsVisible() && pHScrollBar->HasGrab()))
748 // One of the scroll bars is tracking mouse movement. Do not
749 // highlight the slide under the mouse in this case.
750 SetPageUnderMouse(SharedPageDescriptor());
751 return;
754 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
755 if (pWindow && pWindow->IsVisible() && ! pWindow->IsMouseCaptured())
757 const Window::PointerState aPointerState (pWindow->GetPointerState());
758 const ::tools::Rectangle aWindowBox (pWindow->GetPosPixel(), pWindow->GetSizePixel());
759 if (aWindowBox.Contains(aPointerState.maPos))
761 UpdatePageUnderMouse(aPointerState.maPos);
762 return;
766 SetPageUnderMouse(SharedPageDescriptor());
769 void SlideSorterView::UpdatePageUnderMouse (
770 const Point& rMousePosition)
772 SetPageUnderMouse(mrSlideSorter.GetController().GetPageAt(rMousePosition));
775 void SlideSorterView::SetPageUnderMouse (
776 const model::SharedPageDescriptor& rpDescriptor)
778 if (mpPageUnderMouse == rpDescriptor)
779 return;
781 if (mpPageUnderMouse)
782 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, false);
784 mpPageUnderMouse = rpDescriptor;
786 if (mpPageUnderMouse)
787 SetState(mpPageUnderMouse, PageDescriptor::ST_MouseOver, true);
789 // Change the quick help text to display the name of the page under
790 // the mouse.
791 mpToolTip->SetPage(rpDescriptor);
794 bool SlideSorterView::SetState (
795 const model::SharedPageDescriptor& rpDescriptor,
796 const PageDescriptor::State eState,
797 const bool bStateValue)
799 if ( ! rpDescriptor)
800 return false;
802 const bool bModified (rpDescriptor->SetState(eState, bStateValue));
803 if ( ! bModified)
804 return false;
806 // When the page object is not visible (i.e. not on the screen then
807 // nothing has to be painted.
808 if (rpDescriptor->HasState(PageDescriptor::ST_Visible))
810 // For most states a change of that state leads to visible
811 // difference and we have to request a repaint.
812 if (eState != PageDescriptor::ST_WasSelected)
813 RequestRepaint(rpDescriptor);
816 return bModified;
819 std::shared_ptr<PageObjectPainter> const & SlideSorterView::GetPageObjectPainter()
821 if ( ! mpPageObjectPainter)
822 mpPageObjectPainter = std::make_shared<PageObjectPainter>(mrSlideSorter);
823 return mpPageObjectPainter;
826 //===== SlideSorterView::DrawLock =============================================
828 SlideSorterView::DrawLock::DrawLock (SlideSorter const & rSlideSorter)
829 : mrView(rSlideSorter.GetView()),
830 mpWindow(rSlideSorter.GetContentWindow())
832 if (mrView.mnLockRedrawSmph == 0)
833 mrView.maRedrawRegion.SetEmpty();
834 ++mrView.mnLockRedrawSmph;
837 SlideSorterView::DrawLock::~DrawLock()
839 OSL_ASSERT(mrView.mnLockRedrawSmph>0);
840 --mrView.mnLockRedrawSmph;
841 if (mrView.mnLockRedrawSmph == 0)
842 if (mpWindow)
844 mpWindow->Invalidate(mrView.maRedrawRegion);
848 void SlideSorterView::DrawLock::Dispose()
850 mpWindow.reset();
853 } // end of namespace ::sd::slidesorter::view
855 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */