From c49b2c61da89879c0652ac98bc88ae5432e08b7d Mon Sep 17 00:00:00 2001 From: Alberth Date: Wed, 13 Sep 2023 11:39:30 +0200 Subject: [PATCH] Add header stacking, tune remaining tables --- .../Lua/dialogs/resizables/level_editor.lua | 13 ++- CorsixTH/Lua/level_editor/data_storage.lua | 95 ++++++++++++------- 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/CorsixTH/Lua/dialogs/resizables/level_editor.lua b/CorsixTH/Lua/dialogs/resizables/level_editor.lua index 0f4dfd7f34..fc4117ece7 100644 --- a/CorsixTH/Lua/dialogs/resizables/level_editor.lua +++ b/CorsixTH/Lua/dialogs/resizables/level_editor.lua @@ -103,6 +103,8 @@ local function _makeTableSection(settings) -- * "label_col_width" (int) Optional with of the left-most column. -- * "data_col_width" (int) Optional with of a column (excluding the row -- names column at the left). + -- * "value_width" Width of a value. Defaults to "data_col_width". If less, + -- table headers gets stacked two rows in order to reduce width. -- * "row_height" (int) Optional height of a row. -- * "intercol_sep" (int) Optional horizontal space between columns. -- * "interrow_sep" (int) Optional vertical space between rows. @@ -120,6 +122,7 @@ local function _makeTableSection(settings) section.col_label_sep = settings.col_label_sep or section.col_label_sep section.data_col_width = settings.data_col_width or section.data_col_width section.label_col_width = settings.label_col_width or section.label_col_width + section.value_width = settings.value_width or section.value_width section.row_height = settings.row_height or section.row_height section.intercol_sep = settings.intercol_sep or section.intercol_sep section.interrow_sep = settings.interrow_sep or section.interrow_sep @@ -224,7 +227,7 @@ function UILevelEditor:_makeTownLevelssEditPage() local town_level_section = _makeTableSection({ title_path = "level_editor.titles.town_levels", title_size = _TITLE_SIZE, - label_col_width = 100, data_col_width = _DATA_COL_WIDTH, + label_col_width = 100, data_col_width = 100, row_names = town_row_names, col_values = {towns_col1, towns_col2, towns_col3, towns_col4}, col_names = towns_col_names @@ -419,7 +422,7 @@ function UILevelEditor:_makeStaffLevelsEditPage12() local staff_levels1 = _makeTableSection({ title_path = "level_editor.titles.staff_level1", title_size = _TITLE_SIZE, - label_col_width = 80, data_col_width = _DATA_COL_WIDTH, + label_col_width = 80, data_col_width = 130, value_width = 95, col_names = { "level_editor.staff_levels.col_names.Month", "level_editor.staff_levels.col_names.Nurses", @@ -440,7 +443,7 @@ function UILevelEditor:_makeStaffLevelsEditPage12() local staff_levels2 = _makeTableSection({ title_path = "level_editor.titles.staff_level2", title_size = _TITLE_SIZE, - label_col_width = 80, data_col_width = _DATA_COL_WIDTH, + label_col_width = 80, data_col_width = 130, value_width = 95, col_names = { "level_editor.staff_levels.col_names.ShrkRate", "level_editor.staff_levels.col_names.SurgRate", @@ -721,7 +724,7 @@ function UILevelEditor:_makeEmergencyControlEditPage() local section = _makeTableSection({ title_path = "level_editor.titles.emergency_control", title_size = _TITLE_SIZE, - label_col_width = 90, data_col_width = 90, + label_col_width = 90, data_col_width = 90, value_width = 65, row_names = emergency_control_row_names, col_names = { "level_editor.emergency_control.col_names.StartMonth", @@ -949,7 +952,7 @@ local function _makeAwardsSection() return _makeTableSection({ title_path = "level_editor.titles.awards", title_size = _TITLE_SIZE, - label_col_width = 250, data_col_width = _DATA_COL_WIDTH, + label_col_width = 200, data_col_width = _DATA_COL_WIDTH, value_width = 70, col_names = { "level_editor.awards.col_names.award_condition", "level_editor.awards.col_names.bonus", diff --git a/CorsixTH/Lua/level_editor/data_storage.lua b/CorsixTH/Lua/level_editor/data_storage.lua index e21603e472..f6c9b105b9 100644 --- a/CorsixTH/Lua/level_editor/data_storage.lua +++ b/CorsixTH/Lua/level_editor/data_storage.lua @@ -38,7 +38,6 @@ local NAME_LABEL_SETTINGS = { --!param name (str) Name of the translated string to get. --!return (text) The retrieved translated string. local function getTranslatedText(name) - print("Getting translated text: " .. name) return TreeAccess.readTree(_S, name) end @@ -332,18 +331,18 @@ function LevelTableSection:LevelTableSection(title_path, row_name_paths, assert(values) - local table_rows_cols = self:_getTableColsRows() + local num_rows_cols = self:_getTableColsRows() -- Verify dimensions (hor, vert). - assert(#self.row_name_paths == table_rows_cols.h, + assert(#self.row_name_paths == num_rows_cols.h, "Unequal number of rows: names = " .. #self.row_name_paths - .. ", values height = " .. table_rows_cols.h) - assert(#self.col_name_paths == table_rows_cols.w, + .. ", values height = " .. num_rows_cols.h) + assert(#self.col_name_paths == num_rows_cols.w, "Unequal number of columns: names = " .. #self.col_name_paths - .. ", values width = " .. table_rows_cols.w) + .. ", values width = " .. num_rows_cols.w) for i, c in ipairs(values) do - assert(#c == table_rows_cols.h, - "Column " .. i .. ": count=" .. #c .. ", height=" .. table_rows_cols.h) + assert(#c == num_rows_cols.h, + "Column " .. i .. ": count=" .. #c .. ", height=" .. num_rows_cols.h) end self.title_size = Size(200, 25) -- Size of the title. @@ -352,6 +351,7 @@ function LevelTableSection:LevelTableSection(title_path, row_name_paths, self.col_label_sep = 10 -- Amount of horizontal space between the row names and the first column. self.label_col_width = 100 -- Width of the label column. self.data_col_width = self.label_col_width -- Width of columns. + self.value_width = nil -- If set, width of the value itself. If it's smaller than "data_col_width", row names get stacked in 2 rows. self.row_height = 18 -- Height of a row values (also sets the row label). self.intercol_sep = 5 -- Horizontal space between two columns in the table. self.interrow_sep = 2 -- Vertical space between two rows in the table. @@ -380,49 +380,80 @@ function LevelTableSection:layout(window, pos) self._widgets = {} self._text_boxes = {} - local x, y = pos.x, pos.y - local max_x = x + local y = pos.y + -- Title. if self.title_path then - _makeLabel(window, self._widgets, x, y, self.title_size, self.title_path, nil, TITLE_LABEL_SETTINGS) + _makeLabel(window, self._widgets, pos.x, y, self.title_size, self.title_path, nil, TITLE_LABEL_SETTINGS) y = y + self.title_size.h + self.title_sep - max_x = math.max(max_x, x + self.title_size.w) end - local table_rows_cols = self:_getTableColsRows() + -- The table, starting off with a bunch of computations for positioning the widgets. + local num_rows_cols = self:_getTableColsRows() + + -- Collect the relevant sizes and widths for laying out the table. local label_size = Size(self.label_col_width, self.row_height) -- Size of the first column. local datacol_size = Size(self.data_col_width, self.row_height) -- Size of the other columns. - -- Column headers above the data values (2nd row and further). - x = pos.x + label_size.w + self.col_label_sep -- Skip space for the row labels - for col = 1, table_rows_cols.w do - _makeLabel(window, self._widgets, x, y, datacol_size, self.col_name_paths[col], + local stacking = self.value_width and num_rows_cols.w > 1 -- Whether title headers are stacked. + local value_width = self.value_width and self.value_width or self.data_col_width + value_width = math.max(20, math.min(value_width, self.data_col_width)) -- With of a value. + local value_size = Size(value_width, self.row_height) + + --! Split value width and label with into left and right parts wrt center of the row. + local function _split_width(length) + local left = math.floor(length / 2) + return left, length - left + end + local left_val_width, right_val_width = _split_width(value_width) + local left_datacl_width, right_label_width = _split_width(self.data_col_width) + + -- Compute horizontal distance between two rows. + -- Between adjacent columns, there is a right-part of a value, some separation, + -- and a left-part of a value.Between adjacent columns, there is one half of a + -- label and some separation. Take the maximum of both to make it always fit. + local interrow_distance = right_val_width + self.intercol_sep + left_val_width + interrow_distance = math.max(interrow_distance, + self.intercol_sep + math.max(left_datacl_width, right_label_width)) + + -- Value columns x positions are relative to the center of the first data column. + -- Note that left_val_width < left_datacl_width, so the latter will always fit. + local x_first_data_col = pos.x + label_size.w + self.col_label_sep + left_datacl_width + + -- Column headers above the data values (1st data row and further). + -- + -- We always alternate between top_y and bottom_y while positing table headers, + -- where sometimes both rows are on top of each other. + local top_y = y + local bottom_y = top_y + if stacking then bottom_y = bottom_y + self.row_height + self.row_label_sep end + + local x = x_first_data_col -- Skip space for the row labels + for col = 1, num_rows_cols.w do + _makeLabel(window, self._widgets, x - left_datacl_width, + (col % 2 == 1) and bottom_y or top_y, datacol_size, self.col_name_paths[col], self.col_tooltip_paths[col], NAME_LABEL_SETTINGS) - x = x + datacol_size.w - if col < table_rows_cols.w then x = x + self.intercol_sep end + x = x + interrow_distance end - max_x = math.max(max_x, x) - y = y + self.row_height + self.row_label_sep + y = bottom_y + self.row_height + self.row_label_sep - -- Rows (label at the left as well as all data columns). - for row = 1, table_rows_cols.h do + -- All data rows with labels at the left and the data values. + for row = 1, num_rows_cols.h do x = pos.x _makeLabel(window, self._widgets, x, y, label_size, self.row_name_paths[row], self.row_tooltip_paths[row], NAME_LABEL_SETTINGS) - x = x + label_size.w + self.col_label_sep - for col = 1, table_rows_cols.w do + + x = x_first_data_col + for col = 1, num_rows_cols.w do assert(self.values[col][row], "No value found at row " .. row .. ", column " .. col) - _makeTextBox(window, self._text_boxes, x, y, datacol_size, self.values[col][row]) - x = x + datacol_size.w - if col < table_rows_cols.w then x = x + self.intercol_sep end + _makeTextBox(window, self._text_boxes, x - left_val_width, y, value_size, self.values[col][row]) + x = x + interrow_distance end - max_x = math.max(max_x, x) - y = y + self.row_height - if row < table_rows_cols.h then y = y + self.interrow_sep end + y = y + self.row_height + self.interrow_sep end self:setVisible(false) -- Initially hide all. - return y + return y - self.interrow_sep end --! Load the values from the level config or write the values into a *new*