Improve space management for EditorFileDialog

Move buttons related to the file view on the container above so that they take less horizontal space and make search bar similar to the one in FileDialog
This commit is contained in:
vPumpking 2024-10-09 15:57:30 +02:00
parent 4c4e673344
commit 2642090cc8
3 changed files with 162 additions and 39 deletions

View file

@ -37,12 +37,24 @@
Adds the given [param menu] to the side of the file dialog with the given [param title] text on top. Only one side menu is allowed. Adds the given [param menu] to the side of the file dialog with the given [param title] text on top. Only one side menu is allowed.
</description> </description>
</method> </method>
<method name="clear_filename_filter">
<return type="void" />
<description>
Clear the filter for file names.
</description>
</method>
<method name="clear_filters"> <method name="clear_filters">
<return type="void" /> <return type="void" />
<description> <description>
Removes all filters except for "All Files (*)". Removes all filters except for "All Files (*)".
</description> </description>
</method> </method>
<method name="get_filename_filter" qualifiers="const">
<return type="String" />
<description>
Returns the value of the filter for file names.
</description>
</method>
<method name="get_line_edit"> <method name="get_line_edit">
<return type="LineEdit" /> <return type="LineEdit" />
<description> <description>
@ -96,6 +108,13 @@
Shows the [EditorFileDialog] at the default size and position for file dialogs in the editor, and selects the file name if there is a current file. Shows the [EditorFileDialog] at the default size and position for file dialogs in the editor, and selects the file name if there is a current file.
</description> </description>
</method> </method>
<method name="set_filename_filter">
<return type="void" />
<param index="0" name="filter" type="String" />
<description>
Sets the value of the filter for file names.
</description>
</method>
<method name="set_option_default"> <method name="set_option_default">
<return type="void" /> <return type="void" />
<param index="0" name="option" type="int" /> <param index="0" name="option" type="int" />
@ -168,6 +187,12 @@
Emitted when a file is selected. Emitted when a file is selected.
</description> </description>
</signal> </signal>
<signal name="filename_filter_changed">
<param index="0" name="filter" type="String" />
<description>
Emitted when the filter for file names changes.
</description>
</signal>
<signal name="files_selected"> <signal name="files_selected">
<param index="0" name="paths" type="PackedStringArray" /> <param index="0" name="paths" type="PackedStringArray" />
<description> <description>

View file

