Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add a tab bar to the uilist showing categories, if there are any #77123

Merged
merged 2 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/advanced_inv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2077,9 +2077,9 @@ void query_destination_callback::draw_squares( const uilist *menu )
ImGui::NewLine();
cata_assert( menu->entries.size() >= 9 );
int sel = 0;
if( menu->hovered >= 0 && static_cast<size_t>( menu->hovered ) < menu->entries.size() ) {
if( menu->previewing >= 0 && static_cast<size_t>( menu->previewing ) < menu->entries.size() ) {
sel = _adv_inv.screen_relative_location(
static_cast <aim_location>( menu->hovered + 1 ) );
static_cast <aim_location>( menu->previewing + 1 ) );
}
for( int i = 1; i < 10; i++ ) {
aim_location loc = _adv_inv.screen_relative_location( static_cast <aim_location>( i ) );
Expand Down
2 changes: 1 addition & 1 deletion src/item_contents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ void pocket_favorite_callback::refresh( uilist *menu )
continue;
}

if( i == menu->hovered ) {
if( i == menu->previewing ) {
selected_pocket = pocket;
pocket_num = std::get<1>( pocket_val ) + 1;
break;
Expand Down
6 changes: 3 additions & 3 deletions src/magic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2530,8 +2530,8 @@ class spellcasting_callback : public uilist_callback
ImGui::NewLine();
if( ImGui::BeginChild( "spell info", { desired_extra_space_right( ), 0 }, false,
ImGuiWindowFlags_AlwaysAutoResize ) ) {
if( menu->hovered >= 0 && static_cast<size_t>( menu->hovered ) < known_spells.size() ) {
display_spell_info( menu->hovered );
if( menu->previewing >= 0 && static_cast<size_t>( menu->previewing ) < known_spells.size() ) {
display_spell_info( menu->previewing );
}
}
ImGui::EndChild();
Expand Down Expand Up @@ -2944,7 +2944,7 @@ spell &known_magic::select_spell( Character &guy )
-1.0,
-1.0,
std::max( 80, TERMX * 3 / 8 ) *ImGui::CalcTextSize( "X" ).x,
clamp( static_cast<int>( known_spells_sorted.size() ), 24, TERMY * 9 / 10 ) *ImGui::GetTextLineHeightWithSpacing(),
clamp( static_cast<int>( known_spells_sorted.size() ), 24, TERMY * 9 / 10 ) *ImGui::GetTextLineHeight(),
};

spell_menu.title = _( "Choose a Spell" );
Expand Down
2 changes: 1 addition & 1 deletion src/magic_teleporter_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class teleporter_callback : public uilist_callback
}
void refresh( uilist *menu ) override {
ImGui::TableSetColumnIndex( 2 );
const int entnum = menu->hovered;
const int entnum = menu->previewing;
if( entnum >= 0 && static_cast<size_t>( entnum ) < index_pairs.size() ) {
avatar &player_character = get_avatar();
int dist = rl_dist( player_character.global_omt_location(), index_pairs[entnum] );
Expand Down
86 changes: 60 additions & 26 deletions src/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,29 @@ void uilist_impl::draw_controls()
ImGui::Separator();
}

if( !parent.categories.empty() ) {
if( ImGui::BeginTabBar( "##categories",
ImGuiTabBarFlags_FittingPolicyScroll | ImGuiTabBarFlags_NoCloseWithMiddleMouseButton ) ) {
for( size_t i = 0; i < parent.categories.size(); i++ ) {
auto cat = parent.categories[ i ];
bool selected = i == parent.switch_to_category;
ImGuiTabItemFlags_ flags = ImGuiTabItemFlags_None;
if( selected ) {
flags = ImGuiTabItemFlags_SetSelected;
parent.switch_to_category = -1;
}
if( ImGui::BeginTabItem( cat.second.c_str(), nullptr, flags ) ) {
if( parent.current_category != i ) {
parent.current_category = i;
parent.filterlist();
}
ImGui::EndTabItem();
}
}
ImGui::EndTabBar();
}
}

// An invisible table with three columns. Used to create a sidebar effect.
// Ideally we would use a layout engine for this, but ImGui does not natively support any.
// TODO: Investigate using Stack Layout (https://github.com/thedmd/imgui/tree/feature/layout-external)
Expand Down Expand Up @@ -127,7 +150,7 @@ void uilist_impl::draw_controls()
}
if( ImGui::Selectable( "##s", is_selected, flags ) ) {
parent.fselected = i;
parent.selected = parent.hovered = parent.fentries[ parent.fselected ];
parent.selected = parent.previewing = parent.fentries[ parent.fselected ];
// We are going to return now that the user clicked on something, so scrolling seems
// unnecessary. However, the debug spawn item function reuses the same menu to let the
// user spawn multiple items and it’s weird if the correct item isn’t scrolled into view
Expand All @@ -140,7 +163,7 @@ void uilist_impl::draw_controls()
ImGui::GetCurrentContext()->HoveredIdPreviousFrame;
if( is_hovered && mouse_moved ) {
// this row is hovered and the hover state just changed, show context for it
parent.hovered = parent.fentries[ i ];
parent.previewing = parent.fentries[ i ];
}

// Force the spacing to be set to the padding value.
Expand Down Expand Up @@ -189,7 +212,7 @@ void uilist_impl::draw_controls()
if( !parent.footer_text.empty() ) {
description = parent.footer_text;
} else {
description = parent.entries[parent.hovered].desc;
description = parent.entries[parent.previewing].desc;
}
cataimgui::draw_colored_text( description );
}
Expand Down Expand Up @@ -441,7 +464,7 @@ void uilist::init()
ret_evt = input_event(); // last input event
keymap.clear(); // keymap[input_event] == index, for entries[index]
selected = 0; // current highlight, for entries[index]
hovered = 0; // current mouse highlight, for entries[index]
previewing = 0; // current mouse highlight, for entries[index]
entries.clear(); // uilist_entry(int returnval, bool enabled, int keycode, std::string text, ... TODO: submenu stuff)
started = false; // set to true when width and key calculations are done, and window is generated.
desc_enabled = false; // don't show option description by default
Expand Down Expand Up @@ -471,7 +494,7 @@ void uilist::init()
max_column_len = 0; // for calculating space for second column

categories.clear();
current_category = 0;
switch_to_category = current_category = 0;

input_category = "UILIST";
additional_actions.clear();
Expand Down Expand Up @@ -583,12 +606,12 @@ void uilist::filterlist()
if( fentries.empty() ) {
selected = -1;
} else {
selected = fentries [ 0 ];
previewing = selected = fentries [ 0 ];
}
} else if( fselected < static_cast<int>( fentries.size() ) ) {
selected = fentries[fselected];
previewing = selected = fentries[fselected];
} else {
fselected = selected = -1;
previewing = fselected = selected = -1;
}
// scroll to top of screen if all remaining entries fit the screen.
if( static_cast<int>( fentries.size() ) <= vmax ) {
Expand Down Expand Up @@ -681,6 +704,11 @@ void uilist::calc_data()
text_size.y += ( s.ItemSpacing.y * expected_num_lines ) + ( s.ItemSpacing.y * 2.0 );
}

