Permits the renaming of files and folders inline for items in the FileSystemDock.
This is a continuation of: https://github.com/godotengine/godot/pull/76794 which didn't consider DISPLAY_MODE_SPLIT. Fixes: https://github.com/godotengine/godot/issues/77527 and https://github.com/godotengine/godot-proposals/issues/4933
This commit is contained in:
parent
72f7131be1
commit
28038feb04
|
@ -76,6 +76,94 @@ Control *FileSystemList::make_custom_tooltip(const String &p_text) const {
|
|||
return FileSystemDock::get_singleton()->create_tooltip_for_path(get_item_metadata(idx));
|
||||
}
|
||||
|
||||
void FileSystemList::_line_editor_submit(String p_text) {
|
||||
popup_editor->hide();
|
||||
|
||||
emit_signal(SNAME("item_edited"));
|
||||
queue_redraw();
|
||||
}
|
||||
|
||||
bool FileSystemList::edit_selected() {
|
||||
ERR_FAIL_COND_V_MSG(!is_anything_selected(), false, "No item selected.");
|
||||
int s = get_current();
|
||||
ensure_current_is_visible();
|
||||
|
||||
Rect2 rect;
|
||||
Rect2 popup_rect;
|
||||
Vector2 ofs;
|
||||
|
||||
Vector2 icon_size = get_item_icon(s)->get_size();
|
||||
|
||||
// Handles the different icon modes (TOP/LEFT).
|
||||
switch (get_icon_mode()) {
|
||||
case ItemList::ICON_MODE_LEFT:
|
||||
rect = get_item_rect(s, true);
|
||||
ofs = Vector2(0, Math::floor((MAX(line_editor->get_minimum_size().height, rect.size.height) - rect.size.height) / 2));
|
||||
popup_rect.position = get_screen_position() + rect.position - ofs;
|
||||
popup_rect.size = rect.size;
|
||||
|
||||
// Adjust for icon position and size.
|
||||
popup_rect.size.x -= icon_size.x;
|
||||
popup_rect.position.x += icon_size.x;
|
||||
break;
|
||||
case ItemList::ICON_MODE_TOP:
|
||||
rect = get_item_rect(s, false);
|
||||
popup_rect.position = get_screen_position() + rect.position;
|
||||
popup_rect.size = rect.size;
|
||||
|
||||
// Adjust for icon position and size.
|
||||
popup_rect.size.y -= icon_size.y;
|
||||
popup_rect.position.y += icon_size.y;
|
||||
break;
|
||||
}
|
||||
|
||||
popup_editor->set_position(popup_rect.position);
|
||||
popup_editor->set_size(popup_rect.size);
|
||||
|
||||
String name = get_item_text(s);
|
||||
line_editor->set_text(name);
|
||||
line_editor->select(0, name.rfind("."));
|
||||
|
||||
popup_editor->popup();
|
||||
popup_editor->child_controls_changed();
|
||||
line_editor->grab_focus();
|
||||
return true;
|
||||
}
|
||||
|
||||
String FileSystemList::get_edit_text() {
|
||||
return line_editor->get_text();
|
||||
}
|
||||
|
||||
void FileSystemList::_text_editor_popup_modal_close() {
|
||||
if (Input::get_singleton()->is_key_pressed(Key::ESCAPE) ||
|
||||
Input::get_singleton()->is_key_pressed(Key::KP_ENTER) ||
|
||||
Input::get_singleton()->is_key_pressed(Key::ENTER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_line_editor_submit(line_editor->get_text());
|
||||
}
|
||||
|
||||
void FileSystemList::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("item_edited"));
|
||||
}
|
||||
|
||||
FileSystemList::FileSystemList() {
|
||||
popup_editor = memnew(Popup);
|
||||
add_child(popup_editor);
|
||||
|
||||
popup_editor_vb = memnew(VBoxContainer);
|
||||
popup_editor_vb->add_theme_constant_override("separation", 0);
|
||||
popup_editor_vb->set_anchors_and_offsets_preset(PRESET_FULL_RECT);
|
||||
popup_editor->add_child(popup_editor_vb);
|
||||
|
||||
line_editor = memnew(LineEdit);
|
||||
line_editor->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
popup_editor_vb->add_child(line_editor);
|
||||
line_editor->connect("text_submitted", callable_mp(this, &FileSystemList::_line_editor_submit));
|
||||
popup_editor->connect("popup_hide", callable_mp(this, &FileSystemList::_text_editor_popup_modal_close));
|
||||
}
|
||||
|
||||
FileSystemDock *FileSystemDock::singleton = nullptr;
|
||||
|
||||
Ref<Texture2D> FileSystemDock::_get_tree_item_icon(bool p_is_valid, String p_file_type) {
|
||||
|
@ -1581,13 +1669,15 @@ void FileSystemDock::_folder_removed(String p_folder) {
|
|||
}
|
||||
|
||||
void FileSystemDock::_rename_operation_confirm() {
|
||||
if (!tree->is_anything_selected()) {
|
||||
return;
|
||||
}
|
||||
String new_name;
|
||||
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();
|
||||
|
||||
if (tree->has_focus()) {
|
||||
new_name = s->get_text(col_index).strip_edges();
|
||||
} else if (files->has_focus()) {
|
||||
new_name = files->get_edit_text().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;
|
||||
|
@ -1607,10 +1697,12 @@ void FileSystemDock::_rename_operation_confirm() {
|
|||
}
|
||||
}
|
||||
|
||||
// Restores Tree to restore original names.
|
||||
if (rename_error) {
|
||||
// Restore original name.
|
||||
if (rename_error && tree->has_focus()) {
|
||||
s->set_text(col_index, old_name);
|
||||
return;
|
||||
} else if (rename_error && files->has_focus()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String old_path = to_rename.path.ends_with("/") ? to_rename.path.left(-1) : to_rename.path;
|
||||
|
@ -2032,21 +2124,27 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
|
|||
} break;
|
||||
|
||||
case FILE_RENAME: {
|
||||
if (tree->is_anything_selected() && !p_selected.is_empty()) {
|
||||
if (!p_selected.is_empty()) {
|
||||
// Set to_rename variable for callback execution.
|
||||
to_rename.path = p_selected[0];
|
||||
to_rename.is_file = !to_rename.path.ends_with("/");
|
||||
if (to_rename.path == "res://") {
|
||||
break;
|
||||
}
|
||||
|
||||
// Edit node in Tree.
|
||||
tree->grab_focus();
|
||||
tree->edit_selected(true);
|
||||
if (tree->has_focus()) {
|
||||
// Edit node in Tree.
|
||||
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());
|
||||
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());
|
||||
}
|
||||
} else if (files->has_focus()) {
|
||||
files->edit_selected();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -3337,6 +3435,7 @@ FileSystemDock::FileSystemDock() {
|
|||
files->connect("gui_input", callable_mp(this, &FileSystemDock::_file_list_gui_input));
|
||||
files->connect("multi_selected", callable_mp(this, &FileSystemDock::_file_multi_selected));
|
||||
files->connect("empty_clicked", callable_mp(this, &FileSystemDock::_file_list_empty_clicked));
|
||||
files->connect("item_edited", callable_mp(this, &FileSystemDock::_rename_operation_confirm));
|
||||
files->set_custom_minimum_size(Size2(0, 15 * EDSCALE));
|
||||
files->set_allow_rmb_select(true);
|
||||
file_list_vb->add_child(files);
|
||||
|
|
|
@ -57,7 +57,24 @@ class FileSystemTree : public Tree {
|
|||
};
|
||||
|
||||
class FileSystemList : public ItemList {
|
||||
virtual Control *make_custom_tooltip(const String &p_text) const;
|
||||
GDCLASS(FileSystemList, ItemList);
|
||||
|
||||
VBoxContainer *popup_editor_vb = nullptr;
|
||||
Popup *popup_editor = nullptr;
|
||||
LineEdit *line_editor = nullptr;
|
||||
|
||||
virtual Control *make_custom_tooltip(const String &p_text) const override;
|
||||
void _line_editor_submit(String p_text);
|
||||
void _text_editor_popup_modal_close();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
bool edit_selected();
|
||||
String get_edit_text();
|
||||
|
||||
FileSystemList();
|
||||
};
|
||||
|
||||
class FileSystemDock : public VBoxContainer {
|
||||
|
|
Loading…
Reference in New Issue