#include #include #include #include #define check_init(func,parms) \ if (func parms < 0) { \ fprintf(stderr, #func ": %s\n", allegro_error); \ return EXIT_FAILURE; \ } /* Cribbed from guiproc.c */ static void dotted_rect(int x1, int y1, int x2, int y2, int fg, int bg) { int x = ((x1+y1) & 1) ? 1 : 0; int c; /* two loops to avoid bank switches */ for (c=x1; c<=x2; c++) putpixel(screen, c, y1, (((c+y1) & 1) == x) ? fg : bg); for (c=x1; c<=x2; c++) putpixel(screen, c, y2, (((c+y2) & 1) == x) ? fg : bg); for (c=y1+1; cx = d->y = 0; d->w = SCREEN_W; d->h = SCREEN_H; return D_O_K; case MSG_CLICK: return D_WANTDRAG; default: return D_O_K; } } /* gui proc to prove a point */ int my_blinkenlight(int msg, DIALOG* d, int c) { if (msg == MSG_DRAW) { circlefill(screen, d->x, d->y, d->w - 1, d->d1 ? gui_mg_color : d->bg); circle(screen, d->x, d->y, d->w, d->fg); } return D_O_K; } /* gui proc to demonstrate dragging */ int my_drag_proc(int msg, DIALOG* d, int c) { int l = d->x, t = d->y, r = l + d->w - 1, b = t + d->h - 1; int cx = (l + r) / 2, cy = (t + b) / 2; switch (msg) { case MSG_DRAW: if (d->flags & D_DRAGGED) { rect(screen, l, t, r, b, d->fg); rect(screen, l + 1, t + 1, r - 1, b - 1, d->fg); rectfill(screen, l + 2, t + 2, r - 2, b - 2, d->bg); circlefill(screen, cx, cy, MIN(d->w, d->h) / 4, d->fg); circlefill(screen, cx, cy, MIN(d->w, d->h) / 4 - 3, d->bg); hline(screen, l + 3, cy, r - 3, d->fg); vline(screen, cx, t + 3, b - 3, d->fg); line(screen, l + 4, cy, l + 10, cy - 3, d->fg); line(screen, l + 4, cy, l + 10, cy + 3, d->fg); line(screen, r - 4, cy, r - 10, cy - 3, d->fg); line(screen, r - 4, cy, r - 10, cy + 3, d->fg); line(screen, cx, t + 4, cx - 3, t + 10, d->fg); line(screen, cx, t + 4, cx + 3, t + 10, d->fg); line(screen, cx, b - 4, cx - 3, b - 10, d->fg); line(screen, cx, b - 4, cx + 3, b - 10, d->fg); } else if (d->flags & D_GOTMOUSE) { rect(screen, l, t, r, b, d->fg); dotted_rect(l + 1, t + 1, r - 1, b - 1, d->fg, d->bg); rectfill(screen, l + 2, t + 2, r - 2, b - 2, d->bg); circlefill(screen, cx, cy, MIN(d->w, d->h) / 4, d->fg); circlefill(screen, cx, cy, MIN(d->w, d->h) / 4 - 2, d->bg); } else { rect(screen, l, t, r, b, d->fg); rectfill(screen, l + 1, t + 1, r - 1, b - 1, d->bg); circle(screen, cx, cy, MIN(d->w, d->h) / 4, d->fg); } return D_O_K; /* This means any mouse button has been pressed */ case MSG_CLICK: return D_REDRAWME | D_WANTDRAG; case MSG_LRELEASE: case MSG_MRELEASE: case MSG_RRELEASE: case MSG_GOTMOUSE: case MSG_LOSTMOUSE: return D_REDRAWME; case MSG_DRAG: d->x += (short)(c >> 16); d->y += (short)(c & 0xffff); return D_REDRAW; default: return D_O_K; } } /* my_button_proc: * A button object (the dp field points to the text string). This object * can be selected by clicking on it with the mouse or by pressing its * keyboard shortcut. If the D_EXIT flag is set, selecting it will close * the dialog, otherwise it will toggle on and off. */ /* This is my drag-enabled modification */ int my_button_proc(int msg, DIALOG *d, int c) { int black; int rtm; int l, t, r, b, cx, cy; int state1, state2; switch (msg) { case MSG_DRAW: if (d->flags & D_SELECTED) { l = d->x + 1; t = d->y + 1; state1 = d->bg; state2 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; } else { l = d->x; t = d->y; state1 = (d->flags & D_DISABLED) ? gui_mg_color : d->fg; state2 = d->bg; } r = l + d->w - 2; b = t + d->h - 2; cx = (l + r) / 2; cy = (t + b - text_height(font)) / 2 + 1; rectfill(screen, l + 1, t + 1, r - 1, b - 1, state2); rect(screen, l, t, r, b, state1); rtm = text_mode(-1); gui_textout(screen, d->dp, cx, cy, state1, TRUE); text_mode(rtm); if (d->flags & D_SELECTED) { hline(screen, l - 1, t - 1, r - 1, d->bg); vline(screen, l - 1, t - 1, b - 1, d->bg); } else { black = makecol(0,0,0); hline(screen, l + 1, b + 1, r + 1, black); vline(screen, r + 1, t + 1, b + 1, black); } if ((d->flags & D_GOTFOCUS) && (!(d->flags & D_SELECTED) || !(d->flags & D_EXIT))) dotted_rect(l + 1, t + 1, r - 1, b - 1, state1, state2); break; case MSG_WANTFOCUS: return D_WANTFOCUS; case MSG_KEY: /* close dialog? */ if (d->flags & D_EXIT) { return D_CLOSE; } /* or just toggle */ d->flags ^= D_SELECTED; return D_REDRAWME; case MSG_CLICK: /* what state was the button originally in? */ /* D_INTERNAL is used to remember the original state */ if (d->flags & D_EXIT) d->flags &= ~D_SELECTED; if (d->flags & D_SELECTED) d->flags |= D_INTERNAL; else d->flags &= ~D_INTERNAL; return D_WANTDRAG | D_REDRAWME; case MSG_DRAG: /* track the mouse until it is released */ state1 = d->flags & D_INTERNAL; state2 = ((gui_mouse_x() >= d->x) && (gui_mouse_y() >= d->y) && (gui_mouse_x() < d->x + d->w) && (gui_mouse_y() < d->y + d->h)); if (d->flags & D_SELECTED) state2 = !state2; /* redraw? */ if (((state1) && (!state2)) || ((state2) && (!state1))) { d->flags ^= D_SELECTED; scare_mouse(); object_message(d, MSG_DRAW, 0); unscare_mouse(); } break; case MSG_LRELEASE: case MSG_MRELEASE: case MSG_RRELEASE: /* should we close the dialog? */ if ((d->flags & D_SELECTED) && (d->flags & D_EXIT)) { d->flags ^= D_SELECTED; return D_CLOSE; } break; } return D_O_K; } /* A way of keeping the my_dialog definition more concise */ static char title[] = "Andy's Test Thing"; static char b1[] = "Old Button"; static char b2[] = "New Button"; static char b3[] = "E&xit"; static char r1[] = "Radio #1"; static char r2[] = "Radio #2"; static char r3[] = "Radio #3"; static char c1[] = "Check #1"; static char c2[] = "Check #2"; static char c3[] = "Check #3"; static char edit[81] = "Foo"; static DIALOG my_dialog[] = { /* dialog proc x y w h fgbgkey flags d1 d2 dp p2p3 */ {d_clear_proc, 0, 0, 0, 0,0,0, 0, 0, 0,0, 0,0,0}, {d_yield_proc, 0, 0, 0, 0,0,0, 0, 0, 0,0, 0,0,0}, {my_grab_proc, 0, 0, 0, 0,0,0, 0, 0, 0,0, 0,0,0}, {d_shadow_box_proc,100,100,440,200,0,0, 0, 0, 0,0, 0,0,0}, {d_ctext_proc, 320,108, 0, 0,0,0, 0, 0, 0,0,title,0,0}, {d_button_proc, 110,130,120, 24,0,0, 0, 0, 0,0, b1,0,0}, {my_button_proc, 240,130,120, 24,0,0, 0, 0, 0,0, b2,0,0}, {d_radio_proc, 110,160,120, 11,0,0, 0, 0, 1,0, r1,0,0}, {d_radio_proc, 110,185,120, 11,0,0, 0, 0, 1,0, r2,0,0}, {d_radio_proc, 110,210,120, 11,0,0, 0, 0, 1,0, r3,0,0}, {d_check_proc, 240,160,120, 11,0,0, 0, 0, 0,0, c1,0,0}, {d_check_proc, 240,185,120, 11,0,0, 0, 0, 0,0, c2,0,0}, {d_check_proc, 240,210,120, 11,0,0, 0, 0, 0,0, c3,0,0}, {d_edit_proc, 410,130,120, 10,0,0, 0, 0, 80,0, edit,0,0}, {d_slider_proc, 110,240,250, 20,0,0, 0, 0,100,0, 0,0,0}, {my_button_proc, 480,260, 50, 24,0,0,'x',D_EXIT, 0,0, b3,0,0}, {my_drag_proc, 430,150, 49, 49,0,0, 0, 0, 0,0, 0,0,0}, {my_blinkenlight, 110,110, 4, 4,0,0, 0, 0, 0,0, 0,0,0}, {NULL, 0, 0, 0, 0,0,0, 0, 0, 0,0, 0,0,0} }; int main(void) { DIALOG_PLAYER* p; DIALOG* w; BITMAP* buf; BITMAP* real_screen; /* Initialize Allegro */ check_init(install_allegro, (SYSTEM_AUTODETECT, &errno, atexit)); check_init(install_timer, ()); check_init(install_keyboard, ()); check_init(install_mouse, ()); set_color_depth(32); check_init(set_gfx_mode, (GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0)); set_uformat(U_ASCII); timer_simulate_retrace(1); buf = create_bitmap(SCREEN_W, SCREEN_H); show_mouse(buf); /* Select the first radio button */ for (w = &my_dialog[0]; w->proc != d_radio_proc; w++); w->flags |= D_SELECTED; /* Adjust the dialogue colors */ gui_bg_color = makecol(0xef, 0xef, 0xef); gui_mg_color = makecol(0x8f, 0x8f, 0x8f); gui_fg_color = makecol(0x5f, 0x5f, 0x5f); set_dialog_color(my_dialog, gui_fg_color, gui_bg_color); /* Start the gui */ real_screen = screen; screen = buf; p = init_dialog(my_dialog, -1); /* Locate the light */ for (w = &my_dialog[0]; w->proc != my_blinkenlight; w++); /* My do_dialog */ while (update_dialog(p)) { /* Animate the blinking light */ if (retrace_count >= 17) { w->d1 ^= (retrace_count / 17) & 1; scare_mouse(); object_message(w, MSG_DRAW, 0); unscare_mouse(); retrace_count = 0; } /* Update the screen from the double buffer */ blit(buf, real_screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H); } /* Done! */ show_mouse(NULL); screen = real_screen; destroy_bitmap(buf); return shutdown_dialog(p); } END_OF_MAIN();