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

Allow scrolling of string_input_popup descriptions #58609

Merged
1 change: 0 additions & 1 deletion src/crafting_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1481,7 +1481,6 @@ const recipe *select_crafting_recipe( int &batch_size_out, const recipe_id goto_

description +=
_( "\nUse <color_red>up/down arrow</color> to go through your search history." );
description += "\n\n\n";

string_input_popup popup;
popup
Expand Down
106 changes: 72 additions & 34 deletions src/string_input_popup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,21 @@ void string_input_popup::create_window()
break;
}
}
w_height += static_cast<int>( title_split.size() ) - 1;
title_height = static_cast<int>( title_split.size() ) - 1;
w_height += title_height;
}

descformatted.clear();
if( !_description.empty() ) {
const int twidth = std::min( utf8_width( remove_color_tags( _description ) ), w_width - 4 );
descformatted = foldstring( _description, twidth );
w_height += descformatted.size();
description_height = foldstring( _description, twidth ).size();
w_height += description_height;
if( w_height > TERMY ) {
description_height = TERMY - 2 - title_height - 1;
w_height = TERMY;
}
}
// length of title + border (left) + space
_startx = titlesize + 2;
_startx = titlesize + 1;

if( _max_length <= 0 ) {
_max_length = 1024;
Expand All @@ -82,9 +86,16 @@ void string_input_popup::create_window()

const int w_y = ( TERMY - w_height ) / 2;
const int w_x = std::max( ( TERMX - w_width ) / 2, 0 );
w = catacurses::newwin( w_height, w_width, point( w_x, w_y ) );

_starty = w_height - 2; // The ____ looks better at the bottom right when the title folds
_starty = title_height;
w_full = catacurses::newwin( w_height, w_width, point( w_x, w_y ) );
if( !_description.empty() ) {
w_description = catacurses::newwin( description_height, w_width - 1, point( w_x,
w_y + 1 ) );
desc_view_ptr = std::make_unique<scrolling_text_view>( w_description );
desc_view_ptr->set_text( _description );
}
w_title_and_entry = catacurses::newwin( w_height - description_height - 2, w_width - 2,
point( w_x + 1, w_y + 1 + description_height ) );

custom_window = false;
}
Expand All @@ -111,6 +122,10 @@ void string_input_popup::create_context()
#endif
ctxt->register_action( "TEXT.INPUT_FROM_FILE" );
ctxt->register_action( "HELP_KEYBINDINGS" );
ctxt->register_action( "PAGE_UP" );
ctxt->register_action( "PAGE_DOWN" );
ctxt->register_action( "SCROLL_UP" );
ctxt->register_action( "SCROLL_DOWN" );
ctxt->register_action( "ANY_INPUT" );
}

Expand All @@ -137,17 +152,17 @@ void string_input_popup::show_history( utf8_wrapper &ret )
hmenu.w_height_setup = [&]() -> int {
// number of lines that make up the menu window: 2*border+entries
int height = 2 + hmenu.entries.size();
if( getbegy( w ) < height )
if( getbegy( w_full ) < height )
{
height = std::max( getbegy( w ), 4 );
height = std::max( getbegy( w_full ), 4 );
}
return height;
};
hmenu.w_x_setup = [&]( int ) -> int {
return getbegx( w );
return getbegx( w_full );
};
hmenu.w_y_setup = [&]( const int height ) -> int {
return std::max( getbegy( w ) - height, 0 );
return std::max( getbegy( w_full ) - height, 0 );
};

bool finished = false;
Expand Down Expand Up @@ -228,27 +243,26 @@ void string_input_popup::update_input_history( utf8_wrapper &ret, bool up )
void string_input_popup::draw( const utf8_wrapper &ret, const utf8_wrapper &edit ) const
{
if( !custom_window ) {
werase( w );
draw_border( w );
werase( w_full );
draw_border( w_full );
wnoutrefresh( w_full );

for( size_t i = 0; i < descformatted.size(); ++i ) {
trim_and_print( w, point( 1, 1 + i ), w_width - 2, _desc_color, descformatted[i] );
}
int pos_y = descformatted.size() + 1;
int pos_y = 0;
for( int i = 0; i < static_cast<int>( title_split.size() ) - 1; i++ ) {
mvwprintz( w, point( i + 1, pos_y++ ), _title_color, title_split[i] );
mvwprintz( w_title_and_entry, point( i, pos_y++ ), _title_color, title_split[i] );
}
right_print( w, pos_y, w_width - titlesize - 1, _title_color, title_split.back() );
trim_and_print( w_title_and_entry, point( 0, pos_y ), titlesize, _title_color, title_split.back() );
}

const int scrmax = _endx - _startx;
// remove the scrolled out of view part from the input string
const utf8_wrapper ds( ret.substr_display( shift, scrmax ) );
int start_x_edit = _startx;
// Clear the line
mvwprintw( w, point( _startx, _starty ), std::string( std::max( 0, scrmax ), ' ' ) );
mvwprintw( w_title_and_entry, point( _startx, _starty ), std::string( std::max( 0, scrmax ),
' ' ) );
// Print the whole input string in default color
mvwprintz( w, point( _startx, _starty ), _string_color, "%s", ds.c_str() );
mvwprintz( w_title_and_entry, point( _startx, _starty ), _string_color, "%s", ds.c_str() );
size_t sx = ds.display_width();
// Print the cursor in its own color
point cursor_pos;
Expand All @@ -263,17 +277,17 @@ void string_input_popup::draw( const utf8_wrapper &ret, const utf8_wrapper &edit
}
const size_t left_over = ret.substr( 0, a ).display_width() - shift;
cursor_pos = point( _startx + left_over, _starty );
mvwprintz( w, cursor_pos, _cursor_color, "%s", cursor.c_str() );
mvwprintz( w_title_and_entry, cursor_pos, _cursor_color, "%s", cursor.c_str() );
start_x_edit += left_over;
} else if( _max_length > 0
&& ret.display_width() >= static_cast<size_t>( _max_length ) ) {
cursor_pos = point( _startx + sx, _starty );
mvwprintz( w, cursor_pos, _cursor_color, " " );
mvwprintz( w_title_and_entry, cursor_pos, _cursor_color, " " );
start_x_edit += sx;
sx++; // don't override trailing ' '
} else {
cursor_pos = point( _startx + sx, _starty );
mvwprintz( w, cursor_pos, _cursor_color, "_" );
mvwprintz( w_title_and_entry, cursor_pos, _cursor_color, "_" );
start_x_edit += sx;
sx++; // don't override trailing '_'
}
Expand All @@ -291,16 +305,22 @@ void string_input_popup::draw( const utf8_wrapper &ret, const utf8_wrapper &edit
}
}
if( l > 0 ) {
mvwprintz( w, point( _startx + sx, _starty ), _underscore_color, std::string( l, '_' ) );
mvwprintz( w_title_and_entry, point( _startx + sx, _starty ), _underscore_color, std::string( l,
'_' ) );
}
}
if( !edit.empty() ) {
mvwprintz( w, point( start_x_edit, _starty ), _cursor_color, "%s", edit.c_str() );
mvwprintz( w_title_and_entry, point( start_x_edit, _starty ), _cursor_color, "%s", edit.c_str() );
}

