From 2958e3731009bb9e8e16c633fed87e003cb934fd Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 9 Jan 2020 17:31:26 +0100 Subject: [PATCH] Tables: Storing per-column SkipItems as a shortcut. Comments, Spacings. # Conflicts: # imgui_internal.h --- imgui.h | 2 +- imgui_demo.cpp | 2 +- imgui_internal.h | 21 +++++++++------------ imgui_tables.cpp | 34 ++++++++++++++++++---------------- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/imgui.h b/imgui.h index e0f51274..e03b8985 100644 --- a/imgui.h +++ b/imgui.h @@ -694,7 +694,7 @@ namespace ImGui // Tables: Sorting // - Call TableGetSortSpecs() to retrieve latest sort specs for the table. Return value will be NULL if no sorting. // - You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since last call, or the first time. - // - Don't hold on this structure over multiple frames. + // - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()! IMGUI_API const ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting). // Tab Bars, Tabs diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f1c40e0b..5c300e54 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3618,7 +3618,7 @@ static void ShowDemoWindowTables() ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeTopRow", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeTopRow); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeLeftColumn", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeLeftColumn); - + if (ImGui::BeginTable("##table1", 7, flags, size)) { ImGui::TableSetupColumn("Line #", ImGuiTableColumnFlags_NoHide); // Make the first column not hideable to match our use of ImGuiTableFlags_ScrollFreezeLeftColumn diff --git a/imgui_internal.h b/imgui_internal.h index 9b980e0d..1b3eb592 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1823,11 +1823,12 @@ struct ImGuiTabBar #define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code #define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64. -// [Internal] sizeof() ~ 96 +// [Internal] sizeof() ~ 100 struct ImGuiTableColumn { + ImRect ClipRect; // Clipping rectangle for the column ImGuiID UserID; // Optional, value passed to TableSetupColumn() - ImGuiTableColumnFlags FlagsIn; // Flags as input by user. See ImGuiTableColumnFlags_ + ImGuiTableColumnFlags FlagsIn; // Flags as they were provided by user. See ImGuiTableColumnFlags_ ImGuiTableColumnFlags Flags; // Effective flags. See ImGuiTableColumnFlags_ float ResizeWeight; // ~1.0f. Master width data when (Flags & _WidthStretch) float MinX; // Absolute positions @@ -1836,19 +1837,19 @@ struct ImGuiTableColumn float WidthGiven; // == (MaxX - MinX). FIXME-TABLE: Store all persistent width in multiple of FontSize? float StartXRows; // Start position for the frame, currently ~(MinX + CellPaddingX) float StartXHeaders; - ImS16 ContentWidthRowsFrozen; // Contents width. Because freezing is non correlated from headers we need all 4 variants (ImDrawCmd merging uses different data than alignment code). - ImS16 ContentWidthRowsUnfrozen; // (encoded as ImS16 because we actually rarely use those width) - ImS16 ContentWidthHeadersUsed; // TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls - ImS16 ContentWidthHeadersDesired; float ContentMaxPosRowsFrozen; // Submitted contents absolute maximum position, from which we can infer width. float ContentMaxPosRowsUnfrozen; // (kept as float because we need to manipulate those between each cell change) float ContentMaxPosHeadersUsed; float ContentMaxPosHeadersDesired; - ImRect ClipRect; - ImS16 NameOffset; // Offset into parent ColumnsName[] + ImS16 ContentWidthRowsFrozen; // Contents width. Because row freezing is not correlated with headers/not-headers we need all 4 variants (ImDrawCmd merging uses different data than alignment code). + ImS16 ContentWidthRowsUnfrozen; // (encoded as ImS16 because we actually rarely use those width) + ImS16 ContentWidthHeadersUsed; // TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls + ImS16 ContentWidthHeadersDesired; + ImS16 NameOffset; // Offset into parent ColumnsNames[] bool IsActive; // Is the column not marked Hidden by the user (regardless of clipping). We're not calling this "Visible" here because visibility also depends on clipping. bool NextIsActive; bool IsClipped; // Set when not overlapping the host window clipping rectangle. We don't use the opposite "!Visible" name because Clipped can be altered by events. + bool SkipItems; ImS8 IndexDisplayOrder; // Index within DisplayOrder[] (column may be reordered by users) ImS8 IndexWithinActiveSet; // Index within active set (<= IndexOrder) ImS8 DrawChannelCurrent; // Index within DrawSplitter.Channels[] @@ -2178,10 +2179,6 @@ namespace ImGui IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset); // Tables - //IMGUI_API int GetTableColumnNo(); - //IMGUI_API bool SetTableColumnNo(int column_n); - //IMGUI_API int GetTableLineNo(); - IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f); IMGUI_API void TableBeginUpdateColumns(ImGuiTable* table); IMGUI_API void TableUpdateDrawChannels(ImGuiTable* table); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index b3958d23..781392b8 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -68,20 +68,22 @@ // - TableBeginUpdateColumns() - apply resize/order requests, lock columns active state, order // - TableSetupColumn() user submit columns details (optional) // - TableAutoHeaders() or TableHeader() user submit a headers row (optional) -// - TableSortSpecsClickColumn() +// - TableSortSpecsClickColumn() - when clicked: alter sort order and sort direction // - TableGetSortSpecs() user queries updated sort specs (optional) // - TableNextRow() / TableNextCell() user begin into the first row, also automatically called by TableAutoHeaders() -// - TableUpdateLayout() - called by the FIRST call to TableNextRow() -// - TableUpdateDrawChannels() - setup ImDrawList channels -// - TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission -// - TableDrawContextMenu() - draw right-click context menu +// - TableUpdateLayout() - called by the FIRST call to TableNextRow()! +// - TableUpdateDrawChannels() - setup ImDrawList channels +// - TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission +// - TableDrawContextMenu() - draw right-click context menu +// - TableEndCell() - close existing cell if not the first time +// - TableBeginCell() - enter into current cell // - [...] user emit contents // - EndTable() user ends the table // - TableDrawBorders() - draw outer borders, inner vertical borders // - TableDrawMergeChannels() - merge draw channels if clipping isn't required // - TableSetColumnWidth() - apply resizing width -// - TableUpdateColumnsWeightFromWidth() -// - EndChild() - (if ScrollX/ScrollY is set) +// - TableUpdateColumnsWeightFromWidth() - recompute columns weights (of weighted columns) from their respective width +// - EndChild() - (if ScrollX/ScrollY is set) //----------------------------------------------------------------------------- // Configuration @@ -700,7 +702,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) column->ClipRect.Max.x = offset_x; column->ClipRect.Max.y = FLT_MAX; column->ClipRect.ClipWithFull(host_clip_rect); - column->IsClipped = true; + column->IsClipped = column->SkipItems = true; continue; } @@ -731,6 +733,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) column->ClipRect.ClipWithFull(host_clip_rect); column->IsClipped = (column->ClipRect.Max.x <= column->ClipRect.Min.x) && (column->AutoFitQueue & 1) == 0 && (column->CannotSkipItemsQueue & 1) == 0; + column->SkipItems = column->IsClipped || table->HostSkipItems; if (column->IsClipped) { // Columns with the _WidthAlwaysAutoResize sizing policy will never be updated then. @@ -1580,9 +1583,10 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_no) const float start_x = (table->RowFlags & ImGuiTableRowFlags_Headers) ? column->StartXHeaders : column->StartXRows; window->DC.LastItemId = 0; - window->DC.CursorPos = ImVec2(start_x, table->RowPosY1 + table->CellPaddingY); + window->DC.CursorPos.x = start_x; + window->DC.CursorPos.y = table->RowPosY1 + table->CellPaddingY; window->DC.CursorMaxPos.x = window->DC.CursorPos.x; - window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT // FIXME-TABLE: Recurse + window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT window->DC.CurrLineTextBaseOffset = table->RowTextBaseline; window->WorkRect.Min.y = window->DC.CursorPos.y; @@ -1593,10 +1597,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_no) if (!column->IsActive) window->DC.CursorPos.y = ImMax(window->DC.CursorPos.y, table->RowPosY2); - // FIXME-COLUMNS: Setup baseline, preserve across columns (how can we obtain first line baseline tho..) - // window->DC.CurrLineTextBaseOffset = ImMax(window->DC.CurrLineTextBaseOffset, g.Style.FramePadding.y); - - window->SkipItems = column->IsClipped ? true : table->HostSkipItems; + window->SkipItems = column->SkipItems; if (table->Flags & ImGuiTableFlags_NoClipX) { table->DrawSplitter.SetCurrentChannel(window->DrawList, 1); @@ -1615,7 +1616,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_no) } } -// [Internal] Called by TableNextRow()TableNextCell()! +// [Internal] Called by TableNextRow()/TableNextCell()! void ImGui::TableEndCell(ImGuiTable* table) { ImGuiTableColumn* column = &table->Columns[table->CurrentColumn]; @@ -2078,7 +2079,8 @@ void ImGui::TableSortSpecsClickColumn(ImGuiTable* table, ImGuiTableColumn* click } // Return NULL if no sort specs. -// You can sort your data again when 'SpecsChanged == true'.It will be true with sorting specs have changed since last call, or the first time. +// You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since last call, or the first time. +// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()! const ImGuiTableSortSpecs* ImGui::TableGetSortSpecs() { ImGuiContext& g = *GImGui;