=== Overview ===
[xuni.git] / src / widget / scrollbar.c
blobe071ed333212254888eb5436d3ce819e16907986
1 /*! \file scrollbar.c
3 */
5 #include "../graphics.h"
6 #include "../memory.h"
7 #include "../error.h"
8 #include "dump.h"
9 #include "widgets.h"
10 #include "scrollbar.h"
11 #include "box.h"
12 #include "button.h"
14 static void init_vertical_scrollbar(struct widget_t *widget,
15 struct xuni_t *xuni);
16 static void init_horizontal_scrollbar(struct widget_t *widget,
17 struct xuni_t *xuni);
19 static void free_scrollbar(struct xuni_t *xuni, struct widget_t *widget);
20 static void reposition_scrollbar(struct xuni_t *xuni,
21 struct widget_t *widget);
22 static void rescale_scrollbar(struct xuni_t *xuni, struct widget_t *widget);
23 static void paint_scrollbar(struct xuni_t *xuni, struct widget_t *widget);
25 static double calculate_seek_height(struct widget_t *widget,
26 struct xuni_t *xuni);
28 void scrollbar_widget_event(struct xuni_t *xuni, struct widget_t *widget,
29 enum widget_event_t event) {
31 static void (*function[])(struct xuni_t *xuni, struct widget_t *widget)
32 = {
34 free_scrollbar,
36 paint_scrollbar,
37 reposition_scrollbar,
38 rescale_scrollbar
41 call_widget_event_func(xuni, widget, event, function,
42 sizeof(function) / sizeof(*function));
45 void init_scrollbar(struct widget_t *widget, struct xuni_t *xuni, int max,
46 enum scrollbar_orientation_t orientation) {
48 widget->type = WIDGET_SCROLLBAR;
49 widget->p.scrollbar = xuni_memory_allocate(sizeof(*widget->p.scrollbar));
51 widget->p.scrollbar->pos = 0;
52 widget->p.scrollbar->max = max;
53 widget->p.scrollbar->orientation = orientation;
55 if(orientation == SCROLLBAR_ORIENTATION_VERTICAL) {
56 init_vertical_scrollbar(widget, xuni);
58 else if(orientation == SCROLLBAR_ORIENTATION_HORIZONTAL) {
59 init_horizontal_scrollbar(widget, xuni);
61 else {
62 printf("Unsupported scrollbar orientation: %i\n", (int)orientation);
66 static void init_vertical_scrollbar(struct widget_t *widget,
67 struct xuni_t *xuni) {
69 double height = widget->pos->scale.w /* / screen_ratio(xuni->smode) */;
71 /* seek bar */
72 add_allocate_widget_compose(widget, "alwaysinbox");
74 init_widget_pos(last_compose_widget(widget), 0, height,
75 100.0, 100.0 - height * 2, POS_PACK_NONE);
76 init_box(last_compose_widget(widget), BOX_STYLE_ALWAYSIN, 0);
78 /*last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_INDEPENDENT;*/
80 /* up button */
81 add_allocate_widget_compose(widget, "less");
83 init_widget_pos(last_compose_widget(widget), 0, 0, 100.0, height,
84 POS_PACK_NONE);
85 init_button(last_compose_widget(widget), 0);
87 init_button_image(xuni, last_compose_widget(widget),
88 widget_nameid_access(xuni->theme->current, THEME_SCROLL_UP));
90 /*last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_INDEPENDENT;*/
92 /* seek button */
93 add_allocate_widget_compose(widget, "seek");
95 init_widget_pos(last_compose_widget(widget), 0, height, 100.0, height,
96 POS_PACK_NONE);
97 init_button(last_compose_widget(widget), 0);
99 /*last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_INDEPENDENT;*/
101 /* down button */
102 add_allocate_widget_compose(widget, "more");
104 init_widget_pos(last_compose_widget(widget), 0, 100.0 - height,
105 100.0, height, POS_PACK_NONE);
106 init_button(last_compose_widget(widget), 0);
108 init_button_image(xuni, last_compose_widget(widget),
109 widget_nameid_access(xuni->theme->current, THEME_SCROLL_DOWN));
111 /*last_compose_widget(widget)->visibility &= ~WIDGET_VISIBILITY_INDEPENDENT;
113 widget->visibility &= ~WIDGET_VISIBILITY_NOT_COMPOSE;*/
116 static void init_horizontal_scrollbar(struct widget_t *widget,
117 struct xuni_t *xuni) {
119 double width = widget->pos->scale.h;
121 /* seek bar */
122 add_allocate_widget_compose(widget, "alwaysinbox");
124 init_widget_pos(last_compose_widget(widget), width, 0,
125 100.0 - width * 2, 100.0, POS_PACK_NONE);
126 init_box(last_compose_widget(widget), BOX_STYLE_ALWAYSIN, 0);
128 /* left button */
129 add_allocate_widget_compose(widget, "less");
131 init_widget_pos(last_compose_widget(widget), 0, 0, width, 100.0,
132 POS_PACK_NONE);
133 init_button(last_compose_widget(widget), 0);
135 init_button_image(xuni, last_compose_widget(widget),
136 widget_nameid_access(xuni->theme->current, THEME_SCROLL_LEFT));
138 /* seek button */
139 add_allocate_widget_compose(widget, "seek");
141 init_widget_pos(last_compose_widget(widget), width, 0, width, 100.0,
142 POS_PACK_NONE);
143 init_button(last_compose_widget(widget), 0);
145 /* right button */
146 add_allocate_widget_compose(widget, "more");
148 init_widget_pos(last_compose_widget(widget), 100.0 - width, 0,
149 width, 100.0, POS_PACK_NONE);
150 init_button(last_compose_widget(widget), 0);
152 init_button_image(xuni, last_compose_widget(widget),
153 widget_nameid_access(xuni->theme->current, THEME_SCROLL_RIGHT));
156 static void free_scrollbar(struct xuni_t *xuni, struct widget_t *widget) {
157 xuni_memory_free(widget->p.scrollbar);
160 static void paint_scrollbar(struct xuni_t *xuni, struct widget_t *widget) {
161 widget_event(xuni, widget->compose->widget[WID_SCROLLBAR_SEEKBAR],
162 WIDGET_EVENT_PAINT);
164 /*set_widget_clip(widget->compose->widget[WID_SCROLLBAR_UP]
165 ->compose->widget[WID_BUTTON_LABEL],
166 widget->compose->widget[WID_SCROLLBAR_UP]->pos->real.x,
167 widget->compose->widget[WID_SCROLLBAR_UP]->pos->real.y,
168 0, 0,
169 widget->pos->real.w,
170 widget->pos->real.h);*/
172 widget_event(xuni, widget->compose->widget[WID_SCROLLBAR_UP],
173 WIDGET_EVENT_PAINT);
174 widget_event(xuni, widget->compose->widget[WID_SCROLLBAR_SEEK],
175 WIDGET_EVENT_PAINT);
177 /*set_widget_clip(widget->compose->widget[WID_SCROLLBAR_DOWN]
178 ->compose->widget[WID_BUTTON_LABEL],
179 widget->compose->widget[WID_SCROLLBAR_DOWN]->pos->real.x,
180 widget->compose->widget[WID_SCROLLBAR_DOWN]->pos->real.y,
181 0, 0,
182 widget->pos->real.w,
183 widget->pos->real.h);*/
185 /*printf("Painting WID_SCROLLBAR_DOWN at (%i,%i)\n",
186 widget->compose->widget[WID_SCROLLBAR_DOWN]->pos->real.x,
187 widget->compose->widget[WID_SCROLLBAR_DOWN]->pos->real.y);*/
189 widget_event(xuni, widget->compose->widget[WID_SCROLLBAR_DOWN],
190 WIDGET_EVENT_PAINT);
193 static void reposition_scrollbar(struct xuni_t *xuni,
194 struct widget_t *widget) {
196 struct widget_t *seek = widget->compose->widget[WID_SCROLLBAR_SEEK];
197 struct widget_t *seekbar = widget->compose->widget[WID_SCROLLBAR_SEEKBAR];
199 if(widget->p.scrollbar->orientation == SCROLLBAR_ORIENTATION_VERTICAL) {
200 add_widget_clip(xuni, seek,
201 0, (seekbar->pos->scale.h - seek->pos->scale.h)
202 * widget->p.scrollbar->pos / 100.0,
203 0, 0, 0, 0);
205 else {
206 add_widget_clip(xuni, seek,
207 (seekbar->pos->scale.w - seek->pos->scale.w)
208 * widget->p.scrollbar->pos / 100.0, 0,
209 0, 0, 0, 0);
213 static void rescale_scrollbar(struct xuni_t *xuni, struct widget_t *widget) {
214 /* what did this do?
216 struct widget_t *seek = widget->compose->widget[WID_SCROLLBAR_SEEK];
218 seek->pos->real.x += get_scrollbar_pos_int(widget);*/
221 static double calculate_seek_height(struct widget_t *widget,
222 struct xuni_t *xuni) {
224 double ratio;
226 ratio = (widget->pos->scale.w / 100.0 * xuni->smode->screen->w)
227 / (widget->pos->scale.h / 100.0 * xuni->smode->screen->h);
229 return (100.0 / 15.0) / (real_scale_height(widget));
232 /* !!! doesn't really need to be passed xuni */
233 void set_scrollbar_max(struct xuni_t *xuni, struct widget_t *widget,
234 int max) {
236 widget->p.scrollbar->max = max;
238 if(widget->p.scrollbar->max < 0) widget->p.scrollbar->max = 0;
240 /* in rescale_scrollbar(), this doesn't work the first time */
242 struct widget_t *seek, *seekbar;
243 double boxheight, minheight, value;
245 seek = widget->compose->widget[WID_SCROLLBAR_SEEK];
246 seekbar = widget->compose->widget[WID_SCROLLBAR_SEEKBAR];
248 if(max <= 0) {
249 seek->pos->scale.h = seekbar->pos->scale.h;
251 else {
252 value = 1.0 / (1.0 + max / (double)widget->pos->real.h);
254 /* boxheight not used */
255 boxheight = get_box_height(xuni, xuni->theme->current);
257 minheight = calculate_seek_height(widget, xuni);
258 /*if(value < boxheight) {
259 seek->pos->scale.h = boxheight;
261 seek->pos->scale.h = seekbar->pos->scale.h * value;
262 if(seek->pos->scale.h < minheight) {
263 seek->pos->scale.h = minheight;
264 /*printf("set to minimum\n");*/
267 /*printf("value=%f, minheight=%f, seek->pos->scale.h=%f\n",
268 value, minheight, seek->pos->scale.h);*/
271 widget_event(xuni, widget, WIDGET_EVENT_RESCALE);
274 /*printf("set_scrollbar_max(): max=%i pos=%f\n", max,
275 widget->p.scrollbar->pos);*/
277 /*restrict_int(&widget->p.scrollbar->pos, widget->p.scrollbar->max);*/
279 /*widget_event(xuni->smode, widget, WIDGET_EVENT_RESCALE);*/
282 /*! Scrolls the scrollbar \a widget by \a amount, where \a amount is the exact
283 pixel value to move the scrollbar by.
284 \param xuni The xuni_t structure.
285 \param widget The scrollbar widget that should be scrolled. An error will
286 ensue if this widget is not a scrollbar.
287 \param amount The number of pixels to scroll the scrollbar by.
289 void move_scrollbar(struct xuni_t *xuni, struct widget_t *widget,
290 int amount) {
292 /*struct widget_t *seek, *seekbar;*/
294 if(!widget) return;
296 if(assert_widget_type(xuni, widget, WIDGET_SCROLLBAR,
297 __FILE__, __LINE__)) {
299 return;
302 widget->p.scrollbar->pos
303 += (double)amount / widget->p.scrollbar->max * 100.0;
305 restrict_pos(&widget->p.scrollbar->pos);
307 /*seek = widget->compose->widget[WID_SCROLLBAR_SEEK];
308 seekbar = widget->compose->widget[WID_SCROLLBAR_SEEKBAR];*/
310 /*printf("====\n");
311 printf("seekbar height: %f\n"
312 "seek height: %f\n"
313 "range: %f\n",
314 seekbar->pos->scale.h,
315 seek->pos->scale.h,
316 (seekbar->pos->scale.h - seek->pos->scale.h));
317 printf("max: %i\n"
318 "pos: %i\n"
319 "percentage: %f\n",
320 widget->p.scrollbar->max,
321 widget->p.scrollbar->pos,
322 ((double)widget->p.scrollbar->max / widget->p.scrollbar->pos));*/
324 /*add_widget_clip(seek,
325 0, (seekbar->pos->scale.h - seek->pos->scale.h)
326 * ((double)widget->p.scrollbar->pos / widget->p.scrollbar->max),
327 0, 0, 0, 0);*/
329 /*widget_event(xuni->smode, widget, WIDGET_EVENT_RESCALE);*/
332 /*! Returns the position of the scrollbar \a widget as a percentage value.
333 Note that this value should stay the same between rescalings.
334 \param widget The scrollbar to return the position of.
335 \return The position that the scrollbar \a widget is scrolled to.
337 double get_scrollbar_pos(struct widget_t *widget) {
338 return widget->p.scrollbar->pos;
341 /*! Converts a scrollbar's position to an absolute pixel value. Note that
342 because scrollbar values are stored as percentages, this function still
343 works if it gets rescaled. The functions that use the value of this
344 function will have to call it again, but it will return the right values.
345 \param widget The scrollbar widget to examine.
346 \return How far the scrollbar is scrolled, as a pixel value.
348 int get_scrollbar_pos_int(struct widget_t *widget) {
349 return widget->p.scrollbar->pos / 100.0 * widget->p.scrollbar->max;