Skip to content

Commit

Permalink
Merge pull request #72871 from katemonster33/imgui_keybindings_focus_fix
Browse files Browse the repository at this point in the history
  • Loading branch information
akrieger authored Apr 8, 2024
2 parents 0095b30 + f9b0f34 commit a1e69f1
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 19 deletions.
56 changes: 56 additions & 0 deletions src/cata_imgui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "input.h"
#include "output.h"
#include "ui_manager.h"
#include "input_context.h"

static ImGuiKey cata_key_to_imgui( int cata_key );

Expand Down Expand Up @@ -461,6 +462,13 @@ class cataimgui::window_impl
}
};

class cataimgui::filter_box_impl
{
public:
std::array<char, 255> text;
ImGuiID id;
};

cataimgui::window::window( int window_flags )
{
p_impl = nullptr;
Expand Down Expand Up @@ -599,3 +607,51 @@ cataimgui::bounds cataimgui::window::get_bounds()
{
return { -1.f, -1.f, -1.f, -1.f };
}

void cataimgui::window::draw_filter( const input_context &ctxt, bool filtering_active )
{
if( !filter_impl ) {
filter_impl = std::make_unique<cataimgui::filter_box_impl>();
filter_impl->id = 0;
filter_impl->text[0] = '\0';
}

if( !filtering_active ) {
action_button( "FILTER", ctxt.get_button_text( "FILTER" ) );
ImGui::SameLine();
action_button( "RESET_FILTER", ctxt.get_button_text( "RESET_FILTER" ) );
ImGui::SameLine();
} else {
action_button( "QUIT", ctxt.get_button_text( "QUIT", _( "Cancel" ) ) );
ImGui::SameLine();
action_button( "TEXT.CONFIRM", ctxt.get_button_text( "TEXT.CONFIRM", _( "OK" ) ) );
ImGui::SameLine();
}
ImGui::BeginDisabled( !filtering_active );
ImGui::InputText( "##FILTERBOX", filter_impl->text.data(),
filter_impl->text.size() );
ImGui::EndDisabled();
if( !filter_impl->id ) {
filter_impl->id = GImGui->LastItemData.ID;
}
}

std::string cataimgui::window::get_filter()
{
if( filter_impl ) {
return std::string( filter_impl->text.data() );
} else {
return std::string();
}
}

void cataimgui::window::clear_filter()
{
if( filter_impl && filter_impl->id != 0 ) {
ImGuiInputTextState *input_state = ImGui::GetInputTextState( filter_impl->id );
if( input_state ) {
input_state->ClearText();
filter_impl->text[0] = '\0';
}
}
}
5 changes: 5 additions & 0 deletions src/cata_imgui.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct item_info_data;
struct point;
class ImVec2;
class Font;
class input_context;

namespace cataimgui
{
Expand Down Expand Up @@ -78,6 +79,7 @@ void imvec2_to_point( ImVec2 *src, point *dest );
class window
{
std::unique_ptr<class window_impl> p_impl;
std::unique_ptr<class filter_box_impl> filter_impl;
bounds cached_bounds;
protected:
explicit window( int window_flags = 0 );
Expand All @@ -102,6 +104,8 @@ class window
size_t get_text_height( const char *text );
size_t str_width_to_pixels( size_t len );
size_t str_height_to_pixels( size_t len );
std::string get_filter();
void clear_filter();
void mark_resized();

protected:
Expand All @@ -112,6 +116,7 @@ class window
std::string button_action;
virtual bounds get_bounds();
virtual void draw_controls() = 0;
void draw_filter( const input_context &ctxt, bool filtering_active );
};

#if !(defined(TILES) || defined(WIN32))
Expand Down
86 changes: 67 additions & 19 deletions src/input_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
#include "imgui/imgui.h"

enum class kb_menu_status {
remove, reset, add, add_global, execute, show
remove, reset, add, add_global, execute, show, filter
};

class keybindings_ui : public cataimgui::window
Expand All @@ -48,7 +48,6 @@ class keybindings_ui : public cataimgui::window
const nc_color unbound_key = c_light_red;
const nc_color h_unbound_key = h_light_red;
input_context *ctxt;
char filter_text_impl[255]; // NOLINT(modernize-avoid-c-arrays)
public:
// current status: adding/removing/reseting/executing/showing keybindings
kb_menu_status status = kb_menu_status::show, last_status = kb_menu_status::execute;
Expand All @@ -61,7 +60,7 @@ class keybindings_ui : public cataimgui::window
std::string hotkeys;
int highlight_row_index = -1;
size_t scroll_offset = 0;
std::string filter_text;
//std::string filter_text;
keybindings_ui( bool permit_execute_action, input_context *parent );
void init();

Expand Down Expand Up @@ -321,6 +320,44 @@ std::string input_context::get_desc( const std::string &action_descriptor,
return rval;
}


std::string input_context::get_button_text( const std::string &action_descriptor ) const
{
std::string action_name = get_action_name( action_descriptor );
if( action_name.empty() ) {
action_name = action_descriptor;
}
return get_button_text( action_descriptor, action_name );
}

std::string input_context::get_button_text( const std::string &action_descriptor,
const std::string &action_text ) const
{
if( action_descriptor == "ANY_INPUT" ) {
return ""; // what sort of crazy button would this be?
}

bool is_local = false;
const std::vector<input_event> &events = inp_mngr.get_input_for_action( action_descriptor,
category, &is_local );
if( events.empty() ) {
return action_text;
}

std::vector<input_event> inputs_to_show;
for( const input_event &event : events ) {
if( is_event_type_enabled( event.type ) ) {
inputs_to_show.push_back( event );
}
}

if( inputs_to_show.empty() ) {
return action_text;
} else {
return string_format( "[%s] %s", inputs_to_show[0].long_description(), action_text );
}
}

std::string input_context::get_desc(
const std::string &action_descriptor,
const std::string &text,
Expand Down Expand Up @@ -608,7 +645,6 @@ static const std::map<fallback_action, int> fallback_keys = {
keybindings_ui::keybindings_ui( bool permit_execute_action,
input_context *parent ) : cataimgui::window( "KEYBINDINGS", ImGuiWindowFlags_NoNav )
{
filter_text_impl[0] = '\0';
this->ctxt = parent;

legend.push_back( colorize( _( "Unbound keys" ), unbound_key ) );
Expand Down Expand Up @@ -655,23 +691,24 @@ void keybindings_ui::draw_controls()
ImGui::SetCursorPosX( str_width_to_pixels( width ) - ( get_text_width(
button_text_no_color ) +
( ImGui::GetStyle().FramePadding.x * 2 ) + ImGui::GetStyle().ItemSpacing.x ) );
ImGui::BeginDisabled( status == kb_menu_status::filter );
action_button( buttons[legend_idx].first, button_text_no_color );
ImGui::EndDisabled();
}
for( ; legend_idx < legend.size(); legend_idx++ ) {
draw_colored_text( legend[legend_idx], c_white );
}
if( last_status != status && status == kb_menu_status::show ) {
ImGui::SetKeyboardFocusHere( 0 );
draw_filter( *ctxt, status == kb_menu_status::filter );
if( last_status != status && status == kb_menu_status::filter ) {
ImGui::SetKeyboardFocusHere( -1 );
}
strncpy( filter_text_impl, filter_text.c_str(), filter_text.length() );
ImGui::InputText( "##NOLABEL", filter_text_impl, std::extent_v< decltype( filter_text_impl )>,
status == kb_menu_status::show ? ImGuiInputTextFlags_None : ImGuiInputTextFlags_ReadOnly );
filter_text.assign( filter_text_impl );
ImGui::Separator();

if( last_status != status && status == kb_menu_status::show ) {
ImGui::SetNextWindowFocus();
}
if( ImGui::BeginTable( "KB_KEYS", 2, ImGuiTableFlags_ScrollY ) ) {
if( last_status != status && status != kb_menu_status::show ) {
ImGui::SetKeyboardFocusHere( 0 );
}

ImGui::TableSetupColumn( "Action Name",
ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_NoSort );
float keys_col_width = str_width_to_pixels( width ) - str_width_to_pixels( TERMX >= 100 ? 62 : 52 );
Expand Down Expand Up @@ -1299,10 +1336,13 @@ action_id input_context::display_menu_imgui( const bool permit_execute_action )
ctxt.register_action( "ADD_LOCAL" );
ctxt.register_action( "ADD_GLOBAL" );
ctxt.register_action( "TEXT.CLEAR" );
ctxt.register_action( "TEXT.CONFIRM" );
ctxt.register_action( "PAGE_UP" );
ctxt.register_action( "PAGE_DOWN" );
ctxt.register_action( "END" );
ctxt.register_action( "HOME" );
ctxt.register_action( "FILTER" );
ctxt.register_action( "RESET_FILTER" );
ctxt.register_action( "TEXT.INPUT_FROM_FILE" );
if( permit_execute_action ) {
ctxt.register_action( "EXECUTE" );
Expand Down Expand Up @@ -1357,13 +1397,19 @@ action_id input_context::display_menu_imgui( const bool permit_execute_action )
}

kb_menu.filtered_registered_actions = filter_strings_by_phrase( org_registered_actions,
kb_menu.filter_text );
kb_menu.get_filter() );

// In addition to the modifiable hotkeys, we also check for hardcoded
// keys, e.g. '+', '-', '=', '.' in order to prevent the user from
// entering an unrecoverable state.
if( action == "ADD_LOCAL"
|| raw_input_char == fallback_keys.at( fallback_action::add_local ) ) {
if( kb_menu.status == kb_menu_status::filter ) {
if( action == "QUIT" ) {
kb_menu.clear_filter( );
kb_menu.status = kb_menu_status::show;
} else if( action == "TEXT.CONFIRM" ) {
kb_menu.status = kb_menu_status::show;
}
} else if( action == "ADD_LOCAL" ) {
if( !kb_menu.filtered_registered_actions.empty() ) {
kb_menu.status = kb_menu_status::add;
}
Expand Down Expand Up @@ -1391,19 +1437,21 @@ action_id input_context::display_menu_imgui( const bool permit_execute_action )
} else if( action == "PAGE_UP" || action == "PAGE_DOWN" || action == "HOME" || action == "END" ) {
continue; // do nothing - on tiles version for some reason this counts as pressing various alphabet keys
} else if( action == "TEXT.CLEAR" ) {
kb_menu.filter_text.assign( "" );
kb_menu.clear_filter();
kb_menu.filtered_registered_actions = filter_strings_by_phrase( org_registered_actions,
"" );
} else if( !kb_menu.get_is_open() ) {
break;
} else if( action == "FILTER" ) {
kb_menu.status = kb_menu_status::filter;
} else if( action == "RESET_FILTER" ) {
kb_menu.clear_filter();
} else if( action == "QUIT" ) {
if( kb_menu.status != kb_menu_status::show ) {
kb_menu.status = kb_menu_status::show;
} else {
break;
}
} else if( action == "TEXT.INPUT_FROM_FILE" ) {
kb_menu.filter_text += get_input_string_from_file();
} else if( action == "HELP_KEYBINDINGS" ) {
// update available hotkeys in case they've changed
kb_menu.hotkeys = ctxt.get_available_single_char_hotkeys( display_help_hotkeys );
Expand Down
21 changes: 21 additions & 0 deletions src/input_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,27 @@ class input_context
unsigned int max_limit = 0,
const input_event_filter &evt_filter = allow_all_keys ) const;

/**
* Get a description for the action parameter along with a printable hotkey
* for the description in the format [%s] %s
*
* @param action_descriptor The action descriptor for which to return
* a description of the bound keys.
*/
std::string get_button_text( const std::string &action_descriptor ) const;

/**
* Get a description for the action parameter along with a printable hotkey
* for the description in the format [%s] %s
*
* @param action_descriptor The action descriptor for which to return
* a description of the bound keys.
*
* @param action_text The human readable description of the action.
*/
std::string get_button_text( const std::string &action_descriptor,
const std::string &action_text ) const;

/**
* Get a description based on `text`. If a bound key for `action_descriptor`
* satisfying `evt_filter` is contained in `text`, surround the key with
Expand Down

0 comments on commit a1e69f1

Please sign in to comment.