From 622811fde68b2648a9c2f1001e1b892eb0e9295a Mon Sep 17 00:00:00 2001 From: CarrotOfPower <260066004+CarrotOfPower@users.noreply.github.com> Date: Sun, 9 Aug 2026 22:18:01 +0200 Subject: [PATCH] [Project Manager] Fix Wrap Long Project Title for 4.7 Fixes several issues where long project titles were not wrapping correctly in the project list. Co-authored-by: unit-tick --- editor/project_manager/project_list.cpp | 117 ++++++++++-------------- editor/project_manager/project_list.h | 20 ++-- 2 files changed, 61 insertions(+), 76 deletions(-) diff --git a/editor/project_manager/project_list.cpp b/editor/project_manager/project_list.cpp index 7f34a4787b2e..3fbc8e71379e 100644 --- a/editor/project_manager/project_list.cpp +++ b/editor/project_manager/project_list.cpp @@ -175,7 +175,7 @@ void ProjectListItemControl::_notification(int p_what) { } break; case NOTIFICATION_READY: { - set_project_title_autowrap(); + callable_mp(this, &ProjectListItemControl::set_project_title_autowrap).call_deferred(); } break; } } @@ -424,72 +424,58 @@ void ProjectListItemControl::set_is_grayed(bool p_grayed) { } } -void ProjectListItemControl::set_project_title_index(int p_title_index) { - project_title_index = p_title_index; -} - void ProjectListItemControl::set_project_title_autowrap() { + ProjectList *pl = get_list(); title_fullsize_cache = project_title->get_size().x; - window_size_cache = get_window()->get_size().x; int tag_size = 0; int tag_maxsize = 0; for (Node *child : tag_container->iterate_children()) { ProjectTag *tag = Object::cast_to(child); - tag_size += tag->get_size().x; - - if (tag_maxsize == 0) { - tag_maxsize = tag->get_custom_maximum_size().x; + int temp_tag_size = tag->get_size().x; + tag_size += temp_tag_size; + if (temp_tag_size > tag_maxsize) { + tag_maxsize = temp_tag_size; } } + tag_fullsize_cache = tag_size; tag_size_cache = MIN(tag_size, tag_maxsize); - int &title_size_cache = get_list()->title_size_cache[project_title_index]; - int size_check = 800 * EDSCALE; - if (title_size_cache == 0) { - title_size_cache = size_check; + int &abs_title_and_tags_minsize = pl->abs_title_and_tags_minsize_cache; + if (abs_title_and_tags_minsize == 0) { + ProjectTag *tag = memnew(ProjectTag("dummy")); + const int abs_tag_maxsize = tag->get_custom_maximum_size().x; + memdelete(tag); + abs_title_and_tags_minsize = (200 * EDSCALE) + abs_tag_maxsize; } - if (title_fullsize_cache > size_check - tag_size_cache) { - resize_project_title(); + int &title_size = pl->title_size_cache; + if (title_size == 0) { + // Available space for the project title at startup. + title_size = 764 * EDSCALE + ProjectManager::DEFAULT_WINDOW_WIDTH - 1152; } -} -void ProjectListItemControl::resize_project_title() { - if (get_window() == nullptr) { - return; + if (title_fullsize_cache > title_size - tag_size) { + resize_project_title(title_size, abs_title_and_tags_minsize); } +} - int window_size = get_window()->get_size().x; - int difference = window_size - window_size_cache; - window_size_cache = window_size; - - int &title_size_cache = get_list()->title_size_cache[project_title_index]; - title_size_cache += difference; - - if (title_size_cache > title_fullsize_cache + tag_size_cache) { - project_title->set_custom_maximum_size(Vector2(-1, -1)); - project_title->set_custom_minimum_size(Vector2(0, 0)); - project_title->set_autowrap_mode(TextServer::AUTOWRAP_OFF); - +void ProjectListItemControl::resize_project_title(int p_title_size, int p_abs_title_and_tags_minsize) { + if (p_title_size >= title_fullsize_cache + tag_fullsize_cache) { + if (project_title->get_autowrap_mode() != TextServer::AUTOWRAP_OFF) { + project_title->set_custom_maximum_size(Vector2(-1, -1)); + project_title->set_custom_minimum_size(Vector2(0, 0)); + project_title->set_autowrap_mode(TextServer::AUTOWRAP_OFF); + } return; } - ProjectTag tag = ProjectTag("dummy"); - int tag_maxsize = tag.get_custom_maximum_size().x; - int title_maxsize = title_size_cache - tag_size_cache; - int title_minsize = title_size_cache - tag_maxsize; - int abs_minsize = (200 * EDSCALE); - if (title_fullsize_cache > abs_minsize) { - if (title_minsize < abs_minsize) { - title_minsize = abs_minsize + tag_maxsize - tag_size_cache; - } - if (title_maxsize < title_minsize) { - project_title->set_custom_maximum_size(Vector2(title_minsize, -1)); - } else { - project_title->set_custom_maximum_size(Vector2(title_maxsize, -1)); - } - project_title->set_custom_minimum_size(Vector2(title_minsize, 0)); + const int abs_title_minsize = p_abs_title_and_tags_minsize - tag_size_cache; + if (title_fullsize_cache >= abs_title_minsize) { + const int title_maxsize = p_title_size - tag_size_cache; + const int title_size = MAX(title_maxsize, abs_title_minsize); + project_title->set_custom_maximum_size(Vector2(title_size, -1)); + project_title->set_custom_minimum_size(Vector2(title_size, 0)); project_title->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART); } } @@ -701,7 +687,11 @@ void ProjectList::_notification(int p_what) { AccessibilityServer::get_singleton()->update_set_role(ae, AccessibilityServerEnums::AccessibilityRole::ROLE_LIST_BOX); AccessibilityServer::get_singleton()->update_set_list_item_count(ae, _projects.size()); AccessibilityServer::get_singleton()->update_set_flag(ae, AccessibilityServerEnums::AccessibilityFlags::FLAG_MULTISELECTABLE, false); - } + } break; + + case NOTIFICATION_READY: { + window_size_cache = get_window()->get_size().x; + } break; } } @@ -934,14 +924,12 @@ void ProjectList::update_project_list() { // If you have 150 projects, it may read through 150 files on your disk at once + load 150 icons. // FIXME: Does it really have to be a full, hard reload? Runtime updates should be made much cheaper. - int temp_title_index = -1; if (ProjectManager::get_singleton()->is_initialized()) { // Clear whole list for (int i = 0; i < _projects.size(); ++i) { Item &project = _projects.write[i]; CRASH_COND(project.control == nullptr); - temp_title_index = project.project_title_index; memdelete(project.control); // Why not queue_free()? } @@ -954,9 +942,6 @@ void ProjectList::update_project_list() { // Create controls for (int i = 0; i < _projects.size(); ++i) { - Item &item = _projects.write[i]; - item.project_title_index = temp_title_index; - _create_project_item_control(i); } @@ -1144,14 +1129,10 @@ int ProjectList::refresh_project(const String &dir_path) { bool was_selected = _selected_project_paths.has(dir_path); - int temp_title_index = -1; - // Remove item in any case for (int i = 0; i < _projects.size(); ++i) { const Item &existing_item = _projects[i]; if (existing_item.path == dir_path) { - temp_title_index = existing_item.project_title_index; - _remove_project(i, false); break; } @@ -1163,7 +1144,6 @@ int ProjectList::refresh_project(const String &dir_path) { Item item = load_project_data(dir_path, is_favorite); - item.project_title_index = temp_title_index; _projects.push_back(item); _create_project_item_control(_projects.size() - 1); @@ -1230,15 +1210,6 @@ void ProjectList::_create_project_item_control(int p_index) { #endif hb->connect("request_menu", callable_mp(this, &ProjectList::_open_menu).bind(hb)); - if (item.project_title_index == -1) { - project_title_index_count++; - title_size_cache[project_title_index_count] = 0; - item.project_title_index = project_title_index_count; - hb->set_project_title_index(project_title_index_count); - } else { - hb->set_project_title_index(item.project_title_index); - } - project_list_vbox->add_child(hb); item.control = hb; } @@ -1587,8 +1558,18 @@ void ProjectList::erase_selected_projects(bool p_delete_project_contents) { // Resize project titles. void ProjectList::resize_project_titles() { + Window *win = get_window(); + if (win == nullptr) { + return; + } + + const int window_size = win->get_size().x; + const int difference = window_size - window_size_cache; + window_size_cache = window_size; + title_size_cache += difference; + for (Item &item : _projects) { - item.control->resize_project_title(); + item.control->resize_project_title(title_size_cache, abs_title_and_tags_minsize_cache); } } diff --git a/editor/project_manager/project_list.h b/editor/project_manager/project_list.h index 6ff4dbfa7581..f07c63c4e750 100644 --- a/editor/project_manager/project_list.h +++ b/editor/project_manager/project_list.h @@ -62,8 +62,6 @@ class ProjectListItemControl : public HBoxContainer { Color favorite_focus_color; - int project_title_index = -1; - bool project_is_missing = false; bool icon_needs_reload = true; bool is_selected = false; @@ -97,8 +95,8 @@ class ProjectListItemControl : public HBoxContainer { // Caches for resizing project titles. int title_fullsize_cache = 0; + int tag_fullsize_cache = 0; int tag_size_cache = 0; - int window_size_cache = 0; protected: void _notification(int p_what); @@ -119,10 +117,9 @@ class ProjectListItemControl : public HBoxContainer { void set_is_favorite(bool p_favorite); void set_is_missing(bool p_missing); void set_is_grayed(bool p_grayed); - void set_project_title_index(int p_title_index); void set_project_title_autowrap(); - void resize_project_title(); + void resize_project_title(int p_title_size, int p_abs_title_and_tags_minsize); ProjectListItemControl(); }; @@ -171,7 +168,6 @@ class ProjectList : public ScrollContainer { bool missing = false; bool recovery_mode = false; int version = 0; - int project_title_index = -1; ProjectListItemControl *control = nullptr; @@ -220,8 +216,9 @@ class ProjectList : public ScrollContainer { String get_last_edited_string() const; }; - HashMap title_size_cache; - int project_title_index_count = -1; + int window_size_cache = 0; + int title_size_cache = 0; + int abs_title_and_tags_minsize_cache = 0; private: String _config_path; @@ -304,6 +301,13 @@ class ProjectList : public ScrollContainer { static bool project_feature_looks_like_version(const String &p_feature); + // Compact mode. + + bool compact_mode = false; + bool compact_mode_cache = false; + bool sb_visible_cache = false; + int compact_size_cache = 0; + // Initialization & loading. void save_config();