From 0e95d034eba8dffe52d2f0108f2a7cc18d61205c Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Sat, 4 Jan 2025 18:17:38 +0100 Subject: [PATCH] Allow file browser to optionally display file sizes --- data/language/en-GB.txt | 7 +- src/openrct2-ui/UiStringIds.h | 11 +- src/openrct2-ui/windows/LoadSave.cpp | 328 ++++++++++++++++++++------- src/openrct2/config/Config.cpp | 7 +- src/openrct2/config/Config.h | 2 + src/openrct2/config/ConfigTypes.h | 2 + src/openrct2/world/Location.hpp | 5 + 7 files changed, 274 insertions(+), 88 deletions(-) diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt index c757fb185f..0eabfa7e1a 100644 --- a/data/language/en-GB.txt +++ b/data/language/en-GB.txt @@ -2617,7 +2617,7 @@ STR_5368 :Reset crash status STR_5371 :Object selection STR_5372 :Invert right mouse dragging STR_5373 :Name {STRINGID} -STR_5374 :Date {STRINGID} +STR_5374 :Date modified {STRINGID} STR_5375 :▲ STR_5376 :▼ STR_5404 :Name already exists @@ -3787,3 +3787,8 @@ STR_6709 :Enter Smooth Strength between {COMMA16} and {COMMA16} STR_6710 :Stable sort STR_6711 :Filename: STR_6712 :Save +STR_6713 :{COMMA32} {STRINGID} +STR_6714 :Filename +STR_6715 :Date modified +STR_6716 :File size +STR_6717 :File size {STRINGID} diff --git a/src/openrct2-ui/UiStringIds.h b/src/openrct2-ui/UiStringIds.h index 58ac27ee76..46eb01e308 100644 --- a/src/openrct2-ui/UiStringIds.h +++ b/src/openrct2-ui/UiStringIds.h @@ -845,17 +845,22 @@ namespace OpenRCT2 STR_SET_LAND_TO_BE_OWNED_TIP = 3221, // Window: LoadSave - STR_DATE = 5374, + STR_DATE_COLUMN = 5374, STR_FILEBROWSER_ACTION_NEW_FILE = 2719, STR_FILEBROWSER_ACTION_NEW_FOLDER = 5985, STR_FILEBROWSER_ACTION_UP = 2718, + STR_FILEBROWSER_CUSTOMISE_DATE = 6715, + STR_FILEBROWSER_CUSTOMISE_FILENAME = 6714, + STR_FILEBROWSER_CUSTOMISE_SIZE = 6716, STR_FILEBROWSER_FILE_NAME_PROMPT = 2710, + STR_FILEBROWSER_FILE_SIZE_VALUE = 6713, STR_FILEBROWSER_FOLDER_NAME_PROMPT = 5986, STR_FILEBROWSER_OVERWRITE_PROMPT = 2708, STR_FILEBROWSER_OVERWRITE_TITLE = 2709, STR_FILEBROWSER_SAVE_BUTTON = 6712, + STR_FILEBROWSER_SIZE_COLUMN = 6717, STR_FILEBROWSER_USE_SYSTEM_WINDOW = 2707, - STR_FILENAME = 6711, + STR_FILENAME_LABEL = 6711, STR_FILE_DIALOG_TITLE_INSTALL_NEW_TRACK_DESIGN = 1039, STR_FILE_DIALOG_TITLE_LOAD_GAME = 1036, STR_FILE_DIALOG_TITLE_LOAD_HEIGHTMAP = 6042, @@ -867,7 +872,7 @@ namespace OpenRCT2 STR_LANDSCAPE_SAVE_FAILED = 1049, STR_LOADSAVE_DEFAULT = 5891, STR_LOADSAVE_DEFAULT_TIP = 5892, - STR_NAME = 5373, + STR_NAME_COLUMN = 5373, STR_OPENRCT2_HEIGHTMAP_FILE = 6055, STR_OPENRCT2_LANDSCAPE_FILE = 1045, STR_OPENRCT2_SAVED_GAME = 1043, diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index ed9b1fa2f4..008a88bb6f 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -46,11 +47,11 @@ namespace OpenRCT2::Ui::Windows { #pragma region Widgets - static constexpr ScreenSize kWindowSizeInit = { 350, 400 }; - static constexpr ScreenSize kWindowSizeMin = { kWindowSizeInit.width, kWindowSizeInit.height / 2 }; + static constexpr ScreenSize kWindowSizeInit = { 400, 350 }; + static constexpr ScreenSize kWindowSizeMin = kWindowSizeInit / 2; static constexpr ScreenSize kWindowSizeMax = kWindowSizeInit * 2; - static constexpr uint16_t DATE_TIME_GAP = 2; + static constexpr uint16_t kDateTimeGap = 2; enum { @@ -63,7 +64,9 @@ namespace OpenRCT2::Ui::Windows WIDX_NEW_FOLDER, WIDX_NEW_FILE, WIDX_SORT_NAME, + WIDX_SORT_SIZE, WIDX_SORT_DATE, + WIDX_SORT_CUSTOMISE, WIDX_SCROLL, WIDX_FILENAME_TEXTBOX, WIDX_SAVE, @@ -82,8 +85,10 @@ namespace OpenRCT2::Ui::Windows MakeWidget({ 88, 36}, { 84, 14 }, WindowWidgetType::Button, WindowColour::Primary, STR_FILEBROWSER_ACTION_UP ), // WIDX_UP MakeWidget({ 172, 36}, { 87, 14 }, WindowWidgetType::Button, WindowColour::Primary, STR_FILEBROWSER_ACTION_NEW_FOLDER ), // WIDX_NEW_FOLDER MakeWidget({ 259, 36}, { 87, 14 }, WindowWidgetType::Button, WindowColour::Primary, STR_FILEBROWSER_ACTION_NEW_FILE ), // WIDX_NEW_FILE - MakeWidget({ 4, 55}, { 170, 14 }, WindowWidgetType::TableHeader, WindowColour::Primary ), // WIDX_SORT_NAME - MakeWidget({(WW - 5) / 2 + 1, 55}, { 170, 14 }, WindowWidgetType::TableHeader, WindowColour::Primary ), // WIDX_SORT_DATE + MakeWidget({ 4, 55}, { 160, 14 }, WindowWidgetType::TableHeader, WindowColour::Primary ), // WIDX_SORT_NAME + MakeWidget({(WW - 5) / 3 + 1, 55}, { 160, 14 }, WindowWidgetType::TableHeader, WindowColour::Primary ), // WIDX_SORT_SIZE + MakeWidget({(WW - 5) / 3 + 1, 55}, { 160, 14 }, WindowWidgetType::TableHeader, WindowColour::Primary ), // WIDX_SORT_DATE + MakeWidget({ (WW - 19), 55}, { 14, 14 }, WindowWidgetType::Button, WindowColour::Primary, STR_DROPDOWN_GLYPH ), // WIDX_SORT_CUSTOMISE MakeWidget({ 4, 68}, { 342, 303 }, WindowWidgetType::Scroll, WindowColour::Primary, SCROLL_VERTICAL ), // WIDX_SCROLL MakeWidget({ 64, WH - 50}, { WW - 133, 14 }, WindowWidgetType::TextBox, WindowColour::Secondary ), // WIDX_FILENAME_TEXTBOX MakeWidget({ WW - 65, WH - 50}, { 60, 14 }, WindowWidgetType::Button, WindowColour::Secondary, STR_FILEBROWSER_SAVE_BUTTON ), // WIDX_SAVE @@ -109,6 +114,9 @@ namespace OpenRCT2::Ui::Windows time_t date_modified{ 0 }; std::string date_formatted{}; std::string time_formatted{}; + uint64_t fileSizeBytes; + uint64_t fileSizeFormatted; + StringId fileSizeUnit; FileType type{}; bool loaded{ false }; }; @@ -139,6 +147,10 @@ namespace OpenRCT2::Ui::Windows return -difftime(a.date_modified, b.date_modified) < 0; case FileBrowserSort::DateAscending: return difftime(a.date_modified, b.date_modified) < 0; + case FileBrowserSort::SizeDescending: + return a.fileSizeBytes - b.fileSizeBytes; + case FileBrowserSort::SizeAscending: + return b.fileSizeBytes - a.fileSizeBytes; } return String::logicalCmp(a.name.c_str(), b.name.c_str()) < 0; } @@ -519,8 +531,8 @@ namespace OpenRCT2::Ui::Windows _listItems.clear(); // Show "new" buttons when saving - window_loadsave_widgets[WIDX_NEW_FILE].type = includeNewItem ? WindowWidgetType::Button : WindowWidgetType::Empty; - window_loadsave_widgets[WIDX_NEW_FOLDER].type = includeNewItem ? WindowWidgetType::Button : WindowWidgetType::Empty; + widgets[WIDX_NEW_FILE].type = includeNewItem ? WindowWidgetType::Button : WindowWidgetType::Empty; + widgets[WIDX_NEW_FOLDER].type = includeNewItem ? WindowWidgetType::Button : WindowWidgetType::Empty; int32_t drives = Platform::GetDrives(); if (directory.empty() && drives) @@ -611,6 +623,24 @@ namespace OpenRCT2::Ui::Windows newListItem.date_formatted = Platform::FormatShortDate(newListItem.date_modified); newListItem.time_formatted = Platform::FormatTime(newListItem.date_modified); + // File size + newListItem.fileSizeBytes = Platform::GetFileSize(newListItem.path.c_str()); + if (newListItem.fileSizeBytes > (1024 * 1024)) + { + newListItem.fileSizeFormatted = newListItem.fileSizeBytes / (1024 * 1024); + newListItem.fileSizeUnit = STR_SIZE_MEGABYTE; + } + else if (newListItem.fileSizeBytes > 1024) + { + newListItem.fileSizeFormatted = newListItem.fileSizeBytes / 1024; + newListItem.fileSizeUnit = STR_SIZE_KILOBYTE; + } + else + { + newListItem.fileSizeFormatted = newListItem.fileSizeBytes; + newListItem.fileSizeUnit = STR_SIZE_BYTE; + } + // Mark if file is the currently loaded game newListItem.loaded = newListItem.path.compare(gCurrentLoadedPath) == 0; @@ -654,7 +684,7 @@ namespace OpenRCT2::Ui::Windows // Check how this date is represented (e.g. 2000-02-20, or 00/02/20) std::string date = Platform::FormatShortDate(long_time); - maxDateWidth = GfxGetStringWidth(date.c_str(), FontStyle::Medium) + DATE_TIME_GAP; + maxDateWidth = GfxGetStringWidth(date.c_str(), FontStyle::Medium) + kDateTimeGap; // Some locales do not use leading zeros for months and days, so let's try October, too. tm.tm_mon = 10; @@ -663,12 +693,12 @@ namespace OpenRCT2::Ui::Windows // Again, check how this date is represented (e.g. 2000-10-20, or 00/10/20) date = Platform::FormatShortDate(long_time); - maxDateWidth = std::max(maxDateWidth, GfxGetStringWidth(date.c_str(), FontStyle::Medium) + DATE_TIME_GAP); + maxDateWidth = std::max(maxDateWidth, GfxGetStringWidth(date.c_str(), FontStyle::Medium) + kDateTimeGap); // Time appears to be universally represented with two digits for minutes, so 12:00 or 00:00 should be // representable. std::string time = Platform::FormatTime(long_time); - maxTimeWidth = GfxGetStringWidth(time.c_str(), FontStyle::Medium) + DATE_TIME_GAP; + maxTimeWidth = GfxGetStringWidth(time.c_str(), FontStyle::Medium) + kDateTimeGap; } void SortList() @@ -686,7 +716,7 @@ namespace OpenRCT2::Ui::Windows if (!uiContext->HasFilePicker()) { disabled_widgets |= (1uLL << WIDX_BROWSE); - window_loadsave_widgets[WIDX_BROWSE].type = WindowWidgetType::Empty; + widgets[WIDX_BROWSE].type = WindowWidgetType::Empty; } // TODO: Split LOADSAVETYPE_* into two proper enum classes (one for load/save, the other for the type) @@ -750,16 +780,7 @@ namespace OpenRCT2::Ui::Windows void OnResize() override { - if (width < min_width) - { - Invalidate(); - width = min_width; - } - if (height < min_height) - { - Invalidate(); - height = min_height; - } + WindowSetResize(*this, kWindowSizeMin.width, kWindowSizeMin.height, kWindowSizeMax.width, kWindowSizeMax.height); auto& config = Config::Get().general; config.FileBrowserWidth = width; @@ -779,98 +800,158 @@ namespace OpenRCT2::Ui::Windows { ResizeFrameWithPage(); - Widget* date_widget = &window_loadsave_widgets[WIDX_SORT_DATE]; - date_widget->right = width - 5; - date_widget->left = date_widget->right - - (maxDateWidth + maxTimeWidth + (4 * DATE_TIME_GAP) + (kScrollBarWidth + 1)); + Widget& customiseWidget = widgets[WIDX_SORT_CUSTOMISE]; + customiseWidget.right = width - 5; + customiseWidget.left = customiseWidget.right - 14; - window_loadsave_widgets[WIDX_SORT_NAME].left = 4; - window_loadsave_widgets[WIDX_SORT_NAME].right = window_loadsave_widgets[WIDX_SORT_DATE].left - 1; + auto& config = Config::Get().general; + if (config.FileBrowserShowDateColumn) + { + // Date column on the right + Widget& dateWidget = widgets[WIDX_SORT_DATE]; + dateWidget.type = WindowWidgetType::TableHeader; + dateWidget.right = customiseWidget.left - 1; + dateWidget.left = dateWidget.right - (maxDateWidth + maxTimeWidth + (4 * kDateTimeGap) + (kScrollBarWidth + 1)); - window_loadsave_widgets[WIDX_SCROLL].right = width - 5; - window_loadsave_widgets[WIDX_SCROLL].bottom = height - 30; + if (config.FileBrowserShowSizeColumn) + { + // File size column in the middle + Widget& sizeWidget = widgets[WIDX_SORT_SIZE]; + sizeWidget.type = WindowWidgetType::TableHeader; + sizeWidget.right = dateWidget.left - 1; + sizeWidget.left = sizeWidget.right - 65; + + // Name column is next to size column + widgets[WIDX_SORT_NAME].right = sizeWidget.left - 1; + } + else + { + // Hide file size header + Widget& sizeWidget = widgets[WIDX_SORT_SIZE]; + sizeWidget.type = WindowWidgetType::Empty; + + // Name column is next to date column + widgets[WIDX_SORT_NAME].right = dateWidget.left - 1; + } + } + else if (config.FileBrowserShowSizeColumn) + { + // Hide date header + Widget& dateWidget = widgets[WIDX_SORT_DATE]; + dateWidget.type = WindowWidgetType::Empty; + + // File size column on the right + Widget& sizeWidget = widgets[WIDX_SORT_SIZE]; + sizeWidget.type = WindowWidgetType::TableHeader; + sizeWidget.right = customiseWidget.left - 1; + sizeWidget.left = sizeWidget.right - 65; + + // Name column is next to size column + widgets[WIDX_SORT_NAME].right = sizeWidget.left - 1; + } + else + { + // Name is the only column + widgets[WIDX_SORT_NAME].right = customiseWidget.left - 1; + + // Hide other columns + widgets[WIDX_SORT_SIZE].type = WindowWidgetType::Empty; + widgets[WIDX_SORT_DATE].type = WindowWidgetType::Empty; + } + + widgets[WIDX_SCROLL].right = width - 5; + widgets[WIDX_SCROLL].bottom = height - 30; if (_type & LOADSAVETYPE_SAVE) { - window_loadsave_widgets[WIDX_SCROLL].bottom -= 18; + widgets[WIDX_SCROLL].bottom -= 18; // Get 'Save' button string width auto saveLabel = LanguageGetString(STR_FILEBROWSER_SAVE_BUTTON); auto saveLabelWidth = GfxGetStringWidth(saveLabel, FontStyle::Medium) + 16; - window_loadsave_widgets[WIDX_SAVE].top = height - 42; - window_loadsave_widgets[WIDX_SAVE].bottom = height - 30; - window_loadsave_widgets[WIDX_SAVE].left = width - saveLabelWidth - 5; - window_loadsave_widgets[WIDX_SAVE].right = width - 5; + widgets[WIDX_SAVE].type = WindowWidgetType::Button; + widgets[WIDX_SAVE].top = height - 42; + widgets[WIDX_SAVE].bottom = height - 30; + widgets[WIDX_SAVE].left = width - saveLabelWidth - 5; + widgets[WIDX_SAVE].right = width - 5; // Get 'Filename:' string width - auto filenameLabel = LanguageGetString(STR_FILENAME); + auto filenameLabel = LanguageGetString(STR_FILENAME_LABEL); auto filenameLabelWidth = GfxGetStringWidth(filenameLabel, FontStyle::Medium); - window_loadsave_widgets[WIDX_FILENAME_TEXTBOX].top = height - 42; - window_loadsave_widgets[WIDX_FILENAME_TEXTBOX].bottom = height - 30; - window_loadsave_widgets[WIDX_FILENAME_TEXTBOX].left = 4 + filenameLabelWidth + 6; - window_loadsave_widgets[WIDX_FILENAME_TEXTBOX].right = window_loadsave_widgets[WIDX_SAVE].left - 5; + widgets[WIDX_FILENAME_TEXTBOX].type = WindowWidgetType::TextBox; + widgets[WIDX_FILENAME_TEXTBOX].top = height - 42; + widgets[WIDX_FILENAME_TEXTBOX].bottom = height - 30; + widgets[WIDX_FILENAME_TEXTBOX].left = 4 + filenameLabelWidth + 6; + widgets[WIDX_FILENAME_TEXTBOX].right = widgets[WIDX_SAVE].left - 5; + } + else + { + widgets[WIDX_SAVE].type = WindowWidgetType::Empty; + widgets[WIDX_FILENAME_TEXTBOX].type = WindowWidgetType::Empty; } // 'Use system file browser' - window_loadsave_widgets[WIDX_BROWSE].top = height - 24; - window_loadsave_widgets[WIDX_BROWSE].bottom = height - 6; + widgets[WIDX_BROWSE].top = height - 24; + widgets[WIDX_BROWSE].bottom = height - 6; } void OnDraw(DrawPixelInfo& dpi) override { DrawWidgets(dpi); - const auto shortPath = ShortenPath(_directory, width - 8, FontStyle::Medium); + { + const auto shortPath = ShortenPath(_directory, width - 8, FontStyle::Medium); - // Format text - std::string buffer; - buffer.assign("{BLACK}"); - buffer += shortPath; + // Format text + std::string buffer; + buffer.assign("{BLACK}"); + buffer += shortPath; - // Draw path text - const auto normalisedPath = Platform::StrDecompToPrecomp(buffer.data()); - const auto* normalisedPathC = normalisedPath.c_str(); - auto ft = Formatter(); - ft.Add(normalisedPathC); - DrawTextEllipsised(dpi, windowPos + ScreenCoordsXY{ 4, 20 }, width - 8, STR_STRING, ft); + // Draw path text + const auto normalisedPath = Platform::StrDecompToPrecomp(buffer.data()); + const auto* normalisedPathC = normalisedPath.c_str(); - // Name button text - StringId id = STR_NONE; - if (Config::Get().general.LoadSaveSort == FileBrowserSort::NameAscending) - id = STR_UP; - else if (Config::Get().general.LoadSaveSort == FileBrowserSort::NameDescending) - id = STR_DOWN; + auto ft = Formatter(); + ft.Add(normalisedPathC); + DrawTextEllipsised(dpi, windowPos + ScreenCoordsXY{ 4, 20 }, width - 8, STR_STRING, ft); + } - // Draw name button indicator. - auto& sort_name_widget = widgets[WIDX_SORT_NAME]; - ft = Formatter(); - ft.Add(id); - DrawTextBasic( - dpi, windowPos + ScreenCoordsXY{ sort_name_widget.left + 11, sort_name_widget.top + 1 }, STR_NAME, ft, - { COLOUR_GREY }); + const auto drawButtonCaption = [dpi, this]( + Widget& widget, StringId strId, FileBrowserSort ascSort, + FileBrowserSort descSort) { + StringId indicatorId = STR_NONE; + if (Config::Get().general.LoadSaveSort == ascSort) + indicatorId = STR_UP; + else if (Config::Get().general.LoadSaveSort == descSort) + indicatorId = STR_DOWN; - // Date button text - if (Config::Get().general.LoadSaveSort == FileBrowserSort::DateAscending) - id = STR_UP; - else if (Config::Get().general.LoadSaveSort == FileBrowserSort::DateDescending) - id = STR_DOWN; - else - id = STR_NONE; + auto ft = Formatter(); + ft.Add(indicatorId); - auto& sort_date_widget = widgets[WIDX_SORT_DATE]; - ft = Formatter(); - ft.Add(id); - DrawTextBasic( - dpi, windowPos + ScreenCoordsXY{ sort_date_widget.left + 5, sort_date_widget.top + 1 }, STR_DATE, ft, - { COLOUR_GREY }); + auto cdpi = const_cast(dpi); + DrawTextBasic(cdpi, windowPos + ScreenCoordsXY{ widget.left + 5, widget.top + 1 }, strId, ft, { COLOUR_GREY }); + }; + + auto& config = Config::Get().general; + drawButtonCaption( + widgets[WIDX_SORT_NAME], STR_NAME_COLUMN, FileBrowserSort::NameAscending, FileBrowserSort::NameDescending); + + if (config.FileBrowserShowSizeColumn) + drawButtonCaption( + widgets[WIDX_SORT_SIZE], STR_FILEBROWSER_SIZE_COLUMN, FileBrowserSort::SizeAscending, + FileBrowserSort::SizeDescending); + + if (config.FileBrowserShowDateColumn) + drawButtonCaption( + widgets[WIDX_SORT_DATE], STR_DATE_COLUMN, FileBrowserSort::DateAscending, FileBrowserSort::DateDescending); // 'Filename:' label if (_type & LOADSAVETYPE_SAVE) { auto& widget = widgets[WIDX_FILENAME_TEXTBOX]; - DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 5, widget.top + 2 }, STR_FILENAME, ft, { COLOUR_GREY }); + DrawTextBasic(dpi, windowPos + ScreenCoordsXY{ 5, widget.top + 2 }, STR_FILENAME_LABEL, {}, { COLOUR_GREY }); } } @@ -930,6 +1011,20 @@ namespace OpenRCT2::Ui::Windows Invalidate(); break; + case WIDX_SORT_SIZE: + if (Config::Get().general.LoadSaveSort == FileBrowserSort::SizeDescending) + { + Config::Get().general.LoadSaveSort = FileBrowserSort::SizeAscending; + } + else + { + Config::Get().general.LoadSaveSort = FileBrowserSort::SizeDescending; + } + Config::Save(); + SortList(); + Invalidate(); + break; + case WIDX_SORT_DATE: if (Config::Get().general.LoadSaveSort == FileBrowserSort::DateDescending) { @@ -967,6 +1062,56 @@ namespace OpenRCT2::Ui::Windows } } + void OnMouseDown(WidgetIndex widgetIndex) override + { + if (widgetIndex != WIDX_SORT_CUSTOMISE) + return; + + gDropdownItems[0].Format = STR_TOGGLE_OPTION; + gDropdownItems[1].Format = STR_TOGGLE_OPTION; + gDropdownItems[2].Format = STR_TOGGLE_OPTION; + gDropdownItems[0].Args = STR_FILEBROWSER_CUSTOMISE_FILENAME; + gDropdownItems[1].Args = STR_FILEBROWSER_CUSTOMISE_SIZE; + gDropdownItems[2].Args = STR_FILEBROWSER_CUSTOMISE_DATE; + + Widget* widget = &widgets[WIDX_SORT_CUSTOMISE]; + + WindowDropdownShowTextCustomWidth( + { windowPos.x + widget->left - 70, windowPos.y + widget->top }, widget->height() + 1, colours[1], 0, + Dropdown::Flag::StayOpen, 3, 90); + + auto& config = Config::Get().general; + + Dropdown::SetChecked(0, true); + Dropdown::SetChecked(1, config.FileBrowserShowSizeColumn); + Dropdown::SetChecked(2, config.FileBrowserShowDateColumn); + } + + void OnDropdown(WidgetIndex widgetIndex, int32_t selectedIndex) override + { + if (widgetIndex != WIDX_SORT_CUSTOMISE) + return; + + auto& config = Config::Get().general; + bool changed = false; + if (selectedIndex == 1) + { + config.FileBrowserShowSizeColumn ^= true; + changed = true; + } + else if (selectedIndex == 2) + { + config.FileBrowserShowDateColumn ^= true; + changed = true; + } + + if (changed) + { + Config::Save(); + Invalidate(); + } + } + void OnTextInput(WidgetIndex widgetIndex, std::string_view text) override { if (text.empty()) @@ -1085,8 +1230,13 @@ namespace OpenRCT2::Ui::Windows GfxFillRect( dpi, { { dpi.x, dpi.y }, { dpi.x + dpi.width - 1, dpi.y + dpi.height - 1 } }, ColourMapA[colours[1].colour].mid_light); + const int32_t listWidth = widgets[WIDX_SCROLL].width(); - const int32_t dateAnchor = widgets[WIDX_SORT_DATE].left + maxDateWidth + DATE_TIME_GAP; + const auto sizeColumnLeft = widgets[WIDX_SORT_SIZE].left; + const auto dateColumnLeft = widgets[WIDX_SORT_DATE].left; + const int32_t dateAnchor = dateColumnLeft + maxDateWidth + kDateTimeGap; + + auto& config = Config::Get().general; for (int32_t i = 0; i < no_list_items; i++) { @@ -1127,18 +1277,30 @@ namespace OpenRCT2::Ui::Windows DrawTextEllipsised(dpi, { 15, y }, max_file_width, stringId, ft); // Print formatted modified date, if this is a file - if (_listItems[i].type == FileType::file) + if (_listItems[i].type != FileType::file) + continue; + + if (config.FileBrowserShowSizeColumn) + { + ft = Formatter(); + ft.Add(STR_FILEBROWSER_FILE_SIZE_VALUE); + ft.Add(_listItems[i].fileSizeFormatted); + ft.Add(_listItems[i].fileSizeUnit); + DrawTextEllipsised(dpi, { sizeColumnLeft + 2, y }, maxDateWidth + maxTimeWidth, stringId, ft); + } + + if (config.FileBrowserShowDateColumn) { ft = Formatter(); ft.Add(STR_STRING); ft.Add(_listItems[i].date_formatted.c_str()); DrawTextEllipsised( - dpi, { dateAnchor - DATE_TIME_GAP, y }, maxDateWidth, stringId, ft, { TextAlignment::RIGHT }); + dpi, { dateAnchor - kDateTimeGap, y }, maxDateWidth, stringId, ft, { TextAlignment::RIGHT }); ft = Formatter(); ft.Add(STR_STRING); ft.Add(_listItems[i].time_formatted.c_str()); - DrawTextEllipsised(dpi, { dateAnchor + DATE_TIME_GAP, y }, maxTimeWidth, stringId, ft); + DrawTextEllipsised(dpi, { dateAnchor + kDateTimeGap, y }, maxTimeWidth, stringId, ft); } } } diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index 1672670da9..3d20337eff 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -200,7 +200,8 @@ namespace OpenRCT2::Config model->DefaultInspectionInterval = reader->GetInt32("default_inspection_interval", 2); model->LastRunVersion = reader->GetString("last_run_version", ""); model->InvertViewportDrag = reader->GetBoolean("invert_viewport_drag", false); - model->LoadSaveSort = reader->GetEnum("load_save_sort", FileBrowserSort::NameAscending, Enum_FileBrowserSort); + model->LoadSaveSort = reader->GetEnum( + "load_save_sort", FileBrowserSort::NameAscending, Enum_FileBrowserSort); model->MinimizeFullscreenFocusLoss = reader->GetBoolean("minimize_fullscreen_focus_loss", true); model->DisableScreensaver = reader->GetBoolean("disable_screensaver", true); @@ -255,6 +256,8 @@ namespace OpenRCT2::Config model->FileBrowserWidth = reader->GetInt32("file_browser_width", 0); model->FileBrowserHeight = reader->GetInt32("file_browser_height", 0); + model->FileBrowserShowSizeColumn = reader->GetBoolean("file_browser_show_size_column", true); + model->FileBrowserShowDateColumn = reader->GetBoolean("file_browser_show_date_column", true); } } @@ -343,6 +346,8 @@ namespace OpenRCT2::Config writer->WriteInt64("last_version_check_time", model->LastVersionCheckTime); writer->WriteInt32("file_browser_width", model->FileBrowserWidth); writer->WriteInt32("file_browser_height", model->FileBrowserHeight); + writer->WriteBoolean("file_browser_show_size_column", model->FileBrowserShowSizeColumn); + writer->WriteBoolean("file_browser_show_date_column", model->FileBrowserShowDateColumn); } static void ReadInterface(IIniReader* reader) diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index 6b9c91f927..ad9c1eda9f 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -119,6 +119,8 @@ namespace OpenRCT2::Config int64_t LastVersionCheckTime; int16_t FileBrowserWidth; int16_t FileBrowserHeight; + bool FileBrowserShowSizeColumn; + bool FileBrowserShowDateColumn; }; struct Interface diff --git a/src/openrct2/config/ConfigTypes.h b/src/openrct2/config/ConfigTypes.h index 6b3a8bf65e..0419ec4fee 100644 --- a/src/openrct2/config/ConfigTypes.h +++ b/src/openrct2/config/ConfigTypes.h @@ -23,6 +23,8 @@ enum class FileBrowserSort : int32_t { NameAscending, NameDescending, + SizeAscending, + SizeDescending, DateAscending, DateDescending, }; diff --git a/src/openrct2/world/Location.hpp b/src/openrct2/world/Location.hpp index fe097ddb1d..e7c8c6a617 100644 --- a/src/openrct2/world/Location.hpp +++ b/src/openrct2/world/Location.hpp @@ -50,6 +50,11 @@ struct ScreenSize { return ScreenSize{ width * scalar, height * scalar }; } + + constexpr ScreenSize operator/(int32_t scalar) const + { + return ScreenSize{ width / scalar, height / scalar }; + } }; struct ScreenCoordsXY