diff --git a/src/crafting_gui.cpp b/src/crafting_gui.cpp index b741cbea8bc20..77ef9a0e53e3a 100644 --- a/src/crafting_gui.cpp +++ b/src/crafting_gui.cpp @@ -1481,7 +1481,6 @@ const recipe *select_crafting_recipe( int &batch_size_out, const recipe_id goto_ description += _( "\nUse up/down arrow to go through your search history." ); - description += "\n\n\n"; string_input_popup popup; popup diff --git a/src/string_input_popup.cpp b/src/string_input_popup.cpp index 15d6f0192797f..dc954b375dad7 100644 --- a/src/string_input_popup.cpp +++ b/src/string_input_popup.cpp @@ -63,17 +63,21 @@ void string_input_popup::create_window() break; } } - w_height += static_cast( title_split.size() ) - 1; + title_height = static_cast( 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; @@ -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( 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; } @@ -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" ); } @@ -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; @@ -228,17 +243,15 @@ 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( 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; @@ -246,9 +259,10 @@ void string_input_popup::draw( const utf8_wrapper &ret, const utf8_wrapper &edit 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; @@ -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( _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 '_' } @@ -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 ) @@ -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; } @@ -355,10 +375,10 @@ const std::string &string_input_popup::query_string( const bool loop, const bool std::unique_ptr ui; if( !draw_only && !custom_window ) { ui = std::make_unique(); - 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 ); @@ -490,6 +510,24 @@ const std::string &string_input_popup::query_string( const bool loop, const bool if( _position < static_cast( 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 @@ -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; diff --git a/src/string_input_popup.h b/src/string_input_popup.h index c67d11c4c536a..0fa9299fd9eed 100644 --- a/src/string_input_popup.h +++ b/src/string_input_popup.h @@ -14,6 +14,7 @@ #include "cursesdef.h" class input_context; +class scrolling_text_view; class utf8_wrapper; struct point; @@ -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 descformatted; + int title_height = 0; + int description_height = 0; std::vector 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 desc_view_ptr; std::unique_ptr ctxt_ptr; input_context *ctxt = nullptr;