//Draw scrolling description
if( !custom_window && desc_view_ptr ) {
desc_view_ptr->draw( _desc_color );
wnoutrefresh( w_description );
}
// Move curses cursor to text cursor for screen readers and IME preview positioning
wmove( w, cursor_pos );
wnoutrefresh( w );
wmove( w_title_and_entry, cursor_pos );
wnoutrefresh( w_title_and_entry );
}

void string_input_popup::query( const bool loop, const bool draw_only )
Expand Down Expand Up @@ -337,7 +357,7 @@ int64_t string_input_popup::query_int64_t( const bool loop, const bool draw_only

const std::string &string_input_popup::query_string( const bool loop, const bool draw_only )
{
if( !custom_window && !w ) {
if( !custom_window && !w_full ) {
create_window();
_position = -1;
}
Expand All @@ -355,10 +375,10 @@ const std::string &string_input_popup::query_string( const bool loop, const bool
std::unique_ptr<ui_adaptor> ui;
if( !draw_only && !custom_window ) {
ui = std::make_unique<ui_adaptor>();
ui->position_from_window( w );
ui->position_from_window( w_full );
ui->on_screen_resize( [this]( ui_adaptor & ui ) {
create_window();
ui.position_from_window( w );
ui.position_from_window( w_full );
} );
ui->on_redraw( [&]( const ui_adaptor & ) {
draw( ret, edit );
Expand Down Expand Up @@ -490,6 +510,24 @@ const std::string &string_input_popup::query_string( const bool loop, const bool
if( _position < static_cast<int>( ret.size() ) ) {
ret.erase( _position, 1 );
}
/*Note: SCROLL_UP/SCROLL_DOWN should by default only trigger on mousewheel,
* since up/down arrow were handled above */
} else if( action == "SCROLL_UP" ) {
if( desc_view_ptr ) {
desc_view_ptr->scroll_up();
}
} else if( action == "SCROLL_DOWN" ) {
if( desc_view_ptr ) {
desc_view_ptr->scroll_down();
}
} else if( action == "PAGE_UP" ) {
if( desc_view_ptr ) {
desc_view_ptr->page_up();
}
} else if( action == "PAGE_DOWN" ) {
if( desc_view_ptr ) {
desc_view_ptr->page_down();
}
} else if( action == "TEXT.PASTE" || action == "TEXT.INPUT_FROM_FILE"
|| ( action == "ANY_INPUT" && !ev.text.empty() ) ) {
// paste, input from file, or text input
Expand Down Expand Up @@ -551,11 +589,11 @@ const std::string &string_input_popup::query_string( const bool loop, const bool
string_input_popup &string_input_popup::window( const catacurses::window &w, const point &start,
int endx )
{
if( !custom_window && this->w ) {
if( !custom_window && this->w_full ) {
// default window already created
return *this;
}
this->w = w;
this->w_title_and_entry = w;
_startx = start.x;
_starty = start.y;
_endx = endx;
Expand Down
9 changes: 7 additions & 2 deletions src/string_input_popup.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "cursesdef.h"

class input_context;
class scrolling_text_view;
class utf8_wrapper;
struct point;

Expand Down Expand Up @@ -73,12 +74,16 @@ class string_input_popup // NOLINT(cata-xy)
// Cache when using the default window
int w_width = 0;
int w_height = 0;
std::vector<std::string> descformatted;
int title_height = 0;
int description_height = 0;
std::vector<std::string> title_split;
int titlesize = 0;

bool custom_window = false;
catacurses::window w;
catacurses::window w_full;
catacurses::window w_description;
catacurses::window w_title_and_entry;
std::unique_ptr<scrolling_text_view> desc_view_ptr;

std::unique_ptr<input_context> ctxt_ptr;
input_context *ctxt = nullptr;
Expand Down