Release s3d 0.2.2
[s3d.git] / libs3dw / scrollbar.c
blob02834be18628a45e6d0ad1d693ed244b7500eeba
1 /*
2 * scrollbar.c
4 * Copyright (C) 2006-2011 Simon Wunderlich <dotslash@packetmixer.de>
6 * This file is part of the s3d Widgets, a Widget Library for s3d.
7 * See http://s3d.berlios.de/ for more updates.
9 * s3d Widgets is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * s3d Widgets is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the s3d Widgets; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <s3d.h>
26 #include <s3dw.h>
27 #include <s3dw_int.h>
28 #include <stdlib.h> /* malloc() */
29 #include <string.h> /* strdup() */
31 static void s3dw_scrollbar_draw(s3dw_widget *widget)
33 s3dw_scrollbar *scrollbar = (s3dw_scrollbar *)widget;
34 float back_vertices[3*32];
35 int i, j;
36 unsigned int back_polygons[44*4] = {
37 /* box outside */
38 0, 4, 5, 0, 0, 5, 1, 0,
39 1, 5, 6, 0, 1, 6, 2, 0,
40 3, 2, 7, 0, 7, 2, 6, 0,
41 3, 7, 4, 0, 3, 4, 0, 0,
43 /* sides of big box */
44 12, 13, 9, 0, 12, 9, 8, 0,
45 14, 15, 11, 0, 14, 11, 10, 0,
47 /* inlay box */
48 9, 16, 17, 0, 9, 17, 10, 0,
49 17, 18, 14, 0, 17, 14, 10, 0,
50 13, 14, 18, 0, 13, 18, 19, 0,
51 13, 19, 16, 0, 13, 16, 9, 0,
53 /* inlay box back */
54 19, 18, 17, 0, 19, 17, 16, 0,
56 /* up arrow background surface */
57 7, 6, 15, 0,
58 7, 15, 14, 0,
59 7, 14, 13, 0,
60 7, 13, 12, 0,
62 /* up arrow face */
63 20, 23, 24, 0, 20, 24, 21, 0,
64 21, 24, 25, 0, 21, 25, 22, 0,
65 20, 22, 25, 0, 20, 25, 23, 0,
66 23, 25, 24, 0,
68 /* down arrow background surface */
69 4, 8, 9, 0,
70 4, 9, 10, 0,
71 4, 10, 11, 0,
72 4, 11, 5, 0,
74 /* down arrow face */
75 26, 27, 31, 0, 26, 31, 30, 0,
76 31, 27, 28, 0, 31, 28, 29, 0,
77 26, 30, 29, 0, 26, 29, 28, 0,
78 30, 31, 29, 0
81 unsigned int bar_polygons[14*4] = {
82 /* front */
83 0, 4, 5, 0, 0, 5, 1, 0,
84 1, 5, 6, 0, 1, 6, 2, 0,
85 3, 2, 6, 0, 3, 6, 7, 0,
86 3, 7, 4, 0, 3, 4, 0, 0,
88 7, 6, 4, 0, 4, 6, 5, 0,
90 /* back, only visible sides */
91 2, 3, 11, 0, 2, 11, 10, 0,
92 1, 9, 8, 0, 1, 8, 0, 0
94 float bar_vertices[12*3];
95 float w, h;
96 float temp;
99 w = (scrollbar->type == S3DW_SBAR_VERT) ? widget->width : widget->height;
100 h = (scrollbar->type == S3DW_SBAR_VERT) ? widget->height : widget->width;
101 /* outside/big box */
102 back_vertices[0*3+0] = w * 0.0;
103 back_vertices[0*3+1] = 0.0 - h;
104 back_vertices[0*3+2] = 0.0;
105 back_vertices[1*3+0] = w * 1.0;
106 back_vertices[1*3+1] = 0.0 - h;
107 back_vertices[1*3+2] = 0.0;
108 back_vertices[2*3+0] = w * 1.0;
109 back_vertices[2*3+1] = 0.0;
110 back_vertices[2*3+2] = 0.0;
111 back_vertices[3*3+0] = w * 0.0;
112 back_vertices[3*3+1] = 0.0;
113 back_vertices[3*3+2] = 0.0;
114 back_vertices[4*3+0] = w * 0.125;
115 back_vertices[4*3+1] = w * 0.125 - h;
116 back_vertices[4*3+2] = 0.25;
117 back_vertices[5*3+0] = w * 0.875;
118 back_vertices[5*3+1] = w * 0.125 - h;
119 back_vertices[5*3+2] = 0.25;
120 back_vertices[6*3+0] = w * 0.875;
121 back_vertices[6*3+1] = w * -0.125;
122 back_vertices[6*3+2] = 0.25;
123 back_vertices[7*3+0] = w * 0.125;
124 back_vertices[7*3+1] = w * -0.125;
125 back_vertices[7*3+2] = 0.25;
127 /* downside inlay */
128 back_vertices[8*3+0] = w * 0.125;
129 back_vertices[8*3+1] = w - h;
130 back_vertices[8*3+2] = 0.25;
131 back_vertices[9*3+0] = w * 0.25;
132 back_vertices[9*3+1] = w - h;
133 back_vertices[9*3+2] = 0.25;
134 back_vertices[10*3+0] = w * 0.75;
135 back_vertices[10*3+1] = w - h;
136 back_vertices[10*3+2] = 0.25;
137 back_vertices[11*3+0] = w * 0.875;
138 back_vertices[11*3+1] = w - h;
139 back_vertices[11*3+2] = 0.25;
141 /* upside inlay */
142 back_vertices[12*3+0] = w * 0.125;
143 back_vertices[12*3+1] = -w;
144 back_vertices[12*3+2] = 0.25;
145 back_vertices[13*3+0] = w * 0.25;
146 back_vertices[13*3+1] = -w;
147 back_vertices[13*3+2] = 0.25;
148 back_vertices[14*3+0] = w * 0.75;
149 back_vertices[14*3+1] = -w;
150 back_vertices[14*3+2] = 0.25;
151 back_vertices[15*3+0] = w * 0.875;
152 back_vertices[15*3+1] = -w;
153 back_vertices[15*3+2] = 0.25;
155 /* inlay box */
156 back_vertices[16*3+0] = w * 0.25;
157 back_vertices[16*3+1] = w * 0.125 - h + w;
158 back_vertices[16*3+2] = 0.125;
159 back_vertices[17*3+0] = w * 0.75;
160 back_vertices[17*3+1] = w * 0.125 - h + w;
161 back_vertices[17*3+2] = 0.125;
162 back_vertices[18*3+0] = w * 0.75;
163 back_vertices[18*3+1] = w * -0.125 - w;
164 back_vertices[18*3+2] = 0.125;
165 back_vertices[19*3+0] = w * 0.25;
166 back_vertices[19*3+1] = w * -0.125 - w;
167 back_vertices[19*3+2] = 0.125;
169 /* arrow up */
170 back_vertices[20*3+0] = w * 0.25;
171 back_vertices[20*3+1] = w * -0.875;
172 back_vertices[20*3+2] = 0.25;
173 back_vertices[21*3+0] = w * 0.75;
174 back_vertices[21*3+1] = w * -0.875;
175 back_vertices[21*3+2] = 0.25;
176 back_vertices[22*3+0] = w * 0.5;
177 back_vertices[22*3+1] = w * -0.25;
178 back_vertices[22*3+2] = 0.25;
179 back_vertices[23*3+0] = w * 0.375;
180 back_vertices[23*3+1] = w * -0.75;
181 back_vertices[23*3+2] = 0.375;
182 back_vertices[24*3+0] = w * 0.625;
183 back_vertices[24*3+1] = w * -0.75;
184 back_vertices[24*3+2] = 0.375;
185 back_vertices[25*3+0] = w * 0.5;
186 back_vertices[25*3+1] = w * -0.375;
187 back_vertices[25*3+2] = 0.375;
189 /* arrow down */
190 back_vertices[26*3+0] = w * 0.25;
191 back_vertices[26*3+1] = -h + w * 0.875;
192 back_vertices[26*3+2] = 0.25;
193 back_vertices[27*3+0] = w * 0.75;
194 back_vertices[27*3+1] = -h + w * 0.875;
195 back_vertices[27*3+2] = 0.25;
196 back_vertices[28*3+0] = w * 0.5;
197 back_vertices[28*3+1] = -h + w * 0.25;
198 back_vertices[28*3+2] = 0.25;
199 back_vertices[29*3+0] = w * 0.375;
200 back_vertices[29*3+1] = -h + w * 0.75;
201 back_vertices[29*3+2] = 0.375;
202 back_vertices[30*3+0] = w * 0.625;
203 back_vertices[30*3+1] = -h + w * 0.75;
204 back_vertices[30*3+2] = 0.375;
205 back_vertices[31*3+0] = w * 0.5;
206 back_vertices[31*3+1] = -h + w * 0.375;
207 back_vertices[31*3+2] = 0.375;
209 /* scrollbar bar poinst */
210 bar_vertices[0*3+0] = w * 0.25;
211 bar_vertices[0*3+1] = -(h - 3) + w * 0.125;
212 bar_vertices[0*3+2] = 0.25;
213 bar_vertices[1*3+0] = w * 0.75;
214 bar_vertices[1*3+1] = -(h - 3) + w * 0.125;
215 bar_vertices[1*3+2] = 0.25;
216 bar_vertices[2*3+0] = w * 0.75;
217 bar_vertices[2*3+1] = -w * 0.125;
218 bar_vertices[2*3+2] = 0.25;
219 bar_vertices[3*3+0] = w * 0.25;
220 bar_vertices[3*3+1] = -w * 0.125;
221 bar_vertices[3*3+2] = 0.25;
223 bar_vertices[4*3+0] = w * 0.125;
224 bar_vertices[4*3+1] = -(h - 3) + w * 0.25;
225 bar_vertices[4*3+2] = 0.375;
226 bar_vertices[5*3+0] = w * 0.875;
227 bar_vertices[5*3+1] = -(h - 3) + w * 0.25;
228 bar_vertices[5*3+2] = 0.375;
229 bar_vertices[6*3+0] = w * 0.875;
230 bar_vertices[6*3+1] = -w * 0.25;
231 bar_vertices[6*3+2] = 0.375;
232 bar_vertices[7*3+0] = w * 0.125;
233 bar_vertices[7*3+1] = -w * 0.25;
234 bar_vertices[7*3+2] = 0.375;
236 bar_vertices[8*3+0] = w * 0.125;
237 bar_vertices[8*3+1] = -(h - 3) + w * 0.25;
238 bar_vertices[8*3+2] = 0.175;
239 bar_vertices[9*3+0] = w * 0.875;
240 bar_vertices[9*3+1] = -(h - 3) + w * 0.25;
241 bar_vertices[9*3+2] = 0.175;
242 bar_vertices[10*3+0] = w * 0.875;
243 bar_vertices[10*3+1] = -w * 0.25;
244 bar_vertices[10*3+2] = 0.175;
245 bar_vertices[11*3+0] = w * 0.125;
246 bar_vertices[11*3+1] = -w * 0.25;
247 bar_vertices[11*3+2] = 0.175;
252 if (scrollbar->type == S3DW_SBAR_HORI) { /* rotate x and y for horizontal scrollbar */
253 for (i = 0; i < 32; i++) {
254 temp = back_vertices[i*3];
255 back_vertices[i*3] = -back_vertices[i*3+1];
256 back_vertices[i*3+1] = -temp;
258 for (i = 0; i < 44; i++) { /* change clockwiseness */
259 j = back_polygons[i*4];
260 back_polygons[i*4] = back_polygons[i*4+1];
261 back_polygons[i*4+1] = j;
263 for (i = 0; i < 12; i++) {
264 temp = bar_vertices[i*3];
265 bar_vertices[i*3] = -bar_vertices[i*3+1];
266 bar_vertices[i*3+1] = -temp;
268 for (i = 0; i < 14; i++) { /* change clockwiseness */
269 j = bar_polygons[i*4];
270 bar_polygons[i*4] = bar_polygons[i*4+1];
271 bar_polygons[i*4+1] = j;
275 widget->oid = s3d_new_object();
276 scrollbar->loid = s3d_new_object();
277 scrollbar->roid = s3d_new_object();
278 scrollbar->baroid = s3d_new_object();
279 s3d_push_materials_a(widget->oid, widget->style->input_mat, 1);
280 s3d_push_materials_a(scrollbar->loid, widget->style->input_mat, 1);
281 s3d_push_materials_a(scrollbar->roid, widget->style->input_mat, 1);
282 s3d_push_materials_a(scrollbar->baroid, widget->style->input_mat, 1);
283 s3d_push_vertices(widget->oid, back_vertices, 20);
284 s3d_push_vertices(scrollbar->loid, back_vertices, 32);
285 s3d_push_vertices(scrollbar->roid, back_vertices, 32);
286 s3d_push_vertices(scrollbar->baroid, bar_vertices, 12);
288 s3d_push_polygons(widget->oid, back_polygons , 22);
289 s3d_push_polygons(scrollbar->loid, back_polygons + 4*22, 11);
290 s3d_push_polygons(scrollbar->roid, back_polygons + 4*33, 11);
291 s3d_push_polygons(scrollbar->baroid, bar_polygons , 14);
292 s3d_link(widget->oid, widget->parent->oid);
293 s3d_link(scrollbar->loid, widget->oid);
294 s3d_link(scrollbar->roid, widget->oid);
295 s3d_link(scrollbar->baroid, widget->oid);
296 s3d_translate(widget->oid, widget->x, -widget->y, 0);
297 if (scrollbar->type == S3DW_SBAR_VERT)
298 s3d_translate(scrollbar->baroid, 0, -1.5, 0);
299 else
300 s3d_translate(scrollbar->baroid, 1.5, 0, 0);
303 /* show the scrollbar */
304 void s3dw_scrollbar_show(s3dw_widget *widget)
306 s3dw_scrollbar *scrollbar = (s3dw_scrollbar *)widget;
307 s3d_flags_on(widget->oid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
308 s3d_flags_on(scrollbar->loid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
309 s3d_flags_on(scrollbar->roid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
310 s3d_flags_on(scrollbar->baroid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
313 /* hides the scrollbar */
314 void s3dw_scrollbar_hide(s3dw_widget *widget)
316 s3dw_scrollbar *scrollbar = (s3dw_scrollbar *)widget;
317 s3d_flags_off(widget->oid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
318 s3d_flags_off(scrollbar->loid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
319 s3d_flags_off(scrollbar->roid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
320 s3d_flags_off(scrollbar->baroid, S3D_OF_VISIBLE | S3D_OF_SELECTABLE);
323 /* create a new scrollbar in the surface */
324 s3dw_scrollbar *s3dw_scrollbar_new(s3dw_widget *parent, int type, float posx, float posy, float length)
326 s3dw_scrollbar *scrollbar;
327 s3dw_widget *widget;
328 scrollbar = (s3dw_scrollbar *)malloc(sizeof(s3dw_scrollbar));
329 widget = s3dw_widget_new((s3dw_widget *)scrollbar);
330 widget->type = S3DW_TSCROLLBAR;
331 if ((scrollbar->type = type) == S3DW_SBAR_HORI) {
332 widget->height = 1;
333 widget->width = length;
334 } else {
335 widget->width = 1;
336 widget->height = length;
338 widget->x = posx;
339 widget->y = posy;
340 widget->oid = -1;
341 scrollbar->loid = -1;
342 scrollbar->roid = -1;
343 scrollbar->baroid = -1;
344 scrollbar->lonclick = s3dw_nothing;
345 scrollbar->ronclick = s3dw_nothing;
346 s3dw_widget_append(parent, widget);
347 s3dw_scrollbar_draw(widget);
348 return scrollbar;
351 void s3dw_scrollbar_erase(s3dw_widget *widget)
353 s3dw_scrollbar *scrollbar = (s3dw_scrollbar *)widget;
354 s3d_del_object(widget->oid);
355 s3d_del_object(scrollbar->loid);
356 s3d_del_object(scrollbar->roid);
357 s3d_del_object(scrollbar->baroid);
359 /* destroy the scrollbar */
360 void s3dw_scrollbar_destroy(s3dw_widget *widget)
362 s3dw_scrollbar *scrollbar = (s3dw_scrollbar *)widget;
363 s3dw_scrollbar_erase(widget);
364 free(scrollbar);
366 /* handle key events */
367 int s3dw_scrollbar_event_key(s3dw_widget *S3DUNUSED(widget), struct s3d_key_event *S3DUNUSED(keys))
369 return 0;
371 /* handle click events */
372 int s3dw_scrollbar_event_click(s3dw_widget *widget, uint32_t oid)
374 s3dw_scrollbar *scrollbar = (s3dw_scrollbar *)widget;
375 if (scrollbar->loid == (int)oid) {
376 scrollbar->lonclick(widget);
377 return 1;
379 if (scrollbar->roid == (int)oid) {
380 scrollbar->ronclick(widget);
381 return 1;
384 return 0;