Tables: Rescale fixed widths when font size change to support varying dpi scale at runtime and on .ini reload.
This commit is contained in:
parent
6bc0bbccf3
commit
fec9d7d226
@ -1985,6 +1985,7 @@ struct ImGuiTable
|
||||
float ColumnsTotalWidth; // Sum of current column width
|
||||
float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window
|
||||
float ResizedColumnNextWidth;
|
||||
float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
|
||||
ImRect OuterRect; // Note: OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable().
|
||||
ImRect WorkRect;
|
||||
ImRect InnerClipRect;
|
||||
@ -2070,6 +2071,7 @@ struct ImGuiTableSettings
|
||||
{
|
||||
ImGuiID ID; // Set to 0 to invalidate/delete the setting
|
||||
ImGuiTableFlags SaveFlags; // Indicate data we want to save using the Resizable/Reorderable/Sortable/Hideable flags (could be using its own flags..)
|
||||
float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
|
||||
ImS8 ColumnsCount;
|
||||
ImS8 ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher
|
||||
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
|
||||
|
@ -328,6 +328,21 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
if (table->IsSettingsRequestLoad)
|
||||
TableLoadSettings(table);
|
||||
|
||||
// Handle DPI/font resize
|
||||
// This is designed to facilitate DPI changes with the assumption that e.g. style.CellPadding has been scaled as well.
|
||||
// It will also react to changing fonts with mixed results. It doesn't need to be perfect but merely provide a decent transition.
|
||||
// FIXME-DPI: Provide consistent standards for reference size. Perhaps using g.CurrentDpiScale would be more self explanatory.
|
||||
// This is will lead us to non-rounded WidthRequest in columns, which should work but is a poorly tested path.
|
||||
const float new_ref_scale_unit = g.FontSize; // g.Font->GetCharAdvance('A') ?
|
||||
if (table->RefScale != 0.0f && table->RefScale != new_ref_scale_unit)
|
||||
{
|
||||
const float scale_factor = new_ref_scale_unit / table->RefScale;
|
||||
//IMGUI_DEBUG_LOG("[table] %08X RefScaleUnit %.3f -> %.3f, scaling width by %.3f\n", table->ID, table->RefScaleUnit, new_ref_scale_unit, scale_factor);
|
||||
for (int n = 0; n < columns_count; n++)
|
||||
table->Columns[n].WidthRequest = table->Columns[n].WidthRequest * scale_factor;
|
||||
}
|
||||
table->RefScale = new_ref_scale_unit;
|
||||
|
||||
// Disable output until user calls TableNextRow() or TableNextCell() leading to the TableUpdateLayout() call..
|
||||
// This is not strictly necessary but will reduce cases were "out of table" output will be misleading to the user.
|
||||
// Because we cannot safely assert in EndTable() when no rows have been created, this seems like our best option.
|
||||
@ -607,6 +622,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
// (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very
|
||||
// large height (= first frame scrollbar display very off + clipper would skip lots of items).
|
||||
// This is merely making the side-effect less extreme, but doesn't properly fixes it.
|
||||
// FIXME: Move this to ->WidthGiven to avoid temporary lossyless?
|
||||
if (column->AutoFitQueue > 0x01 && table->IsInitializing)
|
||||
column->WidthRequest = ImMax(column->WidthRequest, min_column_width * 4.0f);
|
||||
}
|
||||
@ -2392,6 +2408,7 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
|
||||
ImGuiTableColumnSettings* column_settings = settings->GetColumnSettings();
|
||||
|
||||
// FIXME-TABLE: Logic to avoid saving default widths?
|
||||
bool save_ref_scale = false;
|
||||
settings->SaveFlags = ImGuiTableFlags_Resizable;
|
||||
for (int n = 0; n < table->ColumnsCount; n++, column++, column_settings++)
|
||||
{
|
||||
@ -2402,6 +2419,8 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
|
||||
column_settings->SortDirection = column->SortDirection;
|
||||
column_settings->IsVisible = column->IsVisible;
|
||||
column_settings->IsWeighted = (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? 1 : 0;
|
||||
if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) == 0)
|
||||
save_ref_scale = true;
|
||||
|
||||
// We skip saving some data in the .ini file when they are unnecessary to restore our state
|
||||
// FIXME-TABLE: We don't have logic to easily compare SortOrder to DefaultSortOrder yet so it's always saved when present.
|
||||
@ -2413,6 +2432,7 @@ void ImGui::TableSaveSettings(ImGuiTable* table)
|
||||
settings->SaveFlags |= ImGuiTableFlags_Hideable;
|
||||
}
|
||||
settings->SaveFlags &= table->Flags;
|
||||
settings->RefScale = save_ref_scale ? table->RefScale : 0.0f;
|
||||
|
||||
MarkIniSettingsDirty();
|
||||
}
|
||||
@ -2438,6 +2458,7 @@ void ImGui::TableLoadSettings(ImGuiTable* table)
|
||||
settings = TableGetBoundSettings(table);
|
||||
}
|
||||
table->SettingsLoadedFlags = settings->SaveFlags;
|
||||
table->RefScale = settings->RefScale;
|
||||
IM_ASSERT(settings->ColumnsCount == table->ColumnsCount);
|
||||
|
||||
// Serialize ImGuiTableSettings/ImGuiTableColumnSettings into ImGuiTable/ImGuiTableColumn
|
||||
@ -2517,6 +2538,8 @@ static void TableSettingsHandler_ReadLine(ImGuiContext*, ImGuiSettingsHandler*,
|
||||
float f = 0.0f;
|
||||
int column_n = 0, r = 0, n = 0;
|
||||
|
||||
if (sscanf(line, "RefScale=%f", &f) == 1) { settings->RefScale = f; return; }
|
||||
|
||||
if (sscanf(line, "Column %d%n", &column_n, &r) == 1)
|
||||
{
|
||||
if (column_n < 0 || column_n >= settings->ColumnsCount)
|
||||
@ -2553,6 +2576,8 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
|
||||
|
||||
buf->reserve(buf->size() + 30 + settings->ColumnsCount * 50); // ballpark reserve
|
||||
buf->appendf("[%s][0x%08X,%d]\n", handler->TypeName, settings->ID, settings->ColumnsCount);
|
||||
if (settings->RefScale != 0.0f)
|
||||
buf->appendf("RefScale=%g\n", settings->RefScale);
|
||||
ImGuiTableColumnSettings* column = settings->GetColumnSettings();
|
||||
for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++)
|
||||
{
|
||||
@ -2610,7 +2635,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
||||
const char* name = TableGetColumnName(table, n);
|
||||
BulletText("Column %d order %d name '%s': +%.1f to +%.1f\n"
|
||||
"Visible: %d, Clipped: %d, DrawChannels: %d,%d\n"
|
||||
"WidthGiven/Request: %.1f/%.1f, WidthWeight: %.3f\n"
|
||||
"WidthGiven/Request: %.2f/%.2f, WidthWeight: %.3f\n"
|
||||
"ContentWidth: RowsFrozen %d, RowsUnfrozen %d, HeadersUsed/Ideal %d/%d\n"
|
||||
"SortOrder: %d, SortDir: %s\n"
|
||||
"UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s..",
|
||||
|
Loading…
Reference in New Issue
Block a user