ImVec2 tabs_size = {};
if( !categories.empty() ) {
tabs_size.y = ImGui::GetTextLineHeightWithSpacing() + ( 2.0 * s.FramePadding.y );
}

ImVec2 desc_size = {};
if( desc_enabled ) {
desc_size = calc_size( footer_text );
Expand All @@ -695,30 +723,36 @@ void uilist::calc_data()
float expected_num_lines = desc_size.y / ImGui::GetTextLineHeight();
desc_size.y += ( s.ItemSpacing.y * expected_num_lines ) + ( s.ItemSpacing.y * 2.0 );
}
float additional_height = title_size.y + text_size.y + desc_size.y + 2.0 *
float additional_height = title_size.y + text_size.y + desc_size.y + tabs_size.y + 2.0 *
( s.FramePadding.y + s.WindowBorderSize );

if( vmax * ImGui::GetTextLineHeightWithSpacing() + additional_height >
ImGui::GetMainViewport()->Size.y ) {
vmax = floorf( ( ImGui::GetMainViewport()->Size.y - additional_height ) /
0.9 * ImGui::GetMainViewport()->Size.y ) {
vmax = floorf( ( 0.9 * ImGui::GetMainViewport()->Size.y - additional_height +
( s.FramePadding.y * 2.0 ) ) /
ImGui::GetTextLineHeightWithSpacing() );
}

float padding = 2.0f * s.CellPadding.x;
calculated_hotkey_width = ImGui::CalcTextSize( "X" ).x;
calculated_hotkey_width = ImGui::CalcTextSize( "M" ).x;
calculated_label_width = 0.0;
calculated_secondary_width = 0.0;
for( int fentry : fentries ) {
calculated_label_width = std::max( calculated_label_width, calc_size( entries[fentry].txt ).x );
for( const uilist_entry &entry : entries ) {
calculated_label_width = std::max( calculated_label_width, calc_size( entry.txt ).x );
calculated_secondary_width = std::max( calculated_secondary_width,
calc_size( entries[fentry].ctxt ).x );
calc_size( entry.ctxt ).x );
}
calculated_menu_size = { 0.0, 0.0 };
calculated_menu_size.x += calculated_hotkey_width + padding;
calculated_menu_size.x += calculated_label_width + padding;
calculated_menu_size.x += calculated_secondary_width + padding;
calculated_menu_size.y = std::min( ImGui::GetMainViewport()->Size.y - additional_height,
vmax * ImGui::GetTextLineHeightWithSpacing() ) + ( s.FramePadding.y * 2.0 );
float max_avail_height = ImGui::GetMainViewport()->Size.y;
if( desired_bounds.has_value() ) {
max_avail_height = desired_bounds.value().h;
}
calculated_menu_size.y = std::min( max_avail_height - additional_height +
( s.FramePadding.y * 2.0 ),
vmax * ImGui::GetTextLineHeightWithSpacing() + ( s.FramePadding.y * 2.0 ) );

extra_space_left = 0.0;
extra_space_right = 0.0;
Expand Down Expand Up @@ -828,7 +862,7 @@ bool uilist::scrollby( const int scrollby )
}
}
if( static_cast<size_t>( fselected ) < fentries.size() ) {
selected = hovered = fentries [ fselected ];
selected = previewing = fentries [ fselected ];
if( callback != nullptr ) {
callback->select( this );
}
Expand Down Expand Up @@ -955,13 +989,13 @@ void uilist::query( bool loop, int timeout, bool allow_unfiltered_hotkeys )
} else if( filtering && ret_act == "UILIST.FILTER" ) {
inputfilter();
} else if( !categories.empty() && ( ret_act == "UILIST.LEFT" || ret_act == "UILIST.RIGHT" ) ) {
current_category += ret_act == "UILIST.LEFT" ? -1 : 1;
if( current_category < 0 ) {
current_category = categories.size() - 1;
} else if( current_category >= static_cast<int>( categories.size() ) ) {
current_category = 0;
int tmp = current_category + ( ret_act == "UILIST.LEFT" ? -1 : 1 );
if( tmp < 0 ) {
tmp = categories.size() - 1;
} else if( tmp >= static_cast<int>( categories.size() ) ) {
tmp = 0;
}
filterlist();
switch_to_category = static_cast<size_t>( tmp );
} else if( iter != keymap.end() ) {
if( allow_unfiltered_hotkeys ) {
const bool enabled = entries[iter->second].enabled;
Expand Down Expand Up @@ -1078,7 +1112,7 @@ void uilist::settext( const std::string &str )

void uilist::set_selected( int index )
{
selected = hovered = std::clamp( index, 0, static_cast<int>( entries.size() - 1 ) );
selected = previewing = std::clamp( index, 0, static_cast<int>( entries.size() - 1 ) );
}

void uilist::add_category( const std::string &key, const std::string &name )
Expand Down Expand Up @@ -1146,7 +1180,7 @@ void uimenu::finalize_addentries()

void uimenu::set_selected( int index )
{
menu.selected = menu.hovered = index;
menu.selected = menu.previewing = index;
}

void uimenu::set_title( const std::string &title )
Expand Down
9 changes: 5 additions & 4 deletions src/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ struct uilist_entry {
* }
* }
* void refresh( uilist *menu ) {
* if( menu->hovered >= 0 && static_cast<size_t>( menu->hovered ) < game_z.size() ) {
* ImGui::TextColored( c_red, "( %s )", game_z[menu->hovered]->name() );
* if( menu->previewing >= 0 && static_cast<size_t>( menu->previewing ) < game_z.size() ) {
* ImGui::TextColored( c_red, "( %s )", game_z[menu->previewing]->name() );
* }
* }
* }
Expand Down Expand Up @@ -486,7 +486,8 @@ class uilist // NOLINT(cata-xy)
bool need_to_scroll = false;
std::vector<std::pair<std::string, std::string>> categories;
std::function<bool( const uilist_entry &, const std::string & )> category_filter;
int current_category = 0;
size_t current_category = 0;
size_t switch_to_category = 0;

public:
// Results
Expand All @@ -495,7 +496,7 @@ class uilist // NOLINT(cata-xy)
input_event ret_evt;
int ret = 0;
int selected = 0;
int hovered = 0;
int previewing = 0;

void set_selected( int index );
};
Expand Down
8 changes: 4 additions & 4 deletions src/wish.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ class wish_mutate_callback: public uilist_callback

ImGui::TableSetColumnIndex( 2 );

if( menu->hovered >= 0 && static_cast<size_t>( menu->hovered ) < vTraits.size() ) {
const mutation_branch &mdata = vTraits[menu->hovered].obj();
if( menu->previewing >= 0 && static_cast<size_t>( menu->previewing ) < vTraits.size() ) {
const mutation_branch &mdata = vTraits[menu->previewing].obj();

ImGui::TextUnformatted( mdata.valid ? _( "Valid" ) : _( "Nonvalid" ) );
ImGui::NewLine();
Expand Down Expand Up @@ -677,7 +677,7 @@ class wish_monster_callback: public uilist_callback
info_size.x = desired_extra_space_right( );
ImGui::TableSetColumnIndex( 2 );
if( ImGui::BeginChild( "monster info", info_size ) ) {
const int entnum = menu->hovered;
const int entnum = menu->previewing;
const bool valid_entnum = entnum >= 0 && static_cast<size_t>( entnum ) < mtypes.size();
if( entnum != lastent ) {
lastent = entnum;
Expand Down Expand Up @@ -998,7 +998,7 @@ class wish_item_callback: public uilist_callback
info_size.x = desired_extra_space_right( );
ImGui::TableSetColumnIndex( 2 );
if( ImGui::BeginChild( "monster info", info_size ) ) {
const int entnum = menu->hovered;
const int entnum = menu->previewing;
if( entnum >= 0 && static_cast<size_t>( entnum ) < standard_itype_ids.size() ) {
item tmp = wishitem_produce( *standard_itype_ids[entnum], flags, false );

Expand Down
Loading