Editor: Wrap Long Project Title

Wraps project titles above 800px (on 100% Editor Scale) to prevent
SideBar being pushed beyond Project Manager boundaries.

(cherry picked from commit bb1bd267b9b78acb31421d13eca0d3d996b72a3a)
This commit is contained in:
unit-tick authored and Thaddeus Crews committed 2026-07-09 13:02:42 -05:00
1 parent d6096250e5
commit 2575428deb
4 files changed
+121 -9

No files matched your search

+97 -7
View File
@@ -107,7 +107,6 @@ void ProjectListItemControl::_notification(int p_what) {
explore_button->set_button_icon(get_editor_theme_icon(SNAME("Load")));
#endif
}
if (touch_menu_button) {
touch_menu_button->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl")));
}
@@ -176,9 +175,7 @@ void ProjectListItemControl::_notification(int p_what) {
} break;
case NOTIFICATION_READY: {
const Callable callback = callable_mp(this, &ProjectListItemControl::update_title_size);
get_window()->connect(SNAME("size_changed"), callback);
callback.call_deferred();
set_project_title_autowrap();
} break;
}
}
@@ -427,8 +424,74 @@ void ProjectListItemControl::set_is_grayed(bool p_grayed) {
}
}
void ProjectListItemControl::update_title_size() {
project_title->set_custom_minimum_size(Vector2(get_size().x * 0.5, 0));
void ProjectListItemControl::set_project_title_index(int p_title_index) {
project_title_index = p_title_index;
}
void ProjectListItemControl::set_project_title_autowrap() {
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<ProjectTag>(child);
tag_size += tag->get_size().x;
if (tag_maxsize == 0) {
tag_maxsize = tag->get_custom_maximum_size().x;
}
}
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;
}
if (title_fullsize_cache > size_check - tag_size_cache) {
resize_project_title();
}
}
void ProjectListItemControl::resize_project_title() {
if (get_window() == nullptr) {
return;
}
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);
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));
project_title->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
}
}
void ProjectListItemControl::_bind_methods() {
@@ -482,7 +545,6 @@ ProjectListItemControl::ProjectListItemControl() {
project_title->set_focus_mode(FOCUS_ACCESSIBILITY);
project_title->set_name("ProjectName");
project_title->set_h_size_flags(Control::SIZE_FILL);
project_title->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
title_hb->add_child(project_title);
tag_container = memnew(HFlowContainer);
@@ -872,11 +934,14 @@ 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()?
}
@@ -889,6 +954,9 @@ 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);
}
@@ -1076,10 +1144,14 @@ 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;
}
@@ -1091,6 +1163,7 @@ 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);
@@ -1157,6 +1230,15 @@ 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;
}
@@ -1502,6 +1584,14 @@ void ProjectList::erase_selected_projects(bool p_delete_project_contents) {
update_dock_menu();
}
// Resize project titles.
void ProjectList::resize_project_titles() {
for (Item &item : _projects) {
item.control->resize_project_title();
}
}
// Missing projects.
bool ProjectList::is_any_project_missing() const {
+20 -1
View File
@@ -62,6 +62,8 @@ 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;
@@ -91,6 +93,13 @@ class ProjectListItemControl : public HBoxContainer {
void _accessibility_action_focus(const Variant &p_data);
void _accessibility_action_blur(const Variant &p_data);
private:
// Caches for resizing project titles.
int title_fullsize_cache = 0;
int tag_size_cache = 0;
int window_size_cache = 0;
protected:
void _notification(int p_what);
static void _bind_methods();
@@ -110,8 +119,10 @@ public:
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 update_title_size();
void resize_project_title();
ProjectListItemControl();
};
@@ -160,6 +171,7 @@ public:
bool missing = false;
bool recovery_mode = false;
int version = 0;
int project_title_index = -1;
ProjectListItemControl *control = nullptr;
@@ -208,6 +220,9 @@ public:
String get_last_edited_string() const;
};
HashMap<int, int> title_size_cache;
int project_title_index_count = -1;
private:
String _config_path;
ConfigFile _config;
@@ -323,6 +338,10 @@ public:
int get_single_selected_index() const;
void erase_selected_projects(bool p_delete_project_contents);
// Resize project titles.
void resize_project_titles();
// Missing projects.
bool is_any_project_missing() const;
@@ -143,6 +143,9 @@ void ProjectManager::_notification(int p_what) {
}
_update_list_placeholder();
} break;
case NOTIFICATION_RESIZED: {
project_list->resize_project_titles();
} break;
}
}
+1 -1
View File
@@ -57,6 +57,7 @@ const String ProjectTag::get_tag() const {
ProjectTag::ProjectTag(const String &p_text, bool p_display_close) {
add_theme_constant_override(SNAME("separation"), 0);
set_v_size_flags(SIZE_SHRINK_CENTER);
set_custom_maximum_size(Vector2(336 * EDSCALE, -1));
tag_string = p_text;
display_close = p_display_close;
@@ -80,6 +81,5 @@ ProjectTag::ProjectTag(const String &p_text, bool p_display_close) {
button->set_accessibility_name(vformat(TTR("Project Tag: %s"), p_text));
button->set_icon_alignment(HORIZONTAL_ALIGNMENT_RIGHT);
button->set_theme_type_variation(SNAME("ProjectTagButton"));
button->set_custom_maximum_size(Vector2(334 * EDSCALE, -1));
button->set_mouse_filter(MOUSE_FILTER_PASS);
}