[AD] excustom

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


The attached patch updates excustom to also include a menu, since
animating the clock while a menu is active is what really will cause
problems to users of the Allegro GUI.

Ideally, we would revisit that "dialog is shut down while menu is
active" thing and implement proper clipping of siblings for all dialogs.
As we in the meantime know the rectangle taken by each dialog, it should
be possible. But then, updating the GUI is nothing which can be done
right now.

I'll also try to add an extra example showing the use of gui_screen,
since I guess that really needs an example. Maybe named "exguidb", and
it would display a simple GUI on a double buffer.

-- 
Elias Pschernig
Index: examples/excustom.c
===================================================================
RCS file: /cvsroot/alleg/allegro/examples/excustom.c,v
retrieving revision 1.13
diff -u -p -r1.13 excustom.c
--- examples/excustom.c	13 Feb 2005 21:01:29 -0000	1.13
+++ examples/excustom.c	21 Aug 2005 17:09:57 -0000
@@ -1,16 +1,18 @@
 /*
  *    Example program for the Allegro library, by Shawn Hargreaves.
  *
- *    A follow up of the exgui.c example showing how to customise the
- *    default Allegro framework. In this case a dialog procedure
- *    animates a graphical clock without disrupting other GUI
- *    dialogs.  A more simple option shows how to dynamically change
- *    the font used by all GUI elements.
+ *    A follow up of the exgui.c example showing how to customise the default
+ *    Allegro framework, for example, how to use a custom font. It also shows a
+ *    dialog procedure which animates a graphical clock without disrupting other
+ *    GUI dialogs. This is especially tricky with Allegro's menus, since the
+ *    active dialog gets shut down as long as the menu is handled. The only way
+ *    around it, as is demonstrated here, is to forcefully update the dialog
+ *    yourself.
  */
 
 
 #include <time.h>
-
+#include <stdio.h>
 #include <allegro.h>
 #include "example.h"
 
