static ui_event scroll_process_direction(Menu_Type m, int dir) { ui_event eout = new ui_event(); /* Reject diagonals */ if (Misc.ddx[dir] != 0 && Misc.ddy[dir] != 0) { //this was empty. TODO: Maybe return null? } /* Forward/back */ else if (Misc.ddx[dir] != 0) { eout.type = Misc.ddx[dir] < 0 ? ui_event_type.EVT_ESCAPE : ui_event_type.EVT_SELECT; } /* Move up or down to the next valid & visible row */ else if (Misc.ddy[dir] != 0) { m.cursor += Misc.ddy[dir]; eout.type = ui_event_type.EVT_MOVE; } return(eout); }
/* * Handle mouse input in a menu. * * Mouse output is either moving, selecting, escaping, or nothing. Returns * true if something changes as a result of the click. */ bool handle_mouse(ui_event ein, out ui_event eout) { throw new NotImplementedException(); //int new_cursor; //if (!region_inside(&menu.active, in)) //{ // /* A click to the left of the active region is 'back' */ // if (!region_inside(&menu.active, in) && // in.mouse.x < menu.active.col) // out.type = EVT_ESCAPE; //} //else //{ // int count = menu.filter_list ? menu.filter_count : menu.count; // new_cursor = menu.skin.get_cursor(in.mouse.y, in.mouse.x, // count, menu.top, &menu.active); // if (is_valid_row(menu, new_cursor)) // { // if (new_cursor == menu.cursor || !(menu.flags & MN_DBL_TAP)) // out.type = EVT_SELECT; // else // out.type = EVT_MOVE; // menu.cursor = new_cursor; // } //} //return out.type != EVT_NONE; }
static bool cmd_list_action(Menu_Type m, ui_event mevent, int oid) { if (mevent.type == ui_event_type.EVT_SELECT) { return(cmd_menu(ref Command_List.all[oid], m.menu_data)); } else { return(false); } }
/* Check whether a (mouse) event is inside a region */ public bool region_inside(ui_event key) { throw new NotImplementedException(); ////TODO make sure this is right... I don't think it is... I need to ensure the mouse.x/y is correct //if ((col > key.mouse.x) || (col + width <= key.mouse.x)) // return false; //if ((row > key.mouse.y) || (row + page_rows <= key.mouse.y)) // return false; //return true; }
/** * Handle any menu command keys / SELECT events. * * Returns true if the key was handled at all (including if it's not handled * and just ignored). */ bool handle_action(ui_event min) { if (row_funcs.row_handler != null) { int oid = cursor; if (filter_list != null) { oid = filter_list[cursor]; } return(row_funcs.row_handler(this, min, oid)); } return(false); }
static bool menu_action_handle(Menu_Type m, ui_event Event, int oid) { throw new NotImplementedException(); //menu_action *acts = menu_priv(m); //if (event.type == EVT_SELECT) //{ // if (!(acts.flags & MN_ACT_GRAYED) && acts[oid].action) // { // acts[oid].action(acts[oid].name, m.cursor); // return true; // } //} //return false; }
/** * Handle a textui mouseclick. */ static void process_click(ui_event e) { throw new NotImplementedException(); // int x, y; // if (!OPT(mouse_movement)) return; // y = KEY_GRID_Y(e); // x = KEY_GRID_X(e); // /* Check for a valid location */ // if (!in_bounds_fully(y, x)) return; // /* XXX show context menu here */ // if ((p_ptr.py == y) && (p_ptr.px == x)) // textui_cmd_rest(); // else /* if (e.mousebutton == 1) */ // { // if (p_ptr.timed[TMD_CONFUSED]) // { // cmd_insert(CMD_WALK); // } // else // { // cmd_insert(CMD_PATHFIND); // cmd_set_arg_point(cmd_get_top(), 0, y, x); // } // } //#if 0 // else if (e.mousebutton == 2) // { // target_set_location(y, x); // msg_print("Target set."); // } //#endif }
/** * Handle navigation keypresses. * * Returns true if they key was intelligible as navigation, regardless of * whether any action was taken. */ bool handle_keypress(ui_event ein, ref ui_event eout) { bool eat = false; int count = (this.filter_list != null) ? this.filter_count : this.count; if(eout == null) eout = new ui_event(); /* Get the new cursor position from the menu item tags */ int new_cursor = get_cursor_key(this.top, ein.key); if (new_cursor >= 0 && is_valid_row(new_cursor)) { if ((this.flags & (int)menu_type_flags.MN_DBL_TAP) == 0 || new_cursor == this.cursor) eout.type = ui_event_type.EVT_SELECT; else eout.type = ui_event_type.EVT_MOVE; this.cursor = new_cursor; } /* Escape stops us here */ else if (ein.key.code == keycode_t.ESCAPE) eout.type = ui_event_type.EVT_ESCAPE; /* Menus with no rows can't be navigated or used, so eat all keypresses */ else if (count <= 0) eat = true; /* Try existing, known keys */ else if (ein.key.code == (keycode_t)' ') { int rows = this.active.page_rows; int total = count; if (rows < total) { /* Go to start of next page */ this.cursor += this.active.page_rows; if (this.cursor >= total - 1) this.cursor = 0; this.top = this.cursor; eout.type = ui_event_type.EVT_MOVE; } else { eat = true; } } else if (ein.key.code == (keycode_t)'\n' || ein.key.code == (keycode_t)'\r') eout.type = ui_event_type.EVT_SELECT; /* Try directional movement */ else { int dir = Utilities.target_dir(ein.key); if (dir != 0) { eout = this.skin.process_dir(this, dir); if (eout.type == ui_event_type.EVT_MOVE) { while (!is_valid_row(this.cursor)) { /* Loop around */ if (this.cursor > count - 1) this.cursor = 0; else if (this.cursor < 0) this.cursor = count - 1; else this.cursor += Misc.ddy[dir]; } Misc.assert(this.cursor >= 0); Misc.assert(this.cursor < count); } } } return eat; }
/** * Handle any menu command keys / SELECT events. * * Returns true if the key was handled at all (including if it's not handled * and just ignored). */ bool handle_action(ui_event min) { if (row_funcs.row_handler != null) { int oid = cursor; if (filter_list != null) oid = filter_list[cursor]; return row_funcs.row_handler(this, min, oid); } return false; }
static ui_event scroll_process_direction(Menu_Type m, int dir) { ui_event eout = new ui_event(); /* Reject diagonals */ if(Misc.ddx[dir] != 0 && Misc.ddy[dir] != 0) { //this was empty. TODO: Maybe return null? } /* Forward/back */ else if(Misc.ddx[dir] != 0) eout.type = Misc.ddx[dir] < 0 ? ui_event_type.EVT_ESCAPE : ui_event_type.EVT_SELECT; /* Move up or down to the next valid & visible row */ else if(Misc.ddy[dir] != 0) { m.cursor += Misc.ddy[dir]; eout.type = ui_event_type.EVT_MOVE; } return eout; }
/* * Run a menu. * * If popup is true, the screen is saved before the menu is drawn, and * restored afterwards. Each time a popup menu is redrawn, it resets the * screen before redrawing. */ public ui_event select(ui_event_type notify, bool popup) { ui_event min = new ui_event(); //EVENT_EMPTY; bool no_act = ((flags & (int)menu_type_flags.MN_NO_ACTION) == 1) ? true : false; Misc.assert(active.width != 0 && active.page_rows != 0); notify |= (ui_event_type.EVT_SELECT | ui_event_type.EVT_ESCAPE); if(popup) { Utilities.screen_save(); } /* Stop on first unhandled event */ while ((min.type & notify) == 0) { ui_event mout = new ui_event(); refresh(popup); min = Utilities.inkey_ex(); /* Handle mouse & keyboard commands */ if (min.type == ui_event_type.EVT_MOUSE) { handle_mouse(min, out mout); } else if (min.type == ui_event_type.EVT_KBRD) { if (!no_act && (cmd_keys != null && cmd_keys.Length > 0) && cmd_keys.IndexOf((char)min.key.code) >= 0 && handle_action(min)) continue; handle_keypress(min, ref mout); } else if (min.type == ui_event_type.EVT_RESIZE) { menu_calc_size(); if (row_funcs.resize != null) row_funcs.resize(this); } /* XXX should redraw menu here if cursor has moved */ /* If we've selected an item, then send that event out */ if (mout.type == ui_event_type.EVT_SELECT && !no_act && handle_action(mout)) continue; /* Notify about the outgoing type */ if ((notify & mout.type) != (ui_event_type)0) { if(popup) { Utilities.screen_load(); } return mout; } } if(popup) { Utilities.screen_load(); } return min; }
/* * Request a command from the user. * * Note that "caret" ("^") is treated specially, and is used to * allow manual input of control characters. This can be used * on many machines to request repeated tunneling (Ctrl-H) and * on the Macintosh to request "Control-Caret". * * Note that "backslash" is treated specially, and is used to bypass any * keymap entry for the following character. This is useful for macros. */ static ui_event get_command() { int mode = (int)(Option.rogue_like_commands.value ? Keymap.Mode.ROGUE : Keymap.Mode.ORIG); keypress[] tmp = new keypress[2] { new keypress(), new keypress() }; ui_event ke = new ui_event(); //ui_event ret = ke; keypress[] act = null; /* Get command */ while (true) { /* Hack -- no flush needed */ Term.msg_flag = false; /* Activate "command mode" */ Utilities.inkey_flag = true; /* Get a command */ ke = Utilities.inkey_ex(); if (ke.type == ui_event_type.EVT_KBRD) { bool keymap_ok = true; switch ((char)ke.key.code) { case '0': { int count = TextUI.get_count(); throw new NotImplementedException(); //if (count == -1 || !get_com_ex("Command: ", &ke)) // continue; //else // p_ptr.command_arg = count; //break; } case '\\': { /* Allow keymaps to be bypassed */ throw new NotImplementedException(); //(void)get_com_ex("Command: ", &ke); //keymap_ok = false; //break; } case '^': { throw new NotImplementedException(); ///* Allow "control chars" to be entered */ //if (get_com("Control: ", &ke.key)) // ke.key.code = KTRL(ke.key.code); //break; } } /* Find any relevant keymap */ if (keymap_ok) { act = Keymap.find(mode, ke.key); //if (act == null) { // ret = ke; //} } } /* Erase the message line */ Utilities.prt("", 0, 0); if (ke.type == ui_event_type.EVT_BUTTON) { /* Buttons are always specified in standard keyset */ act = tmp; tmp[0] = ke.key; } /* Apply keymap if not inside a keymap already */ if (ke.key.code != (keycode_t)0 && act != null && Utilities.inkey_next == null) { //int n = 0; //while (n < act.Length && act[n] != null)//act[n].type // n++; ///* Make room for the terminator */ //n += 1; /* Install the keymap */ for (int q = 0; q < act.Length; q++) //It used to check for q < n instead { request_command_buffer[q] = act[q]; //memcpy(request_command_buffer, act, n); } /* Start using the buffer */ Utilities.inkey_next = new List <keypress>(request_command_buffer); /* Continue */ //ret.type = ke.type; //ret.mouse = ke.mouse; //ret.key = act[0]; continue; } /* Done */ break; } return(ke); }
/* * Convert a "key event" into a "location" (X) */ public static int KEY_GRID_X(ui_event K) { return ((int)(((K.mouse.x - COL_MAP) / Term.tile_width) + Term.instance.offset_x)); }
/* * */ static bool store_menu_handle(Menu_Type m, ui_event mevent, int oid) { bool processed = true; if (mevent.type == ui_event_type.EVT_SELECT) { /* Nothing for now, except "handle" the event */ return true; /* In future, maybe we want a display a list of what you can do. */ } else if (mevent.type == ui_event_type.EVT_KBRD) { bool storechange = false; switch ((char)mevent.key.code) { case 's': case 'd': storechange = store_sell(); break; case 'p': case 'g': storechange = store_purchase(oid); break; case 'l': case 'x': store_examine(oid); break; case '?': { /* Toggle help */ if ((store_flags & STORE_SHOW_HELP) != 0) store_flags &= ~(STORE_SHOW_HELP); else store_flags |= STORE_SHOW_HELP; /* Redisplay */ store_flags |= STORE_INIT_CHANGE; break; } case '=': { Do_Command.options(); store_menu_set_selections(m, false); break; } default: processed = store_process_command_key(mevent.key); break; } if ((char)mevent.key.code == UIEvent.KTRL('R')) { /* XXX redraw functionality should be another menu_iter handler */ Term.clear(); store_flags |= (STORE_FRAME_CHANGE | STORE_GOLD_CHANGE); } /* Let the game handle any core commands (equipping, etc) */ Game_Command.process_command(cmd_context.CMD_STORE, true); if (storechange) store_menu_recalc(m); if (processed) { Game_Event.signal(Game_Event.Event_Type.INVENTORY); Game_Event.signal(Game_Event.Event_Type.EQUIPMENT); } /* Notice and handle stuff */ Misc.p_ptr.notice_stuff(); Misc.p_ptr.handle_stuff(); /* Display the store */ store_display_recalc(m); store_menu_recalc(m); store_redraw(); return processed; } return false; }
/** * Handle navigation keypresses. * * Returns true if they key was intelligible as navigation, regardless of * whether any action was taken. */ bool handle_keypress(ui_event ein, ref ui_event eout) { bool eat = false; int count = (this.filter_list != null) ? this.filter_count : this.count; if (eout == null) { eout = new ui_event(); } /* Get the new cursor position from the menu item tags */ int new_cursor = get_cursor_key(this.top, ein.key); if (new_cursor >= 0 && is_valid_row(new_cursor)) { if ((this.flags & (int)menu_type_flags.MN_DBL_TAP) == 0 || new_cursor == this.cursor) { eout.type = ui_event_type.EVT_SELECT; } else { eout.type = ui_event_type.EVT_MOVE; } this.cursor = new_cursor; } /* Escape stops us here */ else if (ein.key.code == keycode_t.ESCAPE) { eout.type = ui_event_type.EVT_ESCAPE; } /* Menus with no rows can't be navigated or used, so eat all keypresses */ else if (count <= 0) { eat = true; } /* Try existing, known keys */ else if (ein.key.code == (keycode_t)' ') { int rows = this.active.page_rows; int total = count; if (rows < total) { /* Go to start of next page */ this.cursor += this.active.page_rows; if (this.cursor >= total - 1) { this.cursor = 0; } this.top = this.cursor; eout.type = ui_event_type.EVT_MOVE; } else { eat = true; } } else if (ein.key.code == (keycode_t)'\n' || ein.key.code == (keycode_t)'\r') { eout.type = ui_event_type.EVT_SELECT; } /* Try directional movement */ else { int dir = Utilities.target_dir(ein.key); if (dir != 0) { eout = this.skin.process_dir(this, dir); if (eout.type == ui_event_type.EVT_MOVE) { while (!is_valid_row(this.cursor)) { /* Loop around */ if (this.cursor > count - 1) { this.cursor = 0; } else if (this.cursor < 0) { this.cursor = count - 1; } else { this.cursor += Misc.ddy[dir]; } } Misc.assert(this.cursor >= 0); Misc.assert(this.cursor < count); } } } return(eat); }
public const int QUIVER_TAGS = 0x80; /* 0-9 are quiver slots when selecting */ /* * Convert a "key event" into a "location" (Y) */ public static int KEY_GRID_Y(ui_event K) { return((int)(((K.mouse.y - ROW_MAP) / Term.tile_height) + Term.instance.offset_y)); }
static bool cmd_list_action(Menu_Type m, ui_event mevent, int oid) { if (mevent.type == ui_event_type.EVT_SELECT) return cmd_menu(ref Command_List.all[oid], m.menu_data); else return false; }
/* * Run a menu. * * If popup is true, the screen is saved before the menu is drawn, and * restored afterwards. Each time a popup menu is redrawn, it resets the * screen before redrawing. */ public ui_event select(ui_event_type notify, bool popup) { ui_event min = new ui_event(); //EVENT_EMPTY; bool no_act = ((flags & (int)menu_type_flags.MN_NO_ACTION) == 1) ? true : false; Misc.assert(active.width != 0 && active.page_rows != 0); notify |= (ui_event_type.EVT_SELECT | ui_event_type.EVT_ESCAPE); if (popup) { Utilities.screen_save(); } /* Stop on first unhandled event */ while ((min.type & notify) == 0) { ui_event mout = new ui_event(); refresh(popup); min = Utilities.inkey_ex(); /* Handle mouse & keyboard commands */ if (min.type == ui_event_type.EVT_MOUSE) { handle_mouse(min, out mout); } else if (min.type == ui_event_type.EVT_KBRD) { if (!no_act && (cmd_keys != null && cmd_keys.Length > 0) && cmd_keys.IndexOf((char)min.key.code) >= 0 && handle_action(min)) { continue; } handle_keypress(min, ref mout); } else if (min.type == ui_event_type.EVT_RESIZE) { menu_calc_size(); if (row_funcs.resize != null) { row_funcs.resize(this); } } /* XXX should redraw menu here if cursor has moved */ /* If we've selected an item, then send that event out */ if (mout.type == ui_event_type.EVT_SELECT && !no_act && handle_action(mout)) { continue; } /* Notify about the outgoing type */ if ((notify & mout.type) != (ui_event_type)0) { if (popup) { Utilities.screen_load(); } return(mout); } } if (popup) { Utilities.screen_load(); } return(min); }
/* * Convert a "key event" into a "location" (X) */ public static int KEY_GRID_X(ui_event K) { return((int)(((K.mouse.x - COL_MAP) / Term.tile_width) + Term.instance.offset_x)); }
/* Allow the user to select from the current menu, and return the * corresponding command to the game. Some actions are handled entirely * by the UI (displaying help text, for instance). */ static birth_stage menu_question(birth_stage current, Menu_Type current_menu, Command_Code choice_command) { birthmenu_data menu_data = current_menu.menu_data as birthmenu_data; birth_stage next = birth_stage.BIRTH_RESET; /* Print the question currently being asked. */ clear_question(); Term.putstr(QUESTION_COL, QUESTION_ROW, -1, ConsoleColor.Yellow, menu_data.hint); current_menu.cmd_keys = "?=*\x18"; /* ?, =, *, <ctl-X> */ while (next == birth_stage.BIRTH_RESET) { /* Display the menu, wait for a selection of some sort to be made. */ ui_event cx = current_menu.select(ui_event_type.EVT_KBRD, false); /* As all the menus are displayed in "hierarchical" style, we allow * use of "back" (left arrow key or equivalent) to step back in * the proces as well as "escape". */ if (cx.type == ui_event_type.EVT_ESCAPE) { next = birth_stage.BIRTH_BACK; } else if (cx.type == ui_event_type.EVT_SELECT) { if (current == birth_stage.BIRTH_ROLLER_CHOICE) { Game_Command.insert(Command_Code.FINALIZE_OPTIONS); if (current_menu.cursor != 0) { /* Do a first roll of the stats */ Game_Command.insert(Command_Code.ROLL_STATS); next = current + 2; } else { /* * Make sure we've got a point-based char to play with. * We call point_based_start here to make sure we get * an update on the points totals before trying to * display the screen. The call to CMD_RESET_STATS * forces a rebuying of the stats to give us up-to-date * totals. This is, it should go without saying, a hack. */ point_based_start(); Game_Command.insert(Command_Code.RESET_STATS); Game_Command.get_top().set_arg_choice(0, 1); next = current + 1; } } else { Game_Command.insert(choice_command); Game_Command.get_top().set_arg_choice(0, current_menu.cursor); next = current + 1; } } else if (cx.type == ui_event_type.EVT_KBRD) { /* '*' chooses an option at random from those the game's provided. */ if (cx.key.code == (keycode_t)'*' && menu_data.allow_random) { current_menu.cursor = Random.randint0(current_menu.count); Game_Command.insert(choice_command); Game_Command.get_top().set_arg_choice(0, current_menu.cursor); current_menu.refresh(false); next = current + 1; } else if (cx.key.code == (keycode_t)'=') { Do_Command.options_birth(); next = current; } else if (cx.key.code == (keycode_t)UIEvent.KTRL('X')) { Game_Command.insert(Command_Code.QUIT); next = birth_stage.BIRTH_COMPLETE; } else if (cx.key.code == (keycode_t)'?') { Do_Command.help(); } } } return(next); }
/* * Convert a "key event" into a "location" (Y) */ public static int KEY_GRID_Y(ui_event K) { return ((int) (((K.mouse.y - ROW_MAP) / Term.tile_height) + Term.instance.offset_y)); }
/** Convert a string of keypresses into their textual representation */ public static string keypress_to_text(ui_event[] src, bool expand_backslash) { string buf = ""; foreach (ui_event evt in src){ if (evt.type != ui_event_type.EVT_KBRD) break; keycode_t i = evt.key.code; byte mods = evt.key.mods; string desc = keycode_find_desc(i); /* un-ktrl control characters if they don't have a description */ /* this is so that Tab (^I) doesn't get turned into ^I but gets * displayed as [Tab] */ if ((byte)i < 0x20 && desc == null){ mods |= (byte)keycode_t.KC_MOD_CONTROL; i = (keycode_t)UN_KTRL(i); } if (mods != 0) { if (((mods & (byte)keycode_t.KC_MOD_CONTROL) != 0) && (mods & ~(byte)keycode_t.KC_MOD_CONTROL) == 0) { buf += "^"; } else { buf += "{"; if((mods & (byte)keycode_t.KC_MOD_CONTROL) != 0) buf += "^"; if((mods & (byte)keycode_t.KC_MOD_SHIFT) != 0) buf += "S"; if((mods & (byte)keycode_t.KC_MOD_ALT) != 0) buf += "A"; if((mods & (byte)keycode_t.KC_MOD_META) != 0) buf += "M"; if((mods & (byte)keycode_t.KC_MOD_KEYPAD) != 0) buf += "K"; buf += "}"; } } if (desc != null) { buf += "[" + desc + "]"; } else { switch ((char)i) { case '\a': buf += "\a"; break; case '\\': { if (expand_backslash) buf += "\\\\"; else buf += "\\"; break; } case '^': buf += "\\^"; break; case '[': buf += "\\["; break; default: { if ((char)i < 127) buf += (char)i; else buf += "\\x" + i.ToString("X2"); break; } } } } return buf; }