Add support for 'modeless' windows - windows that will allow events to be passed on to the underlying window. Intended for the editor

This commit is contained in:
Chris Taylor 2011-10-09 18:31:44 +08:00
parent 5f87108ba4
commit 3121fb4990
12 changed files with 53 additions and 23 deletions

View file

@ -3,6 +3,7 @@ D1X-Rebirth Changelog
20111009
--------
main/render.c: Initialise dyn_light using memset, fixing a warning
arch/include/event.h, arch/include/window.h, arch/sdl/event.c, arch/sdl/window.c, include/ui.h, ui/dialog.c, ui/file.c, ui/keypress.c, ui/menu.c, ui/message.c, ui/popup.c: Add support for 'modeless' windows - windows that will allow events to be passed on to the underlying window. Intended for the editor
20110927
--------

View file

@ -14,7 +14,7 @@ typedef enum event_type
EVENT_MOUSE_BUTTON_DOWN,
EVENT_MOUSE_BUTTON_UP,
EVENT_MOUSE_DOUBLE_CLICKED, // editor only for now
EVENT_MOUSE_DOUBLE_CLICKED,
EVENT_MOUSE_MOVED,
EVENT_KEY_COMMAND,
@ -47,7 +47,7 @@ void event_flush();
void set_default_handler(int (*handler)(d_event *event));
int call_default_handler(d_event *event);
// Send an event to the front window as first priority, then the default handler
// Send an event to the front window as first priority, then to the windows behind if it's not modal (editor), then the default handler
void event_send(d_event *event);
// Sends input, idle and draw events to event handlers

View file

