Subversion Repositories Games.Descent

Rev

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

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. #include <stdexcept>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23.  
  24. #include "u_mem.h"
  25. #include "maths.h"
  26. #include "pstypes.h"
  27. #include "gr.h"
  28. #include "ui.h"
  29. #include "event.h"
  30. #include "mouse.h"
  31. #include "window.h"
  32. #include "dxxerror.h"
  33.  
  34. #include "key.h"
  35.  
  36. namespace dcx {
  37.  
  38. UI_GADGET * selected_gadget;
  39.  
  40. constexpr std::integral_constant<uint8_t, 1> UI_GADGET_BUTTON::s_kind;
  41. constexpr std::integral_constant<uint8_t, 2> UI_GADGET_LISTBOX::s_kind;
  42. constexpr std::integral_constant<uint8_t, 3> UI_GADGET_SCROLLBAR::s_kind;
  43. constexpr std::integral_constant<uint8_t, 4> UI_GADGET_RADIO::s_kind;
  44. constexpr std::integral_constant<uint8_t, 5> UI_GADGET_CHECKBOX::s_kind;
  45. constexpr std::integral_constant<uint8_t, 6> UI_GADGET_INPUTBOX::s_kind;
  46. constexpr std::integral_constant<uint8_t, 7> UI_GADGET_USERBOX::s_kind;
  47. constexpr std::integral_constant<uint8_t, 9> UI_GADGET_ICON::s_kind;
  48.  
  49. namespace {
  50.  
  51. struct event_gadget : d_event
  52. {
  53.         UI_GADGET *const gadget;
  54.         constexpr event_gadget(const event_type t, UI_GADGET *const g) :
  55.                 d_event(t), gadget(g)
  56.         {
  57.         }
  58. };
  59.  
  60. }
  61.  
  62. void ui_gadget_add(UI_DIALOG * dlg, short x1, short y1, short x2, short y2, UI_GADGET *gadget)
  63. {
  64.         if (dlg->gadget == NULL )
  65.         {
  66.                 dlg->gadget = gadget;
  67.                 gadget->prev = gadget;
  68.                 gadget->next = gadget;
  69.         } else {
  70.                 dlg->gadget->prev->next = gadget;
  71.                 gadget->next = dlg->gadget;
  72.                 gadget->prev = dlg->gadget->prev;
  73.                 dlg->gadget->prev = gadget;
  74.         }
  75.  
  76.         gadget->when_tab = NULL;
  77.         gadget->when_btab = NULL;
  78.         gadget->when_up = NULL;
  79.         gadget->when_down = NULL;
  80.         gadget->when_left = NULL;
  81.         gadget->when_right = NULL;
  82.         gadget->status = 1;
  83.         gadget->oldstatus = 0;
  84.         if ( x1==0 && x2==0 && y1==0 && y2== 0 )
  85.                 gadget->canvas.reset();
  86.         else
  87.                 gadget->canvas = gr_create_sub_canvas(window_get_canvas(*ui_dialog_get_window(dlg)), x1, y1, x2-x1+1, y2-y1+1);
  88.         gadget->x1 = gadget->canvas->cv_bitmap.bm_x;
  89.         gadget->y1 = gadget->canvas->cv_bitmap.bm_y;
  90.         gadget->x2 = gadget->canvas->cv_bitmap.bm_x+x2-x1+1;
  91.         gadget->y2 = gadget->canvas->cv_bitmap.bm_y+y2-y1+1;
  92.         gadget->parent = NULL;
  93.         gadget->hotkey = -1;
  94. }
  95.  
  96.  
  97. #if 0
  98. int is_under_another_window( UI_DIALOG * dlg, UI_GADGET * gadget )
  99. {
  100.         UI_DIALOG * temp;
  101.  
  102.         temp = dlg->next;
  103.  
  104.         while( temp != NULL )   {
  105.                 if (    ( gadget->x1 > temp->x)                                         &&
  106.                                 ( gadget->x1 < (temp->x+temp->width) )  &&
  107.                                 ( gadget->y1 > temp->y)                                         &&
  108.                                 ( gadget->y1 < (temp->y+temp->height) )
  109.                         )      
  110.                 {
  111.                                 //gadget->status =1;
  112.                                 return 1;
  113.                 }
  114.                
  115.  
  116.                 if (    ( gadget->x2 > temp->x)                                         &&
  117.                                 ( gadget->x2 < (temp->x+temp->width) )  &&
  118.                                 ( gadget->y2 > temp->y)                                         &&
  119.                                 ( gadget->y2 < (temp->y+temp->height) )
  120.                         )
  121.                 {
  122.                                 //gadget->status =1;
  123.                                 return 1;
  124.                 }
  125.                
  126.  
  127.                 temp = temp->next;
  128.         }
  129.         return 0;
  130. }
  131. #endif
  132.  
  133.  
  134. int ui_mouse_on_gadget( UI_GADGET * gadget )
  135. {
  136.         int x, y, z;
  137.        
  138.         mouse_get_pos(&x, &y, &z);
  139.         if ((x >= gadget->x1) && (x <= gadget->x2-1) && (y >= gadget->y1) &&    (y <= gadget->y2-1) )
  140.         {
  141. #if 0   // check is no longer required - if it is under another window, that dialog's handler would have returned 1
  142.                 if (is_under_another_window(dlg, gadget))
  143.                         return 0;
  144. #endif
  145.                 return 1;
  146.         } else
  147.                 return 0;
  148. }
  149.  
  150. static window_event_result ui_gadget_do(UI_DIALOG *dlg, UI_GADGET *g,const d_event &event)
  151. {
  152.         switch( g->kind )
  153.         {
  154.                 case UI_GADGET_BUTTON::s_kind:
  155.                         return ui_button_do(dlg, static_cast<UI_GADGET_BUTTON *>(g), event);
  156.                 case UI_GADGET_LISTBOX::s_kind:
  157.                         return ui_listbox_do(dlg, static_cast<UI_GADGET_LISTBOX *>(g), event);
  158.                 case UI_GADGET_SCROLLBAR::s_kind:
  159.                         return ui_scrollbar_do(dlg, static_cast<UI_GADGET_SCROLLBAR *>(g), event);
  160.                 case UI_GADGET_RADIO::s_kind:
  161.                         return ui_radio_do(dlg, static_cast<UI_GADGET_RADIO *>(g), event);
  162.                 case UI_GADGET_CHECKBOX::s_kind:
  163.                         return ui_checkbox_do(dlg, static_cast<UI_GADGET_CHECKBOX *>(g), event);
  164.                 case UI_GADGET_INPUTBOX::s_kind:
  165.                         return ui_inputbox_do(dlg, static_cast<UI_GADGET_INPUTBOX *>(g), event);
  166.                 case UI_GADGET_USERBOX::s_kind:
  167.                         return ui_userbox_do(dlg, static_cast<UI_GADGET_USERBOX *>(g), event);
  168.                 case UI_GADGET_ICON::s_kind:
  169.                         return ui_icon_do(dlg, static_cast<UI_GADGET_ICON *>(g), event);
  170.         }
  171.         return window_event_result::ignored;
  172. }
  173.  
  174. window_event_result ui_gadget_send_event(UI_DIALOG *dlg, event_type type, UI_GADGET *gadget)
  175. {
  176.         const event_gadget event{type, gadget};
  177.  
  178.         if (gadget->parent)
  179.                 return ui_gadget_do(dlg, gadget->parent, event);
  180.  
  181.         return window_send_event(*ui_dialog_get_window(dlg), event);
  182. }
  183.  
  184. UI_GADGET *ui_event_get_gadget(const d_event &event)
  185. {
  186.         auto &e = static_cast<const event_gadget &>(event);
  187.         Assert(e.type >= EVENT_UI_GADGET_PRESSED);      // Any UI event
  188.         return e.gadget;
  189. }
  190.  
  191. window_event_result ui_dialog_do_gadgets(UI_DIALOG * dlg,const d_event &event)
  192. {
  193.         int keypress = 0;
  194.         UI_GADGET * tmp, * tmp1;
  195.  
  196.         if (event.type == EVENT_KEY_COMMAND)
  197.                 keypress = event_key_get(event);
  198.  
  199.         tmp = dlg->gadget;
  200.  
  201.         if (tmp == NULL) return window_event_result::ignored;
  202.  
  203.         if (selected_gadget==NULL)
  204.                 selected_gadget = tmp;
  205.  
  206.         tmp1 = dlg->keyboard_focus_gadget;
  207.  
  208.         do
  209.         {
  210.                 if (ui_mouse_on_gadget(tmp) && B1_JUST_PRESSED )
  211.                 {
  212.                         selected_gadget = tmp;
  213.                         if (tmp->parent!=NULL)
  214.                         {
  215.                                 while (tmp->parent != NULL )
  216.                                         tmp = tmp->parent;
  217.                                 dlg->keyboard_focus_gadget = tmp;
  218.                                 break;
  219.                         }
  220.                         else
  221.                         {
  222.                                 dlg->keyboard_focus_gadget = tmp;
  223.                                 break;
  224.                         }
  225.                 }
  226.                 if ( tmp->hotkey == keypress )
  227.                 {
  228.                         dlg->keyboard_focus_gadget = tmp;
  229.                         break;
  230.                 }
  231.                 tmp = tmp->next;
  232.         } while( tmp != dlg->gadget );
  233.  
  234.         if (dlg->keyboard_focus_gadget != NULL)
  235.         {
  236.                 [=]{
  237.                 UI_GADGET *UI_GADGET::*when;
  238.                 switch (keypress )
  239.                 {
  240.                         case (KEY_TAB):
  241.                                 when = &UI_GADGET::when_tab;
  242.                                 break;
  243.                         case (KEY_TAB+KEY_SHIFTED):
  244.                                 when = &UI_GADGET::when_btab;
  245.                                 break;
  246.                         case (KEY_UP):
  247.                                 when = &UI_GADGET::when_up;
  248.                                 break;
  249.                         case (KEY_DOWN):
  250.                                 when = &UI_GADGET::when_down;
  251.                                 break;
  252.                         case (KEY_LEFT):
  253.                                 when = &UI_GADGET::when_left;
  254.                                 break;
  255.                         case (KEY_RIGHT):
  256.                                 when = &UI_GADGET::when_right;
  257.                                 break;
  258.                         default:
  259.                                 return;
  260.                 }
  261.                 if (const auto p = dlg->keyboard_focus_gadget->*when)
  262.                         dlg->keyboard_focus_gadget = p;
  263.                 }();
  264.         }
  265.  
  266.         window_event_result rval = window_event_result::ignored;
  267.         if (dlg->keyboard_focus_gadget != tmp1)
  268.         {
  269.                 if (dlg->keyboard_focus_gadget != NULL )
  270.                         dlg->keyboard_focus_gadget->status = 1;
  271.                 if (tmp1 != NULL )
  272.                         tmp1->status = 1;
  273.                 rval = window_event_result::handled;
  274.                
  275.                 if (keypress)
  276.                         return rval;
  277.         }
  278.  
  279.         tmp = dlg->gadget;
  280.         do
  281.         {
  282.                 // If it is under another dialog, that dialog's handler would have returned 1 for mouse events.
  283.                 // Key events are handled in a priority depending on the window ordering.
  284.                 //if (!is_under_another_window( dlg, tmp ))
  285.                         rval = ui_gadget_do(dlg, tmp, event);
  286.                
  287.                 if (rval == window_event_result::deleted)
  288.                         break;
  289.  
  290.                 tmp = tmp->next;
  291.         } while(/*!rval &&*/ tmp != dlg->gadget);       // have to look for pesky scrollbars in case an arrow button or arrow key are held down
  292.        
  293.         return rval;
  294. }
  295.  
  296.  
  297.  
  298. UI_GADGET * ui_gadget_get_next( UI_GADGET * gadget )
  299. {
  300.         UI_GADGET * tmp;
  301.  
  302.         tmp = gadget->next;
  303.  
  304.         while( tmp != gadget && (tmp->parent!=NULL) )
  305.                 tmp = tmp->next;
  306.  
  307.         return tmp;
  308. }
  309.  
  310. UI_GADGET * ui_gadget_get_prev( UI_GADGET * gadget )
  311. {
  312.         UI_GADGET * tmp;
  313.  
  314.         tmp = gadget->prev;
  315.  
  316.         while( tmp != gadget && (tmp->parent!=NULL) )
  317.                 tmp = tmp->prev;
  318.  
  319.         return tmp;
  320. }
  321.  
  322. void ui_gadget_calc_keys( UI_DIALOG * dlg)
  323. {
  324.         UI_GADGET * tmp;
  325.  
  326.         tmp = dlg->gadget;
  327.  
  328.         if (tmp==NULL) return;
  329.  
  330.         do
  331.         {
  332.                 tmp->when_tab = ui_gadget_get_next(tmp);
  333.                 tmp->when_btab = ui_gadget_get_prev(tmp);
  334.  
  335.                 tmp = tmp->next;
  336.         } while( tmp != dlg->gadget );
  337.  
  338. }
  339.  
  340. }
  341.