xref: /AOO41X/main/sd/source/ui/slidesorter/controller/SlsScrollBarManager.cxx (revision a5b190bfa3e1bed4623e2958a8877664a3b5506c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_sd.hxx"
29 
30 #include "controller/SlsScrollBarManager.hxx"
31 
32 #include "SlideSorter.hxx"
33 #include "controller/SlideSorterController.hxx"
34 #include "controller/SlsVisibleAreaManager.hxx"
35 #include "model/SlideSorterModel.hxx"
36 #include "model/SlsPageDescriptor.hxx"
37 #include "view/SlideSorterView.hxx"
38 #include "view/SlsLayouter.hxx"
39 #include "view/SlsTheme.hxx"
40 #include "Window.hxx"
41 #include "sdpage.hxx"
42 
43 #include <boost/limits.hpp>
44 
45 #include <vcl/scrbar.hxx>
46 
47 namespace sd { namespace slidesorter { namespace controller {
48 
49 ScrollBarManager::ScrollBarManager (SlideSorter& rSlideSorter)
50     : mrSlideSorter(rSlideSorter),
51       mpHorizontalScrollBar(mrSlideSorter.GetHorizontalScrollBar()),
52       mpVerticalScrollBar(mrSlideSorter.GetVerticalScrollBar()),
53       mnHorizontalPosition (0),
54       mnVerticalPosition (0),
55       maScrollBorder (20,20),
56       mnHorizontalScrollFactor (0.15),
57       mnVerticalScrollFactor (0.25),
58       mpScrollBarFiller(mrSlideSorter.GetScrollBarFiller()),
59       maAutoScrollTimer(),
60       maAutoScrollOffset(0,0),
61       mbIsAutoScrollActive(false),
62       mpContentWindow(mrSlideSorter.GetContentWindow()),
63       maAutoScrollFunctor()
64 {
65     // Hide the scroll bars by default to prevent display errors while
66     // switching between view shells:  In the short time between initiating
67     // such a switch and the final rearrangement of UI controls the scroll
68     // bars and the filler where displayed in the upper left corner of the
69     // ViewTabBar.
70     mpHorizontalScrollBar->Hide();
71     mpVerticalScrollBar->Hide();
72     mpScrollBarFiller->Hide();
73 
74     maAutoScrollTimer.SetTimeout(25);
75     maAutoScrollTimer.SetTimeoutHdl (
76         LINK(this, ScrollBarManager, AutoScrollTimeoutHandler));
77 }
78 
79 
80 
81 
82 ScrollBarManager::~ScrollBarManager (void)
83 {
84 }
85 
86 
87 
88 
89 void ScrollBarManager::LateInitialization (void)
90 {
91 }
92 
93 
94 
95 
96 void ScrollBarManager::Connect (void)
97 {
98     if (mpVerticalScrollBar != NULL)
99     {
100         mpVerticalScrollBar->SetScrollHdl (
101             LINK(this, ScrollBarManager, VerticalScrollBarHandler));
102     }
103     if (mpHorizontalScrollBar != NULL)
104     {
105         mpHorizontalScrollBar->SetScrollHdl(
106             LINK(this, ScrollBarManager, HorizontalScrollBarHandler));
107     }
108 }
109 
110 
111 
112 
113 void ScrollBarManager::Disconnect (void)
114 {
115     if (mpVerticalScrollBar != NULL)
116     {
117         mpVerticalScrollBar->SetScrollHdl (Link());
118     }
119     if (mpHorizontalScrollBar != NULL)
120     {
121         mpHorizontalScrollBar->SetScrollHdl (Link());
122     }
123 }
124 
125 
126 
127 
128 /** Placing the scroll bars is an iterative process.  The visibility of one
129     scroll bar affects the remaining size and thus may lead to the other
130     scroll bar becoming visible.
131 
132     First we determine the visibility of the horizontal scroll bar.  After
133     that we do the same for the vertical scroll bar.  To have an initial
134     value for the required size we call the layouter before that.  When one
135     of the two scroll bars is made visible then the size of the browser
136     window changes and a second call to the layouter becomes necessary.
137     That call is made anyway after this method returns.
138 */
139 Rectangle ScrollBarManager::PlaceScrollBars (
140     const Rectangle& rAvailableArea,
141     const bool bIsHorizontalScrollBarAllowed,
142     const bool bIsVerticalScrollBarAllowed)
143 {
144     Rectangle aRemainingSpace (DetermineScrollBarVisibilities(
145         rAvailableArea,
146         bIsHorizontalScrollBarAllowed,
147         bIsVerticalScrollBarAllowed));
148 
149     if (mpHorizontalScrollBar!=NULL && mpHorizontalScrollBar->IsVisible())
150         PlaceHorizontalScrollBar (rAvailableArea);
151 
152     if (mpVerticalScrollBar!=NULL && mpVerticalScrollBar->IsVisible())
153         PlaceVerticalScrollBar (rAvailableArea);
154 
155     if (mpScrollBarFiller!=NULL && mpScrollBarFiller->IsVisible())
156         PlaceFiller (rAvailableArea);
157 
158     return aRemainingSpace;
159 }
160 
161 
162 
163 
164 void ScrollBarManager::PlaceHorizontalScrollBar (const Rectangle& aAvailableArea)
165 {
166     // Save the current relative position.
167     mnHorizontalPosition = double(mpHorizontalScrollBar->GetThumbPos())
168         / double(mpHorizontalScrollBar->GetRange().Len());
169 
170     // Place the scroll bar.
171     Size aScrollBarSize (mpHorizontalScrollBar->GetSizePixel());
172     mpHorizontalScrollBar->SetPosSizePixel (
173         Point(aAvailableArea.Left(),
174             aAvailableArea.Bottom()-aScrollBarSize.Height()+1),
175         Size (aAvailableArea.GetWidth() - GetVerticalScrollBarWidth(),
176             aScrollBarSize.Height()));
177 
178     // Restore the relative position.
179     mpHorizontalScrollBar->SetThumbPos(
180         (long)(0.5 + mnHorizontalPosition * mpHorizontalScrollBar->GetRange().Len()));
181 }
182 
183 
184 
185 
186 void ScrollBarManager::PlaceVerticalScrollBar (const Rectangle& aArea)
187 {
188     const sal_Int32 nThumbPosition (mpVerticalScrollBar->GetThumbPos());
189 
190     // Place the scroll bar.
191     Size aScrollBarSize (mpVerticalScrollBar->GetSizePixel());
192     Point aPosition (aArea.Right()-aScrollBarSize.Width()+1, aArea.Top());
193     Size aSize (aScrollBarSize.Width(), aArea.GetHeight() - GetHorizontalScrollBarHeight());
194     mpVerticalScrollBar->SetPosSizePixel(aPosition, aSize);
195 
196     // Restore the position.
197     mpVerticalScrollBar->SetThumbPos(nThumbPosition);
198     mnVerticalPosition = nThumbPosition / double(mpVerticalScrollBar->GetRange().Len());
199 }
200 
201 
202 
203 
204 void ScrollBarManager::PlaceFiller (const Rectangle& aArea)
205 {
206     mpScrollBarFiller->SetPosSizePixel(
207         Point(
208             aArea.Right()-mpVerticalScrollBar->GetSizePixel().Width()+1,
209             aArea.Bottom()-mpHorizontalScrollBar->GetSizePixel().Height()+1),
210         Size (
211             mpVerticalScrollBar->GetSizePixel().Width(),
212             mpHorizontalScrollBar->GetSizePixel().Height()));
213 }
214 
215 
216 
217 
218 void ScrollBarManager::UpdateScrollBars (bool bResetThumbPosition, bool bUseScrolling)
219 {
220     Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
221     SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
222     Size aWindowModelSize (pWindow->PixelToLogic(pWindow->GetSizePixel()));
223 
224     // The horizontal scroll bar is only shown when the window is
225     // horizontally smaller than the view.
226     if (mpHorizontalScrollBar != NULL && mpHorizontalScrollBar->IsVisible())
227     {
228         mpHorizontalScrollBar->Show();
229         mpHorizontalScrollBar->SetRange (
230             Range(aModelArea.Left(), aModelArea.Right()));
231         if (bResetThumbPosition)
232         {
233             mpHorizontalScrollBar->SetThumbPos (0);
234             mnHorizontalPosition = 0;
235         }
236         else
237             mnHorizontalPosition =
238                 double(mpHorizontalScrollBar->GetThumbPos())
239                 / double(mpHorizontalScrollBar->GetRange().Len());
240 
241         mpHorizontalScrollBar->SetVisibleSize (aWindowModelSize.Width());
242 
243         const long nWidth (mpContentWindow->PixelToLogic(
244             mpContentWindow->GetSizePixel()).Width());
245         // Make the line size about 10% of the visible width.
246         mpHorizontalScrollBar->SetLineSize (nWidth / 10);
247         // Make the page size about 90% of the visible width.
248         mpHorizontalScrollBar->SetPageSize ((nWidth * 9) / 10);
249     }
250     else
251     {
252         mnHorizontalPosition = 0;
253     }
254 
255     // The vertical scroll bar is always shown.
256     if (mpVerticalScrollBar != NULL && mpVerticalScrollBar->IsVisible())
257     {
258         mpVerticalScrollBar->SetRange (
259             Range(aModelArea.Top(), aModelArea.Bottom()));
260         if (bResetThumbPosition)
261         {
262             mpVerticalScrollBar->SetThumbPos (0);
263             mnVerticalPosition = 0;
264         }
265         else
266             mnVerticalPosition =
267                 double(mpVerticalScrollBar->GetThumbPos())
268                 / double(mpVerticalScrollBar->GetRange().Len());
269 
270         mpVerticalScrollBar->SetVisibleSize (aWindowModelSize.Height());
271 
272         const long nHeight (mpContentWindow->PixelToLogic(
273             mpContentWindow->GetSizePixel()).Height());
274         // Make the line size about 10% of the visible height.
275         mpVerticalScrollBar->SetLineSize (nHeight / 10);
276         // Make the page size about 90% of the visible height.
277         mpVerticalScrollBar->SetPageSize ((nHeight * 9) / 10);
278     }
279     else
280     {
281         mnVerticalPosition = 0;
282     }
283 
284 
285     double nEps (::std::numeric_limits<double>::epsilon());
286     if (fabs(mnHorizontalPosition-pWindow->GetVisibleX()) > nEps
287         || fabs(mnVerticalPosition-pWindow->GetVisibleY()) > nEps)
288     {
289         mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
290         if (bUseScrolling)
291             pWindow->SetVisibleXY(mnHorizontalPosition, mnVerticalPosition);
292         else
293             SetWindowOrigin(mnHorizontalPosition, mnVerticalPosition);
294     }
295 }
296 
297 
298 
299 
300 IMPL_LINK(ScrollBarManager, VerticalScrollBarHandler, ScrollBar*, pScrollBar)
301 {
302     if (pScrollBar!=NULL
303         && pScrollBar==mpVerticalScrollBar.get()
304         && pScrollBar->IsVisible()
305         && mrSlideSorter.GetContentWindow()!=NULL)
306     {
307         double nRelativePosition = double(pScrollBar->GetThumbPos())
308             / double(pScrollBar->GetRange().Len());
309         mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
310         mrSlideSorter.GetContentWindow()->SetVisibleXY(-1, nRelativePosition);
311         mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
312     }
313     return sal_True;
314 }
315 
316 
317 
318 
319 IMPL_LINK(ScrollBarManager, HorizontalScrollBarHandler, ScrollBar*, pScrollBar)
320 {
321     if (pScrollBar!=NULL
322         && pScrollBar==mpHorizontalScrollBar.get()
323         && pScrollBar->IsVisible()
324         && mrSlideSorter.GetContentWindow()!=NULL)
325     {
326         double nRelativePosition = double(pScrollBar->GetThumbPos())
327             / double(pScrollBar->GetRange().Len());
328         mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
329         mrSlideSorter.GetContentWindow()->SetVisibleXY(nRelativePosition, -1);
330         mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
331     }
332     return sal_True;
333 }
334 
335 
336 
337 
338 void ScrollBarManager::SetWindowOrigin (
339     double nHorizontalPosition,
340     double nVerticalPosition)
341 {
342     mnHorizontalPosition = nHorizontalPosition;
343     mnVerticalPosition = nVerticalPosition;
344 
345     SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
346     Size aViewSize (pWindow->GetViewSize());
347     Point aOrigin (
348         (long int) (mnHorizontalPosition * aViewSize.Width()),
349         (long int) (mnVerticalPosition * aViewSize.Height()));
350 
351     pWindow->SetWinViewPos (aOrigin);
352     pWindow->UpdateMapMode ();
353     pWindow->Invalidate ();
354 }
355 
356 
357 
358 
359 /** Determining the visibility of the scroll bars is quite complicated.  The
360     visibility of one influences that of the other because showing a scroll
361     bar makes the available space smaller and may lead to the need of
362     displaying the other.
363     To solve this we test all four combinations of showing or hiding each
364     scroll bar and use the best one.  The best one is that combination that
365     a) shows the least number of scroll bars with preference of showing the
366     vertical over showing the horizontal and
367     b) when not showing a scroll bar the area used by the page objects fits
368     into the available area in the scroll bars orientation.
369 */
370 Rectangle ScrollBarManager::DetermineScrollBarVisibilities (
371     const Rectangle& rAvailableArea,
372     const bool bIsHorizontalScrollBarAllowed,
373     const bool bIsVerticalScrollBarAllowed)
374 {
375     // Test which combination of scroll bars is the best.
376     bool bShowHorizontal = false;
377     bool bShowVertical = false;
378     if (mrSlideSorter.GetModel().GetPageCount() == 0)
379     {
380         // No pages => no scroll bars.
381     }
382     else if (TestScrollBarVisibilities(false, false, rAvailableArea))
383     {
384         // Nothing to be done.
385     }
386     else if (bIsHorizontalScrollBarAllowed
387         && TestScrollBarVisibilities(true, false, rAvailableArea))
388     {
389         bShowHorizontal = true;
390     }
391     else if (bIsVerticalScrollBarAllowed
392         && TestScrollBarVisibilities(false, true, rAvailableArea))
393     {
394         bShowVertical = true;
395     }
396     else
397     {
398         bShowHorizontal = true;
399         bShowVertical = true;
400     }
401 
402     // Make the visibility of the scroll bars permanent.
403     mpVerticalScrollBar->Show(bShowVertical);
404     mpHorizontalScrollBar->Show(bShowHorizontal);
405     mpScrollBarFiller->Show(bShowVertical && bShowHorizontal);
406 
407     // Adapt the remaining space accordingly.
408     Rectangle aRemainingSpace (rAvailableArea);
409     if (bShowVertical)
410         aRemainingSpace.Right() -= mpVerticalScrollBar->GetSizePixel().Width();
411     if (bShowHorizontal)
412         aRemainingSpace.Bottom() -= mpHorizontalScrollBar->GetSizePixel().Height();
413 
414     return aRemainingSpace;
415 }
416 
417 
418 
419 
420 bool ScrollBarManager::TestScrollBarVisibilities (
421     bool bHorizontalScrollBarVisible,
422     bool bVerticalScrollBarVisible,
423     const Rectangle& rAvailableArea)
424 {
425     model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
426 
427     // Adapt the available size by subtracting the sizes of the scroll bars
428     // visible in this combination.
429     Size aBrowserSize (rAvailableArea.GetSize());
430     if (bHorizontalScrollBarVisible)
431         aBrowserSize.Height() -= mpHorizontalScrollBar->GetSizePixel().Height();
432     if (bVerticalScrollBarVisible)
433         aBrowserSize.Width() -= mpVerticalScrollBar->GetSizePixel().Width();
434 
435     // Tell the view to rearrange its page objects and check whether the
436     // page objects can be shown without clipping.
437     bool bRearrangeSuccess (mrSlideSorter.GetView().GetLayouter().Rearrange (
438         mrSlideSorter.GetView().GetOrientation(),
439         aBrowserSize,
440         rModel.GetPageDescriptor(0)->GetPage()->GetSize(),
441         rModel.GetPageCount()));
442 
443     if (bRearrangeSuccess)
444     {
445         Size aPageSize = mrSlideSorter.GetView().GetLayouter().GetTotalBoundingBox().GetSize();
446         Size aWindowModelSize = mpContentWindow->PixelToLogic(aBrowserSize);
447 
448         // The content may be clipped, i.e. not fully visible, in one
449         // direction only when the scroll bar is visible in that direction.
450         if (aPageSize.Width() > aWindowModelSize.Width())
451             if ( ! bHorizontalScrollBarVisible)
452                 return false;
453         if (aPageSize.Height() > aWindowModelSize.Height())
454             if ( ! bVerticalScrollBarVisible)
455                 return false;
456 
457         return true;
458     }
459     else
460         return false;
461 }
462 
463 
464 
465 
466 void ScrollBarManager::SetTopLeft (const Point aNewTopLeft)
467 {
468     if (( ! mpVerticalScrollBar
469             || mpVerticalScrollBar->GetThumbPos() == aNewTopLeft.Y())
470         && ( ! mpHorizontalScrollBar
471             || mpHorizontalScrollBar->GetThumbPos() == aNewTopLeft.X()))
472         return;
473 
474     // Flush pending repaints before scrolling to avoid temporary artifacts.
475     mrSlideSorter.GetContentWindow()->Update();
476 
477     if (mpVerticalScrollBar)
478     {
479         mpVerticalScrollBar->SetThumbPos(aNewTopLeft.Y());
480         mnVerticalPosition = aNewTopLeft.Y() / double(mpVerticalScrollBar->GetRange().Len());
481     }
482     if (mpHorizontalScrollBar)
483     {
484         mpHorizontalScrollBar->SetThumbPos(aNewTopLeft.X());
485         mnHorizontalPosition = aNewTopLeft.X() / double(mpHorizontalScrollBar->GetRange().Len());
486     }
487 
488     mrSlideSorter.GetContentWindow()->SetVisibleXY(mnHorizontalPosition, mnVerticalPosition);
489     mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
490 }
491 
492 
493 
494 
495 sal_Int32 ScrollBarManager::GetTop (void) const
496 {
497     if (mpVerticalScrollBar != NULL)
498         return mpVerticalScrollBar->GetThumbPos();
499     else
500         return 0;
501 }
502 
503 
504 
505 
506 sal_Int32 ScrollBarManager::GetLeft (void) const
507 {
508     if (mpHorizontalScrollBar != NULL)
509         return mpHorizontalScrollBar->GetThumbPos();
510     else
511         return 0;
512 }
513 
514 
515 
516 
517 int ScrollBarManager::GetVerticalScrollBarWidth (void) const
518 {
519     if (mpVerticalScrollBar != NULL && mpVerticalScrollBar->IsVisible())
520         return mpVerticalScrollBar->GetSizePixel().Width();
521     else
522         return 0;
523 }
524 
525 
526 
527 
528 int ScrollBarManager::GetHorizontalScrollBarHeight (void) const
529 {
530     if (mpHorizontalScrollBar != NULL && mpHorizontalScrollBar->IsVisible())
531         return mpHorizontalScrollBar->GetSizePixel().Height();
532     else
533         return 0;
534 }
535 
536 
537 
538 
539 void ScrollBarManager::CalcAutoScrollOffset (const Point& rMouseWindowPosition)
540 {
541     SharedSdWindow pWindow (mrSlideSorter.GetContentWindow());
542 
543     int nDx = 0;
544     int nDy = 0;
545 
546     Size aWindowSize = pWindow->GetOutputSizePixel();
547     Rectangle aWindowArea (pWindow->GetPosPixel(), aWindowSize);
548     Rectangle aViewPixelArea (
549         pWindow->LogicToPixel(mrSlideSorter.GetView().GetModelArea()));
550 
551     if (aWindowSize.Width() > maScrollBorder.Width() * 3
552         && mpHorizontalScrollBar != NULL
553         && mpHorizontalScrollBar->IsVisible())
554     {
555         if (rMouseWindowPosition.X() < maScrollBorder.Width()
556             && aWindowArea.Left() > aViewPixelArea.Left())
557         {
558             nDx = -1 + (int)(mnHorizontalScrollFactor
559                 * (rMouseWindowPosition.X() - maScrollBorder.Width()));
560         }
561 
562         if (rMouseWindowPosition.X() >= (aWindowSize.Width() - maScrollBorder.Width())
563             && aWindowArea.Right() < aViewPixelArea.Right())
564         {
565             nDx = 1 + (int)(mnHorizontalScrollFactor
566                 * (rMouseWindowPosition.X() - aWindowSize.Width()
567                     + maScrollBorder.Width()));
568         }
569     }
570 
571     if (aWindowSize.Height() > maScrollBorder.Height() * 3
572         && aWindowSize.Height() < aViewPixelArea.GetHeight())
573     {
574         if (rMouseWindowPosition.Y() < maScrollBorder.Height()
575             && aWindowArea.Top() > aViewPixelArea.Top())
576         {
577             nDy = -1 + (int)(mnVerticalScrollFactor
578                 * (rMouseWindowPosition.Y() - maScrollBorder.Height()));
579         }
580 
581         if (rMouseWindowPosition.Y() >= (aWindowSize.Height() - maScrollBorder.Height())
582             && aWindowArea.Bottom() < aViewPixelArea.Bottom())
583         {
584             nDy = 1 + (int)(mnVerticalScrollFactor
585                 * (rMouseWindowPosition.Y() - aWindowSize.Height()
586                     + maScrollBorder.Height()));
587         }
588     }
589 
590     maAutoScrollOffset = Size(nDx,nDy);
591 }
592 
593 
594 
595 
596 bool ScrollBarManager::AutoScroll (
597     const Point& rMouseWindowPosition,
598     const ::boost::function<void(void)>& rAutoScrollFunctor)
599 {
600     maAutoScrollFunctor = rAutoScrollFunctor;
601     CalcAutoScrollOffset(rMouseWindowPosition);
602     bool bResult (true);
603     if ( ! mbIsAutoScrollActive)
604         bResult = RepeatAutoScroll();
605 
606     return bResult;
607 }
608 
609 
610 
611 
612 void ScrollBarManager::StopAutoScroll (void)
613 {
614     maAutoScrollTimer.Stop();
615     mbIsAutoScrollActive = false;
616 }
617 
618 
619 
620 
621 bool ScrollBarManager::RepeatAutoScroll (void)
622 {
623     if (maAutoScrollOffset != Size(0,0))
624     {
625         if (mrSlideSorter.GetViewShell() != NULL)
626         {
627             mrSlideSorter.GetViewShell()->Scroll(
628                 maAutoScrollOffset.Width(),
629                 maAutoScrollOffset.Height());
630             mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
631 
632             if (maAutoScrollFunctor)
633                 maAutoScrollFunctor();
634 
635             mbIsAutoScrollActive = true;
636             maAutoScrollTimer.Start();
637 
638             return true;
639         }
640     }
641 
642     maAutoScrollFunctor = ::boost::function<void(void)>();
643     mbIsAutoScrollActive = false;
644     return false;
645 }
646 
647 
648 
649 
650 IMPL_LINK(ScrollBarManager, AutoScrollTimeoutHandler, Timer *, EMPTYARG)
651 {
652     RepeatAutoScroll();
653 
654     return 0;
655 }
656 
657 
658 
659 
660 void ScrollBarManager::Scroll(
661     const Orientation eOrientation,
662     const Unit eUnit,
663     const sal_Int32 nDistance)
664 {
665     bool bIsVertical (false);
666     switch (eOrientation)
667     {
668         case Orientation_Horizontal: bIsVertical = false; break;
669         case Orientation_Vertical: bIsVertical = true; break;
670         default:
671             OSL_ASSERT(eOrientation==Orientation_Horizontal || eOrientation==Orientation_Vertical);
672             return;
673     }
674 
675     Point aNewTopLeft (
676         mpHorizontalScrollBar ? mpHorizontalScrollBar->GetThumbPos() : 0,
677         mpVerticalScrollBar ? mpVerticalScrollBar->GetThumbPos() : 0);
678     switch (eUnit)
679     {
680         case Unit_Pixel:
681             if (bIsVertical)
682                 aNewTopLeft.Y() += nDistance;
683             else
684                 aNewTopLeft.X() += nDistance;
685             break;
686 
687         case Unit_Slide:
688         {
689             view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
690 
691             // Calculate estimate of new location.
692             if (bIsVertical)
693                 aNewTopLeft.Y() += nDistance * rLayouter.GetPageObjectSize().Height();
694             else
695                 aNewTopLeft.X() += nDistance * rLayouter.GetPageObjectSize().Width();
696 
697             // Adapt location to show whole slides.
698             if (bIsVertical)
699                 if (nDistance > 0)
700                 {
701                     const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
702                         Point(aNewTopLeft.X(), aNewTopLeft.Y()+mpVerticalScrollBar->GetVisibleSize()),
703                         true));
704                     aNewTopLeft.Y() = rLayouter.GetPageObjectBox(nIndex,true).Bottom()
705                         - mpVerticalScrollBar->GetVisibleSize();
706                 }
707                 else
708                 {
709                     const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
710                         Point(aNewTopLeft.X(), aNewTopLeft.Y()),
711                         true));
712                     aNewTopLeft.Y() = rLayouter.GetPageObjectBox(nIndex,true).Top();
713                 }
714             else
715                 if (nDistance > 0)
716                 {
717                     const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
718                         Point(aNewTopLeft.X()+mpVerticalScrollBar->GetVisibleSize(), aNewTopLeft.Y()),
719                         true));
720                     aNewTopLeft.X() = rLayouter.GetPageObjectBox(nIndex,true).Right()
721                         - mpVerticalScrollBar->GetVisibleSize();
722                 }
723                 else
724                 {
725                     const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
726                         Point(aNewTopLeft.X(), aNewTopLeft.Y()),
727                             true));
728                     aNewTopLeft.X() = rLayouter.GetPageObjectBox(nIndex,true).Left();
729                 }
730         }
731     }
732     mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
733     SetTopLeft(aNewTopLeft);
734 }
735 
736 
737 } } } // end of namespace ::sd::slidesorter::controller
738