@ -175,6 +175,7 @@ void EditorFileDialog::_update_theme_item_cache() {
theme_cache.back_folder = get_editor_theme_icon(SNAME("Back")); theme_cache.back_folder = get_editor_theme_icon(SNAME("Back"));
theme_cache.reload = get_editor_theme_icon(SNAME("Reload")); theme_cache.reload = get_editor_theme_icon(SNAME("Reload"));
theme_cache.toggle_hidden = get_editor_theme_icon(SNAME("GuiVisibilityVisible")); theme_cache.toggle_hidden = get_editor_theme_icon(SNAME("GuiVisibilityVisible"));
theme_cache.toggle_filename_filter = get_editor_theme_icon(SNAME("FilenameFilter"));
theme_cache.favorite = get_editor_theme_icon(SNAME("Favorites")); theme_cache.favorite = get_editor_theme_icon(SNAME("Favorites"));
theme_cache.mode_thumbnails = get_editor_theme_icon(SNAME("FileThumbnail")); theme_cache.mode_thumbnails = get_editor_theme_icon(SNAME("FileThumbnail"));
theme_cache.mode_list = get_editor_theme_icon(SNAME("FileList")); theme_cache.mode_list = get_editor_theme_icon(SNAME("FileList"));
@ -329,6 +330,7 @@ void EditorFileDialog::shortcut_input(const Ref<InputEvent> &p_event) {
handled = true; handled = true;
} }
if (ED_IS_SHORTCUT("file_dialog/focus_filter", p_event)) { if (ED_IS_SHORTCUT("file_dialog/focus_filter", p_event)) {
show_search_filter_button->set_pressed(!show_search_filter_button->is_pressed());
_focus_filter_box(); _focus_filter_box();
handled = true; handled = true;
} }
@ -1146,6 +1148,15 @@ void EditorFileDialog::_filter_selected(int) {
update_file_list(); update_file_list();
} }
void EditorFileDialog::_search_filter_selected() {
Vector items = item_list->get_selected_items();
if (!items.is_empty()) {
int index = items[0];
file->set_text(item_list->get_item_text(index));
file->emit_signal("text_submitted", file->get_text());
}
}
void EditorFileDialog::update_filters() { void EditorFileDialog::update_filters() {
filter->clear(); filter->clear();
@ -1187,6 +1198,23 @@ void EditorFileDialog::clear_filters() {
invalidate(); invalidate();
} }
void EditorFileDialog::clear_search_filter() {
set_search_filter("");
update_search_filter_gui();
invalidate();
}
void EditorFileDialog::update_search_filter_gui() {
filter_hb->set_visible(show_search_filter);
if (!show_search_filter) {
search_string.clear();
}
if (filter_box->get_text() == search_string) {
return;
}
filter_box->set_text(search_string);
}
void EditorFileDialog::add_filter(const String &p_filter, const String &p_description) { void EditorFileDialog::add_filter(const String &p_filter, const String &p_description) {
if (p_description.is_empty()) { if (p_description.is_empty()) {
filters.push_back(p_filter); filters.push_back(p_filter);
@ -1206,10 +1234,24 @@ void EditorFileDialog::set_filters(const Vector<String> &p_filters) {
invalidate(); invalidate();
} }
void EditorFileDialog::set_search_filter(const String &p_search_filter) {
if (search_string == p_search_filter) {
return;
}
search_string = p_search_filter;
update_search_filter_gui();
emit_signal(SNAME("filename_filter_changed"), filter);
invalidate();
}
Vector<String> EditorFileDialog::get_filters() const { Vector<String> EditorFileDialog::get_filters() const {
return filters; return filters;
} }
String EditorFileDialog::get_search_filter() const {
return search_string;
}
String EditorFileDialog::get_current_dir() const { String EditorFileDialog::get_current_dir() const {
return dir_access->get_current_dir(); return dir_access->get_current_dir();
} }
@ -1392,6 +1434,11 @@ void EditorFileDialog::_focus_filter_box() {
void EditorFileDialog::_filter_changed(const String &p_text) { void EditorFileDialog::_filter_changed(const String &p_text) {
search_string = p_text; search_string = p_text;
invalidate(); invalidate();
item_list->deselect_all();
if (item_list->get_item_count() > 0) {
item_list->call_deferred("select", 0);
}
} }
void EditorFileDialog::_file_sort_popup(int p_id) { void EditorFileDialog::_file_sort_popup(int p_id) {
@ -1492,6 +1539,7 @@ void EditorFileDialog::_update_icons() {
favorite->set_icon(theme_cache.favorite); favorite->set_icon(theme_cache.favorite);
show_hidden->set_icon(theme_cache.toggle_hidden); show_hidden->set_icon(theme_cache.toggle_hidden);
makedir->set_icon(theme_cache.create_folder); makedir->set_icon(theme_cache.create_folder);
show_search_filter_button->set_icon(theme_cache.toggle_filename_filter);
filter_box->set_right_icon(theme_cache.filter_box); filter_box->set_right_icon(theme_cache.filter_box);
file_sort_button->set_icon(theme_cache.file_sort_button); file_sort_button->set_icon(theme_cache.file_sort_button);
@ -1972,6 +2020,9 @@ void EditorFileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_option_count"), &EditorFileDialog::get_option_count); ClassDB::bind_method(D_METHOD("get_option_count"), &EditorFileDialog::get_option_count);
ClassDB::bind_method(D_METHOD("add_option", "name", "values", "default_value_index"), &EditorFileDialog::add_option); ClassDB::bind_method(D_METHOD("add_option", "name", "values", "default_value_index"), &EditorFileDialog::add_option);
ClassDB::bind_method(D_METHOD("get_selected_options"), &EditorFileDialog::get_selected_options); ClassDB::bind_method(D_METHOD("get_selected_options"), &EditorFileDialog::get_selected_options);
ClassDB::bind_method(D_METHOD("clear_filename_filter"), &EditorFileDialog::clear_search_filter);
ClassDB::bind_method(D_METHOD("set_filename_filter", "filter"), &EditorFileDialog::set_search_filter);
ClassDB::bind_method(D_METHOD("get_filename_filter"), &EditorFileDialog::get_search_filter);
ClassDB::bind_method(D_METHOD("get_current_dir"), &EditorFileDialog::get_current_dir); ClassDB::bind_method(D_METHOD("get_current_dir"), &EditorFileDialog::get_current_dir);
ClassDB::bind_method(D_METHOD("get_current_file"), &EditorFileDialog::get_current_file); ClassDB::bind_method(D_METHOD("get_current_file"), &EditorFileDialog::get_current_file);
ClassDB::bind_method(D_METHOD("get_current_path"), &EditorFileDialog::get_current_path); ClassDB::bind_method(D_METHOD("get_current_path"), &EditorFileDialog::get_current_path);
@ -2000,6 +2051,7 @@ void EditorFileDialog::_bind_methods() {
ADD_SIGNAL(MethodInfo("file_selected", PropertyInfo(Variant::STRING, "path"))); ADD_SIGNAL(MethodInfo("file_selected", PropertyInfo(Variant::STRING, "path")));
ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths"))); ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths")));
ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir"))); ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir")));
ADD_SIGNAL(MethodInfo("filename_filter_changed", PropertyInfo(Variant::STRING, "filter")));
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access"); ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
ADD_PROPERTY(PropertyInfo(Variant::INT, "display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"), "set_display_mode", "get_display_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "display_mode", PROPERTY_HINT_ENUM, "Thumbnails,List"), "set_display_mode", "get_display_mode");
@ -2046,6 +2098,24 @@ void EditorFileDialog::set_show_hidden_files(bool p_show) {
invalidate(); invalidate();
} }
void EditorFileDialog::set_show_search_filter(bool p_show) {
if (p_show == show_search_filter) {
return;
}
if (p_show) {
filter_box->grab_focus();
} else {
search_string.clear();
filter_box->clear();
if (filter_box->has_focus()) {
item_list->call_deferred("grab_focus");
}
}
show_search_filter = p_show;
update_search_filter_gui();
invalidate();
}
bool EditorFileDialog::is_showing_hidden_files() const { bool EditorFileDialog::is_showing_hidden_files() const {
return show_hidden_files; return show_hidden_files;
} }
@ -2189,7 +2259,6 @@ EditorFileDialog::EditorFileDialog() {
dir = memnew(LineEdit); dir = memnew(LineEdit);
dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE); dir->set_structured_text_bidi_override(TextServer::STRUCTURED_TEXT_FILE);
pathhb->add_child(dir); pathhb->add_child(dir);
dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
refresh = memnew(Button); refresh = memnew(Button);
refresh->set_theme_type_variation("FlatButton"); refresh->set_theme_type_variation("FlatButton");
@ -2204,37 +2273,6 @@ EditorFileDialog::EditorFileDialog() {
favorite->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_favorite_pressed)); favorite->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_favorite_pressed));
pathhb->add_child(favorite); pathhb->add_child(favorite);
show_hidden = memnew(Button);
show_hidden->set_theme_type_variation("FlatButton");
show_hidden->set_toggle_mode(true);
show_hidden->set_pressed(is_showing_hidden_files());
show_hidden->set_tooltip_text(TTR("Toggle the visibility of hidden files."));
show_hidden->connect(SceneStringName(toggled), callable_mp(this, &EditorFileDialog::set_show_hidden_files));
pathhb->add_child(show_hidden);
pathhb->add_child(memnew(VSeparator));
Ref<ButtonGroup> view_mode_group;
view_mode_group.instantiate();
mode_thumbnails = memnew(Button);
mode_thumbnails->set_theme_type_variation("FlatButton");
mode_thumbnails->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_THUMBNAILS));
mode_thumbnails->set_toggle_mode(true);
mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS);
mode_thumbnails->set_button_group(view_mode_group);
mode_thumbnails->set_tooltip_text(TTR("View items as a grid of thumbnails."));
pathhb->add_child(mode_thumbnails);
mode_list = memnew(Button);
mode_list->set_theme_type_variation("FlatButton");
mode_list->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_LIST));
mode_list->set_toggle_mode(true);
mode_list->set_pressed(display_mode == DISPLAY_LIST);
mode_list->set_button_group(view_mode_group);
mode_list->set_tooltip_text(TTR("View items as a list."));
pathhb->add_child(mode_list);
shortcuts_container = memnew(HBoxContainer); shortcuts_container = memnew(HBoxContainer);
pathhb->add_child(shortcuts_container); pathhb->add_child(shortcuts_container);
@ -2250,6 +2288,8 @@ EditorFileDialog::EditorFileDialog() {
makedir->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_make_dir)); makedir->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::_make_dir));
pathhb->add_child(makedir); pathhb->add_child(makedir);
dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
body_hsplit = memnew(HSplitContainer); body_hsplit = memnew(HSplitContainer);
body_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL); body_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
vbc->add_child(body_hsplit); vbc->add_child(body_hsplit);
@ -2319,21 +2359,55 @@ EditorFileDialog::EditorFileDialog() {
l = memnew(Label(TTR("Directories & Files:"))); l = memnew(Label(TTR("Directories & Files:")));
l->set_theme_type_variation("HeaderSmall"); l->set_theme_type_variation("HeaderSmall");
l->set_h_size_flags(Control::SIZE_EXPAND_FILL);
lower_hb->add_child(l); lower_hb->add_child(l);
list_vb->add_child(lower_hb); show_hidden = memnew(Button);
preview_hb->add_child(list_vb); show_hidden->set_theme_type_variation("FlatButton");
show_hidden->set_toggle_mode(true);
show_hidden->set_pressed(is_showing_hidden_files());
show_hidden->set_tooltip_text(TTR("Toggle the visibility of hidden files."));
show_hidden->connect(SceneStringName(toggled), callable_mp(this, &EditorFileDialog::set_show_hidden_files));
lower_hb->add_child(show_hidden);
filter_box = memnew(LineEdit); lower_hb->add_child(memnew(VSeparator));
filter_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
filter_box->set_placeholder(TTR("Filter")); Ref<ButtonGroup> view_mode_group;
filter_box->connect(SceneStringName(text_changed), callable_mp(this, &EditorFileDialog::_filter_changed)); view_mode_group.instantiate();
lower_hb->add_child(filter_box);
mode_thumbnails = memnew(Button);
mode_thumbnails->set_theme_type_variation("FlatButton");
mode_thumbnails->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_THUMBNAILS));
mode_thumbnails->set_toggle_mode(true);
mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS);
mode_thumbnails->set_button_group(view_mode_group);
mode_thumbnails->set_tooltip_text(TTR("View items as a grid of thumbnails."));
lower_hb->add_child(mode_thumbnails);
mode_list = memnew(Button);
mode_list->set_theme_type_variation("FlatButton");
mode_list->connect(SceneStringName(pressed), callable_mp(this, &EditorFileDialog::set_display_mode).bind(DISPLAY_LIST));
mode_list->set_toggle_mode(true);
mode_list->set_pressed(display_mode == DISPLAY_LIST);
mode_list->set_button_group(view_mode_group);
mode_list->set_tooltip_text(TTR("View items as a list."));
lower_hb->add_child(mode_list);
lower_hb->add_child(memnew(VSeparator));
file_sort_button = memnew(MenuButton); file_sort_button = memnew(MenuButton);
file_sort_button->set_flat(true); file_sort_button->set_flat(true);
file_sort_button->set_tooltip_text(TTR("Sort files")); file_sort_button->set_tooltip_text(TTR("Sort files"));
show_search_filter_button = memnew(Button);
show_search_filter_button->set_theme_type_variation("FlatButton");
show_search_filter_button->set_toggle_mode(true);
show_search_filter_button->set_pressed(false);
show_search_filter_button->set_tooltip_text(TTR("Toggle the visibility of the filter for file names."));
show_search_filter_button->connect("toggled", callable_mp(this, &EditorFileDialog::set_show_search_filter));
lower_hb->add_child(show_search_filter_button);
PopupMenu *p = file_sort_button->get_popup(); PopupMenu *p = file_sort_button->get_popup();
p->connect(SceneStringName(id_pressed), callable_mp(this, &EditorFileDialog::_file_sort_popup)); p->connect(SceneStringName(id_pressed), callable_mp(this, &EditorFileDialog::_file_sort_popup));
p->add_radio_check_item(TTR("Sort by Name (Ascending)"), static_cast<int>(FileSortOption::FILE_SORT_NAME)); p->add_radio_check_item(TTR("Sort by Name (Ascending)"), static_cast<int>(FileSortOption::FILE_SORT_NAME));
@ -2345,6 +2419,9 @@ EditorFileDialog::EditorFileDialog() {
p->set_item_checked(0, true); p->set_item_checked(0, true);
lower_hb->add_child(file_sort_button); lower_hb->add_child(file_sort_button);
list_vb->add_child(lower_hb);
preview_hb->add_child(list_vb);
// Item (files and folders) list with context menu. // Item (files and folders) list with context menu.
item_list = memnew(ItemList); item_list = memnew(ItemList);
@ -2370,6 +2447,15 @@ EditorFileDialog::EditorFileDialog() {
prev_cc->add_child(preview); prev_cc->add_child(preview);
preview_vb->hide(); preview_vb->hide();
filter_hb = memnew(HBoxContainer);
filter_hb->add_child(memnew(Label(RTR("Filter:"))));
filter_box = memnew(LineEdit);
filter_box->set_h_size_flags(Control::SIZE_EXPAND_FILL);
filter_box->set_placeholder(TTR("Filter"));
filter_hb->add_child(filter_box);
filter_hb->set_visible(false);
item_vb->add_child(filter_hb);
file_box = memnew(HBoxContainer); file_box = memnew(HBoxContainer);
l = memnew(Label(TTR("File:"))); l = memnew(Label(TTR("File:")));
@ -2398,6 +2484,8 @@ EditorFileDialog::EditorFileDialog() {
item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected).bind()); item_list->connect("item_activated", callable_mp(this, &EditorFileDialog::_item_dc_selected).bind());
item_list->connect("empty_clicked", callable_mp(this, &EditorFileDialog::_items_clear_selection)); item_list->connect("empty_clicked", callable_mp(this, &EditorFileDialog::_items_clear_selection));
dir->connect("text_submitted", callable_mp(this, &EditorFileDialog::_dir_submitted)); dir->connect("text_submitted", callable_mp(this, &EditorFileDialog::_dir_submitted));
filter_box->connect(SceneStringName(text_changed), callable_mp(this, &EditorFileDialog::_filter_changed));
filter_box->connect(SceneStringName(text_submitted), callable_mp(this, &EditorFileDialog::_search_filter_selected).unbind(1));
file->connect("text_submitted", callable_mp(this, &EditorFileDialog::_file_submitted)); file->connect("text_submitted", callable_mp(this, &EditorFileDialog::_file_submitted));
filter->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_filter_selected)); filter->connect(SceneStringName(item_selected), callable_mp(this, &EditorFileDialog::_filter_selected));

