summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2023-05-11 11:46:45 +0200
committerRémi Verschelde <rverschelde@gmail.com>2023-05-11 11:46:45 +0200
commit4020cc8acb6ea2d60968583b455f73e453d5f4ac (patch)
tree0fe41a463784f3a962bd9e81fb28486653e820ab
parent3fdf555d4334f0445d5622719a75b961e15fad6b (diff)
parentb08a6084affd1bf657124dc5cda98a6b2cab2fd0 (diff)
downloadredot-engine-4020cc8acb6ea2d60968583b455f73e453d5f4ac.tar.gz
Merge pull request #76794 from Wiwip/inline-edit
Inline editor for the file system dock
-rw-r--r--doc/classes/Tree.xml5
-rw-r--r--editor/filesystem_dock.cpp72
-rw-r--r--editor/filesystem_dock.h2
-rw-r--r--scene/gui/tree.cpp14
-rw-r--r--scene/gui/tree.h3
5 files changed, 56 insertions, 40 deletions
diff --git a/doc/classes/Tree.xml b/doc/classes/Tree.xml
index 2a3cba3a44..afe0088a26 100644
--- a/doc/classes/Tree.xml
+++ b/doc/classes/Tree.xml
@@ -60,8 +60,11 @@
</method>
<method name="edit_selected">
<return type="bool" />
+ <param index="0" name="force_edit" type="bool" default="false" />
<description>
- Edits the selected tree item as if it was clicked. The item must be set editable with [method TreeItem.set_editable]. Returns [code]true[/code] if the item could be edited. Fails if no item is selected.
+ Edits the selected tree item as if it was clicked.
+ Either the item must be set editable with [method TreeItem.set_editable] or [param force_edit] must be [code]true[/code].
+ Returns [code]true[/code] if the item could be edited. Fails if no item is selected.
</description>
</method>
<method name="ensure_cursor_is_visible">
diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp
index 8695caafde..dd80ff49ac 100644
--- a/editor/filesystem_dock.cpp
+++ b/editor/filesystem_dock.cpp
@@ -1561,21 +1561,39 @@ void FileSystemDock::_folder_removed(String p_folder) {
}
void FileSystemDock::_rename_operation_confirm() {
- String new_name = rename_dialog_text->get_text().strip_edges();
+ if (!tree->is_anything_selected()) {
+ return;
+ }
+ TreeItem *s = tree->get_selected();
+ int col_index = tree->get_selected_column();
+ String new_name = s->get_text(col_index);
+ new_name = new_name.strip_edges();
+ String old_name = to_rename.is_file ? to_rename.path.get_file() : to_rename.path.left(-1).get_file();
+
+ bool rename_error = false;
if (new_name.length() == 0) {
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
- return;
+ rename_error = true;
} else if (new_name.contains("/") || new_name.contains("\\") || new_name.contains(":")) {
EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
- return;
+ rename_error = true;
+ } else if (new_name.begins_with(".")) {
+ EditorNode::get_singleton()->show_warning(TTR("This filename begins with a dot rendering the file invisible to the editor.\nIf you want to rename it anyway, use your operating system's file manager."));
+ rename_error = true;
} else if (to_rename.is_file && to_rename.path.get_extension() != new_name.get_extension()) {
if (!EditorFileSystem::get_singleton()->get_valid_extensions().find(new_name.get_extension())) {
EditorNode::get_singleton()->show_warning(TTR("This file extension is not recognized by the editor.\nIf you want to rename it anyway, use your operating system's file manager.\nAfter renaming to an unknown extension, the file won't be shown in the editor anymore."));
- return;
+ rename_error = true;
}
}
- String old_path = to_rename.path.ends_with("/") ? to_rename.path.substr(0, to_rename.path.length() - 1) : to_rename.path;
+ // Restores Tree to restore original names.
+ if (rename_error) {
+ s->set_text(col_index, old_name);
+ return;
+ }
+
+ String old_path = to_rename.path.ends_with("/") ? to_rename.path.left(-1) : to_rename.path;
String new_path = old_path.get_base_dir().path_join(new_name);
if (old_path == new_path) {
return;
@@ -1594,6 +1612,7 @@ void FileSystemDock::_rename_operation_confirm() {
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
#endif
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
+ s->set_text(col_index, old_name);
return;
}
@@ -1992,24 +2011,21 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
} break;
case FILE_RENAME: {
- // Rename the active file.
- if (!p_selected.is_empty()) {
+ if (tree->is_anything_selected() && !p_selected.is_empty()) {
+ // Set to_rename variable for callback execution.
to_rename.path = p_selected[0];
- if (to_rename.path != "res://") {
- to_rename.is_file = !to_rename.path.ends_with("/");
- if (to_rename.is_file) {
- String name = to_rename.path.get_file();
- rename_dialog->set_title(TTR("Renaming file:") + " " + name);
- rename_dialog_text->set_text(name);
- rename_dialog_text->select(0, name.rfind("."));
- } else {
- String name = to_rename.path.substr(0, to_rename.path.length() - 1).get_file();
- rename_dialog->set_title(TTR("Renaming folder:") + " " + name);
- rename_dialog_text->set_text(name);
- rename_dialog_text->select(0, name.length());
- }
- rename_dialog->popup_centered(Size2(250, 80) * EDSCALE);
- rename_dialog_text->grab_focus();
+ to_rename.is_file = !to_rename.path.ends_with("/");
+
+ // Edit node in Tree.
+ tree->grab_focus();
+ tree->edit_selected(true);
+
+ if (to_rename.is_file) {
+ String name = to_rename.path.get_file();
+ tree->set_editor_selection(0, name.rfind("."));
+ } else {
+ String name = to_rename.path.left(-1).get_file(); // Removes the "/" suffix for folders.
+ tree->set_editor_selection(0, name.length());
}
}
} break;
@@ -3228,6 +3244,7 @@ FileSystemDock::FileSystemDock() {
tree->connect("nothing_selected", callable_mp(this, &FileSystemDock::_tree_empty_selected));
tree->connect("gui_input", callable_mp(this, &FileSystemDock::_tree_gui_input));
tree->connect("mouse_exited", callable_mp(this, &FileSystemDock::_tree_mouse_exited));
+ tree->connect("item_edited", callable_mp(this, &FileSystemDock::_rename_operation_confirm));
file_list_vb = memnew(VBoxContainer);
file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL);
@@ -3289,17 +3306,6 @@ FileSystemDock::FileSystemDock() {
add_child(move_dialog);
move_dialog->connect("dir_selected", callable_mp(this, &FileSystemDock::_move_dialog_confirm));
- rename_dialog = memnew(ConfirmationDialog);
- VBoxContainer *rename_dialog_vb = memnew(VBoxContainer);
- rename_dialog->add_child(rename_dialog_vb);
-
- rename_dialog_text = memnew(LineEdit);
- rename_dialog_vb->add_margin_child(TTR("Name:"), rename_dialog_text);
- rename_dialog->set_ok_button_text(TTR("Rename"));
- add_child(rename_dialog);
- rename_dialog->register_text_enter(rename_dialog_text);
- rename_dialog->connect("confirmed", callable_mp(this, &FileSystemDock::_rename_operation_confirm));
-
overwrite_dialog = memnew(ConfirmationDialog);
add_child(overwrite_dialog);
overwrite_dialog->set_ok_button_text(TTR("Overwrite"));
diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h
index 37e325c873..05a6372830 100644
--- a/editor/filesystem_dock.h
+++ b/editor/filesystem_dock.h
@@ -152,8 +152,6 @@ private:
DependencyRemoveDialog *remove_dialog = nullptr;
EditorDirDialog *move_dialog = nullptr;
- ConfirmationDialog *rename_dialog = nullptr;
- LineEdit *rename_dialog_text = nullptr;
ConfirmationDialog *duplicate_dialog = nullptr;
LineEdit *duplicate_dialog_text = nullptr;
DirectoryCreateDialog *make_dir_dialog = nullptr;
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 5f515040ae..b8fc8004c9 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -3864,14 +3864,14 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) {
}
}
-bool Tree::edit_selected() {
+bool Tree::edit_selected(bool p_force_edit) {
TreeItem *s = get_selected();
ERR_FAIL_COND_V_MSG(!s, false, "No item selected.");
ensure_cursor_is_visible();
int col = get_selected_column();
ERR_FAIL_INDEX_V_MSG(col, columns.size(), false, "No item column selected.");
- if (!s->cells[col].editable) {
+ if (!s->cells[col].editable && !p_force_edit) {
return false;
}
@@ -3977,6 +3977,14 @@ bool Tree::is_editing() {
return popup_editor->is_visible();
}
+void Tree::set_editor_selection(int p_from_line, int p_to_line, int p_from_column, int p_to_column, int p_caret) {
+ if (p_from_column == -1 || p_to_column == -1) {
+ line_editor->select(p_from_line, p_to_line);
+ } else {
+ text_editor->select(p_from_line, p_from_column, p_to_line, p_to_column, p_caret);
+ }
+}
+
Size2 Tree::get_internal_min_size() const {
Size2i size;
if (root) {
@@ -5393,7 +5401,7 @@ void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_edited"), &Tree::get_edited);
ClassDB::bind_method(D_METHOD("get_edited_column"), &Tree::get_edited_column);
- ClassDB::bind_method(D_METHOD("edit_selected"), &Tree::edit_selected);
+ ClassDB::bind_method(D_METHOD("edit_selected", "force_edit"), &Tree::edit_selected, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_custom_popup_rect"), &Tree::get_custom_popup_rect);
ClassDB::bind_method(D_METHOD("get_item_area_rect", "item", "column", "button_index"), &Tree::get_item_rect, DEFVAL(-1), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_item_at_position", "position"), &Tree::get_item_at_position);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 63b5df4623..24b649b040 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -727,8 +727,9 @@ public:
int get_item_offset(TreeItem *p_item) const;
Rect2 get_item_rect(TreeItem *p_item, int p_column = -1, int p_button = -1) const;
- bool edit_selected();
+ bool edit_selected(bool p_force_edit = false);
bool is_editing();
+ void set_editor_selection(int p_from_line, int p_to_line, int p_from_column = -1, int p_to_column = -1, int p_caret = 0);
// First item that starts with the text, from the current focused item down and wraps around.
TreeItem *search_item_text(const String &p_find, int *r_col = nullptr, bool p_selectable = false);