From f117df9eeedd8b42d02b8224f1ce45e5e996452f Mon Sep 17 00:00:00 2001 From: Chris Taylor Date: Sun, 2 Oct 2016 14:49:22 +0800 Subject: [PATCH] Allow dcx::window struct to be subclassed - step 2 Allow dcx::window struct to be subclassed step 2. This step renames and reconfigures window_create in window.cpp to be the main constructor. Also add a template constructor that allows an event handler that takes a subclass of window. --- common/arch/sdl/window.cpp | 14 ++++++-------- common/include/fwd-window.h | 5 +++-- common/include/window.h | 16 ++++++++++++---- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/common/arch/sdl/window.cpp b/common/arch/sdl/window.cpp index 7670bb70b..de904cef6 100644 --- a/common/arch/sdl/window.cpp +++ b/common/arch/sdl/window.cpp @@ -25,18 +25,18 @@ namespace dcx { static window *FrontWindow = NULL; static window *FirstWindow = NULL; -window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfunction event_callback, void *data, const void *createdata) +window::window(grs_canvas *src, int x, int y, int w, int h, window_subfunction event_callback, void *data, const void *createdata) { - window *prev = window_get_front(); + window *prev_front = window_get_front(); d_create_event event; - window *wind = new window; + window *wind = this; Assert(src != NULL); Assert(event_callback != NULL); 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; + wind->w_data = data; if (FirstWindow == NULL) FirstWindow = wind; @@ -45,14 +45,12 @@ window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfun FrontWindow->next = wind; wind->next = NULL; FrontWindow = wind; - if (prev) - WINDOW_SEND_EVENT(prev, EVENT_WINDOW_DEACTIVATED); + if (prev_front) + WINDOW_SEND_EVENT(prev_front, EVENT_WINDOW_DEACTIVATED); event.createdata = createdata; WINDOW_SEND_EVENT(wind, EVENT_WINDOW_CREATED); WINDOW_SEND_EVENT(wind, EVENT_WINDOW_ACTIVATED); - - return wind; } int window_close(window *wind) diff --git a/common/include/fwd-window.h b/common/include/fwd-window.h index 9bbebc02e..ffdf870ad 100644 --- a/common/include/fwd-window.h +++ b/common/include/fwd-window.h @@ -24,14 +24,15 @@ enum class window_event_result : uint8_t; template using window_subfunction = window_event_result (*)(window *menu,const d_event &event, T *userdata); +template +using window_subclass_subfunction = window_event_result (*)(T *menu,const d_event &event, void*); + class unused_window_userdata_t; /* No declaration for embed_window_pointer_t or ignore_window_pointer_t * since every user needs the full definition. */ -window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfunction event_callback, void *userdata, const void *createdata); - int window_close(window *wind); int window_exists(window *wind); window *window_get_front(); diff --git a/common/include/window.h b/common/include/window.h index 11807f440..61c84dda3 100644 --- a/common/include/window.h +++ b/common/include/window.h @@ -57,11 +57,19 @@ private: window_subfunction w_callback; // 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) + void *w_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 public: + // For creating the window, there are two ways - using the (older) window_create function + // or using the constructor, passing an event handler that takes a subclass of window. + explicit window(grs_canvas *src, int x, int y, int w, int h, window_subfunction event_callback, void *data, const void *createdata); + + template + window(grs_canvas *src, int x, int y, int w, int h, window_subclass_subfunction event_callback) : + window(src, x, y, w, h, reinterpret_cast>(event_callback), nullptr, nullptr) {} + // Declaring as friends to keep function syntax, for historical reasons (for now at least) // Intended to transition to the class method form friend window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfunction event_callback, void *userdata, const void *createdata); @@ -113,7 +121,7 @@ public: friend window_event_result window_send_event(window &wind, const d_event &event) { - auto r = wind.w_callback(&wind, event, wind.data); + auto r = wind.w_callback(&wind, event, wind.w_data); if (r == window_event_result::close) window_close(&wind); return r; @@ -134,7 +142,7 @@ public: template static inline window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfunction event_callback, T1 *data, T2 *createdata = nullptr) { - auto win = window_create(src, x, y, w, h, reinterpret_cast>(event_callback), static_cast(data), static_cast(createdata)); + auto win = new window(src, x, y, w, h, reinterpret_cast>(event_callback), static_cast(data), static_cast(createdata)); set_embedded_window_pointer(data, win); return win; } @@ -142,7 +150,7 @@ static inline window *window_create(grs_canvas *src, int x, int y, int w, int h, template static inline window *window_create(grs_canvas *src, int x, int y, int w, int h, window_subfunction event_callback, const T1 *userdata, T2 *createdata = nullptr) { - return window_create(src, x, y, w, h, reinterpret_cast>(event_callback), static_cast(const_cast(userdata)), static_cast(createdata)); + return new window(src, x, y, w, h, reinterpret_cast>(event_callback), static_cast(const_cast(userdata)), static_cast(createdata)); } static inline window_event_result (WINDOW_SEND_EVENT)(window &w, const d_event &event, const char *file, unsigned line, const char *e)