View file

@ -128,8 +128,11 @@ private:
Button *refresh = nullptr; Button *refresh = nullptr;
Button *favorite = nullptr; Button *favorite = nullptr;
Button *show_hidden = nullptr; Button *show_hidden = nullptr;
Button *show_search_filter_button = nullptr;
String search_string; String search_string;
bool show_search_filter = false;
HBoxContainer *filter_hb = nullptr;
LineEdit *filter_box = nullptr; LineEdit *filter_box = nullptr;
FileSortOption file_sort = FileSortOption::FILE_SORT_NAME; FileSortOption file_sort = FileSortOption::FILE_SORT_NAME;
MenuButton *file_sort_button = nullptr; MenuButton *file_sort_button = nullptr;
@ -165,6 +168,7 @@ private:
Ref<Texture2D> back_folder; Ref<Texture2D> back_folder;
Ref<Texture2D> reload; Ref<Texture2D> reload;
Ref<Texture2D> toggle_hidden; Ref<Texture2D> toggle_hidden;
Ref<Texture2D> toggle_filename_filter;
Ref<Texture2D> favorite; Ref<Texture2D> favorite;
Ref<Texture2D> mode_thumbnails; Ref<Texture2D> mode_thumbnails;
Ref<Texture2D> mode_list; Ref<Texture2D> mode_list;
@ -206,6 +210,7 @@ private:
void update_dir(); void update_dir();
void update_file_name(); void update_file_name();
void update_file_list(); void update_file_list();
void update_search_filter_gui();
void update_filters(); void update_filters();
void _focus_file_text(); void _focus_file_text();
@ -239,6 +244,7 @@ private:
void _focus_filter_box(); void _focus_filter_box();
void _filter_changed(const String &p_text); void _filter_changed(const String &p_text);
void _search_filter_selected();
void _file_sort_popup(int p_id); void _file_sort_popup(int p_id);
void _delete_items(); void _delete_items();
@ -301,6 +307,9 @@ public:
void add_filter(const String &p_filter, const String &p_description = ""); void add_filter(const String &p_filter, const String &p_description = "");
void set_filters(const Vector<String> &p_filters); void set_filters(const Vector<String> &p_filters);
Vector<String> get_filters() const; Vector<String> get_filters() const;
void clear_search_filter();
void set_search_filter(const String &p_search_filter);
String get_search_filter() const;
void set_enable_multiple_selection(bool p_enable); void set_enable_multiple_selection(bool p_enable);
Vector<String> get_selected_files() const; Vector<String> get_selected_files() const;
@ -341,6 +350,7 @@ public:
static void set_default_show_hidden_files(bool p_show); static void set_default_show_hidden_files(bool p_show);
static void set_default_display_mode(DisplayMode p_mode); static void set_default_display_mode(DisplayMode p_mode);
void set_show_hidden_files(bool p_show); void set_show_hidden_files(bool p_show);
void set_show_search_filter(bool p_show);
bool is_showing_hidden_files() const; bool is_showing_hidden_files() const;
void invalidate(); void invalidate();