The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
scrollbar.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2008 - 2025
3 by Mark de Wever <koraq@xs4all.nl>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16#pragma once
17
19
20namespace gui2
21{
22
23/**
24 * Base class for a scroll bar.
25 *
26 * class will be subclassed for the horizontal and vertical scroll bar.
27 * It might be subclassed for a slider class.
28 *
29 * To make this class generic we talk a lot about offset and length and use
30 * pure virtual functions. The classes implementing us can use the heights or
31 * widths, whichever is applicable.
32 *
33 * The NOTIFY_MODIFIED event is send when the position of scrollbar is changed.
34 *
35 * Common signal handlers:
36 * - connect_signal_notify_modified
37 */
39{
40 /** @todo Abstract the code so this friend is no longer needed. */
41 friend class slider;
42
43public:
44 scrollbar_base(const implementation::builder_styled_widget& builder, const std::string& control_type);
45
46 /**
47 * scroll 'step size'.
48 *
49 * When scrolling we always scroll a 'fixed' amount, these are the
50 * parameters for these amounts.
51 */
53 BEGIN, /**< Go to begin position. */
54 ITEM_BACKWARDS, /**< Go one item towards the begin. */
55 HALF_JUMP_BACKWARDS, /**< Go half the visible items towards the begin.
56 */
57 JUMP_BACKWARDS, /**< Go the visible items towards the begin. */
58 END, /**< Go to the end position. */
59 ITEM_FORWARD, /**< Go one item towards the end. */
60 HALF_JUMP_FORWARD, /**< Go half the visible items towards the end. */
62 }; /**< Go the visible items towards the end. */
63
64 /**
65 * Sets the item position.
66 *
67 * We scroll a predefined step.
68 *
69 * @param scroll 'step size' to scroll.
70 */
71 void scroll(const scroll_mode scroll);
72
73 void scroll_by(const int pixels);
74
75 /** Is the positioner at the beginning of the scrollbar? */
76 bool at_begin() const
77 {
78 return item_position_ == 0;
79 }
80
81 /**
82 * Is the positioner at the and of the scrollbar?
83 *
84 * Note both begin and end might be true at the same time.
85 */
86 bool at_end() const
87 {
89 }
90
91 /** Are all items visible? */
92 bool all_items_visible() const
93 {
95 }
96
97 /***** ***** ***** ***** layout functions ***** ***** ***** *****/
98
99 /** See @ref widget::place. */
100 virtual void place(const point& origin, const point& size) override;
101
102 /***** ***** ***** ***** Inherited ***** ***** ***** *****/
103
104 /** See @ref styled_widget::set_active. */
105 virtual void set_active(const bool active) override;
106
107 /** See @ref styled_widget::get_active. */
108 virtual bool get_active() const override;
109
110 /** See @ref styled_widget::get_state. */
111 virtual unsigned get_state() const override;
112
113 /**
114 * Possible states of the widget.
115 *
116 * Note the order of the states must be the same as defined in settings.hpp.
117 */
124
125 /***** ***** ***** setters / getters for members ***** ****** *****/
126
127 void set_item_count(const unsigned item_count)
128 {
129 item_count_ = item_count;
130 recalculate();
131 }
132 unsigned get_item_count() const
133 {
134 return item_count_;
135 }
136
137 /**
138 * Note the position isn't guaranteed to be the wanted position
139 * the step size is honored. The value will be rouded down.
140 */
141 void set_item_position(const unsigned item_position);
142 unsigned get_item_position() const
143 {
144 return item_position_;
145 }
146
147 unsigned get_visible_items() const
148 {
149 return visible_items_;
150 }
151
152 void set_visible_items(const unsigned visible_items)
153 {
154 visible_items_ = visible_items;
155 recalculate();
156 }
157
158 unsigned get_step_size() const
159 {
160 return step_size_;
161 }
162
163 void set_step_size(const unsigned step_size)
164 {
165 // Step size can't be 0!
166 if(step_size == 0) {
167 throw std::invalid_argument("GUI2: scrollbar step size cannot be 0");
168 }
169
170 step_size_ = step_size;
171 recalculate();
172 }
173
175 {
176 return pixels_per_step_;
177 }
178
179 unsigned get_positioner_offset() const
180 {
181 return positioner_offset_;
182 }
183
184protected:
185 void finalize_setup();
186
187 unsigned get_positioner_length() const
188 {
189 return positioner_length_;
190 }
191
193 {
194 return mouse_;
195 }
196
197 /**
198 * See @ref styled_widget::update_canvas.
199 *
200 * After a recalculation the canvasses also need to be updated.
201 */
202 virtual void update_canvas() override;
203
204 /**
205 * Callback for subclasses to get notified about positioner movement.
206 *
207 * @todo This is a kind of hack due to the fact there's no simple
208 * callback slot mechanism. See whether we can implement a generic way to
209 * attach callback which would remove quite some extra code.
210 */
212 {
213 }
214
215private:
216 void set_state(const state_t state);
217 /**
218 * Current state of the widget.
219 *
220 * The state of the widget determines what to render and how the widget
221 * reacts to certain 'events'.
222 */
224
225 /** The number of items the scrollbar 'holds'. */
226 unsigned item_count_;
227
228 /** The item the positioner is at, starts at 0. */
230
231 /**
232 * The number of items which can be shown at the same time.
233 *
234 * As long as all items are visible we don't need to scroll.
235 */
237
238 /**
239 * Number of items moved when scrolling.
240 *
241 * The step size is the minimum number of items we scroll through when we
242 * move. Normally this value is 1, we can move per item. But for example
243 * sliders want for example to move per 5 items.
244 */
245 unsigned step_size_;
246
247 /**
248 * Number of pixels per step.
249 *
250 * The number of pixels the positioner needs to move to go to the next step.
251 * Note if there is too little space it can happen 1 pixel does more than 1
252 * step.
253 */
255
256 /**
257 * The position the mouse was at the last movement.
258 *
259 * This is used during dragging the positioner.
260 */
262
263 /**
264 * The start offset of the positioner.
265 *
266 * This takes the offset before in consideration.
267 */
269
270 /** The current length of the positioner. */
272
273 /***** ***** ***** ***** Pure virtual functions ***** ***** ***** *****/
274
275 /** Get the length of the scrollbar. */
276 virtual unsigned get_length() const = 0;
277
278 /** The minimum length of the positioner. */
279 virtual unsigned minimum_positioner_length() const = 0;
280
281 /** The maximum length of the positioner. */
282 virtual unsigned maximum_positioner_length() const = 0;
283
284 /**
285 * The number of pixels we can't use since they're used for borders.
286 *
287 * These are the pixels before the widget (left side if horizontal,
288 * top side if vertical).
289 */
290 virtual unsigned offset_before() const = 0;
291
292 /**
293 * The number of pixels we can't use since they're used for borders.
294 *
295 * These are the pixels after the widget (right side if horizontal,
296 * bottom side if vertical).
297 */
298 virtual unsigned offset_after() const = 0;
299
300 /**
301 * Is the coordinate on the positioner?
302 *
303 * @param coordinate Coordinate to test whether it's on the
304 * positioner.
305 *
306 * @returns Whether the location on the positioner is.
307 */
308 virtual bool on_positioner(const point& coordinate) const = 0;
309
310 /**
311 * Is the coordinate on the bar?
312 *
313 * @param coordinate Coordinate to test whether it's on the
314 * bar.
315 *
316 * @returns Whether the location on the bar is.
317 * @retval -1 Coordinate is on the bar before positioner.
318 * @retval 0 Coordinate is not on the bar.
319 * @retval 1 Coordinate is on the bar after the positioner.
320 */
321 virtual int on_bar(const point& coordinate) const = 0;
322
323 /**
324 * Is the coordinate in the bar's orthogonal range?
325 *
326 * @param coordinate Coordinate to test whether it's in-range.
327 *
328 * @returns Whether the location is in the bar's.
329 * orthogonal range.
330 */
331 virtual bool in_orthogonal_range(const point& coordinate) const = 0;
332
333 /**
334 * Gets the relevant difference in between the two positions.
335 *
336 * This function is used to determine how much the positioner needs to be
337 * moved.
338 */
339 virtual int get_length_difference(const point& original,
340 const point& current) const = 0;
341
342 /***** ***** ***** ***** Private functions ***** ***** ***** *****/
343
344 /**
345 * Updates the scrollbar.
346 *
347 * Needs to be called when something changes eg number of items
348 * or available size. It can only be called once we have a size
349 * otherwise we can't calculate a thing.
350 */
351 void recalculate();
352
353 /**
354 * Updates the positioner.
355 *
356 * This is a helper for recalculate().
357 */
359
360 /**
361 * Moves the positioner.
362 *
363 * @param distance The distance moved, negative to begin, positive
364 * to end.
365 */
366 virtual void move_positioner(const int distance);
367
368 /***** ***** ***** signal handlers ***** ****** *****/
369
371 bool& handled,
372 bool& halt);
373
375 bool& handled,
376 bool& halt,
377 const point& coordinate);
378
379 void signal_handler_mouse_leave(const event::ui_event event, bool& handled);
380
382 bool& handled);
383
385 bool& handled);
386};
387
388} // namespace gui2
Base class for a scroll bar.
Definition scrollbar.hpp:39
bool at_begin() const
Is the positioner at the beginning of the scrollbar?
Definition scrollbar.hpp:76
virtual unsigned minimum_positioner_length() const =0
The minimum length of the positioner.
virtual bool get_active() const override
See styled_widget::get_active.
void set_item_position(const unsigned item_position)
Note the position isn't guaranteed to be the wanted position the step size is honored.
void set_step_size(const unsigned step_size)
point get_mouse_position_last_move() const
void signal_handler_mouse_leave(const event::ui_event event, bool &handled)
void signal_handler_left_button_up(const event::ui_event event, bool &handled)
virtual void update_canvas() override
See styled_widget::update_canvas.
unsigned get_positioner_offset() const
unsigned positioner_offset_
The start offset of the positioner.
unsigned get_item_position() const
float pixels_per_step_
Number of pixels per step.
virtual void move_positioner(const int distance)
Moves the positioner.
virtual bool in_orthogonal_range(const point &coordinate) const =0
Is the coordinate in the bar's orthogonal range?
void signal_handler_left_button_down(const event::ui_event event, bool &handled)
bool at_end() const
Is the positioner at the and of the scrollbar?
Definition scrollbar.hpp:86
bool all_items_visible() const
Are all items visible?
Definition scrollbar.hpp:92
virtual void place(const point &origin, const point &size) override
See widget::place.
unsigned get_step_size() const
virtual void child_callback_positioner_moved()
Callback for subclasses to get notified about positioner movement.
float get_pixels_per_step() const
virtual unsigned maximum_positioner_length() const =0
The maximum length of the positioner.
void set_item_count(const unsigned item_count)
state_t
Possible states of the widget.
virtual int on_bar(const point &coordinate) const =0
Is the coordinate on the bar?
void set_state(const state_t state)
unsigned positioner_length_
The current length of the positioner.
unsigned item_count_
The number of items the scrollbar 'holds'.
unsigned get_item_count() const
void recalculate()
Updates the scrollbar.
unsigned visible_items_
The number of items which can be shown at the same time.
virtual unsigned offset_after() const =0
The number of pixels we can't use since they're used for borders.
virtual int get_length_difference(const point &original, const point &current) const =0
Gets the relevant difference in between the two positions.
virtual unsigned get_state() const override
See styled_widget::get_state.
void set_visible_items(const unsigned visible_items)
point mouse_
The position the mouse was at the last movement.
void scroll(const scroll_mode scroll)
Sets the item position.
Definition scrollbar.cpp:71
unsigned get_positioner_length() const
state_t state_
Current state of the widget.
virtual unsigned get_length() const =0
Get the length of the scrollbar.
scroll_mode
scroll 'step size'.
Definition scrollbar.hpp:52
@ ITEM_FORWARD
Go one item towards the end.
Definition scrollbar.hpp:59
@ ITEM_BACKWARDS
Go one item towards the begin.
Definition scrollbar.hpp:54
@ END
Go to the end position.
Definition scrollbar.hpp:58
@ HALF_JUMP_FORWARD
Go half the visible items towards the end.
Definition scrollbar.hpp:60
@ BEGIN
Go to begin position.
Definition scrollbar.hpp:53
@ JUMP_BACKWARDS
Go the visible items towards the begin.
Definition scrollbar.hpp:57
@ HALF_JUMP_BACKWARDS
Go half the visible items towards the begin.
Definition scrollbar.hpp:55
void recalculate_positioner()
Updates the positioner.
void signal_handler_mouse_enter(const event::ui_event event, bool &handled, bool &halt)
virtual unsigned offset_before() const =0
The number of pixels we can't use since they're used for borders.
unsigned get_visible_items() const
unsigned item_position_
The item the positioner is at, starts at 0.
void scroll_by(const int pixels)
Definition scrollbar.cpp:66
virtual void set_active(const bool active) override
See styled_widget::set_active.
void signal_handler_mouse_motion(const event::ui_event event, bool &handled, bool &halt, const point &coordinate)
unsigned step_size_
Number of items moved when scrolling.
virtual bool on_positioner(const point &coordinate) const =0
Is the coordinate on the positioner?
ui_event
The event sent to the dispatcher.
Definition handler.hpp:115
Generic file dialog.
Holds a 2D point.
Definition point.hpp:25