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