mirror of https://github.com/ocornut/imgui
Tables: Shared menu item id for "Size all" variations. Avoid allocation on single sort specs. Fix TableGetColumnIsEnabled(). Massage TableHeaderRows().
This commit is contained in:
parent
e126a64782
commit
155b8bb816
4
imgui.h
4
imgui.h
|
@ -1900,7 +1900,7 @@ struct ImGuiTableSortSpecsColumn
|
|||
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
|
||||
ImGuiSortDirection SortDirection : 8; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending (you can use this or SortSign, whichever is more convenient for your sort function)
|
||||
|
||||
ImGuiTableSortSpecsColumn() { ColumnUserID = 0; ColumnIndex = 0; SortOrder = 0; SortDirection = ImGuiSortDirection_Ascending; }
|
||||
ImGuiTableSortSpecsColumn() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
// Sorting specifications for a table (often handling sort specs for a single column, occasionally more)
|
||||
|
@ -1913,7 +1913,7 @@ struct ImGuiTableSortSpecs
|
|||
int SpecsCount; // Sort spec count. Most often 1 unless e.g. ImGuiTableFlags_MultiSortable is enabled.
|
||||
bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag.
|
||||
|
||||
ImGuiTableSortSpecs() { Specs = NULL; SpecsCount = 0; SpecsDirty = false; }
|
||||
ImGuiTableSortSpecs() { memset(this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -1960,6 +1960,7 @@ struct ImGuiTableCellData
|
|||
ImGuiTableColumnIdx Column; // Column number
|
||||
};
|
||||
|
||||
// FIXME-TABLES: transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
|
||||
struct ImGuiTable
|
||||
{
|
||||
ImGuiID ID;
|
||||
|
@ -2022,7 +2023,8 @@ struct ImGuiTable
|
|||
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
|
||||
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
|
||||
ImDrawListSplitter DrawSplitter; // We carry our own ImDrawList splitter to allow recursion (FIXME: could be stored outside, worst case we need 1 splitter per recursing table)
|
||||
ImVector<ImGuiTableSortSpecsColumn> SortSpecsData; // FIXME-OPT: Fixed-size array / small-vector pattern, optimize for single sort spec
|
||||
ImGuiTableSortSpecsColumn SortSpecsSingle;
|
||||
ImVector<ImGuiTableSortSpecsColumn> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would work be good.
|
||||
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
|
||||
ImGuiTableColumnIdx SortSpecsCount;
|
||||
ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
|
||||
|
@ -2280,6 +2282,7 @@ namespace ImGui
|
|||
IMGUI_API bool TableGetColumnIsEnabled(int column_n = -1); // Return false when column is disabled (hidden) by user (e.g. via context menu, or _DefaultHide flag)
|
||||
IMGUI_API void TableSetColumnIsEnabled(int column_n, bool enabled);
|
||||
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
|
||||
IMGUI_API float TableGetHeaderRowHeight();
|
||||
IMGUI_API void TablePushBackgroundChannel();
|
||||
IMGUI_API void TablePopBackgroundChannel();
|
||||
|
||||
|
|
|
@ -1715,7 +1715,7 @@ bool ImGui::TableGetColumnIsEnabled(int column_n)
|
|||
return false;
|
||||
if (column_n < 0)
|
||||
column_n = table->CurrentColumn;
|
||||
return (table->EnabledMaskByIndex & ((ImU64)1 << column_n)) == 0;
|
||||
return (table->EnabledMaskByIndex & ((ImU64)1 << column_n)) != 0;
|
||||
}
|
||||
|
||||
void ImGui::TableSetColumnIsEnabled(int column_n, bool hidden)
|
||||
|
@ -2134,7 +2134,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME-TABLE: This is a mess, need to redesign how we render borders.
|
||||
// FIXME-TABLE: This is a mess, need to redesign how we render borders (as some are also done in TableEndRow)
|
||||
void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
{
|
||||
ImGuiWindow* inner_window = table->InnerWindow;
|
||||
|
@ -2391,20 +2391,23 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
|
|||
TableSortSpecsSanitize(table);
|
||||
|
||||
// Write output
|
||||
table->SortSpecsData.resize(table->SortSpecsCount);
|
||||
const bool single_sort_specs = (table->SortSpecsCount <= 1);
|
||||
table->SortSpecsMulti.resize(single_sort_specs ? 0 : table->SortSpecsCount);
|
||||
ImGuiTableSortSpecsColumn* sort_specs = single_sort_specs ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
if (column->SortOrder == -1)
|
||||
continue;
|
||||
ImGuiTableSortSpecsColumn* sort_spec = &table->SortSpecsData[column->SortOrder];
|
||||
IM_ASSERT(column->SortOrder < table->SortSpecsCount);
|
||||
ImGuiTableSortSpecsColumn* sort_spec = &sort_specs[column->SortOrder];
|
||||
sort_spec->ColumnUserID = column->UserID;
|
||||
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
|
||||
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
|
||||
sort_spec->SortDirection = column->SortDirection;
|
||||
}
|
||||
table->SortSpecs.Specs = table->SortSpecsData.Data;
|
||||
table->SortSpecs.SpecsCount = table->SortSpecsData.Size;
|
||||
table->SortSpecs.Specs = sort_specs;
|
||||
table->SortSpecs.SpecsCount = table->SortSpecsCount;
|
||||
table->SortSpecs.SpecsDirty = true; // Mark as dirty for user
|
||||
table->IsSortSpecsDirty = false; // Mark as not dirty for us
|
||||
}
|
||||
|
@ -2412,58 +2415,51 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
|
|||
//-------------------------------------------------------------------------
|
||||
// [SECTION] Tables: Headers
|
||||
//-------------------------------------------------------------------------
|
||||
// - TableGetHeaderRowHeight() [Internal]
|
||||
// - TableHeadersRow()
|
||||
// - TableHeader()
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
|
||||
float ImGui::TableGetHeaderRowHeight()
|
||||
{
|
||||
// Caring for a minor edge case:
|
||||
// Calculate row height, for the unlikely case that some labels may be taller than others.
|
||||
// If we didn't do that, uneven header height would highlight but smaller one before the tallest wouldn't catch input for all height.
|
||||
// In your custom header row you may omit this all together and just call TableNextRow() without a height...
|
||||
float row_height = GetTextLineHeight();
|
||||
int columns_count = TableGetColumnCount();
|
||||
for (int column_n = 0; column_n < columns_count; column_n++)
|
||||
if (TableGetColumnIsEnabled(column_n))
|
||||
row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(column_n)).y);
|
||||
row_height += GetStyle().CellPadding.y * 2.0f;
|
||||
return row_height;
|
||||
}
|
||||
|
||||
// [Public] This is a helper to output TableHeader() calls based on the column names declared in TableSetupColumn().
|
||||
// The intent is that advanced users willing to create customized headers would not need to use this helper
|
||||
// and can create their own! For example: TableHeader() may be preceeded by Checkbox() or other custom widgets.
|
||||
// See 'Demo->Tables->Custom headers' for a demonstration of implementing a custom version of this.
|
||||
// This code is constructed to not make much use of internal functions, as it is intended to be a template to copy.
|
||||
// FIXME-TABLE: TableOpenContextMenu() and TableGetHeaderRowHeight() are not public.
|
||||
void ImGui::TableHeadersRow()
|
||||
{
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
IM_ASSERT(table != NULL && "Need to call TableHeadersRow() after BeginTable()!");
|
||||
|
||||
// Calculate row height (for the unlikely case that labels may be are multi-line)
|
||||
// If we didn't do that, uneven header height would work but their highlight won't cover the full row height.
|
||||
float row_height = GetTextLineHeight();
|
||||
const float row_y1 = GetCursorScreenPos().y;
|
||||
const int columns_count = TableGetColumnCount();
|
||||
for (int column_n = 0; column_n < columns_count; column_n++)
|
||||
if (TableGetColumnIsEnabled(column_n))
|
||||
row_height = ImMax(row_height, CalcTextSize(TableGetColumnName(column_n)).y);
|
||||
row_height += style.CellPadding.y * 2.0f;
|
||||
|
||||
// Open row
|
||||
const float row_y1 = GetCursorScreenPos().y;
|
||||
const float row_height = TableGetHeaderRowHeight();
|
||||
TableNextRow(ImGuiTableRowFlags_Headers, row_height);
|
||||
if (table->HostSkipItems) // Merely an optimization, you may skip in your own code.
|
||||
return;
|
||||
|
||||
// This for loop is constructed to not make use of internal functions,
|
||||
// as this is intended to be a base template to copy and build from.
|
||||
const int columns_count = TableGetColumnCount();
|
||||
for (int column_n = 0; column_n < columns_count; column_n++)
|
||||
{
|
||||
if (!TableSetColumnIndex(column_n))
|
||||
continue;
|
||||
|
||||
// [DEBUG] Test custom user elements
|
||||
#if 0
|
||||
if (column_n < 2)
|
||||
{
|
||||
static bool b[2] = {};
|
||||
PushID(column_n);
|
||||
PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||
Checkbox("##", &b[column_n]);
|
||||
PopStyleVar();
|
||||
PopID();
|
||||
SameLine(0.0f, style.ItemInnerSpacing.x);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Push an id to allow unnamed labels (generally accidental, but let's behave nicely with them)
|
||||
// - in your own code you may omit the PushID/PopID all-together, provided you know they won't collide
|
||||
// - table->InstanceCurrent is only >0 when we use multiple BeginTable/EndTable calls with same identifier.
|
||||
|
@ -2474,7 +2470,6 @@ void ImGui::TableHeadersRow()
|
|||
}
|
||||
|
||||
// Allow opening popup from the right-most section after the last column.
|
||||
// FIXME-TABLE: TableOpenContextMenu() is not public yet.
|
||||
ImVec2 mouse_pos = ImGui::GetMousePos();
|
||||
if (IsMouseReleased(1) && TableGetHoveredColumn() == columns_count)
|
||||
if (mouse_pos.y >= row_y1 && mouse_pos.y < row_y1 + row_height)
|
||||
|
@ -2565,9 +2560,8 @@ void ImGui::TableHeader(const char* label)
|
|||
w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);// table->CellPadding.x);
|
||||
if (column->SortOrder != -1)
|
||||
{
|
||||
w_sort_text = 0.0f;
|
||||
|
||||
char sort_order_suf[8];
|
||||
w_sort_text = 0.0f;
|
||||
if (column->SortOrder > 0)
|
||||
{
|
||||
ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);
|
||||
|
@ -2675,11 +2669,11 @@ void ImGui::TableDrawContextMenu(ImGuiTable* table)
|
|||
|
||||
const char* size_all_desc;
|
||||
if (table->ColumnsEnabledFixedCount == table->ColumnsEnabledCount)
|
||||
size_all_desc = "Size all columns to fit"; // All fixed
|
||||
size_all_desc = "Size all columns to fit###SizeAll"; // All fixed
|
||||
else if (table->ColumnsEnabledFixedCount == 0)
|
||||
size_all_desc = "Size all columns to default"; // All stretch
|
||||
size_all_desc = "Size all columns to default###SizeAll"; // All stretch
|
||||
else
|
||||
size_all_desc = "Size all columns to fit/default"; // Mixed
|
||||
size_all_desc = "Size all columns to fit/default###SizeAll";// Mixed
|
||||
if (MenuItem(size_all_desc, NULL))
|
||||
TableSetColumnWidthAutoAll(table);
|
||||
want_separator = true;
|
||||
|
@ -3074,7 +3068,7 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
|
|||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(table->MemoryCompacted == false);
|
||||
table->DrawSplitter.ClearFreeMemory();
|
||||
table->SortSpecsData.clear();
|
||||
table->SortSpecsMulti.clear();
|
||||
table->SortSpecs.Specs = NULL;
|
||||
table->IsSortSpecsDirty = true;
|
||||
table->ColumnsNames.clear();
|
||||
|
|
Loading…
Reference in New Issue