2014-06-01 17:55:23 +00:00
|
|
|
/*
|
|
|
|
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
|
|
|
* It is copyright by its individual contributors, as recorded in the
|
|
|
|
* project's Git history. See COPYING.txt at the top level for license
|
|
|
|
* terms and a link to the Git history.
|
|
|
|
*/
|
2009-05-21 12:16:39 +00:00
|
|
|
/*
|
|
|
|
* A 'window' is simply a canvas that can receive events.
|
|
|
|
* It can be anything from a simple message box to the
|
|
|
|
* game screen when playing.
|
|
|
|
*
|
|
|
|
* See event.c for event handling code.
|
|
|
|
*
|
|
|
|
* -kreator 2009-05-06
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "gr.h"
|
|
|
|
#include "window.h"
|
2009-05-22 10:53:14 +00:00
|
|
|
#include "u_mem.h"
|
2012-07-07 18:35:06 +00:00
|
|
|
#include "dxxerror.h"
|
2009-05-21 12:16:39 +00:00
|
|
|
|
|
|
|
struct window
|
|
|
|
{
|
|
|
|
grs_canvas w_canv; // the window's canvas to draw to
|
2014-10-04 21:47:13 +00:00
|
|
|
window_event_result (*w_callback)(window *wind,const d_event &event, void *data); // the event handler
|
2009-05-21 12:16:39 +00:00
|
|
|
int w_visible; // whether it's visible
|
2011-10-09 10:31:44 +00:00
|
|
|
int w_modal; // modal = accept all user input exclusively
|
2009-05-21 12:16:39 +00:00
|
|
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
static window *FrontWindow = NULL;
|
|
|
|
static window *FirstWindow = NULL;
|
|
|
|
|
2014-12-20 04:36:09 +00:00
|
|
|
window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfunction_t<void>::type event_callback, void *data, const void *createdata)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2010-02-02 03:38:29 +00:00
|
|
|
window *prev = window_get_front();
|
2014-12-20 04:36:09 +00:00
|
|
|
d_create_event event;
|
2014-09-17 02:45:23 +00:00
|
|
|
window *wind = new window;
|
2009-05-21 12:16:39 +00:00
|
|
|
Assert(src != NULL);
|
|
|
|
Assert(event_callback != NULL);
|
2015-01-17 18:31:40 +00:00
|
|
|
gr_init_sub_canvas(wind->w_canv, *src, x, y, w, h);
|
2009-05-21 12:16:39 +00:00
|
|
|
wind->w_callback = event_callback;
|
|
|
|
wind->w_visible = 1; // default to visible
|
2011-10-09 10:31:44 +00:00
|
|
|
wind->w_modal = 1; // default to modal
|
2009-05-21 12:16:39 +00:00
|
|
|
wind->data = data;
|
|
|
|
|
|
|
|
if (FirstWindow == NULL)
|
|
|
|
FirstWindow = wind;
|
|
|
|
wind->prev = FrontWindow;
|
2009-08-10 10:47:17 +00:00
|
|
|
if (FrontWindow)
|
|
|
|
FrontWindow->next = wind;
|
2009-05-21 12:16:39 +00:00
|
|
|
wind->next = NULL;
|
|
|
|
FrontWindow = wind;
|
2010-02-02 03:38:29 +00:00
|
|
|
if (prev)
|
2010-12-05 12:33:25 +00:00
|
|
|
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED);
|
2010-02-02 03:38:29 +00:00
|
|
|
|
2014-12-20 04:36:09 +00:00
|
|
|
event.createdata = createdata;
|
2013-12-13 22:39:01 +00:00
|
|
|
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_CREATED);
|
2010-12-05 12:33:25 +00:00
|
|
|
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
|
2010-02-05 14:05:57 +00:00
|
|
|
|
2009-05-21 12:16:39 +00:00
|
|
|
return wind;
|
|
|
|
}
|
|
|
|
|
2009-12-02 13:49:54 +00:00
|
|
|
int window_close(window *wind)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2010-02-02 03:38:29 +00:00
|
|
|
window *prev;
|
2009-12-02 13:49:54 +00:00
|
|
|
d_event event;
|
2014-10-04 21:47:13 +00:00
|
|
|
window_event_result (*w_callback)(window *wind,const d_event &event, void *data) = wind->w_callback;
|
2009-12-02 13:49:54 +00:00
|
|
|
|
2010-02-08 06:08:55 +00:00
|
|
|
if (wind == window_get_front())
|
2010-12-05 12:33:25 +00:00
|
|
|
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_DEACTIVATED); // Deactivate first
|
2010-02-08 06:08:55 +00:00
|
|
|
|
2014-08-06 02:10:49 +00:00
|
|
|
if (WINDOW_SEND_EVENT(wind, EVENT_WINDOW_CLOSE) == window_event_result::handled)
|
2010-02-02 03:38:29 +00:00
|
|
|
{
|
2010-02-08 06:08:55 +00:00
|
|
|
// User 'handled' the event, cancelling close
|
|
|
|
if (wind == window_get_front())
|
2011-02-03 10:47:54 +00:00
|
|
|
{
|
|
|
|
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
|
|
|
|
}
|
2010-02-08 06:08:55 +00:00
|
|
|
return 0;
|
2010-02-02 03:38:29 +00:00
|
|
|
}
|
2009-12-02 13:49:54 +00:00
|
|
|
|
2009-05-21 12:16:39 +00:00
|
|
|
if (wind == FrontWindow)
|
|
|
|
FrontWindow = wind->prev;
|
|
|
|
if (wind == FirstWindow)
|
|
|
|
FirstWindow = wind->next;
|
|
|
|
if (wind->next)
|
|
|
|
wind->next->prev = wind->prev;
|
|
|
|
if (wind->prev)
|
|
|
|
wind->prev->next = wind->next;
|
|
|
|
|
2010-02-02 03:38:29 +00:00
|
|
|
if ((prev = window_get_front()))
|
2011-02-03 10:47:54 +00:00
|
|
|
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_ACTIVATED);
|
|
|
|
|
2010-02-02 07:52:03 +00:00
|
|
|
event.type = EVENT_WINDOW_CLOSED;
|
2014-10-04 21:47:13 +00:00
|
|
|
w_callback(wind, event, NULL); // callback needs to recognise this is a NULL pointer!
|
2014-09-17 02:45:23 +00:00
|
|
|
delete wind;
|
2009-12-02 13:49:54 +00:00
|
|
|
return 1;
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2010-03-17 09:44:19 +00:00
|
|
|
int window_exists(window *wind)
|
|
|
|
{
|
|
|
|
window *w;
|
|
|
|
|
|
|
|
for (w = FirstWindow; w && w != wind; w = w->next) {}
|
|
|
|
|
|
|
|
return w && w == wind;
|
|
|
|
}
|
|
|
|
|
2009-05-21 12:16:39 +00:00
|
|
|
// Get the top window that's visible
|
|
|
|
window *window_get_front(void)
|
|
|
|
{
|
|
|
|
window *wind;
|
|
|
|
|
|
|
|
for (wind = FrontWindow; (wind != NULL) && !wind->w_visible; wind = wind->prev) {}
|
|
|
|
|
|
|
|
return wind;
|
|
|
|
}
|
|
|
|
|
|
|
|
window *window_get_first(void)
|
|
|
|
{
|
|
|
|
return FirstWindow;
|
|
|
|
}
|
|
|
|
|
|
|
|
window *window_get_next(window *wind)
|
|
|
|
{
|
|
|
|
return wind->next;
|
|
|
|
}
|
|
|
|
|
2010-04-04 09:41:53 +00:00
|
|
|
window *window_get_prev(window *wind)
|
|
|
|
{
|
|
|
|
return wind->prev;
|
|
|
|
}
|
|
|
|
|
2009-05-21 12:16:39 +00:00
|
|
|
// Make wind the front window
|
|
|
|
void window_select(window *wind)
|
|
|
|
{
|
2010-02-02 03:38:29 +00:00
|
|
|
window *prev = window_get_front();
|
2010-02-05 14:05:57 +00:00
|
|
|
d_event event;
|
2010-01-20 05:10:32 +00:00
|
|
|
|
2009-05-21 12:16:39 +00:00
|
|
|
Assert (wind != NULL);
|
|
|
|
|
|
|
|
if (wind == FrontWindow)
|
|
|
|
return;
|
|
|
|
if ((wind == FirstWindow) && FirstWindow->next)
|
|
|
|
FirstWindow = FirstWindow->next;
|
|
|
|
|
|
|
|
if (wind->next)
|
|
|
|
wind->next->prev = wind->prev;
|
|
|
|
if (wind->prev)
|
|
|
|
wind->prev->next = wind->next;
|
|
|
|
wind->prev = FrontWindow;
|
2012-04-09 09:12:01 +00:00
|
|
|
FrontWindow->next = wind;
|
2009-05-21 12:16:39 +00:00
|
|
|
wind->next = NULL;
|
|
|
|
FrontWindow = wind;
|
2010-01-20 05:10:32 +00:00
|
|
|
|
|
|
|
if (window_is_visible(wind))
|
2010-02-02 03:38:29 +00:00
|
|
|
{
|
|
|
|
if (prev)
|
2010-12-05 12:33:25 +00:00
|
|
|
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED);
|
|
|
|
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
|
2010-02-02 03:38:29 +00:00
|
|
|
}
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 18:31:41 +00:00
|
|
|
window *window_set_visible(window &w, int visible)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2010-02-02 03:38:29 +00:00
|
|
|
window *prev = window_get_front();
|
2015-01-17 18:31:41 +00:00
|
|
|
w.w_visible = visible;
|
|
|
|
auto wind = window_get_front(); // get the new front window
|
2010-02-05 14:05:57 +00:00
|
|
|
d_event event;
|
2010-02-02 03:38:29 +00:00
|
|
|
if (wind == prev)
|
2015-01-17 18:31:41 +00:00
|
|
|
return wind;
|
2010-02-02 03:38:29 +00:00
|
|
|
|
|
|
|
if (prev)
|
2010-12-05 12:33:25 +00:00
|
|
|
WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED);
|
2010-02-05 14:05:57 +00:00
|
|
|
|
|
|
|
if (wind)
|
2010-12-05 12:33:25 +00:00
|
|
|
WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED);
|
2015-01-17 18:31:41 +00:00
|
|
|
return wind;
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 18:31:41 +00:00
|
|
|
int window_is_visible(window &wind)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2015-01-17 18:31:41 +00:00
|
|
|
return wind.w_visible;
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 18:31:40 +00:00
|
|
|
grs_canvas &window_get_canvas(window &wind)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2015-01-17 18:31:40 +00:00
|
|
|
return wind.w_canv;
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
|
|
|
|
2012-03-24 06:43:08 +00:00
|
|
|
extern void window_update_canvases(void)
|
|
|
|
{
|
|
|
|
window *wind;
|
|
|
|
|
|
|
|
for (wind = FirstWindow; wind != NULL; wind = wind->next)
|
2014-11-30 22:09:21 +00:00
|
|
|
gr_init_sub_bitmap (wind->w_canv.cv_bitmap,
|
|
|
|
*wind->w_canv.cv_bitmap.bm_parent,
|
2012-03-24 06:43:08 +00:00
|
|
|
wind->w_canv.cv_bitmap.bm_x,
|
|
|
|
wind->w_canv.cv_bitmap.bm_y,
|
|
|
|
wind->w_canv.cv_bitmap.bm_w,
|
|
|
|
wind->w_canv.cv_bitmap.bm_h);
|
|
|
|
}
|
|
|
|
|
2015-01-17 18:31:40 +00:00
|
|
|
window_event_result window_send_event(window &wind, const d_event &event)
|
2009-05-21 12:16:39 +00:00
|
|
|
{
|
2015-01-17 18:31:40 +00:00
|
|
|
return wind.w_callback(&wind, event, wind.data);
|
2009-05-21 12:16:39 +00:00
|
|
|
}
|
2011-10-09 10:31:44 +00:00
|
|
|
|
2015-01-17 18:31:41 +00:00
|
|
|
void window_set_modal(window &wind, int modal)
|
2011-10-09 10:31:44 +00:00
|
|
|
{
|
2015-01-17 18:31:41 +00:00
|
|
|
wind.w_modal = modal;
|
2011-10-09 10:31:44 +00:00
|
|
|
}
|
|
|
|
|
2015-01-17 18:31:40 +00:00
|
|
|
int window_is_modal(window &wind)
|
2011-10-09 10:31:44 +00:00
|
|
|
{
|
2015-01-17 18:31:40 +00:00
|
|
|
return wind.w_modal;
|
2011-10-09 10:31:44 +00:00
|
|
|
}
|