@@ -50,9 +52,9 @@ int change_font_proc(int msg, DIALOG *d,
    /* trap the close return value and change the font */
    if (ret == D_CLOSE) {
       if (font == original_font)
-	 font = datafile[BIG_FONT].dat;
+         font = datafile[BIG_FONT].dat;
       else
-	 font = original_font;
+         font = original_font;
 
       return D_REDRAW; 
    }
@@ -71,7 +73,7 @@ void draw_hand(BITMAP *bmp, int value, i
    int w, h;
 
    angle = ((itofix(value) * 256) / range) + 
-	   ((itofix(v2) * 256) / (range * range2)) - itofix(64);
+           ((itofix(v2) * 256) / (range * range2)) - itofix(64);
 
    x = fixmul(fixcos(angle), length);
    y = fixmul(fixsin(angle), length);
@@ -96,83 +98,72 @@ int clock_proc(int msg, DIALOG *d, int c
 
       /* initialise when we get a start message */
       case MSG_START:
-	 /* store the current time */
-	 current_time = time(NULL);
-	 t = localtime(&current_time);
-	 the_time = *t;
-
-	 /* draw the clock background onto a memory bitmap */
-	 temp = create_bitmap(d->w, d->h);
-	 clear_to_color(temp, d->bg);
-
-	 /* draw borders and a nobble in the middle */
-	 circle(temp, temp->w/2, temp->h/2, temp->w/2-1, d->fg);
-	 circlefill(temp, temp->w/2, temp->h/2, 2, d->fg);
-
-	 /* draw ticks around the edge */
-	 for (angle=0; angle<itofix(256); angle+=itofix(256)/12) {
-	    x = fixcos(angle);
-	    y = fixsin(angle);
-	    line(temp, temp->w/2+fixtoi(x*temp->w*15/32), 
-		       temp->h/2+fixtoi(y*temp->w*15/32), 
-		       temp->w/2+fixtoi(x*temp->w/2), 
-		       temp->h/2+fixtoi(y*temp->w/2), d->fg);
-	 }
-
-	 /* store the clock background bitmap in d->dp */
-	 d->dp = temp;
-	 break;
+         /* store the current time */
+         current_time = time(NULL);
+         t = localtime(&current_time);
+         the_time = *t;
+
+         /* draw the clock background onto a memory bitmap */
+         temp = create_bitmap(d->w, d->h);
+         clear_to_color(temp, d->bg);
+
+         /* draw borders and a nobble in the middle */
+         circle(temp, temp->w/2, temp->h/2, temp->w/2-1, d->fg);
+         circlefill(temp, temp->w/2, temp->h/2, 2, d->fg);
+
+         /* draw ticks around the edge */
+         for (angle=0; angle<itofix(256); angle+=itofix(256)/12) {
+            x = fixcos(angle);
+            y = fixsin(angle);
+            line(temp, temp->w/2+fixtoi(x*temp->w*15/32), 
+                       temp->h/2+fixtoi(y*temp->w*15/32), 
+                       temp->w/2+fixtoi(x*temp->w/2), 
+                       temp->h/2+fixtoi(y*temp->w/2), d->fg);
+         }
+
+         /* store the clock background bitmap in d->dp */
+         d->dp = temp;
+         break;
 
       /* shutdown when we get an end message */
       case MSG_END:
-	 /* destroy the clock background bitmap */
-	 destroy_bitmap(d->dp);
-	 break;
+         /* destroy the clock background bitmap */
+         destroy_bitmap(d->dp);
+         break;
 
       /* update the clock in response to idle messages */
       case MSG_IDLE:
-	 /* read the current time */
-	 current_time = time(NULL);
-	 t = localtime(&current_time);
-
-	 /* check if it has changed */
-	 if ((the_time.tm_sec != t->tm_sec) ||
-	     (the_time.tm_min != t->tm_min) ||
-	     (the_time.tm_hour != t->tm_hour)) {
-	    the_time = *t;
-
-	    /* Redraw ourselves if the time has changed. Note that the dialog
-	     * manager automatically turns off the mouse pointer whenever a
-	     * MSG_DRAW message is sent to an individual object or an entire
-	     * dialog, so we don't have to do it explicitly. Also note the use
-	     * of the object_message function rather than a simple recursive
-	     * call to clock_proc(). This vectors the call through the function
-	     * pointer in the dialog object, which allows other object
-	     * procedures to hook it, for example a different type of clock
-	     * could process the draw messages itself but pass idle messages
-	     * on to this procedure.
-	     */
-	    object_message(d, MSG_DRAW, 0);
-	 }
-	 break;
+         /* read the current time */
+         current_time = time(NULL);
+         t = localtime(&current_time);
+
+         /* check if it has changed */
+         if ((the_time.tm_sec != t->tm_sec) ||
+             (the_time.tm_min != t->tm_min) ||
+             (the_time.tm_hour != t->tm_hour)) {
+            the_time = *t;
+            /* forcefully redraw, in case the menu is active */
+            clock_proc(MSG_DRAW, d, 0);
+         }
+         break;
 
       /* draw the clock in response to draw messages */
       case MSG_DRAW:
-	 /* draw onto a temporary memory bitmap to prevent flicker */
-	 temp = create_bitmap(d->w, d->h);
+         /* draw onto a temporary memory bitmap to prevent flicker */
+         temp = create_bitmap(d->w, d->h);
 
-	 /* copy the clock background onto the temporary bitmap */
-	 blit(d->dp, temp, 0, 0, 0, 0, d->w, d->h);
+         /* copy the clock background onto the temporary bitmap */
+         blit(d->dp, temp, 0, 0, 0, 0, d->w, d->h);
 
-	 /* draw the hands */
-	 draw_hand(temp, the_time.tm_sec, 60, 0, 1, itofix(9)/10, d->fg);
-	 draw_hand(temp, the_time.tm_min, 60, the_time.tm_sec, 60, itofix(5)/6, d->fg);
-	 draw_hand(temp, the_time.tm_hour, 12, the_time.tm_min, 60, itofix(1)/2, d->fg);
-
-	 /* copy the temporary bitmap onto the screen */
-	 blit(temp, screen, 0, 0, d->x, d->y, d->w, d->h);
-	 destroy_bitmap(temp);
-	 break; 
+         /* draw the hands */
+         draw_hand(temp, the_time.tm_sec, 60, 0, 1, itofix(9)/10, d->fg);
+         draw_hand(temp, the_time.tm_min, 60, the_time.tm_sec, 60, itofix(5)/6, d->fg);
+         draw_hand(temp, the_time.tm_hour, 12, the_time.tm_min, 60, itofix(1)/2, d->fg);
+
+         /* copy the temporary bitmap onto the screen */
+         blit(temp, screen, 0, 0, d->x, d->y, d->w, d->h);
+         destroy_bitmap(temp);
+         break; 
    }
 
    /* always return OK status, since the clock doesn't ever need to close 
@@ -183,15 +174,35 @@ int clock_proc(int msg, DIALOG *d, int c
 
 
 
+MENU sub_menu[] =
+{
+   { "Test &1",   NULL,  NULL,      0,  NULL  },
+   { "Test &2",   NULL,  NULL,      0,  NULL  },
+   { NULL,        NULL,  NULL,      0,  NULL  }
+};
+
+
+
+MENU the_menu[] =
+{
+   { "Test &1",   NULL, sub_menu,  0,  NULL  },
+   { "Test &2",   NULL, sub_menu,  0,  NULL  },
+   { NULL,        NULL, NULL,      0,  NULL  }
+};
+
+
+
 DIALOG the_dialog[] =
 {
    /* (dialog proc)     (x)   (y)   (w)   (h)   (fg)  (bg)  (key) (flags)  (d1) (d2)  (dp)           (dp2) (dp3) */
    { d_clear_proc,      0,    0,    0,    0,    255,  0,    0,    0,       0,   0,    NULL,          NULL, NULL  },
-   { d_edit_proc,       12,   82,   256,  48,   255,  0,    0,    0,       LEN, 0,    the_string,    NULL, NULL  },
-   { d_check_proc,      12,   12,   161,  49,   255,  0,    't',  0,       0,   0,    "&Toggle Me",  NULL, NULL  },
-   { clock_proc,        242,  12,   64,   64,   255,  0,    0,    0,       0,   0,    NULL,          NULL, NULL  },
-   { change_font_proc,  12,   142,  141,  49,   255,  0,    'f',  D_EXIT,  0,   0, "Change &Font",   NULL, NULL  },
-   { d_button_proc,     162,  142,  141,  49,   255,  0,    0,    D_EXIT,  0,   0,    "Exit",        NULL, NULL  },
+   { d_menu_proc,       10,   10,   300,  50,   255,  0,    0,    0,       0,   0,    the_menu,      NULL, NULL  },
+   { d_edit_proc,       10,   70,   300,  50,   255,  0,    0,    0,       LEN, 0,    the_string,    NULL, NULL  },
+   { d_check_proc,      10,   140,  300,  50,   255,  0,    't',  0,       0,   0,    "&Toggle Me",  NULL, NULL  },
+   { clock_proc,        430,  10,   200,  200,  255,  0,    0,    0,       0,   0,    NULL,          NULL, NULL  },
+   { change_font_proc,  10,   420,  300,  50,   255,  0,    'f',  D_EXIT,  0,   0, "Change &Font",   NULL, NULL  },
+   { d_button_proc,     330,  420,  300,  50,   255,  0,    0,    D_EXIT,  0,   0,    "Exit",        NULL, NULL  },
+   { d_yield_proc,      0,    0,    0,    0,    0,    0,    0,    0,       0,   0,    NULL,          NULL, NULL  },
    { NULL,              0,    0,    0,    0,    0,    0,    0,    0,       0,   0,    NULL,          NULL, NULL  }
 };
 
@@ -201,6 +212,7 @@ int main(int argc, char *argv[])
 {
    int item;
    char buf[256];
+   DIALOG_PLAYER *player;
 
    if (allegro_init() != 0)
       return 1;
@@ -208,11 +220,11 @@ int main(int argc, char *argv[])
    install_mouse();
    install_timer();
 
-   if (set_gfx_mode(GFX_AUTODETECT, 320, 200, 0, 0) != 0) {
-      if (set_gfx_mode(GFX_SAFE, 320, 200, 0, 0) != 0) {
-	 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
-	 allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
-	 return 1;
+   if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) != 0) {
+      if (set_gfx_mode(GFX_SAFE, 640, 480, 0, 0) != 0) {
+         set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
+         allegro_message("Unable to set any graphic mode\n%s\n", allegro_error);
+         return 1;
       }
    }
 
@@ -223,7 +235,7 @@ int main(int argc, char *argv[])
       the_dialog[item].fg = makecol(0, 0, 0);
       the_dialog[item].bg = makecol(255, 255, 255);
    }
-   
+
    /* load the datafile */
    replace_filename(buf, argv[0], "example.dat", sizeof(buf));
    datafile = load_datafile(buf);
@@ -236,8 +248,20 @@ int main(int argc, char *argv[])
    /* store a copy of the default font */
    original_font = font;
 
-   do_dialog(the_dialog, -1);
-   
+   font = datafile[BIG_FONT].dat;
+
+   show_mouse(screen);
+   player = init_dialog(the_dialog, -1);
+   while (update_dialog(player)) {
+      DIALOG *d;
+      for (d = the_dialog; d->proc; d++) {
+         /* These two can safely be called even while the menu is active. */
+         if (d->proc == d_yield_proc || d->proc == clock_proc)
+            object_message(d, MSG_IDLE, 0);
+      }
+   }
+   shutdown_dialog(player);
+
    unload_datafile (datafile);
 
    return 0;


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/