@ -29,6 +29,8 @@ extern void window_set_visible(window *wind, int visible);
extern int window_is_visible(window *wind);
extern grs_canvas *window_get_canvas(window *wind);
extern int window_send_event(window *wind, d_event *event);
extern void window_set_modal(window *wind, int modal);
extern int window_is_modal(window *wind);
#define WINDOW_SEND_EVENT(w, e) \
do { \

View file

@ -124,13 +124,18 @@ int call_default_handler(d_event *event)
void event_send(d_event *event)
{
window *wind;
int handled = 0;
if ((wind = window_get_front()))
{
if (!window_send_event(wind, event))
call_default_handler(event);
}
else
for (wind = window_get_front(); wind != NULL && !handled; wind = window_get_prev(wind))
if (window_is_visible(wind))
{
handled = window_send_event(wind, event);
if (window_is_modal(wind))
break;
}
if (!handled)
call_default_handler(event);
}

View file

@ -18,6 +18,7 @@ struct window
grs_canvas w_canv; // the window's canvas to draw to
int (*w_callback)(window *wind, d_event *event, void *data); // the event handler
int w_visible; // whether it's visible
int w_modal; // modal = accept all user input exclusively
void *data; // whatever the user wants (eg menu data for 'newmenu' menus)
struct window *prev; // the previous window in the doubly linked list
struct window *next; // the next window in the doubly linked list
@ -41,6 +42,7 @@ window *window_create(grs_canvas *src, int x, int y, int w, int h, int (*event_c
gr_init_sub_canvas(&wind->w_canv, src, x, y, w, h);
wind->w_callback = event_callback;
wind->w_visible = 1; // default to visible
wind->w_modal = 1; // default to modal
wind->data = data;
if (FirstWindow == NULL)
@ -194,3 +196,13 @@ int window_send_event(window *wind, d_event *event)
{
return wind->w_callback(wind, event, wind->data);
}
void window_set_modal(window *wind, int modal)
{
wind->w_modal = modal;
}
int window_is_modal(window *wind)
{
return wind->w_modal;
}

View file

@ -186,12 +186,18 @@ typedef struct {
int moved;
} UI_GADGET_LISTBOX;
enum dialog_flags
{
DF_BORDER = 1,
DF_FILLED = 2,
DF_SAVE_BG = 4,
DF_DIALOG = (4+2+1),
DF_MODAL = 8 // modal = accept all user input exclusively
};
typedef struct _ui_window {
struct window *wind;
int (*callback)(struct _ui_window *, struct d_event *, void *);
short x, y;
short width, height;
short text_x, text_y;
grs_canvas * canvas;
grs_canvas * oldcanvas;
grs_bitmap * background;
@ -200,6 +206,10 @@ typedef struct _ui_window {
struct _ui_window * next;
struct _ui_window * prev;
void *userdata;
short x, y;
short width, height;
short text_x, text_y;
enum dialog_flags flags;
} UI_DIALOG;
typedef struct {
@ -270,12 +280,7 @@ extern int ui_mouse_motion_process(struct d_event *event);
extern void ui_mouse_hide();
extern void ui_mouse_show();
#define DF_BORDER 1
#define DF_FILLED 2
#define DF_SAVE_BG 4
#define DF_DIALOG (4+2+1)
extern UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int (*callback)(UI_DIALOG *, struct d_event *, void *), void *userdata );
extern UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, enum dialog_flags flags, int (*callback)(UI_DIALOG *, struct d_event *, void *), void *userdata );
extern void ui_close_dialog( UI_DIALOG * dlg );
extern UI_GADGET * ui_gadget_add( UI_DIALOG * dlg, short kind, short x1, short y1, short x2, short y2 );

View file

@ -257,7 +257,7 @@ int ui_dialog_handler(window *wind, d_event *event, UI_DIALOG *dlg)
return 0;
}
UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int (*callback)(UI_DIALOG *, d_event *, void *), void *userdata )
UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, enum dialog_flags flags, int (*callback)(UI_DIALOG *, d_event *, void *), void *userdata )
{
UI_DIALOG *dlg;
int sw, sh, req_w, req_h;
@ -277,6 +277,8 @@ UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int
req_w = w;
req_h = h;
dlg->flags = flags;
if (flags & DF_BORDER)
{
@ -332,6 +334,9 @@ UI_DIALOG * ui_create_dialog( short x, short y, short w, short h, int flags, int
return NULL;
}
if (!(flags & DF_MODAL))
window_set_modal(dlg->wind, 0); // make this window modeless, allowing events to propogate through the window stack
if (flags & DF_FILLED)
ui_draw_box_out( 0, 0, req_w-1, req_h-1 );

View file

@ -159,7 +159,7 @@ int ui_get_filename( char * filename, char * Filespec, char * message )
Spaces[i] = ' ';
Spaces[34] = 0;
dlg = ui_create_dialog( 200, 100, 400, 370, DF_DIALOG, NULL, NULL );
dlg = ui_create_dialog( 200, 100, 400, 370, DF_DIALOG | DF_MODAL, NULL, NULL );
ui_dprintf_at( dlg, 10, 5, message );

View file

@ -110,7 +110,7 @@ int GetKeyCode(char * text)
text = text;
dlg = ui_create_dialog( 200, 200, 400, 200, DF_DIALOG, NULL, NULL );
dlg = ui_create_dialog( 200, 200, 400, 200, DF_DIALOG | DF_MODAL, NULL, NULL );
DoneButton = ui_add_gadget_button( dlg, 170, 165, 60, 25, "Ok", NULL );

View file

@ -84,7 +84,7 @@ int MenuX( int x, int y, int NumButtons, char * text[] )
y = h - height;
}
dlg = ui_create_dialog( x, y, width, height, DF_FILLED | DF_SAVE_BG, NULL, NULL );
dlg = ui_create_dialog( x, y, width, height, DF_FILLED | DF_SAVE_BG | DF_MODAL, NULL, NULL );
x = MENU_BORDER+3;
y = MENU_BORDER+3;

View file

@ -116,7 +116,7 @@ int MessageBoxN( short xc, short yc, int NumButtons, char * text, char * Button[
y = h - height;
}
dlg = ui_create_dialog( x, y, width, height, DF_DIALOG, NULL, NULL );
dlg = ui_create_dialog( x, y, width, height, DF_DIALOG | DF_MODAL, NULL, NULL );
//ui_draw_line_in( MESSAGEBOX_BORDER, MESSAGEBOX_BORDER, width-MESSAGEBOX_BORDER, height-MESSAGEBOX_BORDER );

View file

@ -104,7 +104,7 @@ int PopupMenu( int NumButtons, char * text[] )
Mouse.y = y + (MENU_BORDER+3) + button_height/2;
}
dlg = ui_create_dialog( x, y, width, height, DF_DIALOG, NULL, NULL );
dlg = ui_create_dialog( x, y, width, height, DF_DIALOG | DF_MODAL, NULL, NULL );
//mouse_set_pos(Mouse.x, Mouse.y);