Skip to content

Commit 2d80df4

Browse files
[ProjectList] Fix Wrap Long Project Title
Co-authored-by: unit-tick <official.prince.john@gmail.com>
1 parent 7220d45 commit 2d80df4

2 files changed

Lines changed: 81 additions & 71 deletions

File tree

editor/project_manager/project_list.cpp

Lines changed: 74 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "core/input/input.h"
3535
#include "core/io/dir_access.h"
3636
#include "core/object/callable_mp.h"
37+
#include "core/object/class_db.h"
3738
#include "core/os/os.h"
3839
#include "core/os/time.h"
3940
#include "core/version.h"
@@ -175,7 +176,7 @@ void ProjectListItemControl::_notification(int p_what) {
175176
} break;
176177

177178
case NOTIFICATION_READY: {
178-
set_project_title_autowrap();
179+
call_deferred("set_project_title_autowrap");
179180
} break;
180181
}
181182
}
@@ -424,80 +425,90 @@ void ProjectListItemControl::set_is_grayed(bool p_grayed) {
424425
}
425426
}
426427

427-
void ProjectListItemControl::set_project_title_index(int p_title_index) {
428-
project_title_index = p_title_index;
429-
}
430-
431428
void ProjectListItemControl::set_project_title_autowrap() {
432429
title_fullsize_cache = project_title->get_size().x;
433-
window_size_cache = get_window()->get_size().x;
430+
ProjectList *pl = get_list();
431+
pl->window_size_cache = get_window()->get_size().x;
434432

435433
int tag_size = 0;
436-
int tag_maxsize = 0;
437434
for (Node *child : tag_container->iterate_children()) {
438435
ProjectTag *tag = Object::cast_to<ProjectTag>(child);
439436
tag_size += tag->get_size().x;
440-
441-
if (tag_maxsize == 0) {
442-
tag_maxsize = tag->get_custom_maximum_size().x;
443-
}
444-
}
445-
tag_size_cache = MIN(tag_size, tag_maxsize);
446-
int &title_size_cache = get_list()->title_size_cache[project_title_index];
447-
448-
int size_check = 800 * EDSCALE;
449-
if (title_size_cache == 0) {
450-
title_size_cache = size_check;
451437
}
438+
tag_size_cache = tag_size;
452439

453-
if (title_fullsize_cache > size_check - tag_size_cache) {
440+
if (title_fullsize_cache > pl->title_size_cache - tag_size) {
454441
resize_project_title();
455442
}
456443
}
457444

458445
void ProjectListItemControl::resize_project_title() {
459-
if (get_window() == nullptr) {
460-
return;
461-
}
462-
463-
int window_size = get_window()->get_size().x;
464-
int difference = window_size - window_size_cache;
465-
window_size_cache = window_size;
466-
467-
int &title_size_cache = get_list()->title_size_cache[project_title_index];
468-
title_size_cache += difference;
469-
470-
if (title_size_cache > title_fullsize_cache + tag_size_cache) {
446+
const int title_available_space = get_list()->title_size_cache - tag_size_cache;
447+
if (title_fullsize_cache <= title_available_space) {
471448
project_title->set_custom_maximum_size(Vector2(-1, -1));
472449
project_title->set_custom_minimum_size(Vector2(0, 0));
473450
project_title->set_autowrap_mode(TextServer::AUTOWRAP_OFF);
474-
475451
return;
476452
}
477-
ProjectTag tag = ProjectTag("dummy");
478-
int tag_maxsize = tag.get_custom_maximum_size().x;
479-
int title_maxsize = title_size_cache - tag_size_cache;
480-
int title_minsize = title_size_cache - tag_maxsize;
481453

482-
int abs_minsize = (200 * EDSCALE);
454+
const int abs_minsize = (200 * EDSCALE);
483455
if (title_fullsize_cache > abs_minsize) {
484-
if (title_minsize < abs_minsize) {
485-
title_minsize = abs_minsize + tag_maxsize - tag_size_cache;
486-
}
487-
if (title_maxsize < title_minsize) {
488-
project_title->set_custom_maximum_size(Vector2(title_minsize, -1));
489-
} else {
490-
project_title->set_custom_maximum_size(Vector2(title_maxsize, -1));
491-
}
456+
const int title_maxsize = title_available_space;
457+
const int title_minsize = MAX(title_maxsize, abs_minsize);
458+
project_title->set_custom_maximum_size(Vector2(MAX(title_minsize, title_maxsize), -1));
492459
project_title->set_custom_minimum_size(Vector2(title_minsize, 0));
493460
project_title->set_autowrap_mode(TextServer::AUTOWRAP_WORD_SMART);
494461
}
495462
}
496463

464+
int ProjectListItemControl::get_edge_elements_width() const {
465+
// Returns the combined width of the left spacer, favorite button, project icon,
466+
// right spacer, and the separation constant (10 * EDSCALE)
467+
int width = 0;
468+
int child_count = get_child_count();
469+
// Left spacer (first child)
470+
if (child_count > 0) {
471+
Control *spacer = Object::cast_to<Control>(get_child(0));
472+
if (spacer) {
473+
width += spacer->get_size().x;
474+
}
475+
}
476+
// Favorite button
477+
if (favorite_button) {
478+
width += favorite_button->get_size().x;
479+
}
480+
// Project icon
481+
if (project_icon) {
482+
width += project_icon->get_size().x;
483+
}
484+
// Right spacer (last child)
485+
if (child_count > 0) {
486+
Control *right_spacer = Object::cast_to<Control>(get_child(child_count - 1));
487+
if (right_spacer) {
488+
width += right_spacer->get_size().x;
489+
}
490+
}
491+
// Separation constant
492+
width += 10 * EDSCALE;
493+
return width;
494+
}
495+
496+
void ProjectList::_set_title_size_cache() {
497+
if (!_projects.is_empty()) {
498+
Item &item = _projects.write[0];
499+
// Approx. size of project_title + tag_size
500+
title_size_cache = get_size().x - item.control->get_edge_elements_width() - 100 * EDSCALE;
501+
} else {
502+
title_size_cache = -1;
503+
}
504+
}
505+
497506
void ProjectListItemControl::_bind_methods() {
498507
ADD_SIGNAL(MethodInfo("favorite_pressed"));
499508
ADD_SIGNAL(MethodInfo("explore_pressed"));
500509
ADD_SIGNAL(MethodInfo("request_menu"));
510+
511+
ClassDB::bind_method(D_METHOD("set_project_title_autowrap"), &ProjectListItemControl::set_project_title_autowrap);
501512
}
502513

503514
ProjectListItemControl::ProjectListItemControl() {
@@ -661,6 +672,10 @@ bool ProjectList::project_feature_looks_like_version(const String &p_feature) {
661672

662673
void ProjectList::_notification(int p_what) {
663674
switch (p_what) {
675+
case NOTIFICATION_READY: {
676+
_set_title_size_cache();
677+
} break;
678+
664679
case NOTIFICATION_TRANSLATION_CHANGED: {
665680
if (is_ready()) {
666681
for (const Item &item : _projects) {
@@ -936,14 +951,12 @@ void ProjectList::update_project_list() {
936951
// If you have 150 projects, it may read through 150 files on your disk at once + load 150 icons.
937952
// FIXME: Does it really have to be a full, hard reload? Runtime updates should be made much cheaper.
938953

939-
int temp_title_index = -1;
940954
if (ProjectManager::get_singleton()->is_initialized()) {
941955
// Clear whole list
942956
for (int i = 0; i < _projects.size(); ++i) {
943957
Item &project = _projects.write[i];
944958
CRASH_COND(project.control == nullptr);
945959

946-
temp_title_index = project.project_title_index;
947960
memdelete(project.control); // Why not queue_free()?
948961
}
949962

@@ -956,9 +969,6 @@ void ProjectList::update_project_list() {
956969

957970
// Create controls
958971
for (int i = 0; i < _projects.size(); ++i) {
959-
Item &item = _projects.write[i];
960-
item.project_title_index = temp_title_index;
961-
962972
_create_project_item_control(i);
963973
}
964974

@@ -1146,14 +1156,10 @@ int ProjectList::refresh_project(const String &dir_path) {
11461156

11471157
bool was_selected = _selected_project_paths.has(dir_path);
11481158

1149-
int temp_title_index = -1;
1150-
11511159
// Remove item in any case
11521160
for (int i = 0; i < _projects.size(); ++i) {
11531161
const Item &existing_item = _projects[i];
11541162
if (existing_item.path == dir_path) {
1155-
temp_title_index = existing_item.project_title_index;
1156-
11571163
_remove_project(i, false);
11581164
break;
11591165
}
@@ -1165,7 +1171,6 @@ int ProjectList::refresh_project(const String &dir_path) {
11651171

11661172
Item item = load_project_data(dir_path, is_favorite);
11671173

1168-
item.project_title_index = temp_title_index;
11691174
_projects.push_back(item);
11701175
_create_project_item_control(_projects.size() - 1);
11711176

@@ -1233,16 +1238,11 @@ void ProjectList::_create_project_item_control(int p_index) {
12331238
#endif
12341239
hb->connect("request_menu", callable_mp(this, &ProjectList::_open_menu).bind(hb));
12351240

1236-
if (item.project_title_index == -1) {
1237-
project_title_index_count++;
1238-
title_size_cache[project_title_index_count] = 0;
1239-
item.project_title_index = project_title_index_count;
1240-
hb->set_project_title_index(project_title_index_count);
1241-
} else {
1242-
hb->set_project_title_index(item.project_title_index);
1243-
}
1244-
12451241
project_list_vbox->add_child(hb);
1242+
1243+
if (title_size_cache == -1) {
1244+
_set_title_size_cache();
1245+
}
12461246
}
12471247

12481248
void ProjectList::_update_project_control_translatable_fields(const Item &item) {
@@ -1597,6 +1597,16 @@ void ProjectList::erase_selected_projects(bool p_delete_project_contents) {
15971597
// Resize project titles.
15981598

15991599
void ProjectList::resize_project_titles() {
1600+
Window *win = get_window();
1601+
if (win == nullptr) {
1602+
return;
1603+
}
1604+
1605+
const int window_size = win->get_size().x;
1606+
const int difference = window_size - window_size_cache;
1607+
window_size_cache = window_size;
1608+
title_size_cache += difference;
1609+
16001610
for (Item &item : _projects) {
16011611
item.control->resize_project_title();
16021612
}

editor/project_manager/project_list.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ class ProjectListItemControl : public HBoxContainer {
6262

6363
Color favorite_focus_color;
6464

65-
int project_title_index = -1;
66-
6765
bool project_is_missing = false;
6866
bool icon_needs_reload = true;
6967
bool is_selected = false;
@@ -98,7 +96,6 @@ class ProjectListItemControl : public HBoxContainer {
9896

9997
int title_fullsize_cache = 0;
10098
int tag_size_cache = 0;
101-
int window_size_cache = 0;
10299

103100
protected:
104101
void _notification(int p_what);
@@ -120,11 +117,12 @@ class ProjectListItemControl : public HBoxContainer {
120117
void set_is_favorite(bool p_favorite);
121118
void set_is_missing(bool p_missing);
122119
void set_is_grayed(bool p_grayed);
123-
void set_project_title_index(int p_title_index);
124120
void set_project_title_autowrap();
125121

126122
void resize_project_title();
127123

124+
int get_edge_elements_width() const;
125+
128126
ProjectListItemControl();
129127
};
130128

@@ -172,7 +170,6 @@ class ProjectList : public ScrollContainer {
172170
bool missing = false;
173171
bool recovery_mode = false;
174172
int version = 0;
175-
int project_title_index = -1;
176173

177174
ProjectListItemControl *control = nullptr;
178175

@@ -221,8 +218,8 @@ class ProjectList : public ScrollContainer {
221218
String get_last_edited_string() const;
222219
};
223220

224-
HashMap<int, int> title_size_cache;
225-
int project_title_index_count = -1;
221+
int window_size_cache = 0;
222+
int title_size_cache = 0;
226223

227224
private:
228225
String _config_path;
@@ -290,6 +287,9 @@ class ProjectList : public ScrollContainer {
290287
void _deselect_project_nocheck(int p_index);
291288
void _select_project_range(int p_begin, int p_end);
292289

290+
// Title size cache.
291+
void _set_title_size_cache();
292+
293293
// Global menu integration.
294294

295295
void _global_menu_new_window(const Variant &p_tag);

0 commit comments

Comments
 (0)