From fe6131168a397b5b91fe429a38708238452734f4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 3 Nov 2020 18:47:05 +0100 Subject: [PATCH] Tables: Additionally commentary about clipper in the demo + minor padding tweak. --- imgui.h | 3 ++- imgui_demo.cpp | 25 +++++++++++++++++-------- imgui_internal.h | 4 ++-- imgui_tables.cpp | 14 +++++++------- 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/imgui.h b/imgui.h index 4657a98c..ca658a76 100644 --- a/imgui.h +++ b/imgui.h @@ -2246,8 +2246,9 @@ struct ImDrawChannel ImVector _IdxBuffer; }; + // Split/Merge functions are used to split the draw list into different layers which can be drawn into out of order. -// This is used by the Columns api, so items of each column can be batched together in a same draw call. +// This is used by the Columns/Tables API, so items of each column can be batched together in a same draw call. struct ImDrawListSplitter { int _Current; // Current channel number (0) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a392f85b..35b35e72 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1098,7 +1098,7 @@ static void ShowDemoWindowWidgets() ImGui::TableNextColumn(); ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap } - ImGui::EndTable(); + ImGui::EndTable(); } ImGui::Separator(); if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) @@ -3755,7 +3755,7 @@ static void ShowDemoWindowTables() if (open_action != -1) ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Vertical scrolling")) + if (ImGui::TreeNode("Vertical scrolling, with clipping")) { HelpMarker("Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\nWe also demonstrate using ImGuiListClipper to virtualize the submission of many items."); static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; @@ -3774,6 +3774,8 @@ static void ShowDemoWindowTables() ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None); ImGui::TableHeadersRow(); + + // Demonstrate using clipper for large vertical lists ImGuiListClipper clipper; clipper.Begin(1000); while (clipper.Step()) @@ -4393,6 +4395,7 @@ static void ShowDemoWindowTables() ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action); ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Quantity); ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible + ImGui::TableHeadersRow(); // Sort our data if sort specs have been changed! if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs()) @@ -4405,13 +4408,13 @@ static void ShowDemoWindowTables() sorts_specs->SpecsDirty = false; } - // Display data - ImGui::TableHeadersRow(); + // Demonstrate using clipper for large vertical lists ImGuiListClipper clipper; clipper.Begin(items.Size); while (clipper.Step()) for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++) { + // Display a data item MyItem* item = &items[row_n]; ImGui::PushID(item->ID); ImGui::TableNextRow(); @@ -4448,7 +4451,7 @@ static void ShowDemoWindowTables() static int freeze_cols = 1; static int freeze_rows = 1; static int items_count = IM_ARRAYSIZE(template_items_names); - static ImVec2 outer_size_value = ImVec2(0, TEXT_BASE_HEIGHT * 15); + static ImVec2 outer_size_value = ImVec2(0, TEXT_BASE_HEIGHT * 12); static float row_min_height = 0.0f; // Auto static float inner_width_with_scroll = 0.0f; // Auto-extend static bool outer_size_enabled = true; @@ -4609,14 +4612,16 @@ static void ShowDemoWindowTables() // FIXME-TABLE FIXME-NAV: How we can get decent up/down even though we have the buttons here? ImGui::PushButtonRepeat(true); #if 1 + // Demonstrate using clipper for large vertical lists ImGuiListClipper clipper; clipper.Begin(items.Size); while (clipper.Step()) { for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++) #else + // Without clipper { - for (int row_n = 0; row_n < items_count; row_n++) + for (int row_n = 0; row_n < items.Size; row_n++) #endif { MyItem* item = &items[row_n]; @@ -4691,6 +4696,7 @@ static void ShowDemoWindowTables() } ImGui::PopButtonRepeat(); + // Store some info to display debug details below table_scroll_cur = ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY()); table_scroll_max = ImVec2(ImGui::GetScrollMaxX(), ImGui::GetScrollMaxY()); table_draw_list = ImGui::GetWindowDrawList(); @@ -4703,7 +4709,8 @@ static void ShowDemoWindowTables() ImGui::SameLine(0.0f, 0.0f); const int table_draw_list_draw_cmd_count = table_draw_list->CmdBuffer.Size; if (table_draw_list == parent_draw_list) - ImGui::Text(": DrawCmd: +%d (in same window)", table_draw_list_draw_cmd_count - parent_draw_list_draw_cmd_count); + ImGui::Text(": DrawCmd: +%d (in same window)", + table_draw_list_draw_cmd_count - parent_draw_list_draw_cmd_count); else ImGui::Text(": DrawCmd: +%d (in child window), Scroll: (%.f/%.f) (%.f/%.f)", table_draw_list_draw_cmd_count - 1, table_scroll_cur.x, table_scroll_max.x, table_scroll_cur.y, table_scroll_max.y); @@ -4860,8 +4867,10 @@ static void ShowDemoWindowColumns() ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f); ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar); ImGui::Columns(10); + + // Also demonstrate using clipper for large vertical lists int ITEMS_COUNT = 2000; - ImGuiListClipper clipper; // Also demonstrate using the clipper for large list + ImGuiListClipper clipper; clipper.Begin(ITEMS_COUNT); while (clipper.Step()) { diff --git a/imgui_internal.h b/imgui_internal.h index a5d467f2..e87cf283 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1914,8 +1914,8 @@ struct ImGuiTableColumn bool IsVisible; // Is the column not marked Hidden by the user? (could be clipped by scrolling, etc). bool IsVisibleNextFrame; bool IsClipped; // Set when not overlapping the host window clipping rectangle. - bool SkipItems; - ImGuiNavLayer NavLayerCurrent; + bool IsSkipItems; + ImS8 NavLayerCurrent; // ImGuiNavLayer in 1 byte ImS8 DisplayOrder; // Index within Table's IndexToDisplayOrder[] (column may be reordered by users) ImS8 IndexWithinVisibleSet; // Index within visible set (<= IndexToDisplayOrder) ImS8 PrevVisibleColumn; // Index of prev visible column within Columns[], -1 if first visible column diff --git a/imgui_tables.cpp b/imgui_tables.cpp index d18dd881..e1bedea0 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -761,7 +761,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) const int column_n = table->DisplayOrderToIndex[order_n]; ImGuiTableColumn* column = &table->Columns[column_n]; - column->NavLayerCurrent = (table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main; + column->NavLayerCurrent = (ImS8)((table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); if (table->FreezeColumnsCount > 0 && table->FreezeColumnsCount == visible_n) offset_x += work_rect.Min.x - table->OuterRect.Min.x; @@ -777,7 +777,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 = column->SkipItems = true; + column->IsClipped = column->IsSkipItems = true; continue; } @@ -813,7 +813,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (column->IsClipped) table->VisibleUnclippedMaskByIndex &= ~((ImU64)1 << column_n); // Columns with the _WidthAlwaysAutoResize sizing policy will never be updated then. - column->SkipItems = !column->IsVisible || table->HostSkipItems; + column->IsSkipItems = !column->IsVisible || table->HostSkipItems; // Detect hovered column if (is_hovering_table && g.IO.MousePos.x >= column->ClipRect.Min.x && g.IO.MousePos.x < column->ClipRect.Max.x) @@ -1346,7 +1346,7 @@ void ImGui::TableUpdateDrawChannels(ImGuiTable* table) const int channels_for_dummy = (table->ColumnsVisibleCount < table->ColumnsCount || table->VisibleUnclippedMaskByIndex != table->VisibleMaskByIndex) ? +1 : 0; const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy; table->DrawSplitter.Split(table->InnerWindow->DrawList, channels_total); - table->DummyDrawChannel = (channels_for_dummy > 0) ? (ImU8)(channels_total - 1) : -1; + table->DummyDrawChannel = (ImU8)((channels_for_dummy > 0) ? channels_total - 1 : -1); table->BgDrawChannelUnfrozen = (ImU8)((table->FreezeRowsCount > 0) ? channels_for_row + 1 : 0); int draw_channel_current = 1; @@ -1804,7 +1804,7 @@ void ImGui::TableEndRow(ImGuiTable* table) for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { ImGuiTableColumn* column = &table->Columns[column_n]; - column->NavLayerCurrent = (column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main; + column->NavLayerCurrent = (ImS8)((column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); } if (unfreeze_rows_actual) { @@ -1858,7 +1858,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n) window->DC.ColumnsOffset.x = start_x - window->Pos.x - window->DC.Indent.x; // FIXME-WORKRECT window->DC.CurrLineTextBaseOffset = table->RowTextBaseline; window->DC.LastItemId = 0; - window->DC.NavLayerCurrent = column->NavLayerCurrent; + window->DC.NavLayerCurrent = (ImGuiNavLayer)column->NavLayerCurrent; window->WorkRect.Min.y = window->DC.CursorPos.y; window->WorkRect.Min.x = column->MinX + table->CellPaddingX + table->CellSpacingX1; @@ -1868,7 +1868,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n) if (!column->IsVisible) window->DC.CursorPos.y = ImMax(window->DC.CursorPos.y, table->RowPosY2); - window->SkipItems = column->SkipItems; + window->SkipItems = column->IsSkipItems; if (table->Flags & ImGuiTableFlags_NoClip) { table->DrawSplitter.SetCurrentChannel(window->DrawList, 1);