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. #include "gr.h"
  18. #include "window.h"
  19. #include "u_mem.h"
  20. #include "dxxerror.h"
  21. #include "event.h"
  22.  
  23. namespace dcx {
  24.  
  25. static window *FrontWindow = nullptr;
  26. static window *FirstWindow = nullptr;
  27.  
  28. window::window(grs_canvas &src, const int x, const int y, const int w, const int h) :
  29.         // Default to visible and modal
  30.         w_visible(1), w_modal(1), prev(FrontWindow), next(nullptr), w_exists(nullptr)
  31. {
  32.         gr_init_sub_canvas(w_canv, src, x, y, w, h);
  33.  
  34.         if (FirstWindow == nullptr)
  35.                 FirstWindow = this;
  36. }
  37.  
  38. void window::send_creation_events(const void *const createdata)
  39. {
  40.         const auto prev_front = window_get_front();
  41.         if (FrontWindow)
  42.                 FrontWindow->next = this;
  43.         FrontWindow = this;
  44.         if (prev_front)
  45.         {
  46.                 const d_event event{EVENT_WINDOW_DEACTIVATED};
  47.                 WINDOW_SEND_EVENT(prev_front);
  48.         }
  49.         {
  50.                 const d_create_event event{EVENT_WINDOW_CREATED, createdata};
  51.                 WINDOW_SEND_EVENT(this);
  52.         }
  53.         {
  54.                 const d_event event{EVENT_WINDOW_ACTIVATED};
  55.                 WINDOW_SEND_EVENT(this);
  56.         }
  57. }
  58.  
  59. window::~window()
  60. {
  61.         if (w_exists)
  62.                 *w_exists = false;
  63.         if (this == FrontWindow)
  64.                 FrontWindow = this->prev;
  65.         if (this == FirstWindow)
  66.                 FirstWindow = this->next;
  67.         if (this->next)
  68.                 this->next->prev = this->prev;
  69.         if (this->prev)
  70.                 this->prev->next = this->next;
  71. }
  72.  
  73. callback_window::callback_window(grs_canvas &src, const int x, const int y, const int w, const int h, const window_subfunction<void> event_callback, void *const data) :
  74.         window(src, x, y, w, h),
  75.         w_callback((assert(event_callback != nullptr), event_callback)), w_data(data)
  76. {
  77. }
  78.  
  79. window_event_result callback_window::event_handler(const d_event &event)
  80. {
  81.         return w_callback(this, event, w_data);
  82. }
  83.  
  84. int window_close(window *wind)
  85. {
  86.         window *prev;
  87.         window_event_result result;
  88.  
  89.         if (wind == window_get_front())
  90.         {
  91.                 const d_event event{EVENT_WINDOW_DEACTIVATED};
  92.                 WINDOW_SEND_EVENT(wind);        // Deactivate first
  93.         }
  94.  
  95.         {
  96.                 const d_event event{EVENT_WINDOW_CLOSE};
  97.                 result = WINDOW_SEND_EVENT(wind);
  98.         }
  99.         if (result == window_event_result::handled)
  100.         {
  101.                 // User 'handled' the event, cancelling close
  102.                 if (wind == window_get_front())
  103.                 {
  104.                         const d_event event{EVENT_WINDOW_ACTIVATED};
  105.                         WINDOW_SEND_EVENT(wind);
  106.                 }
  107.                 return 0;
  108.         }
  109.  
  110.         menu_destroy_hook(wind);
  111.  
  112.         if (result != window_event_result::deleted)     // don't attempt to re-delete
  113.                 delete wind;
  114.  
  115.         if ((prev = window_get_front()))
  116.         {
  117.                 const d_event event{EVENT_WINDOW_ACTIVATED};
  118.                 WINDOW_SEND_EVENT(prev);
  119.         }
  120.  
  121.         return 1;
  122. }
  123.  
  124. // Get the top window that's visible
  125. window *window_get_front(void)
  126. {
  127.         window *wind;
  128.  
  129.         for (wind = FrontWindow; (wind != NULL) && !wind->w_visible; wind = wind->prev) {}
  130.  
  131.         return wind;
  132. }
  133.  
  134. window *window_get_first(void)
  135. {
  136.         return FirstWindow;
  137. }
  138.  
  139. // Make wind the front window
  140. void window_select(window &wind)
  141. {
  142.         window *prev = window_get_front();
  143.         if (&wind == FrontWindow)
  144.                 return;
  145.         if (&wind == FirstWindow && wind.next)
  146.                 FirstWindow = FirstWindow->next;
  147.  
  148.         if (wind.next)
  149.                 wind.next->prev = wind.prev;
  150.         if (wind.prev)
  151.                 wind.prev->next = wind.next;
  152.         wind.prev = FrontWindow;
  153.         FrontWindow->next = &wind;
  154.         wind.next = nullptr;
  155.         FrontWindow = &wind;
  156.        
  157.         if (wind.is_visible())
  158.         {
  159.                 if (prev)
  160.                 {
  161.                         const d_event event{EVENT_WINDOW_DEACTIVATED};
  162.                         WINDOW_SEND_EVENT(prev);
  163.                 }
  164.                 const d_event event{EVENT_WINDOW_ACTIVATED};
  165.                 WINDOW_SEND_EVENT(&wind);
  166.         }
  167. }
  168.  
  169. window *window_set_visible(window &w, int visible)
  170. {
  171.         window *prev = window_get_front();
  172.         w.w_visible = visible;
  173.         auto wind = window_get_front(); // get the new front window
  174.         if (wind == prev)
  175.                 return wind;
  176.        
  177.         if (prev)
  178.         {
  179.                 const d_event event{EVENT_WINDOW_DEACTIVATED};
  180.                 WINDOW_SEND_EVENT(prev);
  181.         }
  182.  
  183.         if (wind)
  184.         {
  185.                 const d_event event{EVENT_WINDOW_ACTIVATED};
  186.                 WINDOW_SEND_EVENT(wind);
  187.         }
  188.         return wind;
  189. }
  190.  
  191. #if !DXX_USE_OGL
  192. void window_update_canvases()
  193. {
  194.         window *wind;
  195.        
  196.         for (wind = FirstWindow; wind != NULL; wind = wind->next)
  197.                 gr_init_sub_bitmap (wind->w_canv.cv_bitmap,
  198.                                                         *wind->w_canv.cv_bitmap.bm_parent,
  199.                                                         wind->w_canv.cv_bitmap.bm_x,
  200.                                                         wind->w_canv.cv_bitmap.bm_y,
  201.                                                         wind->w_canv.cv_bitmap.bm_w,
  202.                                                         wind->w_canv.cv_bitmap.bm_h);
  203. }
  204. #endif
  205.  
  206. }
  207.