gKit2 light
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;
15  w.console= create_text();
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 {
26 }
27 
28 
29 void 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 
92 struct Rect
93 {
94  int x, y;
95  int w, h;
96 };
97 
98 static
99 bool 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 
104 static
105 Rect 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 
123 static
124 Rect place( Widgets& w, const char *text )
125 {
126  return place(w, (int) strlen(text));
127 }
128 
129 void begin_line( Widgets& w )
130 {
131  // place le prochain widget sur une nouvelle ligne
132  w.px= 0;
133  w.py= w.py +1;
134 }
135 
136 void end_line( Widgets& widgets )
137 {
138  return;
139 }
140 
141 
142 void 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 
155 bool 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 
173 bool 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 
191 bool 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 
232 bool 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 
273 void 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)
288  begin_line= begin_line - 1;
289  if(w.key == SDLK_DOWN)
290  begin_line= begin_line + 1;
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 
319 bool 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 
404 void end( Widgets& w )
405 {
406  return;
407 }
408 
409 void default_color( Widgets& w, const Color& color )
410 {
411  default_color(w.console, color);
412 }
413 
414 void 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:102
bool button(Widgets &w, const char *text, int &status)
Definition: widgets.cpp:155
void clear_button_event()
desactive l'evenement.
Definition: window.cpp:106
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:67
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:60
SDL_KeyboardEvent key_event()
renvoie le dernier evenement. touche speciales.
Definition: window.cpp:56
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:71
void clear_wheel_event()
desactive l'evenement.
Definition: window.cpp:116
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 print(Text &text, const int px, const int py, const char *message)
affiche un texte a la position x, y.
Definition: text.cpp:122
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:112
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
Point min(const Point &a, const Point &b)
renvoie la plus petite composante de chaque point. x, y, z= min(a.x, b.x), min(a.y,...
Definition: vec.cpp:30
representation d'une couleur (rgba) transparente ou opaque.
Definition: color.h:14
Definition: widgets.cpp:93
int wy
scroll
Definition: widgets.h:78
unsigned int mod
touches supplementaires, alt, ctrl, etc.
Definition: widgets.h:81
int fy
position du focus
Definition: widgets.h:74
Text console
affichage des elements de l'interface.
Definition: widgets.h:70
int mb
click
Definition: widgets.h:76
int my
position du click
Definition: widgets.h:77
int focus
focus
Definition: widgets.h:73
int py
placement du prochain widget
Definition: widgets.h:71
int key
touche
Definition: widgets.h:80