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