bump product version to 6.3.0.0.beta1
[LibreOffice.git] / sd / source / ui / slidesorter / controller / SlsScrollBarManager.cxx
blobf7d8f928a4aa1b3c4c350514a0126d9087c955e4
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 <controller/SlsScrollBarManager.hxx>
22 #include <SlideSorter.hxx>
23 #include <ViewShell.hxx>
24 #include <controller/SlideSorterController.hxx>
25 #include <controller/SlsVisibleAreaManager.hxx>
26 #include <model/SlideSorterModel.hxx>
27 #include <model/SlsPageDescriptor.hxx>
28 #include <view/SlideSorterView.hxx>
29 #include <view/SlsLayouter.hxx>
30 #include <view/SlsTheme.hxx>
31 #include <Window.hxx>
32 #include <sdpage.hxx>
34 #include <vcl/scrbar.hxx>
36 namespace sd { namespace slidesorter { namespace controller {
38 static constexpr double gnHorizontalScrollFactor(0.15);
39 static constexpr double gnVerticalScrollFactor(0.25);
41 ScrollBarManager::ScrollBarManager (SlideSorter& rSlideSorter)
42 : mrSlideSorter(rSlideSorter),
43 mpHorizontalScrollBar(mrSlideSorter.GetHorizontalScrollBar()),
44 mpVerticalScrollBar(mrSlideSorter.GetVerticalScrollBar()),
45 mnHorizontalPosition (0),
46 mnVerticalPosition (0),
47 maScrollBorder (20,20),
48 mpScrollBarFiller(mrSlideSorter.GetScrollBarFiller()),
49 maAutoScrollTimer(),
50 maAutoScrollOffset(0,0),
51 mbIsAutoScrollActive(false),
52 mpContentWindow(mrSlideSorter.GetContentWindow()),
53 maAutoScrollFunctor()
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 mpHorizontalScrollBar->Hide();
61 mpVerticalScrollBar->Hide();
62 mpScrollBarFiller->Hide();
64 maAutoScrollTimer.SetTimeout(25);
65 maAutoScrollTimer.SetInvokeHandler (
66 LINK(this, ScrollBarManager, AutoScrollTimeoutHandler));
69 ScrollBarManager::~ScrollBarManager()
73 void ScrollBarManager::Connect()
75 if (mpVerticalScrollBar != nullptr)
77 mpVerticalScrollBar->SetScrollHdl (
78 LINK(this, ScrollBarManager, VerticalScrollBarHandler));
80 if (mpHorizontalScrollBar != nullptr)
82 mpHorizontalScrollBar->SetScrollHdl(
83 LINK(this, ScrollBarManager, HorizontalScrollBarHandler));
87 void ScrollBarManager::Disconnect()
89 if (mpVerticalScrollBar != nullptr)
91 mpVerticalScrollBar->SetScrollHdl( Link<ScrollBar*,void>() );
93 if (mpHorizontalScrollBar != nullptr)
95 mpHorizontalScrollBar->SetScrollHdl( Link<ScrollBar*,void>() );
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.
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.
110 ::tools::Rectangle ScrollBarManager::PlaceScrollBars (
111 const ::tools::Rectangle& rAvailableArea,
112 const bool bIsHorizontalScrollBarAllowed,
113 const bool bIsVerticalScrollBarAllowed)
115 ::tools::Rectangle aRemainingSpace (DetermineScrollBarVisibilities(
116 rAvailableArea,
117 bIsHorizontalScrollBarAllowed,
118 bIsVerticalScrollBarAllowed));
120 if (mpHorizontalScrollBar!=nullptr && mpHorizontalScrollBar->IsVisible())
121 PlaceHorizontalScrollBar (rAvailableArea);
123 if (mpVerticalScrollBar!=nullptr && mpVerticalScrollBar->IsVisible())
124 PlaceVerticalScrollBar (rAvailableArea);
126 if (mpScrollBarFiller!=nullptr && mpScrollBarFiller->IsVisible())
127 PlaceFiller (rAvailableArea);
129 return aRemainingSpace;
132 void ScrollBarManager::PlaceHorizontalScrollBar (const ::tools::Rectangle& aAvailableArea)
134 // Save the current relative position.
135 mnHorizontalPosition = double(mpHorizontalScrollBar->GetThumbPos())
136 / double(mpHorizontalScrollBar->GetRange().Len());
138 // Place the scroll bar.
139 Size aScrollBarSize (mpHorizontalScrollBar->GetSizePixel());
140 mpHorizontalScrollBar->SetPosSizePixel (
141 Point(aAvailableArea.Left(),
142 aAvailableArea.Bottom()-aScrollBarSize.Height()+1),
143 Size (aAvailableArea.GetWidth() - GetVerticalScrollBarWidth(),
144 aScrollBarSize.Height()));
146 // Restore the relative position.
147 mpHorizontalScrollBar->SetThumbPos(
148 static_cast<long>(0.5 + mnHorizontalPosition * mpHorizontalScrollBar->GetRange().Len()));
151 void ScrollBarManager::PlaceVerticalScrollBar (const ::tools::Rectangle& aArea)
153 const sal_Int32 nThumbPosition (mpVerticalScrollBar->GetThumbPos());
155 // Place the scroll bar.
156 Size aScrollBarSize (mpVerticalScrollBar->GetSizePixel());
157 Point aPosition (aArea.Right()-aScrollBarSize.Width()+1, aArea.Top());
158 Size aSize (aScrollBarSize.Width(), aArea.GetHeight() - GetHorizontalScrollBarHeight());
159 mpVerticalScrollBar->SetPosSizePixel(aPosition, aSize);
161 // Restore the position.
162 mpVerticalScrollBar->SetThumbPos(static_cast<long>(nThumbPosition));
163 mnVerticalPosition = nThumbPosition / double(mpVerticalScrollBar->GetRange().Len());
166 void ScrollBarManager::PlaceFiller (const ::tools::Rectangle& aArea)
168 mpScrollBarFiller->SetPosSizePixel(
169 Point(
170 aArea.Right()-mpVerticalScrollBar->GetSizePixel().Width()+1,
171 aArea.Bottom()-mpHorizontalScrollBar->GetSizePixel().Height()+1),
172 Size (
173 mpVerticalScrollBar->GetSizePixel().Width(),
174 mpHorizontalScrollBar->GetSizePixel().Height()));
177 void ScrollBarManager::UpdateScrollBars(bool bUseScrolling)
179 ::tools::Rectangle aModelArea (mrSlideSorter.GetView().GetModelArea());
180 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
181 Size aWindowModelSize (pWindow->PixelToLogic(pWindow->GetSizePixel()));
183 // The horizontal scroll bar is only shown when the window is
184 // horizontally smaller than the view.
185 if (mpHorizontalScrollBar != nullptr && mpHorizontalScrollBar->IsVisible())
187 mpHorizontalScrollBar->Show();
188 mpHorizontalScrollBar->SetRange (
189 Range(aModelArea.Left(), aModelArea.Right()));
190 mnHorizontalPosition =
191 double(mpHorizontalScrollBar->GetThumbPos())
192 / double(mpHorizontalScrollBar->GetRange().Len());
194 mpHorizontalScrollBar->SetVisibleSize (aWindowModelSize.Width());
196 const long nWidth (mpContentWindow->PixelToLogic(
197 mpContentWindow->GetSizePixel()).Width());
198 // Make the line size about 10% of the visible width.
199 mpHorizontalScrollBar->SetLineSize (nWidth / 10);
200 // Make the page size about 90% of the visible width.
201 mpHorizontalScrollBar->SetPageSize ((nWidth * 9) / 10);
203 else
205 mnHorizontalPosition = 0;
208 // The vertical scroll bar is always shown.
209 if (mpVerticalScrollBar != nullptr && mpVerticalScrollBar->IsVisible())
211 mpVerticalScrollBar->SetRange (
212 Range(aModelArea.Top(), aModelArea.Bottom()));
213 mnVerticalPosition =
214 double(mpVerticalScrollBar->GetThumbPos())
215 / double(mpVerticalScrollBar->GetRange().Len());
217 mpVerticalScrollBar->SetVisibleSize (aWindowModelSize.Height());
219 const long nHeight (mpContentWindow->PixelToLogic(
220 mpContentWindow->GetSizePixel()).Height());
221 // Make the line size about 10% of the visible height.
222 mpVerticalScrollBar->SetLineSize (nHeight / 10);
223 // Make the page size about 90% of the visible height.
224 mpVerticalScrollBar->SetPageSize ((nHeight * 9) / 10);
226 else
228 mnVerticalPosition = 0;
231 double nEps (::std::numeric_limits<double>::epsilon());
232 if (fabs(mnHorizontalPosition-pWindow->GetVisibleX()) > nEps
233 || fabs(mnVerticalPosition-pWindow->GetVisibleY()) > nEps)
235 mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
236 if (bUseScrolling)
237 pWindow->SetVisibleXY(mnHorizontalPosition, mnVerticalPosition);
238 else
239 SetWindowOrigin(mnHorizontalPosition, mnVerticalPosition);
243 IMPL_LINK(ScrollBarManager, VerticalScrollBarHandler, ScrollBar*, pScrollBar, void)
245 if (pScrollBar!=nullptr
246 && pScrollBar==mpVerticalScrollBar.get()
247 && pScrollBar->IsVisible()
248 && mrSlideSorter.GetContentWindow())
250 double nRelativePosition = double(pScrollBar->GetThumbPos())
251 / double(pScrollBar->GetRange().Len());
252 mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
253 mrSlideSorter.GetContentWindow()->SetVisibleXY(-1, nRelativePosition);
254 mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
258 IMPL_LINK(ScrollBarManager, HorizontalScrollBarHandler, ScrollBar*, pScrollBar, void)
260 if (pScrollBar!=nullptr
261 && pScrollBar==mpHorizontalScrollBar.get()
262 && pScrollBar->IsVisible()
263 && mrSlideSorter.GetContentWindow())
265 double nRelativePosition = double(pScrollBar->GetThumbPos())
266 / double(pScrollBar->GetRange().Len());
267 mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
268 mrSlideSorter.GetContentWindow()->SetVisibleXY(nRelativePosition, -1);
269 mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
273 void ScrollBarManager::SetWindowOrigin (
274 double nHorizontalPosition,
275 double nVerticalPosition)
277 mnHorizontalPosition = nHorizontalPosition;
278 mnVerticalPosition = nVerticalPosition;
280 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
281 Size aViewSize (pWindow->GetViewSize());
282 Point aOrigin (
283 static_cast<long int>(mnHorizontalPosition * aViewSize.Width()),
284 static_cast<long int>(mnVerticalPosition * aViewSize.Height()));
286 pWindow->SetWinViewPos (aOrigin);
287 pWindow->UpdateMapMode ();
288 pWindow->Invalidate ();
291 /** Determining the visibility of the scroll bars is quite complicated. The
292 visibility of one influences that of the other because showing a scroll
293 bar makes the available space smaller and may lead to the need of
294 displaying the other.
295 To solve this we test all four combinations of showing or hiding each
296 scroll bar and use the best one. The best one is that combination that
297 a) shows the least number of scroll bars with preference of showing the
298 vertical over showing the horizontal and
299 b) when not showing a scroll bar the area used by the page objects fits
300 into the available area in the scroll bars orientation.
302 ::tools::Rectangle ScrollBarManager::DetermineScrollBarVisibilities (
303 const ::tools::Rectangle& rAvailableArea,
304 const bool bIsHorizontalScrollBarAllowed,
305 const bool bIsVerticalScrollBarAllowed)
307 // Test which combination of scroll bars is the best.
308 bool bShowHorizontal = false;
309 bool bShowVertical = false;
310 if (mrSlideSorter.GetModel().GetPageCount() == 0)
312 // No pages => no scroll bars.
314 else if (TestScrollBarVisibilities(false, false, rAvailableArea))
316 // Nothing to be done.
318 else if (bIsHorizontalScrollBarAllowed
319 && TestScrollBarVisibilities(true, false, rAvailableArea))
321 bShowHorizontal = true;
323 else if (bIsVerticalScrollBarAllowed
324 && TestScrollBarVisibilities(false, true, rAvailableArea))
326 bShowVertical = true;
328 else
330 bShowHorizontal = true;
331 bShowVertical = true;
334 // Make the visibility of the scroll bars permanent.
335 mpVerticalScrollBar->Show(bShowVertical);
336 mpHorizontalScrollBar->Show(bShowHorizontal);
337 mpScrollBarFiller->Show(bShowVertical && bShowHorizontal);
339 // Adapt the remaining space accordingly.
340 ::tools::Rectangle aRemainingSpace (rAvailableArea);
341 if (bShowVertical)
342 aRemainingSpace.AdjustRight( -(mpVerticalScrollBar->GetSizePixel().Width()) );
343 if (bShowHorizontal)
344 aRemainingSpace.AdjustBottom( -(mpHorizontalScrollBar->GetSizePixel().Height()) );
346 return aRemainingSpace;
349 bool ScrollBarManager::TestScrollBarVisibilities (
350 bool bHorizontalScrollBarVisible,
351 bool bVerticalScrollBarVisible,
352 const ::tools::Rectangle& rAvailableArea)
354 model::SlideSorterModel& rModel (mrSlideSorter.GetModel());
356 // Adapt the available size by subtracting the sizes of the scroll bars
357 // visible in this combination.
358 Size aBrowserSize (rAvailableArea.GetSize());
359 if (bHorizontalScrollBarVisible)
360 aBrowserSize.AdjustHeight( -(mpHorizontalScrollBar->GetSizePixel().Height()) );
361 if (bVerticalScrollBarVisible)
362 aBrowserSize.AdjustWidth( -(mpVerticalScrollBar->GetSizePixel().Width()) );
364 // Tell the view to rearrange its page objects and check whether the
365 // page objects can be shown without clipping.
366 bool bRearrangeSuccess (mrSlideSorter.GetView().GetLayouter().Rearrange (
367 mrSlideSorter.GetView().GetOrientation(),
368 aBrowserSize,
369 rModel.GetPageDescriptor(0)->GetPage()->GetSize(),
370 rModel.GetPageCount()));
372 if (bRearrangeSuccess)
374 Size aPageSize = mrSlideSorter.GetView().GetLayouter().GetTotalBoundingBox().GetSize();
375 Size aWindowModelSize = mpContentWindow->PixelToLogic(aBrowserSize);
377 // The content may be clipped, i.e. not fully visible, in one
378 // direction only when the scroll bar is visible in that direction.
379 if (aPageSize.Width() > aWindowModelSize.Width())
380 if ( ! bHorizontalScrollBarVisible)
381 return false;
382 if (aPageSize.Height() > aWindowModelSize.Height())
383 if ( ! bVerticalScrollBarVisible)
384 return false;
386 return true;
388 else
389 return false;
392 void ScrollBarManager::SetTopLeft(const Point& rNewTopLeft)
394 if (( ! mpVerticalScrollBar
395 || mpVerticalScrollBar->GetThumbPos() == rNewTopLeft.Y())
396 && ( ! mpHorizontalScrollBar
397 || mpHorizontalScrollBar->GetThumbPos() == rNewTopLeft.X()))
398 return;
400 // Flush pending repaints before scrolling to avoid temporary artifacts.
401 mrSlideSorter.GetContentWindow()->Update();
403 if (mpVerticalScrollBar)
405 mpVerticalScrollBar->SetThumbPos(rNewTopLeft.Y());
406 mnVerticalPosition = rNewTopLeft.Y() / double(mpVerticalScrollBar->GetRange().Len());
408 if (mpHorizontalScrollBar)
410 mpHorizontalScrollBar->SetThumbPos(rNewTopLeft.X());
411 mnHorizontalPosition = rNewTopLeft.X() / double(mpHorizontalScrollBar->GetRange().Len());
414 mrSlideSorter.GetContentWindow()->SetVisibleXY(mnHorizontalPosition, mnVerticalPosition);
415 mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
418 int ScrollBarManager::GetVerticalScrollBarWidth() const
420 if (mpVerticalScrollBar != nullptr && mpVerticalScrollBar->IsVisible())
421 return mpVerticalScrollBar->GetSizePixel().Width();
422 else
423 return 0;
426 int ScrollBarManager::GetHorizontalScrollBarHeight() const
428 if (mpHorizontalScrollBar != nullptr && mpHorizontalScrollBar->IsVisible())
429 return mpHorizontalScrollBar->GetSizePixel().Height();
430 else
431 return 0;
434 void ScrollBarManager::CalcAutoScrollOffset (const Point& rMouseWindowPosition)
436 sd::Window *pWindow (mrSlideSorter.GetContentWindow().get());
438 int nDx = 0;
439 int nDy = 0;
441 Size aWindowSize = pWindow->GetOutputSizePixel();
442 ::tools::Rectangle aWindowArea (pWindow->GetPosPixel(), aWindowSize);
443 ::tools::Rectangle aViewPixelArea (
444 pWindow->LogicToPixel(mrSlideSorter.GetView().GetModelArea()));
446 if (aWindowSize.Width() > maScrollBorder.Width() * 3
447 && mpHorizontalScrollBar != nullptr
448 && mpHorizontalScrollBar->IsVisible())
450 if (rMouseWindowPosition.X() < maScrollBorder.Width()
451 && aWindowArea.Left() > aViewPixelArea.Left())
453 nDx = -1 + static_cast<int>(gnHorizontalScrollFactor
454 * (rMouseWindowPosition.X() - maScrollBorder.Width()));
457 if (rMouseWindowPosition.X() >= (aWindowSize.Width() - maScrollBorder.Width())
458 && aWindowArea.Right() < aViewPixelArea.Right())
460 nDx = 1 + static_cast<int>(gnHorizontalScrollFactor
461 * (rMouseWindowPosition.X() - aWindowSize.Width()
462 + maScrollBorder.Width()));
466 if (aWindowSize.Height() > maScrollBorder.Height() * 3
467 && aWindowSize.Height() < aViewPixelArea.GetHeight())
469 if (rMouseWindowPosition.Y() < maScrollBorder.Height()
470 && aWindowArea.Top() > aViewPixelArea.Top())
472 nDy = -1 + static_cast<int>(gnVerticalScrollFactor
473 * (rMouseWindowPosition.Y() - maScrollBorder.Height()));
476 if (rMouseWindowPosition.Y() >= (aWindowSize.Height() - maScrollBorder.Height())
477 && aWindowArea.Bottom() < aViewPixelArea.Bottom())
479 nDy = 1 + static_cast<int>(gnVerticalScrollFactor
480 * (rMouseWindowPosition.Y() - aWindowSize.Height()
481 + maScrollBorder.Height()));
485 maAutoScrollOffset = Size(nDx,nDy);
488 bool ScrollBarManager::AutoScroll (
489 const Point& rMouseWindowPosition,
490 const ::std::function<void ()>& rAutoScrollFunctor)
492 maAutoScrollFunctor = rAutoScrollFunctor;
493 CalcAutoScrollOffset(rMouseWindowPosition);
494 bool bResult (true);
495 if ( ! mbIsAutoScrollActive)
496 bResult = RepeatAutoScroll();
498 return bResult;
501 void ScrollBarManager::StopAutoScroll()
503 maAutoScrollTimer.Stop();
504 mbIsAutoScrollActive = false;
507 bool ScrollBarManager::RepeatAutoScroll()
509 if (maAutoScrollOffset != Size(0,0))
511 if (mrSlideSorter.GetViewShell() != nullptr)
513 mrSlideSorter.GetViewShell()->Scroll(
514 maAutoScrollOffset.Width(),
515 maAutoScrollOffset.Height());
516 mrSlideSorter.GetView().InvalidatePageObjectVisibilities();
518 if (maAutoScrollFunctor)
519 maAutoScrollFunctor();
521 mbIsAutoScrollActive = true;
522 maAutoScrollTimer.Start();
524 return true;
528 clearAutoScrollFunctor();
529 mbIsAutoScrollActive = false;
530 return false;
533 void ScrollBarManager::clearAutoScrollFunctor()
535 maAutoScrollFunctor = ::std::function<void ()>();
538 IMPL_LINK_NOARG(ScrollBarManager, AutoScrollTimeoutHandler, Timer *, void)
540 RepeatAutoScroll();
543 void ScrollBarManager::Scroll(
544 const Orientation eOrientation,
545 const sal_Int32 nDistance)
547 bool bIsVertical (false);
548 switch (eOrientation)
550 case Orientation_Horizontal: bIsVertical = false; break;
551 case Orientation_Vertical: bIsVertical = true; break;
552 default:
553 OSL_ASSERT(eOrientation==Orientation_Horizontal || eOrientation==Orientation_Vertical);
554 return;
557 Point aNewTopLeft (
558 mpHorizontalScrollBar ? mpHorizontalScrollBar->GetThumbPos() : 0,
559 mpVerticalScrollBar ? mpVerticalScrollBar->GetThumbPos() : 0);
561 view::Layouter& rLayouter (mrSlideSorter.GetView().GetLayouter());
563 // Calculate estimate of new location.
564 if (bIsVertical)
565 aNewTopLeft.AdjustY(nDistance * rLayouter.GetPageObjectSize().Height() );
566 else
567 aNewTopLeft.AdjustX(nDistance * rLayouter.GetPageObjectSize().Width() );
569 // Adapt location to show whole slides.
570 if (bIsVertical)
571 if (nDistance > 0)
573 const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
574 Point(aNewTopLeft.X(), aNewTopLeft.Y()+mpVerticalScrollBar->GetVisibleSize()),
575 true));
576 aNewTopLeft.setY( rLayouter.GetPageObjectBox(nIndex,true).Bottom()
577 - mpVerticalScrollBar->GetVisibleSize() );
579 else
581 const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
582 Point(aNewTopLeft.X(), aNewTopLeft.Y()),
583 true));
584 aNewTopLeft.setY( rLayouter.GetPageObjectBox(nIndex,true).Top() );
586 else
587 if (nDistance > 0)
589 const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
590 Point(aNewTopLeft.X()+mpVerticalScrollBar->GetVisibleSize(), aNewTopLeft.Y()),
591 true));
592 aNewTopLeft.setX( rLayouter.GetPageObjectBox(nIndex,true).Right()
593 - mpVerticalScrollBar->GetVisibleSize() );
595 else
597 const sal_Int32 nIndex (rLayouter.GetIndexAtPoint(
598 Point(aNewTopLeft.X(), aNewTopLeft.Y()),
599 true));
600 aNewTopLeft.setX( rLayouter.GetPageObjectBox(nIndex,true).Left() );
603 mrSlideSorter.GetController().GetVisibleAreaManager().DeactivateCurrentSlideTracking();
604 SetTopLeft(aNewTopLeft);
607 } } } // end of namespace ::sd::slidesorter::controller
609 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */