1 /** 2 * \file ui-menu.h 3 * \brief Generic menu interaction functions 4 * 5 * Copyright (c) 2007 Pete Mack 6 * Copyright (c) 2010 Andi Sidwell 7 * 8 * This work is free software; you can redistribute it and/or modify it 9 * under the terms of either: 10 * 11 * a) the GNU General Public License as published by the Free Software 12 * Foundation, version 2, or 13 * 14 * b) the "Angband licence": 15 * This software may be copied and distributed for educational, research, 16 * and not for profit purposes provided that this copyright and statement 17 * are included in all such copies. Other copyrights may also apply. 18 */ 19 20 #ifndef INCLUDED_UI_MENU_H 21 #define INCLUDED_UI_MENU_H 22 23 #include "ui-output.h" 24 25 /*** Constants ***/ 26 27 /* Colors for interactive menus */ 28 enum 29 { 30 CURS_UNKNOWN = 0, /* Use gray / dark blue for cursor */ 31 CURS_KNOWN = 1 /* Use white / light blue for cursor */ 32 }; 33 34 /** 35 * Type wrapper for various row styles. 36 */ 37 typedef enum _menu_row_style_t { 38 MN_ROW_STYLE_DISABLED = CURS_UNKNOWN, 39 MN_ROW_STYLE_ENABLED = CURS_KNOWN, 40 } menu_row_style_t; 41 42 /** 43 * Type wrapper for row validity. 44 */ 45 typedef enum _menu_row_validity_t { 46 MN_ROW_INVALID = 0, 47 MN_ROW_VALID = 1, 48 MN_ROW_HIDDEN = 2, 49 } menu_row_validity_t; 50 51 /* Cursor colours for different states */ 52 extern const byte curs_attrs[2][2]; 53 54 /* Standard menu orderings */ 55 extern const char lower_case[]; /* abc..z */ 56 extern const char upper_case[]; /* ABC..Z */ 57 extern const char all_letters[]; /* abc..zABC..Z */ 58 59 60 /* 61 Together, these classes define the constant properties of 62 the various menu classes. 63 64 A menu consists of: 65 - menu_iter, which describes how to handle the type of "list" that's 66 being displayed as a menu 67 - a menu_skin, which describes the layout of the menu on the screen. 68 - various bits and bobs of other data (e.g. the actual list of entries) 69 */ 70 struct menu; 71 72 73 74 /*** Predefined menu "skins" ***/ 75 76 /** 77 * Types of predefined skins available. 78 */ 79 typedef enum 80 { 81 /* 82 * A simple list of actions with an associated name and id. 83 * Private data: an array of menu_action 84 */ 85 MN_ITER_ACTIONS = 1, 86 87 /* 88 * A list of strings to be selected from - no associated actions. 89 * Private data: an array of const char * 90 */ 91 MN_ITER_STRINGS = 2 92 } menu_iter_id; 93 94 95 /** 96 * Primitive menu item with bound action. 97 */ 98 typedef struct 99 { 100 int flags; 101 char tag; 102 const char *name; 103 void (*action)(const char *title, int row); 104 } menu_action; 105 106 107 /** 108 * Flags for menu_actions. 109 */ 110 #define MN_ACT_GRAYED 0x0001 /* Allows selection but no action */ 111 #define MN_ACT_HIDDEN 0x0002 /* Row is hidden, but may be selected via tag */ 112 113 114 /** 115 * Underlying function set for displaying lists in a certain kind of way. 116 */ 117 typedef struct 118 { 119 /* Returns menu item tag (optional) */ 120 char (*get_tag)(struct menu *menu, int oid); 121 122 /* 123 * Validity checker (optional--all rows are assumed valid if not present) 124 * Return values will be interpreted as: 0 = no, 1 = yes, 2 = hide. 125 */ 126 int (*valid_row)(struct menu *menu, int oid); 127 128 /* Displays a menu row */ 129 void (*display_row)(struct menu *menu, int oid, bool cursor, 130 int row, int col, int width); 131 132 /* Handle 'positive' events (selections or cmd_keys) */ 133 /* XXX split out into a select handler and a cmd_key handler */ 134 bool (*row_handler)(struct menu *menu, const ui_event *event, int oid); 135 136 /* Called when the screen resizes */ 137 void (*resize)(struct menu *m); 138 } menu_iter; 139 140 141 142 /*** Menu skins ***/ 143 144 /** 145 * Identifiers for the kind of layout to use 146 */ 147 typedef enum 148 { 149 MN_SKIN_SCROLL = 1, /**< Ordinary scrollable single-column list */ 150 MN_SKIN_OBJECT = 2, /**< Special single-column list for object choice */ 151 MN_SKIN_COLUMNS = 3 /**< Multicolumn view */ 152 } skin_id; 153 154 155 /* Class functions for menu layout */ 156 typedef struct 157 { 158 /* Determines the cursor index given a (mouse) location */ 159 int (*get_cursor)(int row, int col, int n, int top, region *loc); 160 161 /* Displays the current list of visible menu items */ 162 void (*display_list)(struct menu *menu, int cursor, int *top, region *); 163 164 /* Specifies the relative menu item given the state of the menu */ 165 char (*get_tag)(struct menu *menu, int pos); 166 167 /* Process a direction */ 168 ui_event (*process_dir)(struct menu *menu, int dir); 169 } menu_skin; 170 171 172 173 /*** Base menu structure ***/ 174 175 /** 176 * Flags for menu appearance & behaviour 177 */ 178 enum 179 { 180 /* Tags are associated with the view, not the element */ 181 MN_REL_TAGS = 0x01, 182 183 /* No tags -- movement key and mouse browsing only */ 184 MN_NO_TAGS = 0x02, 185 186 /* Tags to be generated by the display function */ 187 MN_PVT_TAGS = 0x04, 188 189 /* Tag selections can be made regardless of the case of the key pressed. 190 * i.e. 'a' activates the line tagged 'A'. */ 191 MN_CASELESS_TAGS = 0x08, 192 193 /* double tap (or keypress) for selection; single tap is cursor movement */ 194 MN_DBL_TAP = 0x10, 195 196 /* no select events to be triggered */ 197 MN_NO_ACTION = 0x20, 198 199 /* Tags can be selected via an inscription */ 200 MN_INSCRIP_TAGS = 0x40 201 }; 202 203 204 /* Base menu type */ 205 struct menu 206 { 207 /** Public variables **/ 208 const char *header; 209 const char *title; 210 const char *prompt; 211 212 /* Keyboard shortcuts for menu selection-- shouldn't overlap cmd_keys */ 213 const char *selections; 214 215 /* Menu selections corresponding to inscriptions */ 216 char *inscriptions; 217 218 /* String of characters that when pressed, menu handler should be called */ 219 /* Mustn't overlap with 'selections' or some items may be unselectable */ 220 const char *cmd_keys; 221 222 /* String of characters that when pressed, return an EVT_SWITCH */ 223 /* Mustn't overlap with previous blah blah */ 224 const char *switch_keys; 225 226 /* auxiliary browser help function */ 227 void (*browse_hook)(int oid, void *db, const region *loc); 228 229 /* This is an auxiliary function to allow predefined skins to handle 230 * events for cmd_keys or switch_keys within menu_select() rather than 231 * have menu_select()'s caller handle them. If used, the function 232 * should return true if the event, ev, was handled or false if it was 233 * not. oid is the index of the cursor position in the list. */ 234 bool (*keys_hook)(struct menu *m, const ui_event *ev, int oid); 235 236 /* Flags specifying the behavior of this menu (from struct menu_flags) */ 237 int flags; 238 239 240 /** Private variables **/ 241 242 /* Stored boundary, set by menu_layout(). This is used to calculate 243 * where the menu should be displayed on display & resize */ 244 region boundary; 245 246 int filter_count; /* number of rows in current view */ 247 const int *filter_list; /* optional filter (view) of menu objects */ 248 249 int count; /* number of rows in underlying data set */ 250 void *menu_data; /* the data used to access rows. */ 251 252 const menu_skin *skin; /* menu display style functions */ 253 const menu_iter *row_funcs; /* menu skin functions */ 254 255 /* State variables */ 256 int cursor; /* Currently selected row */ 257 int top; /* Position in list for partial display */ 258 region active; /* Subregion actually active for selection */ 259 int cursor_x_offset; /* Adjustment to the default position of the cursor on a line. */ 260 }; 261 262 263 264 /*** Menu API ***/ 265 266 /** 267 * Allocate and return a new, initialised, menu. 268 */ 269 struct menu *menu_new(skin_id, const menu_iter *iter); 270 struct menu *menu_new_action(menu_action *acts, size_t n); 271 void menu_free(struct menu *m); 272 273 274 /** 275 * Initialise a menu, using the skin and iter functions specified. 276 */ 277 void menu_init(struct menu *menu, skin_id skin, const menu_iter *iter); 278 279 280 /** 281 * Given a predefined menu kind, return its iter functions. 282 */ 283 const menu_iter *menu_find_iter(menu_iter_id iter_id); 284 285 286 /** 287 * Set menu private data and the number of menu items. 288 * 289 * Menu private data is then available from inside menu callbacks using 290 * menu_priv(). 291 */ 292 void menu_setpriv(struct menu *menu, int count, void *data); 293 294 295 /** 296 * Return menu private data, set with menu_setpriv(). 297 */ 298 void *menu_priv(struct menu *menu); 299 300 301 /* 302 * Set a filter on what items a menu can display. 303 * 304 * Use this if your menu private data has 100 items, but you want to choose 305 * which ones of those to display at any given time, e.g. in an inventory menu. 306 * object_list[] should be an array of indexes to display, and n should be its 307 * length. 308 */ 309 void menu_set_filter(struct menu *menu, const int object_list[], int n); 310 311 312 /** 313 * Remove any filters set on a menu by menu_set_filer(). 314 */ 315 void menu_release_filter(struct menu *menu); 316 317 318 /** 319 * Ready a menu for display in the region specified. 320 * 321 * XXX not ready for dynamic resizing just yet 322 */ 323 bool menu_layout(struct menu *menu, const region *loc); 324 325 326 /** 327 * Display a menu. 328 * If reset_screen is true, it will reset the screen to the previously saved 329 * state before displaying. 330 */ 331 void menu_refresh(struct menu *menu, bool reset_screen); 332 333 334 /** 335 * Run a menu. 336 * 337 * 'notify' is a bitwise OR of ui_event_type events that you want to 338 * menu_select to return to you if they're not handled inside the menu loop. 339 * e.g. if you want to handle key events without specifying a menu_iter->handle 340 * function, you can set notify to EVT_KBRD, and any non-navigation keyboard 341 * events will stop the menu loop and return them to you. 342 * 343 * Some events are returned by default, and else are EVT_ESCAPE and EVT_SELECT. 344 * 345 * Event types that can be returned: 346 * EVT_ESCAPE: no selection; go back (by default) 347 * EVT_SELECT: menu->cursor is the selected menu item (by default) 348 * EVT_MOVE: the cursor has moved 349 * EVT_KBRD: unhandled keyboard events 350 * EVT_MOUSE: unhandled mouse events 351 * EVT_RESIZE: resize events 352 * 353 * XXX remove 'notify' 354 * 355 * If popup is true, the screen background is saved before starting the menu, 356 * and restored before each redraw. This allows variably-sized information 357 * at the bottom of the menu. 358 */ 359 ui_event menu_select(struct menu *menu, int notify, bool popup); 360 361 /** 362 * Set the menu cursor to the next valid row. 363 */ 364 void menu_ensure_cursor_valid(struct menu *m); 365 366 367 /* Interal menu stuff that cmd-know needs because it's quite horrible */ 368 bool menu_handle_mouse(struct menu *menu, const ui_event *in, ui_event *out); 369 bool menu_handle_keypress(struct menu *menu, const ui_event *in, ui_event *out); 370 371 /** 372 * Allow adjustment of the cursor's default x offset. 373 */ 374 void menu_set_cursor_x_offset(struct menu *m, int offset); 375 376 /*** Dynamic menu handling ***/ 377 378 struct menu *menu_dynamic_new(void); 379 void menu_dynamic_add(struct menu *m, const char *text, int value); 380 void menu_dynamic_add_valid(struct menu *m, const char *text, int value, menu_row_validity_t valid); 381 void menu_dynamic_add_label(struct menu *m, const char *text, const char label, int value, char *label_list); 382 void menu_dynamic_add_label_valid(struct menu *m, const char *text, const char label, int value, char *label_list, menu_row_validity_t valid); 383 size_t menu_dynamic_longest_entry(struct menu *m); 384 void menu_dynamic_calc_location(struct menu *m, int mx, int my); 385 int menu_dynamic_select(struct menu *m); 386 void menu_dynamic_free(struct menu *m); 387 388 #endif /* INCLUDED_UI_MENU_H */ 389