1 /* guiprocs.c - Kraptor
2 Esto contiene dialogos tipo 3-D para el GUI de Kraptor
3 Fueron tomados de Allegro Dialog Editor
4 y modificados para su uso en Kraptor
5 Ademas, se modifico ciertos graficos, y se agregaron slider,
6 y otros controles 'chetos' (ver el .h)
8 This has the dialogs for the GUI of Kraptor.
9 They where originally made by Julien Cugniere,
10 This source code is altered by Kronoman for the use in Kraptor.
14 * Allegro DIALOG Editor
17 * guiprocs.c : Some thin, 3d-looking GUI procs
19 * Unless otherwise specified, d->bg is ignored.
22 #include <allegro/internal/aintern.h>
24 #define SET_DIALOG(d, _p, _x, _y, _w, _h, _fg, _bg, _k, _f, _d1, _d2, _dp, _dp2, _dp3) {\
25 d.proc = _p; d.x = _x; d.y = _y; d.w = _w; d.h = _h; d.fg = _fg; d.bg = _bg; \
26 d.key = _k; d.flags = _f; d.d1 = _d1; d.d2 = _d2; d.dp = _dp; d.dp2 = _dp2; \
31 /* additionnal colors of the 3d GUI */
39 /* default color set for the GUI
40 Modificado por Kronoman para que ademas, inicie totalmente
41 el GUI de Allegro para funcionar como este GUI
43 void xset_gui_colors(void)
45 gui_text_color
= makecol(0, 0, 0);
46 gui_back_color
= makecol(208, 208, 208);
47 gui_white_color
= makecol(245, 245, 245);
48 gui_light_color
= makecol(223, 223, 223);
49 gui_dark_color
= makecol(187, 187, 187);
50 gui_black_color
= makecol(156, 156, 156);
52 gui_fg_color
= makecol(0, 0, 0);
53 gui_mg_color
= makecol(187, 187, 187);
54 gui_bg_color
= makecol(208, 208, 208);
56 gui_font_baseline
= 0;
58 gui_shadow_box_proc
= xbox_proc
;
59 gui_ctext_proc
= xctext_proc
;
60 gui_button_proc
= xbutton_proc
;
61 gui_edit_proc
= xedit_proc
;
62 gui_list_proc
= xlist_proc
;
63 gui_text_list_proc
= xtext_list_proc
;
64 gui_menu_draw_menu
= xdraw_menu
;
65 gui_menu_draw_menu_item
= xdraw_menu_item
;
70 /***************************************************************************/
71 /********************************* Helpers *********************************/
72 /***************************************************************************/
77 void gui_rect(BITMAP
*bmp
, int x
, int y
, int w
, int h
, int flags
)
84 c3
= (flags
& F_LIGHT
) ? gui_white_color
: gui_light_color
;
90 c2
= (flags
& F_LIGHT
) ? gui_white_color
: gui_light_color
;
95 putpixel(bmp
, x
, y
, c1
);
96 putpixel(bmp
, x
+w
-1, y
, gui_back_color
);
97 putpixel(bmp
, x
, y
+h
-1, gui_back_color
);
98 putpixel(bmp
, x
+w
-1, y
+h
-1, c4
);
99 hline(bmp
, x
+1, y
, x
+w
-2, c2
);
100 vline(bmp
, x
, y
+1, y
+h
-2, c2
);
101 hline(bmp
, x
+1, y
+h
-1, x
+w
-2, c3
);
102 vline(bmp
, x
+w
-1, y
+1, y
+h
-2, c3
);
107 /* directly ripped from Allegro. Maybe this function should be made
108 * available in aintern.h ?
110 void dotted_rect(BITMAP
*bmp
, int x1
, int y1
, int x2
, int y2
, int fg
, int bg
)
112 int x
= ((x1
+y1
) & 1) ? 1 : 0;
115 for (i
=x1
; i
<=x2
; i
++)
117 putpixel(bmp
, i
, y1
, (((i
+y1
) & 1) == x
) ? fg
: bg
);
118 putpixel(bmp
, i
, y2
, (((i
+y2
) & 1) == x
) ? fg
: bg
);
121 for (i
=y1
+1; i
<y2
; i
++)
123 putpixel(bmp
, x1
, i
, (((i
+x1
) & 1) == x
) ? fg
: bg
);
124 putpixel(bmp
, x2
, i
, (((i
+x2
) & 1) == x
) ? fg
: bg
);
130 /* 3d-looking menus */
131 void xdraw_menu(int x
, int y
, int w
, int h
)
133 gui_rect(screen
, x
, y
, w
, h
, 0);
138 /* 3d-looking menu item (ripped from AGUP)
140 void xdraw_menu_item(MENU
*m
, int x
, int y
, int w
, int h
, int bar
, int sel
)
146 if(m
->flags
& D_DISABLED
)
154 bg
= (sel
) ? gui_light_color
: gui_back_color
;
157 rectfill(screen
, x
, y
, x
+w
-1, y
+h
-1, bg
);
165 while((j
) && (j
!= '\t'))
167 i
+= usetc(buf
+i
, j
);
168 j
= ugetc(m
->text
+i
);
172 gui_textout(screen
, buf
, x
+8, y
+1, fg
, FALSE
);
176 tok
= m
->text
+i
+ uwidth(m
->text
+i
);
177 gui_textout(screen
, tok
, x
+w
-gui_strlen(tok
)-10, y
+1, fg
, FALSE
);
180 if((m
->child
) && (!bar
))
182 vline(screen
, x
+w
-11, y
+1, y
+text_height(font
), (sel
) ? gui_white_color
: gui_light_color
);
183 line(screen
, x
+w
-10, y
+1, x
+w
-3, y
+(text_height(font
)/2), (sel
) ? gui_white_color
: gui_light_color
);
184 line(screen
, x
+w
-10, y
+text_height(font
), x
+w
-3, y
+(text_height(font
)/2)+1, gui_dark_color
);
189 hline(screen
, x
, y
+text_height(font
)/2+1, x
+w
-1, gui_dark_color
);
190 hline(screen
, x
, y
+text_height(font
)/2+2, x
+w
-1, gui_light_color
);
191 putpixel(screen
, x
-1, y
+text_height(font
)/2+1, gui_back_color
);
192 putpixel(screen
, x
-1, y
+text_height(font
)/2+2, gui_white_color
);
193 putpixel(screen
, x
+w
, y
+text_height(font
)/2+1, gui_black_color
);
194 putpixel(screen
, x
+w
, y
+text_height(font
)/2+2, gui_back_color
);
197 if(m
->flags
& D_SELECTED
)
199 line(screen
, x
+1, y
+text_height(font
)/2+1, x
+3, y
+text_height(font
)+1, fg
);
200 line(screen
, x
+3, y
+text_height(font
)+1, x
+6, y
+2, fg
);
206 /* draws a 3d-looking scrollable frame */
207 static void xdraw_scrollable_frame(DIALOG
*d
, int listsize
, int offset
, int height
, int fg_color
)
212 /* possibly draw scrollbar */
213 if(listsize
> height
)
215 int focus
= (d
->flags
& D_GOTFOCUS
);
218 i
= ((d
->h
-4) * offset
+ listsize
/2) / listsize
;
219 len
= ((d
->h
-4) * height
+ listsize
/2) / listsize
;
221 gui_rect(screen
, d
->x
, d
->y
, d
->w
-12, d
->h
, F_IN
);
222 gui_rect(screen
, xx
, yy
, 12, d
->h
, F_IN
);
223 rect(screen
, xx
+1, yy
+1, xx
+12-2, yy
+d
->h
-2, gui_white_color
);
225 dotted_rect(screen
, d
->x
+1, d
->y
+1, d
->x
+d
->w
-12-2, d
->y
+d
->h
-2,
226 gui_white_color
, (focus
) ? gui_back_color
: gui_white_color
);
229 rectfill(screen
, xx
+2, yy
+2, xx
+2+8, yy
+2+i
-1, gui_white_color
);
231 gui_rect(screen
, xx
+2, yy
+2+i
, 8, len
, (focus
) ? F_LIGHT
: 0);
232 rectfill(screen
, (xx
+2)+1, (yy
+2+i
)+1, (xx
+2+8-1)-1, (yy
+2+i
+len
-1)-1,
233 (focus
) ? gui_light_color
: gui_back_color
);
236 rectfill(screen
, xx
+2, yy
+2+i
+len
, xx
+2+8, yy
+d
->h
-3, gui_white_color
);
240 gui_rect(screen
, d
->x
, d
->y
, d
->w
, d
->h
, F_IN
);
242 dotted_rect(screen
, d
->x
+1, d
->y
+1, d
->x
+d
->w
-2, d
->y
+d
->h
-2,
243 gui_white_color
, (d
->flags
& D_GOTFOCUS
) ? gui_back_color
: gui_white_color
);
249 /* draws a 3d-looking list (ripped from AGUP) */
250 static void xdraw_list(DIALOG
*d
)
252 typedef char *(*getfuncptr
)(int, int*);
253 int height
, listsize
, i
, len
, bar
, x
, y
, w
;
258 (*(getfuncptr
)d
->dp
)(-1, &listsize
);
259 height
= (d
->h
-4) / text_height(font
);
260 bar
= (listsize
> height
);
261 w
= (bar
? d
->w
-15 : d
->w
-3);
262 fg
= (d
->flags
& D_DISABLED
) ? gui_dark_color
: gui_text_color
;
264 /* draw box contents */
265 for(i
=0; i
<height
; i
++)
267 if(d
->d2
+i
< listsize
)
269 if((sel
) && (sel
[d
->d2
+i
]))
270 bg
= gui_light_color
;
272 bg
= gui_white_color
;
274 ustrncat(s
, (*(getfuncptr
)d
->dp
)(i
+d
->d2
, NULL
), sizeof(s
)-ucwidth(0));
276 y
= d
->y
+ 2 + i
*text_height(font
);
278 rectfill(screen
, x
, y
, x
+7, y
+text_height(font
)-1, bg
);
281 while (text_length(font
, s
) >= MAX(d
->w
- 1 - (bar
? 22 : 10), 1))
286 textout(screen
, font
, s
, x
, y
, fg
);
287 x
+= text_length(font
, s
);
289 rectfill(screen
, x
, y
, d
->x
+w
, y
+text_height(font
)-1, bg
);
292 rectfill(screen
, d
->x
+2, d
->y
+2+i
*text_height(font
),
293 d
->x
+w
, d
->y
+1+(i
+1)*text_height(font
), gui_white_color
);
296 if(d
->y
+2+i
*text_height(font
) <= d
->y
+d
->h
-3)
297 rectfill(screen
, d
->x
+2, d
->y
+2+i
*text_height(font
),
298 d
->x
+w
, d
->y
+d
->h
-3, gui_white_color
);
300 /* draw frame, maybe with scrollbar */
301 xdraw_scrollable_frame(d
, listsize
, d
->d2
, height
, 0);
303 /* draw the focus item */
304 if(d
->d1
< d
->d2
+height
&& d
->d1
>= d
->d2
)
306 y
= d
->y
+ 2 + (d
->d1
-d
->d2
)*text_height(font
);
308 dotted_rect(screen
, d
->x
+2, y
-1, d
->x
+w
, y
+text_height(font
),
309 gui_dark_color
, gui_white_color
);
316 simple text proc, aligns the text depending on d->d1:
318 * 1 - centered on d->x
319 * 2 - centered on the middle of the object
322 static void xdraw_text(BITMAP
*bmp
, DIALOG
*d
, int align
)
324 FONT
*oldfont
= font
;
326 int fg
= (d
->flags
& D_DISABLED
) ? gui_dark_color
: d
->fg
;
331 case 1: x
= d
->x
; center
= TRUE
; break;
332 case 2: x
= d
->x
+ d
->w
/2; center
= TRUE
; break;
333 case 3: x
= d
->x
+d
->w
-gui_strlen(d
->dp
); center
= FALSE
; break;
334 default: x
= d
->x
; center
= FALSE
; break;
338 rtm
= text_mode(gui_back_color
);
339 gui_textout(screen
, d
->dp
, x
, d
->y
, fg
, center
);
346 /***************************************************************************/
347 /************************* 3d-looking GUI objects **************************/
348 /***************************************************************************/
352 /* simple text proc, aligns the text depending on d->d1 (see xdraw_text)*/
353 int xtext_proc(int msg
, DIALOG
*d
, int c
)
356 xdraw_text(screen
, d
, d
->d1
);
362 /* replacement for allegro's d_ctext_proc */
363 int xctext_proc(int msg
, DIALOG
*d
, int c
)
366 xdraw_text(screen
, d
, 1);
372 /* replacement for allegro's d_rtext_proc */
373 int xrtext_proc(int msg
, DIALOG
*d
, int c
)
376 xdraw_text(screen
, d
, 3);
382 /* 3d-looking list proc */
383 int xlist_proc(int msg
, DIALOG
*d
, int c
)
390 return d_list_proc(msg
, d
, c
);
395 /* 3d-looking text list proc */
396 int xtext_list_proc(int msg
, DIALOG
*d
, int c
)
403 return d_text_list_proc(msg
, d
, c
);
408 /* 3d-looking textbox proc (ripped from AGUP) */
409 int xtextbox_proc(int msg
, DIALOG
*d
, int c
)
414 int fg_color
= (d
->flags
& D_DISABLED
) ? gui_dark_color
: gui_text_color
;
415 height
= (d
->h
-8) / text_height(font
);
417 /* tell the object to sort of draw, but only calculate the listsize */
418 _draw_textbox(d
->dp
, &d
->d1
,
419 0, /* DONT DRAW anything */
420 d
->d2
, !(d
->flags
& D_SELECTED
), 8,
421 d
->x
, d
->y
, d
->w
, d
->h
,
422 (d
->flags
& D_DISABLED
),
430 /* now do the actual drawing */
431 _draw_textbox(d
->dp
, &d
->d1
, 1, d
->d2
,
432 !(d
->flags
& D_SELECTED
), 8,
433 d
->x
, d
->y
, d
->w
-bar
, d
->h
,
434 (d
->flags
& D_DISABLED
),
435 fg_color
, gui_white_color
, gui_dark_color
);
437 /* draw the frame around */
438 xdraw_scrollable_frame(d
, d
->d1
, d
->d2
, height
, 0);
442 return d_textbox_proc(msg
, d
, c
);
447 /* a 3d-looking box proc. set d1 to 1 to draw it inward */
448 int xbox_proc(int msg
, DIALOG
*d
, int c
)
452 gui_rect(screen
, d
->x
, d
->y
, d
->w
, d
->h
, d
->d1
);
453 rectfill(screen
, d
->x
+1, d
->y
+1, d
->x
+d
->w
-2, d
->y
+d
->h
-2, gui_back_color
);
460 /* a 3d-box displaying the color in d->bg */
461 int xcolorbox_proc(int msg
, DIALOG
*d
, int c
)
465 gui_rect(screen
, d
->x
, d
->y
, d
->w
, d
->h
, F_IN
);
466 rectfill(screen
, d
->x
+1, d
->y
+1, d
->x
+d
->w
-2, d
->y
+d
->h
-2, d
->bg
);
473 /* a 3d-looking check proc. d1 ignored
475 int xcheck_proc(int msg
, DIALOG
*d
, int c
)
480 int dis
= d
->flags
& D_DISABLED
;
481 int fg
= (dis
) ? gui_dark_color
: gui_text_color
;
482 int bg
= (dis
) ? gui_light_color
: gui_white_color
;
483 // int sg = (dis) ? gui_black_color : gui_back_color;
484 gui_rect(screen
, d
->x
, d
->y
, d
->h
, d
->h
, F_IN
);
485 rectfill(screen
, d
->x
+1, d
->y
+1, d
->x
+d
->h
-2, d
->y
+d
->h
-2, bg
);
487 if(d
->flags
& D_SELECTED
)
489 /* modificado por kronoman para hacer un 'look' mas lindo al check box */
491 rectfill(screen
, d
->x
+3, d
->y
+3, d
->x
+ d
->h
- 4, d
->y
+ d
->h
- 4, (d
->flags
& D_GOTFOCUS
) ? gui_light_color
: gui_back_color
);
492 gui_rect(screen
, d
->x
+2, d
->y
+2, d
->h
-4, d
->h
-4, (d
->flags
& D_GOTFOCUS
) ? F_LIGHT
: 0 );
495 // line(screen, d->x+3, d->y+3, d->x+d->h-4, d->y+d->h-4, gui_light_color);
496 // line(screen, d->x+3, d->y+d->h-4, d->x+d->h-4, d->y+3, gui_light_color);
500 // if(d->flags & D_GOTFOCUS)
501 // dotted_rect(screen, d->x+1, d->y+1, d->x+d->h-2, d->y+d->h-2, sg, bg);
503 text_mode(gui_back_color
);
504 gui_textout(screen
, d
->dp
, d
->x
+d
->h
-1+text_height(font
)/2, d
->y
+(d
->h
-(text_height(font
)-gui_font_baseline
))/2, fg
, FALSE
);
508 return d_check_proc(msg
, d
, c
);
514 * a modified button proc that call a function instead of closing the dialog
515 * dp2 should contain the function: int func()
517 int xbutton_proc(int msg
, DIALOG
*d
, int c
)
520 typedef int (*func_ptr
)(void);
524 int p
= (d
->flags
& D_SELECTED
) ? 1 : 0;
525 int style
= ((p
) ? F_IN
: 0) | ((d
->flags
& D_GOTFOCUS
) ? F_LIGHT
: 0);
526 gui_rect(screen
, d
->x
, d
->y
, d
->w
, d
->h
, style
);
527 rectfill(screen
, d
->x
+1, d
->y
+1, d
->x
+d
->w
-2, d
->y
+d
->h
-2, (d
->flags
& D_GOTFOCUS
) ? gui_light_color
: gui_back_color
);
530 gui_textout(screen
, d
->dp
, d
->x
+p
+ d
->w
/2, d
->y
+p
+ (d
->h
-text_height(font
))/2, (d
->flags
& D_DISABLED
) ? gui_dark_color
: gui_text_color
, 1);
535 ret
= d_button_proc(msg
, d
, c
);
537 if(ret
== D_CLOSE
&& d
->dp2
)
538 ret
= ((func_ptr
)d
->dp2
)() | D_REDRAWME
;
546 * a tricky little mix of a proc, that behave like a d_edit_proc object, but
547 * can have a button at its right that calls a function. The function is in
548 * dp2 in the form int func(DIALOG*), and is passed the dialog calling it.
549 * Its return value is passed back to the dialog manager. PageDown simulates
550 * a click on the button.
552 int xedit_proc(int msg
, DIALOG
*d
, int c
)
555 typedef int (*func_ptr
)(DIALOG
*);
556 int n
= d
->h
-text_height(font
);
559 SET_DIALOG(edit
, d_edit_proc
, d
->x
+n
/2, d
->y
+n
/2, d
->w
-n
, d
->h
-n
, d
->fg
, gui_white_color
, 0, d
->flags
, d
->d1
, d
->d2
, d
->dp
, NULL
, NULL
);
560 SET_DIALOG(button
, xbutton_proc
, 0, d
->y
+1, d
->h
-2, d
->h
-2, d
->fg
, gui_back_color
, 0, d
->flags
|D_EXIT
, 0, 0, "...", NULL
, NULL
);
564 button
.x
= d
->x
+ d
->w
- button
.w
- 1;
567 _default_font seems to have dissappeared in Allegro 4.2
568 According to the original author, function xedit_proc is not used anywhere in the code, so commenting out
569 these lines won't hurt.
570 Miriam Ruiz <little_miry@yahoo.es>, January 2006
574 if(font == &_default_font)
582 /* hack to make this proc look better when used in file_select() */
583 if(d
->h
< text_height(font
)+4)
585 d
->y
-= (text_height(font
)+4 - d
->h
)/2;
586 d
->h
= text_height(font
)+4;
591 if(d
->dp2
&& mouse_x
>= button
.x
)
593 ret
= button
.proc(msg
, &button
, c
);
595 ret
= ((func_ptr
)d
->dp2
)(d
) | D_REDRAWME
;
598 ret
= edit
.proc(msg
, &edit
, c
);
604 gui_rect(screen
, d
->x
, d
->y
, d
->w
, d
->h
, F_IN
);
605 rectfill(screen
, d
->x
+1, d
->y
+1, (d
->dp2
) ? (button
.x
-1) : (d
->x
+d
->w
-2), d
->y
+d
->h
-2, gui_white_color
);
606 ret
= edit
.proc(msg
, &edit
, c
);
608 ret
|= button
.proc(msg
, &button
, c
);
613 if(d
->dp2
&& (c
>>8) == KEY_PGDN
)
614 ret
= ((func_ptr
)d
->dp2
)(d
) | D_REDRAWME
;
619 ret
|= edit
.proc(msg
, &edit
, c
);
631 * displays the current palette, and holds the index of the selected color
632 * in d1. w and h are ignored: the object is sized 130x130. Supports D_EXIT,
633 * allowing to return D_CLOSE on double clicks.
635 int xpalette_proc(int msg
, DIALOG
* d
, int c
)
637 int x
, y
, ret
= D_O_K
;
650 rectfill(screen
, d
->x
+1 + x
*8, d
->y
+1 + y
*8, d
->x
+8 + x
*8, d
->y
+8 + y
*8, palette_color
[x
+16*y
]);
654 x
= d
->x
+1 + 8*(d
->d1
%16);
655 y
= d
->y
+1 + 8*(d
->d1
/16);
656 rect(screen
, x
, y
, x
+8, y
+8, gui_back_color
);
657 rect(screen
, x
-1, y
-1, x
+7, y
+7, gui_text_color
);
659 gui_rect(screen
, d
->x
, d
->y
, d
->w
, d
->h
, F_IN
);
669 x
= (mouse_x
- (d
->x
+1))/8;
670 y
= (mouse_y
- (d
->y
+1))/8;
673 if(c
< 256 && c
!= d
->d1
)
676 return D_REDRAWME
| D_WANTFOCUS
;
687 /* Slider cool, tipo X11, por Kronoman,
688 basado en el slider original, pero mas bonito :^) */
689 int xslider_proc(int msg
, DIALOG
* d
, int c
)
691 int vert
= TRUE
; /* flag: is slider vertical? */
692 int slx
, sly
, slh
, slw
;
693 int hh
= 20; /* handle height (width for horizontal sliders) */
694 int slp
; /* slider position */
696 fixed slratio
, slmax
, slpos
;
701 irange
= (vert
) ? d
->h
: d
->w
;
702 slmax
= itofix(irange
-hh
);
703 slratio
= slmax
/ (d
->d1
);
704 slpos
= slratio
* d
->d2
;
711 rectfill(screen
, d
->x
, d
->y
, d
->x
+d
->w
-2, d
->y
+d
->h
-2,gui_white_color
);
713 gui_rect(screen
, d
->x
, d
->y
, d
->w
- 1, d
->h
-1, F_IN
);
719 sly
= d
->y
+(d
->h
)-(hh
+slp
);
722 } else { /* horizontal */
730 slx
+( slw
-2), sly
+slh
-1,
731 (d
->flags
& D_GOTFOCUS
) ? gui_light_color
: gui_back_color
);
736 (d
->flags
& D_GOTFOCUS
) ? F_LIGHT
: 0 );
740 return d_slider_proc(msg
, d
, c
);
746 * Muestra el bitmap en dp ajustado a w y h
748 int xbitmap_proc(int msg
, DIALOG
*d
, int c
)
750 BITMAP
*b
= (BITMAP
*)d
->dp
;
752 if (msg
==MSG_DRAW
&& d
->dp
!= NULL
)
753 stretch_blit(b
, screen
,
755 d
->x
, d
->y
, d
->w
, d
->h
);