/* * Portions of this file are copyright Rebirth contributors and licensed as * described in COPYING.txt. * Portions of this file are copyright Parallax Software and licensed * according to the Parallax license below. * See COPYING.txt for license details. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Header file for user interface * */ #pragma once #include #include "dxxsconf.h" #include "dsx-ns.h" #include "fwd-event.h" #include "fmtcheck.h" #include "u_mem.h" #ifdef __cplusplus #include #include #include "fwd-gr.h" #include "varutil.h" #include "window.h" #include "ntstring.h" #include #include namespace dcx { struct UI_KEYPAD { using buttontext_element_t = std::array; using buttontext_t = std::array; UI_KEYPAD(); unsigned numkeys; ntstring<99> description; std::array keycode; std::array function_number; buttontext_t buttontext; }; struct UI_EVENT { unsigned int frame; int type; int data; }; struct UI_GADGET { uint8_t kind; short x1,y1,x2,y2; int hotkey; struct UI_GADGET * prev; \ struct UI_GADGET * next; \ struct UI_GADGET * when_tab; \ struct UI_GADGET * when_btab; \ struct UI_GADGET * when_up; \ struct UI_GADGET * when_down; \ struct UI_GADGET * when_left; \ struct UI_GADGET * when_right; \ struct UI_GADGET * parent; \ int status; \ int oldstatus; \ grs_subcanvas_ptr canvas; \ protected: ~UI_GADGET() = default; }; struct UI_GADGET_USERBOX : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; short width, height; short b1_held_down; short b1_clicked; short b1_double_clicked; short b1_dragging; short b1_drag_x1, b1_drag_y1; short b1_drag_x2, b1_drag_y2; short b1_done_dragging; short mouse_onme; short mouse_x, mouse_y; int keypress; grs_bitmap * bitmap; }; struct UI_GADGET_BUTTON : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; std::string text; short width, height; short position; short oldposition; short pressed; uint8_t dim_if_no_function; int hotkey1; int (*user_function)(void); int (*user_function1)(void); }; struct UI_GADGET_INPUTBOX : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; RAIIdmem text; short width, height; short length; short slength; short position; short oldposition; short pressed; short first_time; }; struct UI_GADGET_RADIO : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; RAIIdmem text; short width, height; short position; short oldposition; short pressed; short group; short flag; }; struct UI_GADGET_ICON : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; RAIIdmem text; short width, height; sbyte flag; sbyte pressed; sbyte position; sbyte oldposition; int trap_key; int (*user_function)(void); }; struct UI_GADGET_CHECKBOX : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; RAIIdmem text; short width, height; short position; short oldposition; short pressed; short group; short flag; }; struct UI_GADGET_SCROLLBAR : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; short horz; short width, height; int start; int stop; int position; int window_size; int fake_length; int fake_position; int fake_size; std::unique_ptr up_button, down_button; fix64 last_scrolled; short drag_x, drag_y; int drag_starting; int dragging; int moved; }; struct UI_GADGET_LISTBOX : UI_GADGET { static constexpr auto s_kind = std::integral_constant{}; const char *const *list; short width, height; int num_items; int num_items_displayed; int first_item; int old_first_item; int current_item; int selected_item; int old_current_item; int dragging; int textheight; int moved; std::unique_ptr scrollbar; fix64 last_scrolled; }; enum dialog_flags { DF_BORDER = 1, DF_FILLED = 2, DF_SAVE_BG = 4, DF_DIALOG = (4+2+1), DF_MODAL = 8 // modal = accept all user input exclusively }; template using ui_subfunction_t = window_event_result (*)(struct UI_DIALOG *,const d_event &, T *); template using ui_subclass_subfunction_t = window_event_result (*)(T *,const d_event &, void *); struct UI_DIALOG : embed_window_pointer_t { // TODO: Make these private ui_subfunction_t d_callback; UI_GADGET * gadget; UI_GADGET * keyboard_focus_gadget; void *d_userdata; short d_x, d_y; short d_width, d_height; short d_text_x, d_text_y; enum dialog_flags d_flags; public: // For creating the dialog, there are two ways - using the (older) ui_create_dialog function // or using the constructor, passing an event handler that takes a subclass of UI_DIALOG. explicit UI_DIALOG(short x, short y, short w, short h, enum dialog_flags flags, ui_subfunction_t callback, void *userdata, const void *createdata); template UI_DIALOG(short x, short y, short w, short h, enum dialog_flags flags, ui_subclass_subfunction_t callback) : UI_DIALOG(x, y, w, h, flags, reinterpret_cast>(callback), nullptr, nullptr) {} ~UI_DIALOG(); }; #define B1_JUST_PRESSED (event.type == EVENT_MOUSE_BUTTON_DOWN && event_mouse_get_button(event) == 0) #define B1_JUST_RELEASED (event.type == EVENT_MOUSE_BUTTON_UP && event_mouse_get_button(event) == 0) #define B1_DOUBLE_CLICKED (event.type == EVENT_MOUSE_DOUBLE_CLICKED && event_mouse_get_button(event) == 0) extern grs_font_ptr ui_small_font; extern unsigned char CBLACK,CGREY,CWHITE,CBRIGHT,CRED; extern UI_GADGET * selected_gadget; #define Hline(C,x1,x2,y,c) Hline(C,x1,y,x2,c) #define Vline(C,y1,y2,x,c) Vline(C,x,y1,y2,c) void Hline(grs_canvas &, fix x1, fix x2, fix y, color_palette_index color); void Vline(grs_canvas &, fix y1, fix y2, fix x, color_palette_index color); void ui_string_centered(grs_canvas &, unsigned x, unsigned y, const char *s); void ui_draw_box_out(grs_canvas &, unsigned x1, unsigned y1, unsigned x2, unsigned y2); void ui_draw_box_in(grs_canvas &, unsigned x1, unsigned y1, unsigned x2, unsigned y2); void ui_draw_frame(grs_canvas &, unsigned x1, unsigned y1, unsigned x2, unsigned y2); void ui_draw_shad(grs_canvas &, unsigned x1, unsigned y1, unsigned x2, unsigned y2, color_palette_index c1, color_palette_index c2); int ui_init(); void ui_close(); typedef cstring_tie<10> ui_messagebox_tie; int ui_messagebox( short xc, short yc, const char * text, const ui_messagebox_tie &Button ); #define ui_messagebox(X,Y,N,T,...) ((ui_messagebox)((X),(Y),(T), ui_messagebox_tie(__VA_ARGS__))) class unused_ui_userdata_t; constexpr unused_ui_userdata_t *unused_ui_userdata = nullptr; template UI_DIALOG * ui_create_dialog(const short x, const short y, const short w, const short h, const enum dialog_flags flags, const ui_subfunction_t callback, T1 *const userdata, T2 *const createdata = nullptr) { return new UI_DIALOG(x, y, w, h, flags, reinterpret_cast>(callback), static_cast(userdata), static_cast(createdata)); } template UI_DIALOG *ui_create_dialog(const short x, const short y, const short w, const short h, const enum dialog_flags flags, const ui_subfunction_t callback, std::unique_ptr userdata, T2 *const createdata = nullptr) { auto r = ui_create_dialog(x, y, w, h, flags, callback, userdata.get(), createdata); userdata.release(); return r; } extern class window *ui_dialog_get_window(UI_DIALOG *dlg); extern void ui_dialog_set_current_canvas(UI_DIALOG *dlg); extern void ui_close_dialog( UI_DIALOG * dlg ); #define GADGET_PRESSED(g) (event.type == EVENT_UI_GADGET_PRESSED && ui_event_get_gadget(event) == g) void ui_gadget_add(UI_DIALOG *dlg, short x1, short y1, short x2, short y2, UI_GADGET *); template __attribute_warn_unused_result static std::unique_ptr ui_gadget_add(UI_DIALOG *dlg, short x1, short y1, short x2, short y2) { auto t = std::make_unique(); t->kind = T::s_kind; ui_gadget_add(dlg, x1, y1, x2, y2, t.get()); return t; } __attribute_warn_unused_result std::unique_ptr ui_add_gadget_button(UI_DIALOG * dlg, short x, short y, short w, short h, const char * text, int (*function_to_call)()); window_event_result ui_gadget_send_event(UI_DIALOG *dlg, enum event_type type, UI_GADGET *gadget); extern UI_GADGET *ui_event_get_gadget(const d_event &event); window_event_result ui_dialog_do_gadgets( UI_DIALOG * dlg, const d_event &event ); extern void ui_draw_button( UI_DIALOG *dlg, UI_GADGET_BUTTON * button ); extern int ui_mouse_on_gadget( UI_GADGET * gadget ); window_event_result ui_button_do( UI_DIALOG *dlg, UI_GADGET_BUTTON * button, const d_event &event ); window_event_result ui_listbox_do( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox, const d_event &event ); extern void ui_draw_listbox( UI_DIALOG *dlg, UI_GADGET_LISTBOX * listbox ); std::unique_ptr ui_add_gadget_listbox(UI_DIALOG *dlg, short x, short y, short w, short h, short numitems, char **list); extern void ui_mega_process(); void ui_get_button_size(const grs_font &, const char *text, int &width, int &height); __attribute_warn_unused_result std::unique_ptr ui_add_gadget_scrollbar(UI_DIALOG * dlg, short x, short y, short w, short h, int start, int stop, int position, int window_size); window_event_result ui_scrollbar_do( UI_DIALOG *dlg, UI_GADGET_SCROLLBAR * scrollbar, const d_event &event ); extern void ui_draw_scrollbar( UI_DIALOG *dlg, UI_GADGET_SCROLLBAR * scrollbar ); void ui_dputs_at( UI_DIALOG * dlg, short x, short y, const char * str ); extern void ui_dprintf_at( UI_DIALOG * dlg, short x, short y, const char * format, ... ) __attribute_format_printf(4, 5); #define ui_dprintf_at(A1,A2,A3,F,...) dxx_call_printf_checked(ui_dprintf_at,ui_dputs_at,(A1,A2,A3),(F),##__VA_ARGS__) extern void ui_draw_radio( UI_DIALOG *dlg, UI_GADGET_RADIO * radio ); __attribute_warn_unused_result std::unique_ptr ui_add_gadget_radio(UI_DIALOG * dlg, short x, short y, short w, short h, short group, const char * text); window_event_result ui_radio_do( UI_DIALOG *dlg, UI_GADGET_RADIO * radio, const d_event &event ); extern void ui_radio_set_value(UI_GADGET_RADIO *radio, int value); extern void ui_draw_checkbox( UI_DIALOG *dlg, UI_GADGET_CHECKBOX * checkbox ); __attribute_warn_unused_result std::unique_ptr ui_add_gadget_checkbox(UI_DIALOG * dlg, short x, short y, short w, short h, short group, const char * text); window_event_result ui_checkbox_do( UI_DIALOG *dlg, UI_GADGET_CHECKBOX * checkbox, const d_event &event ); extern void ui_checkbox_check(UI_GADGET_CHECKBOX * checkbox, int check); extern UI_GADGET * ui_gadget_get_prev( UI_GADGET * gadget ); extern UI_GADGET * ui_gadget_get_next( UI_GADGET * gadget ); extern void ui_gadget_calc_keys( UI_DIALOG * dlg); void ui_listbox_change(UI_DIALOG *dlg, UI_GADGET_LISTBOX *listbox, uint_fast32_t numitems, const char *const *list); extern void ui_draw_inputbox( UI_DIALOG *dlg, UI_GADGET_INPUTBOX * inputbox ); __attribute_warn_unused_result std::unique_ptr ui_add_gadget_inputbox(UI_DIALOG * dlg, short x, short y, short w, short h, const char * text); template __attribute_warn_unused_result static inline std::unique_ptr ui_add_gadget_inputbox(UI_DIALOG * dlg, short x, short y, const char (&text)[L]) { static_assert(SL <= L, "SL too large"); return ui_add_gadget_inputbox(dlg, x, y, L, SL, text); } window_event_result ui_inputbox_do( UI_DIALOG *dlg, UI_GADGET_INPUTBOX * inputbox, const d_event &event ); extern void ui_inputbox_set_text(UI_GADGET_INPUTBOX *inputbox, const char *text); window_event_result ui_userbox_do( UI_DIALOG *dlg, UI_GADGET_USERBOX * userbox, const d_event &event ); __attribute_warn_unused_result std::unique_ptr ui_add_gadget_userbox(UI_DIALOG * dlg, short x, short y, short w, short h); extern void ui_draw_userbox( UI_DIALOG *dlg, UI_GADGET_USERBOX * userbox ); int MenuX( int x, int y, int NumButtons, const char *const text[] ); int ui_get_filename(char (&filename)[PATH_MAX], const char *filespec, const char *message); void * ui_malloc( int size ); void ui_free( void * buffer ); #define UI_RECORD_MOUSE 1 #define UI_RECORD_KEYS 2 #define UI_STATUS_NORMAL 0 #define UI_STATUS_RECORDING 1 #define UI_STATUS_PLAYING 2 #define UI_STATUS_FASTPLAY 3 int ui_get_file( char * filename, const char * Filespec ); void ui_draw_icon( UI_GADGET_ICON * icon ); window_event_result ui_icon_do( UI_DIALOG *dlg, UI_GADGET_ICON * icon, const d_event &event ); __attribute_warn_unused_result std::unique_ptr ui_add_gadget_icon(UI_DIALOG * dlg, const char * text, short x, short y, short w, short h, int k,int (*f)()); int DecodeKeyText( const char * text ); void GetKeyDescription(char (&text)[100], uint_fast32_t keypress); int menubar_init(grs_canvas &canvas, const char * filename ); extern void menubar_close(); extern void menubar_hide(); extern void menubar_show(); void ui_pad_init(); void ui_pad_close(); void ui_pad_activate(UI_DIALOG &dlg, uint_fast32_t x, uint_fast32_t y); void ui_pad_deactivate(); void ui_pad_goto(int n); void ui_pad_goto_next(); void ui_pad_goto_prev(); int ui_pad_read( int n, const char * filename ); int ui_pad_get_current(); void ui_pad_draw(UI_DIALOG *dlg, int x, int y); void ui_barbox_open( const char * text, int length ); void ui_barbox_update( int position ); void ui_barbox_close(); extern int ui_button_any_drawn; } #endif