gKit2 light
Loading...
Searching...
No Matches
widgets.cpp
1
2#include <cstdio>
3#include <cassert>
4#include <cstring>
5#include <vector>
6#include <algorithm>
7
8#include "window.h"
9#include "widgets.h"
10
11
13{
14 Widgets w;
16 w.px= 0; w.py= 0;
17 w.focus= 0; w.fx= 0; w.fy= 0;
18 w.mb= 0; w.mx= 0; w.my= 0;
19 w.wx= 0; w.wy= 0;
20 return w;
21}
22
24{
25 release_text(w.console);
26}
27
28
29void begin( Widgets& w )
30{
31 clear(w.console);
32 w.px= 0;
33 w.py= 0;
34
35 SDL_MouseButtonEvent mouse= button_event();
36 w.mb= 0;
37 w.mx= mouse.x / 8;
38 w.my= mouse.y / 16;
39 if(mouse.state == SDL_PRESSED)
40 {
42 w.mb= 1;
43 }
44
45 SDL_MouseWheelEvent wheel= wheel_event();
46 w.wx= 0;
47 w.wy= 0;
48 if(wheel.x != 0 || wheel.y != 0)
49 {
51 w.wx= wheel.x;
52 w.wy= wheel.y;
53 }
54
55 SDL_KeyboardEvent key= key_event( );
56 w.key= 0;
57 w.mod= 0;
58 if(key.type == SDL_KEYDOWN)
59 {
61 w.key= key.keysym.sym;
62 w.mod= key.keysym.mod;
63
64 // filtre les touches speciales
65 switch(w.key)
66 {
67 case SDLK_SPACE:
68 case SDLK_BACKSPACE:
69 case SDLK_DELETE:
70 case SDLK_UP:
71 case SDLK_DOWN:
72 case SDLK_PAGEUP:
73 case SDLK_PAGEDOWN:
74 case SDLK_LEFT:
75 case SDLK_RIGHT:
76 case SDLK_RETURN:
77 break;
78 default:
79 w.key= 0;
80 }
81 }
82
83 SDL_TextInputEvent input= text_event();
84 if(input.text[0] != 0)
85 {
86 w.key= input.text[0];
88 }
89}
90
91
92struct Rect
93{
94 int x, y;
95 int w, h;
96};
97
98static
99bool overlap( const Rect r, const int x, const int y )
100{
101 return (x >= r.x && x < r.x + r.w && y >= r.y && y < r.y + r.h);
102}
103
104static
105Rect place( Widgets& w, const int width, const int height= 1 )
106{
107 Rect r;
108 r.x= w.px;
109 r.y= w.py;
110 r.w= width;
111 r.h= height;
112
113 if(height == 1)
114 // place le prochain widget a droite
115 w.px= r.x + r.w +2; // +2 marge
116 else
117 // place le prochain widget sur la ligne suivante
118 w.py= w.py + height;
119
120 return r;
121}
122
123static
124Rect place( Widgets& w, const char *text )
125{
126 return place(w, (int) strlen(text));
127}
128
130{
131 // place le prochain widget sur une nouvelle ligne
132 w.px= 0;
133 w.py= w.py +1;
134}
135
136void end_line( Widgets& widgets )
137{
138 return;
139}
140
141
142void label( Widgets& w, const char *format, ... )
143{
144 char tmp[4096] = { 0 };
145
146 va_list args;
147 va_start(args, format);
148 vsnprintf(tmp, sizeof(tmp), format, args);
149 va_end(args);
150
151 Rect r= place(w, tmp);
152 print(w.console, r.x, r.y, tmp);
153}
154
155bool button( Widgets& w, const char *text, int& status )
156{
157 Rect r= place(w, (int) strlen(text) +2);
158
159 bool change= false;
160 if(w.mb > 0 && overlap(r, w.mx, w.my))
161 {
162 change= true;
163 status= (status + 1) % 2;
164 }
165
166 char tmp[128];
167 sprintf(tmp, "%c %s", (status != 0) ? 22 : 20, text); // strlen(text) + 2
168
169 print(w.console, r.x, r.y, tmp);
170 return change;
171}
172
173bool select( Widgets& w, const char *text, const int option, int& status )
174{
175 Rect r= place(w, (int) strlen(text) +2);
176
177 bool change= false;
178 if(w.mb > 0 && overlap(r, w.mx, w.my))
179 {
180 change= true;
181 status= option;
182 }
183
184 char tmp[128];
185 sprintf(tmp, "%c %s", (status == option) ? 4 : 3, text); // strlen(text) + 2
186
187 print(w.console, r.x, r.y, tmp);
188 return change;
189}
190
191bool value( Widgets& w, const char *label, int& value, const int value_min, const int value_max, const int value_step )
192{
193 char tmp[128];
194 sprintf(tmp, "%s: %4d", label, value);
195
196 Rect r= place(w, (int) strlen(tmp));
197
198 bool change= false;
199 if(w.mb > 0 && overlap(r, w.mx, w.my))
200 change= true;
201 if(overlap(r, w.mx, w.my))
202 {
203 if(w.wy != 0)
204 value= value + w.wy * value_step;
205 if(w.key == SDLK_UP)
206 value= value + value_step;
207 if(w.key == SDLK_PAGEUP)
208 value= value + value_step * 10;
209 if(w.key == SDLK_DOWN)
210 value= value - value_step;
211 if(w.key == SDLK_PAGEDOWN)
212 value= value - value_step * 10;
213
214 if(value < value_min)
215 value= value_min;
216 if(value > value_max)
217 value= value_max;
218
219 sprintf(tmp, "%s: ", label);
220 int l= (int) strlen(tmp);
221 print(w.console, r.x, r.y, tmp);
222
223 sprintf(tmp, "%4d", value);
224 print_background(w.console, r.x + l, r.y, tmp);
225 }
226 else
227 print(w.console, r.x, r.y, tmp);
228
229 return change;
230}
231
232bool value( Widgets& w, const char *label, float& value, const float value_min, const float value_max, const float value_step )
233{
234 char tmp[128];
235 sprintf(tmp, "%s: %.6f", label, value);
236
237 Rect r= place(w, (int) strlen(tmp));
238
239 bool change= false;
240 if(w.mb > 0 && overlap(r, w.mx, w.my))
241 change= true;
242 if(overlap(r, w.mx, w.my))
243 {
244 if(w.wy != 0)
245 value= value + w.wy * value_step;
246 if(w.key == SDLK_UP)
247 value= value + value_step;
248 if(w.key == SDLK_PAGEUP)
249 value= value + value_step * 10;
250 if(w.key == SDLK_DOWN)
251 value= value - value_step;
252 if(w.key == SDLK_PAGEDOWN)
253 value= value - value_step * 10;
254
255 if(value < value_min)
256 value= value_min;
257 if(value > value_max)
258 value= value_max;
259
260 sprintf(tmp, "%s: ", label);
261 int l= (int) strlen(tmp);
262 print(w.console, r.x, r.y, tmp);
263
264 sprintf(tmp, "%.6f", value);
265 print_background(w.console, r.x + l, r.y, tmp);
266 }
267 else
268 print(w.console, r.x, r.y, tmp);
269
270 return change;
271}
272
273void text_area( Widgets& w, const int height, const char *text, int& begin_line )
274{
275 Rect r= place(w, 128, height);
276
277 if(overlap(r, w.mx, w.my))
278 {
279 if(w.wy != 0)
280 begin_line= begin_line - w.wy;
281 if(w.key == SDLK_PAGEUP)
282 begin_line= begin_line - height;
283 if(w.key == SDLK_PAGEDOWN)
284 begin_line= begin_line + height;
285 if(w.key == SDLK_SPACE)
286 begin_line= begin_line + height / 2;
287 if(w.key == SDLK_UP)
289 if(w.key == SDLK_DOWN)
291 }
292
293 // compter les lignes
294 int n= 1;
295 for(int i= 0; text[i] != 0; i++)
296 if(text[i] == '\n')
297 n++;
298 // ligne de depart, pout que tout le texte reste affiche
299 if(begin_line + height > n)
300 begin_line= n - height;
301 if(begin_line < 1)
302 begin_line= 1;
303 // retrouve le debut de la ligne
304 int line= 1;
305 int offset= 0;
306 for(int i= 0; text[i] != 0; i++)
307 {
308 if(text[i] == '\n')
309 {
310 line++;
311 if(line == begin_line)
312 offset= i;
313 }
314 }
315 // affiche le texte
316 print(w.console, r.x, r.y, text + offset);
317}
318
319bool edit( Widgets& w, int text_size, char *text )
320{
321 assert(text_size > 1);
322 int size= std::min((int) strlen(text), text_size -2);
323 Rect r= place(w, text_size -1);
324
325 // focus
326 bool change= false;
327 if(w.mb > 0)
328 {
329 if(overlap(r, w.mx, w.my))
330 {
331 w.focus= 1;
332 w.fx= w.mx;
333 w.fy= w.my;
334
335 if(w.fx >= r.x + size)
336 w.fx= r.x + size;
337 }
338
339 else
340 change= (w.focus > 0); // click en dehors de la zone editable
341 }
342
343 // edition
344 bool focus= overlap(r, w.fx, w.fy);
345 if(focus && w.key > 0)
346 {
347 int c= w.fx - r.x;
348 assert(c < text_size -1);
349
350 if(w.key == SDLK_BACKSPACE)
351 {
352 w.fx--; // curseur a gauche
353 for(int i= c -1; i >= 0 && i+1 < text_size; i++) text[i]= text[i+1];
354 }
355 else if(w.key == SDLK_DELETE)
356 {
357 // curseur ne bouge pas
358 for(int i= c; i+1 < text_size; i++) text[i]= text[i+1];
359 }
360 else if(w.key == SDLK_LEFT)
361 {
362 w.fx--; // curseur a gauche
363 }
364 else if(w.key == SDLK_RIGHT)
365 {
366 w.fx++; // curseur a droite
367 }
368 else if(w.key == SDLK_RETURN)
369 {
370 w.focus= 0;
371 change= true;
372 }
373 else
374 {
375 w.fx++; // curseur a droite
376 for(int i= text_size -1; i > c; i--) text[i]= text[i -1];
377 text[c]= w.key;
378
379 if(size < text_size - 2)
380 size++;
381 text[size+1]= 0;
382 }
383
384 // verifier que le curseur reste dans la zone editable
385 if(w.fx < r.x)
386 w.fx= r.x;
387 if(w.fx >= r.x + size)
388 w.fx= r.x + size;
389 }
390
391 int i= 0;
392 char tmp[128];
393 for(; text[i] != 0; i++) tmp[i]= text[i]; // copie les caracteres
394 for(; i < text_size; i++) tmp[i]= ' '; // complete avec des espaces
395 tmp[text_size -1]= 0; // termine avec un 0
396
397 print_background(w.console, r.x, r.y, tmp);
398 if(focus)
399 print_background(w.console, w.fx, w.fy, text[w.fx - r.x], 1);
400
401 return change;
402}
403
404void end( Widgets& w )
405{
406 return;
407}
408
409void default_color( Widgets& w, const Color& color )
410{
411 default_color(w.console, color);
412}
413
414void draw( Widgets& w, const int width, const int height )
415{
416 draw(w.console, width, height);
417}
418
419
void begin(Widgets &w)
debut de la description des elements de l'interface graphique.
Definition widgets.cpp:29
void clear(Text &text)
efface le contenu de la console.
Definition text.cpp:72
Widgets create_widgets()
cree une interface graphique. a detruire avec release_widgets( ).
Definition widgets.cpp:12
void release_widgets(Widgets &w)
detruit l'interface graphique.
Definition widgets.cpp:23
SDL_MouseButtonEvent button_event()
renvoie le dernier evenement. etat des boutons de la souris.
Definition window.cpp:100
bool button(Widgets &w, const char *text, int &status)
Definition widgets.cpp:155
void clear_button_event()
desactive l'evenement.
Definition window.cpp:104
void label(Widgets &w, const char *format,...)
cree un texte. meme fonctionnement que printf().
Definition widgets.cpp:142
SDL_TextInputEvent text_event()
renvoie le dernier evenement. saisie de texte.
Definition window.cpp:65
bool value(Widgets &w, const char *label, int &value, const int value_min, const int value_max, const int value_step)
valeur editable par increment.
Definition widgets.cpp:191
void clear_key_event()
desactive l'evenement.
Definition window.cpp:58
SDL_KeyboardEvent key_event()
renvoie le dernier evenement. touche speciales.
Definition window.cpp:54
void end_line(Widgets &widgets)
termine la description des elements de la ligne.
Definition widgets.cpp:136
bool select(Widgets &w, const char *text, const int option, int &status)
Definition widgets.cpp:173
bool edit(Widgets &w, int text_size, char *text)
Definition widgets.cpp:319
void clear_text_event()
desactive l'evenement.
Definition window.cpp:69
void clear_wheel_event()
desactive l'evenement.
Definition window.cpp:114
void end(Widgets &w)
termine la description des elements de l'interface graphique.
Definition widgets.cpp:404
Text create_text()
cree une console. a detruire avec release_text( ).
Definition text.cpp:14
void draw(Widgets &w, const int width, const int height)
affiche les elements decrits entre begin() et end().
Definition widgets.cpp:414
void text_area(Widgets &w, const int height, const char *text, int &begin_line)
Definition widgets.cpp:273
void begin_line(Widgets &w)
place les prochains elements sur une nouvelle ligne.
Definition widgets.cpp:129
void release_text(Text &text)
detruit une console.
Definition text.cpp:64
SDL_MouseWheelEvent wheel_event()
renvoie le dernier evenement. etat de la molette de la souris / glisser sur le pad.
Definition window.cpp:110
void print_background(Text &text, const int px, const int py, const int background, const char c)
affiche un caractere c sur un fond background.
Definition text.cpp:106
void default_color(Widgets &w, const Color &color)
choisit une couleur par defaut pour le texte.
Definition widgets.cpp:409
representation d'une couleur (rgba) transparente ou opaque.
Definition color.h:14
Text console
affichage des elements de l'interface.
Definition widgets.h:70