Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
  3.  * It is copyright by its individual contributors, as recorded in the
  4.  * project's Git history.  See COPYING.txt at the top level for license
  5.  * terms and a link to the Git history.
  6.  */
  7. /*
  8.  *  A 'window' is simply a canvas that can receive events.
  9.  *  It can be anything from a simple message box to the
  10.  *      game screen when playing.
  11.  *
  12.  *  See event.c for event handling code.
  13.  *
  14.  *      -kreator 2009-05-06
  15.  */
  16.  
  17. #pragma once
  18.  
  19. #include "gr.h"
  20. #include "console.h"
  21.  
  22. #ifdef __cplusplus
  23. #include <assert.h>
  24.  
  25. #include "fwd-window.h"
  26. #include "event.h"
  27. namespace dcx {
  28.  
  29. constexpr const unused_window_userdata_t *unused_window_userdata = nullptr;
  30.  
  31. struct embed_window_pointer_t
  32. {
  33.         window *wind;
  34. };
  35.  
  36. struct ignore_window_pointer_t
  37. {
  38. };
  39.  
  40. static inline void set_embedded_window_pointer(embed_window_pointer_t *wp, window *w)
  41. {
  42.         wp->wind = w;
  43. }
  44.  
  45. static inline void set_embedded_window_pointer(ignore_window_pointer_t *, window *) {}
  46.  
  47. class window
  48. {
  49.         grs_canvas w_canv;                                      // the window's canvas to draw to
  50.         int w_visible;                                          // whether it's visible
  51.         int w_modal;                                            // modal = accept all user input exclusively
  52.         class window *prev;                             // the previous window in the doubly linked list
  53.         class window *next;                             // the next window in the doubly linked list
  54.         bool *w_exists;                                 // optional pointer to a tracking variable
  55.        
  56. public:
  57.         // For creating the window, there are two ways - using the (older) window_create function
  58.         // or using the constructor, passing an event handler that takes a subclass of window.
  59.         explicit window(grs_canvas &src, int x, int y, int w, int h);
  60.  
  61.         virtual ~window();
  62.  
  63.         virtual window_event_result event_handler(const d_event &) = 0;
  64.  
  65.         void send_creation_events(const void *createdata);
  66.         // Declaring as friends to keep function syntax, for historical reasons (for now at least)
  67.         // Intended to transition to the class method form
  68.         friend window *window_create(grs_canvas &src, int x, int y, int w, int h, window_subfunction<void> event_callback, void *userdata, const void *createdata);
  69.        
  70.         friend int window_close(window *wind);
  71.         friend window *window_get_front();
  72.         friend window *window_get_first();
  73.         friend void window_select(window &wind);
  74.         friend window *window_set_visible(window &wind, int visible);
  75. #if !DXX_USE_OGL
  76.         friend void window_update_canvases();
  77. #endif
  78.        
  79.         friend grs_canvas &window_get_canvas(window &wind)
  80.         {
  81.                 return wind.w_canv;
  82.         }
  83.        
  84.         friend window *window_set_visible(window *wind, int visible)
  85.         {
  86.                 return window_set_visible(*wind, visible);
  87.         }
  88.  
  89.         int is_visible()
  90.         {
  91.                 return w_visible;
  92.         }
  93.  
  94.         friend int window_is_visible(window *wind)
  95.         {
  96.                 return wind->is_visible();
  97.         }
  98.  
  99.         void set_modal(int modal)
  100.         {
  101.                 w_modal = modal;
  102.         }
  103.  
  104.         friend void window_set_modal(window *wind, int modal)
  105.         {
  106.                 wind->set_modal(modal);
  107.         }
  108.  
  109.         friend int window_is_modal(window &wind)
  110.         {
  111.                 return wind.w_modal;
  112.         }
  113.  
  114.         friend window_event_result window_send_event(window &wind, const d_event &event)
  115.         {
  116.                 auto r = wind.event_handler(event);
  117.                 if (r == window_event_result::close)
  118.                         if (window_close(&wind))
  119.                                 return window_event_result::deleted;
  120.  
  121.                 return r;
  122.         }
  123.  
  124.         friend window *window_get_next(window &wind)
  125.         {
  126.                 return wind.next;
  127.         }
  128.        
  129.         friend window *window_get_prev(window &wind)
  130.         {
  131.                 return wind.prev;
  132.         }
  133.  
  134.         void track(bool *exists)
  135.         {
  136.                 assert(w_exists == nullptr);
  137.                 w_exists = exists;
  138.         }
  139. };
  140.  
  141. class callback_window : public window
  142. {
  143.         window_subfunction<void> w_callback;    // the event handler
  144.         void *w_data;                                           // whatever the user wants (eg menu data for 'newmenu' menus)
  145. public:
  146.         callback_window(grs_canvas &src, int x, int y, int w, int h, window_subfunction<void> event_callback, void *data);
  147.         virtual window_event_result event_handler(const d_event &) override;
  148. };
  149.  
  150. template <typename T1, typename T2 = const void>
  151. static inline callback_window *window_create(grs_canvas &src, int x, int y, int w, int h, window_subfunction<T1> event_callback, T1 *data, T2 *createdata = nullptr)
  152. {
  153.         const auto win = new callback_window(src, x, y, w, h, reinterpret_cast<window_subfunction<void>>(event_callback), static_cast<void *>(data));
  154.         set_embedded_window_pointer(data, win);
  155.         win->send_creation_events(createdata);
  156.         return win;
  157. }
  158.  
  159. template <typename T1, typename T2 = const void>
  160. static inline callback_window *window_create(grs_canvas &src, int x, int y, int w, int h, window_subfunction<const T1> event_callback, const T1 *userdata, T2 *createdata = nullptr)
  161. {
  162.         const auto win = new callback_window(src, x, y, w, h, reinterpret_cast<window_subfunction<void>>(event_callback), static_cast<void *>(const_cast<T1 *>(userdata)));
  163.         win->send_creation_events(createdata);
  164.         return win;
  165. }
  166.  
  167. static inline window_event_result (WINDOW_SEND_EVENT)(window &w, const d_event &event, const char *const file, const unsigned line)
  168. {
  169.         auto &c = window_get_canvas(w);
  170.         con_printf(CON_DEBUG, "%s:%u: sending event %i to window of dimensions %dx%d", file, line, event.type, c.cv_bitmap.bm_w, c.cv_bitmap.bm_h);
  171.         return window_send_event(w, event);
  172. }
  173.  
  174. void menu_destroy_hook(window *w);
  175.  
  176. }
  177. #endif
  178.