1 /** @file scrollareawidget.h  Scrollable area.
2  *
3  * @authors Copyright (c) 2013-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4  *
5  * @par License
6  * LGPL: http://www.gnu.org/licenses/lgpl.html
7  *
8  * <small>This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or (at your
11  * option) any later version. This program is distributed in the hope that it
12  * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
14  * General Public License for more details. You should have received a copy of
15  * the GNU Lesser General Public License along with this program; if not, see:
16  * http://www.gnu.org/licenses</small>
17  */
18 
19 #ifndef LIBAPPFW_SCROLLAREAWIDGET_H
20 #define LIBAPPFW_SCROLLAREAWIDGET_H
21 
22 #include "../GuiWidget"
23 
24 namespace de {
25 
26 /**
27  * Scrollable area.
28  *
29  * Provides a RuleRectangle where child widgets can be placed.
30  *
31  * ScrollAreaWidget does not control its own position or size. The user must
32  * define its rectangle. The content rule rectangle is defined in relation to
33  * the widget's rectangle.
34  *
35  * The user must always define the size of the content area.
36  *
37  * ScrollAreaWidget can optionally independently draw a scroll indicator.
38  * However, the default behavior is that the user must call
39  * glMakeScrollIndicatorGeometry() to include the indicator geometry as part of
40  * the derived/owner widget.
41  *
42  * @ingroup guiWidgets
43  */
44 class LIBAPPFW_PUBLIC ScrollAreaWidget : public GuiWidget
45 {
46     Q_OBJECT
47 
48 public:
49     enum Origin {
50         Top,        ///< Scroll position 0 is at the top.
51         Bottom      ///< Scroll position 0 is at the bottom.
52     };
53 
54 public:
55     ScrollAreaWidget(String const &name = String());
56 
57     void setScrollBarColor(DotPath const &colorId);
58 
59     void setOrigin(Origin origin);
60     Origin origin() const;
61 
62     void setIndicatorUv(Rectanglef const &uv);
63     void setIndicatorUv(Vector2f const &uvPoint);
64 
65     void setContentWidth(int width);
66     void setContentWidth(Rule const &width);
67     void setContentHeight(int height);
68     void setContentHeight(Rule const &height);
69     void setContentSize(Rule const &width, Rule const &height);
70     void setContentSize(ISizeRule const &dimensions);
71     void setContentSize(Vector2i const &size);
72     void setContentSize(Vector2ui const &size);
73 
74     void modifyContentWidth(int delta);
75     void modifyContentHeight(int delta);
76 
77     int contentWidth() const;
78     int contentHeight() const;
79 
80     RuleRectangle const &contentRule() const;
81 
82     AnimationRule &scrollPositionX() const;
83     AnimationRule &scrollPositionY() const;
84     Rule const &maximumScrollX() const;
85     Rule const &maximumScrollY() const;
86 
87     bool isScrolling() const;
88 
89     Rectanglei viewport() const;
90     Vector2i viewportSize() const;
91 
92     /**
93      * Returns the current scroll XY position, with 0 being the top/left corner
94      * and maximumScroll() being the bottom right position.
95      */
96     Vector2i scrollPosition() const;
97 
98     virtual Vector2i scrollPageSize() const;
99 
100     /**
101      * Returns the maximum scroll position. The scrollMaxChanged() signal
102      * is emitted whenever the maximum changes.
103      */
104     Vector2i maximumScroll() const;
105 
106     /**
107      * Scrolls the view to a specified position. Position (0,0) means the top
108      * left corner is visible at the top left corner of the ScrollAreaWidget.
109      *
110      * @param to    Scroll position.
111      * @param span  Animation time span.
112      */
113     void scroll(Vector2i const &to, TimeSpan span = 0);
114 
115     void scrollX(int to, TimeSpan span = 0);
116     void scrollY(int to, TimeSpan span = 0);
117     void scrollY(Rule const &to, TimeSpan span = 0);
118 
119     bool isScrollable() const;
120 
121     /**
122      * Determines if the history view is at the bottom, showing the latest entry.
123      */
124     bool isAtBottom() const;
125 
126     /**
127      * Enables or disables scrolling. By default, scrolling is enabled.
128      *
129      * @param enabled  @c true to enable scrolling.
130      */
131     void enableScrolling(bool enabled);
132 
133     /**
134      * Enables or disables scrolling with Page Up/Down keys.
135      *
136      * @param enabled  @c true to enable Page Up/Down.
137      */
138     void enablePageKeys(bool enabled);
139 
140     /**
141      * Enables or disables the drawing of the scroll indicator.
142      *
143      * @param enabled  @c true to enable the indicator. The default is @c false.
144      */
145     void enableIndicatorDraw(bool enabled);
146 
147     void glMakeScrollIndicatorGeometry(GuiVertexBuilder &verts,
148                                        Vector2f const &origin = Vector2f(0, 0));
149 
150     // Events.
151     //void viewResized() override;
152     void update() override;
153     void drawContent() override;
154     bool handleEvent(Event const &event) override;
155 
156 public slots:
157     void scrollToTop(TimeSpan span = 0.3);
158 
159     /**
160      * Moves the scroll offset of the widget to the bottom of the content.
161      */
162     void scrollToBottom(TimeSpan span = 0.3);
163 
164     void scrollToLeft(TimeSpan span = 0.3);
165     void scrollToRight(TimeSpan span = 0.3);
166 
167     /**
168      * Moves the scroll offset to center on the given widget.
169      *
170      * @param widget  Widget to center on.
171      * @param span    Animation duration.
172      */
173     void scrollToWidget(GuiWidget const &widget, TimeSpan span = 0.3);
174 
175     /**
176      * Finds the topmost scroll area that can be scrolled. May return this widget
177      * if there are no scrollable ancestors.
178      *
179      * @return
180      */
181     ScrollAreaWidget &findTopmostScrollable();
182 
183 protected:
184     void glInit() override;
185     void glDeinit() override;
186 
187 private:
188     DENG2_PRIVATE(d)
189 };
190 
191 } // namespace de
192 
193 #endif // LIBAPPFW_SCROLLAREAWIDGET_H
194