From 8056d638f17c1b1b8564020b7252745323a711a4 Mon Sep 17 00:00:00 2001 From: "Ignacio R. Morelle" Date: Tue, 4 Oct 2016 06:26:55 -0300 Subject: [PATCH] gui2/tfile_dialog: Add support for a filename extension hint This allows setting a hint in save mode so that the name portion of the filename will be selected whenever the user selects a file with a matching extension on the fileview, and so that whenever the textbox is cleared by code (e.g. when browsing into directories) it is pre-filled with the extension with the cursor at the start. With this, the dialog is now feature-complete compared to the GUI1 version. --- src/gui/dialogs/file_dialog.cpp | 38 ++++++++++++++++++++++++++++++--- src/gui/dialogs/file_dialog.hpp | 22 +++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/gui/dialogs/file_dialog.cpp b/src/gui/dialogs/file_dialog.cpp index 3323d1dcc165..f882f72e4d07 100644 --- a/src/gui/dialogs/file_dialog.cpp +++ b/src/gui/dialogs/file_dialog.cpp @@ -36,6 +36,7 @@ #include "gui/widgets/window.hpp" #include "gettext.hpp" #include "log.hpp" +#include "serialization/unicode.hpp" #include @@ -106,6 +107,7 @@ tfile_dialog::tfile_dialog() : title_(_("Find File")) , msg_() , ok_label_() + , extension_() , current_entry_() , current_dir_() , read_only_(false) @@ -383,6 +385,36 @@ tfile_dialog::SELECTION_TYPE tfile_dialog::register_new_selection(const std::str return SELECTION_PARENT_NOT_FOUND; } +void tfile_dialog::set_input_text(ttext_box& t, const std::string& value) +{ + if(value.empty()) { + clear_input_text(t); + return; + } + + t.set_value(value); + + const size_t vallen = t.get_length(); + const size_t extlen = utf8::size(extension_); + + if(save_mode_ && extlen && vallen > extlen) { + // Highlight everything but the extension if it matches + if(value.substr(vallen - extlen) == extension_) { + t.set_selection(0, vallen - extlen); + } + } +} + +void tfile_dialog::clear_input_text(ttext_box& t) +{ + if(save_mode_ && !extension_.empty()) { + t.set_value(extension_); + t.set_selection(0, 0); + } else { + t.clear(); + } +} + void tfile_dialog::refresh_fileview(twindow& window) { cursor::setter cur{cursor::WAIT}; @@ -423,7 +455,7 @@ void tfile_dialog::refresh_fileview(twindow& window) } find_widget(&window, "current_dir", false).set_label(current_dir_); - find_widget(&window, "filename", false).set_value(current_entry_); + set_input_text(find_widget(&window, "filename", false), current_entry_); } void tfile_dialog::push_fileview_row(tlistbox& filelist, const std::string& name, const std::string& icon, bool check_selection) @@ -464,9 +496,9 @@ void tfile_dialog::on_row_selected(twindow& window) // Clear the textbox when selecting .. if(current_entry_ != PARENT_DIR) { - file_textbox.set_value(current_entry_); + set_input_text(file_textbox, current_entry_); } else { - file_textbox.clear(); + clear_input_text(file_textbox); } } diff --git a/src/gui/dialogs/file_dialog.hpp b/src/gui/dialogs/file_dialog.hpp index cba35aab6c53..a3e0a0c4959d 100644 --- a/src/gui/dialogs/file_dialog.hpp +++ b/src/gui/dialogs/file_dialog.hpp @@ -105,6 +105,24 @@ class tfile_dialog : public tdialog */ tfile_dialog& set_filename(const std::string& value); + /** + * Sets the default file extension for file names in save mode. + * + * When this is set to a non-empty string and save mode is active, selecting + * file entries will cause their name portions to be highlighted in the name + * text box if their extensions match the provided template, and any time the + * text box is cleared it will position the cursor before the extension as a + * hint for the user. + * + * The value provided to this method should be preceded by a dot if + * applicable (e.g. ".cfg"). + */ + tfile_dialog& set_extension(const std::string& value) + { + extension_ = value; + return *this; + } + /** * Whether user interface elements for manipulating existing objects are provided. */ @@ -163,6 +181,7 @@ class tfile_dialog : public tdialog std::string msg_; std::string ok_label_; + std::string extension_; std::string current_entry_; std::string current_dir_; @@ -237,6 +256,9 @@ class tfile_dialog : public tdialog */ SELECTION_TYPE register_new_selection(const std::string& name); + void set_input_text(class ttext_box& t, const std::string& value); + void clear_input_text(class ttext_box& t); + /** * Updates the dialog contents to match the internal state. */