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 #ifndef INCLUDED_SD_SOURCE_UI_SLIDESORTER_INC_CONTROLLER_SLSSCROLLBARMANAGER_HXX
21 #define INCLUDED_SD_SOURCE_UI_SLIDESORTER_INC_CONTROLLER_SLSSCROLLBARMANAGER_HXX
22 
23 #include <tools/link.hxx>
24 #include <tools/gen.hxx>
25 #include <vcl/timer.hxx>
26 #include <vcl/scrbar.hxx>
27 #include <vcl/vclptr.hxx>
28 
29 #include <functional>
30 
31 namespace sd { class Window; }
32 
33 namespace sd { namespace slidesorter { class SlideSorter; } }
34 
35 namespace sd { namespace slidesorter { namespace controller {
36 
37 /** Manage the horizontal and vertical scroll bars.  Listen for events, set
38     their sizes, place them in the window, determine their visibilities.
39 
40     <p>Handle auto scrolling, i.e. the scrolling of the window when the
41     mouse comes near the window border while dragging a selection.</p>
42 
43     <p>In order to make the slide sorter be used in the task pane with its
44     own vertical scrollbars the vertical scrollbar of the use of the slide
45     sorter is optional.  When using it the available area in a window is
46     used and the vertical scrollbar is displayed when that area is not large
47     enough.  When the vertical scrollbar is not used then the available area
48     is assumed to be modifiable.  In that case the PlaceScrollBars() method
49     may return an area larger than the one given.<p>
50 */
51 class ScrollBarManager
52 {
53 public:
54     /** Create a new scroll bar manager that manages three controls: the
55         horizontal scroll bar, the vertical scroll bar, and the little
56         window that fills the gap at the bottom right corner that is left
57         between the two scroll bars.  Call LateInitialization() after
58         constructing a new object.
59     */
60     ScrollBarManager (SlideSorter& rSlideSorter);
61 
62     ~ScrollBarManager();
63 
64     /** Register listeners at the scroll bars.  This method is called after
65         startup of a new slide sorter object or after a reactivation of a
66         slide sorter that for example is taken from a cache.
67     */
68     void Connect();
69 
70     /** Remove listeners from the scroll bars.  This method is called when
71         the slide sorter is destroyed or when it is suspended, e.g. put
72         into a cache for later reuse.
73     */
74     void Disconnect();
75 
76     /** Set up the scroll bar, i.e. thumb size and position.  Call this
77         method when the content of the browser window changed, i.e. pages
78         were inserted or deleted, the layout or the zoom factor has
79         changed.
80         @param bScrollToCurrentPosition
81             When <TRUE/> then scroll the window to the new offset that is
82             defined by the scroll bars.  Otherwise the new offset is simply
83             set and the whole window is repainted.
84     */
85     void UpdateScrollBars (
86         bool bScrollToCurrentPosition);
87 
88     /** Place the scroll bars inside the given area.  When the available
89         area is not large enough for the content to display the horizontal
90         and/or vertical scroll bar is enabled.
91         @param rAvailableArea
92             The scroll bars will be placed inside this rectangle.  It is
93             expected to be given in pixel relative to its parent.
94         @param bIsHorizontalScrollBarAllowed
95             Only when this flag is <TRUE/> the horizontal scroll may be
96             displayed.
97         @param bIsVerticalScrollBarAllowed
98             Only when this flag is <TRUE/> the horizontal scroll may be
99             displayed.
100         @return
101             Returns the space that remains after the scroll bars are
102             placed.
103     */
104     ::tools::Rectangle PlaceScrollBars (
105         const ::tools::Rectangle& rAvailableArea,
106         const bool bIsHorizontalScrollBarAllowed,
107         const bool bIsVerticalScrollBarAllowed);
108 
109     /** Update the vertical and horizontal scroll bars so that the visible
110         area has the given top and left values.
111     */
112     void SetTopLeft (const Point& rNewTopLeft);
113 
114     /** Return the width of the vertical scroll bar, which--when
115         shown--should be fixed in contrast to its height.
116         @return
117            Returns 0 when the vertical scroll bar is not shown or does not
118            exist, otherwise its width in pixel is returned.
119     */
120     int GetVerticalScrollBarWidth() const;
121 
122     /** Return the height of the horizontal scroll bar, which--when
123         shown--should be fixed in contrast to its width.
124         @return
125            Returns 0 when the vertical scroll bar is not shown or does not
126            exist, otherwise its height in pixel is returned.
127     */
128     int GetHorizontalScrollBarHeight() const;
129 
130     /** Call this method to scroll a window while the mouse is in dragging a
131         selection.  If the mouse is near the window border or is outside the
132         window then scroll the window accordingly.
133         @param rMouseWindowPosition
134             The mouse position for which the scroll amount is calculated.
135         @param rAutoScrollFunctor
136             Every time when the window is scrolled then this functor is executed.
137         @return
138             When the window is scrolled then this method returns <TRUE/>.
139             When the window is not changed then <FALSE/> is returned.
140     */
141     bool AutoScroll (
142         const Point& rMouseWindowPosition,
143         const ::std::function<void ()>& rAutoScrollFunctor);
144 
145     void StopAutoScroll();
146 
147     void clearAutoScrollFunctor();
148 
149     enum Orientation { Orientation_Horizontal, Orientation_Vertical };
150     /** Scroll the slide sorter by setting the thumbs of the scroll bars and
151         by moving the content of the content window.
152         @param eOrientation
153             Defines whether to scroll horizontally or vertically.
154         @param nDistance
155             distance in slides.
156     */
157     void Scroll(
158         const Orientation eOrientation,
159         const sal_Int32 nDistance);
160 
161 private:
162     SlideSorter& mrSlideSorter;
163 
164     /** The horizontal scroll bar.  Note that is used but not owned by
165         objects of this class.  It is given to the constructor.
166     */
167     VclPtr<ScrollBar> mpHorizontalScrollBar;
168 
169     /** The vertical scroll bar.  Note that is used but not owned by
170         objects of this class.  It is given to the constructor.
171     */
172     VclPtr<ScrollBar> mpVerticalScrollBar;
173 
174     /// Relative horizontal position of the visible area in the view.
175     double mnHorizontalPosition;
176     /// Relative vertical position of the visible area in the view.
177     double mnVerticalPosition;
178     /** The width and height of the border at the inside of the window which
179         when entered while in drag mode leads to a scrolling of the window.
180     */
181     Size const maScrollBorder;
182     /** The only task of this little window is to paint the little square at
183         the bottom right corner left by the two scroll bars (when both are
184         visible).
185     */
186     VclPtr<ScrollBarBox> mpScrollBarFiller;
187 
188     /** The auto scroll timer is used for keep scrolling the window when the
189         mouse reaches its border while dragging a selection.  When the mouse
190         is not moved the timer issues events to keep scrolling.
191     */
192     Timer maAutoScrollTimer;
193     Size maAutoScrollOffset;
194     bool mbIsAutoScrollActive;
195 
196     /** The content window is the one whose view port is controlled by the
197         scroll bars.
198     */
199     VclPtr<sd::Window> mpContentWindow;
200 
201     ::std::function<void ()> maAutoScrollFunctor;
202 
203     void SetWindowOrigin (
204         double nHorizontalPosition,
205         double nVerticalPosition);
206 
207     /** Determine the visibility of the scroll bars so that the window
208         content is not clipped in any dimension without showing a scroll
209         bar.
210         @param rAvailableArea
211             The area in which the scroll bars, the scroll bar filler, and
212             the SlideSorterView will be placed.
213         @return
214             The area that is enclosed by the scroll bars is returned.  It
215             will be filled with the SlideSorterView.
216     */
217     ::tools::Rectangle DetermineScrollBarVisibilities(
218         const ::tools::Rectangle& rAvailableArea,
219         const bool bIsHorizontalScrollBarAllowed,
220         const bool bIsVerticalScrollBarAllowed);
221 
222     /** Typically called by DetermineScrollBarVisibilities() this method
223         tests a specific configuration of the two scroll bars being visible
224         or hidden.
225         @return
226             When the window content can be shown with only being clipped in
227             an orientation where the scroll bar would be shown then <TRUE/>
228             is returned.
229     */
230     bool TestScrollBarVisibilities (
231         bool bHorizontalScrollBarVisible,
232         bool bVerticalScrollBarVisible,
233         const ::tools::Rectangle& rAvailableArea);
234 
235     void CalcAutoScrollOffset (const Point& rMouseWindowPosition);
236     bool RepeatAutoScroll();
237 
238     DECL_LINK(HorizontalScrollBarHandler, ScrollBar*, void);
239     DECL_LINK(VerticalScrollBarHandler, ScrollBar*, void);
240     DECL_LINK(AutoScrollTimeoutHandler, Timer *, void);
241 
242     void PlaceHorizontalScrollBar (const ::tools::Rectangle& aArea);
243     void PlaceVerticalScrollBar (const ::tools::Rectangle& aArea);
244     void PlaceFiller (const ::tools::Rectangle& aArea);
245 };
246 
247 } } } // end of namespace ::sd::slidesorter::controller
248 
249 #endif
250 
251 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
252