Tables: (Breaking) Add TableSetupScrollFreeze() api, remove ImGuiTableFlags_ScrollFreezeXXX flags, tweak comments, move columns block.

Avoid awkwardly named ScrollFreeze flags, raise limit over 3, and will allow for future api maybe freezing bottom/right side.
This commit is contained in:
ocornut 2020-09-23 17:53:52 +02:00
parent 36b2f3b4f1
commit 3021608392
3 changed files with 87 additions and 90 deletions

98
imgui.h
View File

@ -652,11 +652,55 @@ namespace ImGui
// - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open. // - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open.
IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open.
// Columns // Tables
// [ALPHA API] API will evolve! (see: FIXME-TABLE)
// - Full-featured replacement for old Columns API
// - See Demo->Tables for details.
// - See ImGuiTableFlags_ and ImGuiTableColumnsFlags_ enums for a description of available flags.
// The typical call flow is:
// - 1. Call BeginTable()
// - 2. Optionally call TableSetupColumn() to submit column name/flags/defaults
// - 3. Optionally call TableSetupScrollFreeze() to request scroll freezing of columns/rows
// - 4. Optionally call TableAutoHeaders() to submit a header row (names will be pulled from data submitted to TableSetupColumns)
// - 4. Populate contents
// - In most situations you can use TableNextRow() + TableSetColumnIndex() to start appending into a column.
// - If you are using tables as a sort of grid, where every columns is holding the same type of contents,
// you may prefer using TableNextCell() instead of TableNextRow() + TableSetColumnIndex().
// - Submit your content with regular ImGui function.
// - 5. Call EndTable()
#define IMGUI_HAS_TABLE 1
IMGUI_API bool BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true!
IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row.
IMGUI_API bool TableNextCell(); // append into the next column (next column, or next row if currently in last column). Return true if column is visible.
IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true if column is visible.
IMGUI_API int TableGetColumnIndex(); // return current column index.
// Tables: Headers & Columns declaration
// - Use TableSetupScrollFreeze() to lock columns (from the right) or rows (from the top) so they stay visible when scrolled.
// - Use TableSetupColumn() to specify label, resizing policy, default width, id, various other flags etc.
// Important: this will not display anything! The name passed to TableSetupColumn() is used by TableAutoHeaders() and context-menus.
// - Use TableAutoHeaders() to create a row and automatically submit a TableHeader() for each column.
// Headers are required to perform some interactions: reordering, sorting, context menu (FIXME-TABLE: context menu should work without!)
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in some advanced cases (e.g. adding custom widgets in header row).
IMGUI_API void TableSetupScrollFreeze(int columns, int rows);
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = -1.0f, ImU32 user_id = 0);
IMGUI_API void TableAutoHeaders(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
// Tables: Miscellaneous functions
// - Most functions taking 'int column_n' treat the default value of -1 as the same as passing the current column index
// - Sorting: call TableGetSortSpecs() to retrieve latest sort specs for the table. Return value will be NULL if no sorting.
// When 'SpecsDirty == true' you should sort your data. It will be true when sorting specs have changed since last call, or the first time.
// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame!
// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable().
IMGUI_API const char* TableGetColumnName(int column_n = -1); // return NULL if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column.
IMGUI_API bool TableGetColumnIsVisible(int column_n = -1); // return true if column is visible. Same value is also returned by TableNextCell() and TableSetColumnIndex(). Pass -1 to use current column.
IMGUI_API bool TableGetColumnIsSorted(int column_n = -1); // return true if column is included in the sort specs. Rarely used, can be useful to tell if a data change should trigger resort. Equivalent to test ImGuiTableSortSpecs's ->ColumnsMask & (1 << column_n). Pass -1 to use current column.
IMGUI_API int TableGetHoveredColumn(); // return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered.
IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).
IMGUI_API void TableSetBgColor(ImGuiTableBgTarget bg_target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details.
// Columns (Legacy API, prefer using Tables)
// - You can also use SameLine(pos_x) to mimic simplified columns. // - You can also use SameLine(pos_x) to mimic simplified columns.
// - The columns API is work-in-progress and rather lacking (columns are arguably the worst part of dear imgui at the moment!)
// - There is a maximum of 64 columns.
// - Currently working on new 'Tables' api which will replace columns around Q2 2020 (see GitHub #2957).
IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true);
IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished
IMGUI_API int GetColumnIndex(); // get current column index IMGUI_API int GetColumnIndex(); // get current column index
@ -666,42 +710,6 @@ namespace ImGui
IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column
IMGUI_API int GetColumnsCount(); IMGUI_API int GetColumnsCount();
// Tables
// [ALPHA API] API will evolve! (FIXME-TABLE)
// - Full-featured replacement for old Columns API
// - In most situations you can use TableNextRow() + TableSetColumnIndex() to populate a table.
// - If you are using tables as a sort of grid, populating every columns with the same type of contents,
// you may prefer using TableNextCell() instead of TableNextRow() + TableSetColumnIndex().
// - See Demo->Tables for details.
// - See ImGuiTableFlags_ and ImGuiTableColumnsFlags_ enums for a description of available flags.
#define IMGUI_HAS_TABLE 1
IMGUI_API bool BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true!
IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row.
IMGUI_API bool TableNextCell(); // append into the next column (next column, or next row if currently in last column). Return true if column is visible.
IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true if column is visible.
IMGUI_API int TableGetColumnIndex(); // return current column index.
IMGUI_API const char* TableGetColumnName(int column_n = -1); // return NULL if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column.
IMGUI_API bool TableGetColumnIsVisible(int column_n = -1); // return true if column is visible. Same value is also returned by TableNextCell() and TableSetColumnIndex(). Pass -1 to use current column.
IMGUI_API bool TableGetColumnIsSorted(int column_n = -1); // return true if column is included in the sort specs. Rarely used, can be useful to tell if a data change should trigger resort. Equivalent to test ImGuiTableSortSpecs's ->ColumnsMask & (1 << column_n). Pass -1 to use current column.
IMGUI_API int TableGetHoveredColumn(); // return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered.
IMGUI_API void TableSetBgColor(ImGuiTableBgTarget bg_target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details.
// Tables: Headers & Columns declaration
// - Use TableSetupColumn() to specify label, resizing policy, default width, id, various other flags etc.
// Important: this will not display anything! The name passed to TableSetupColumn() is used by TableAutoHeaders() and context-menus.
// - Use TableAutoHeaders() to create a row and automatically submit a TableHeader() for each column.
// Headers are required to perform some interactions: reordering, sorting, context menu (FIXME-TABLE: context menu should work without!)
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in some advanced cases (e.g. adding custom widgets in header row).
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = -1.0f, ImU32 user_id = 0);
IMGUI_API void TableAutoHeaders(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
// Tables: Sorting
// - Call TableGetSortSpecs() to retrieve latest sort specs for the table. Return value will be NULL if no sorting.
// - When 'SpecsDirty == true' you can sort your data. It will be true with sorting specs have changed since last call, or the first time.
// Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame!
// - Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()!
IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).
// Tab Bars, Tabs // Tab Bars, Tabs
IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar IMGUI_API bool BeginTabBar(const char* str_id, ImGuiTabBarFlags flags = 0); // create and append into a TabBar
IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true! IMGUI_API void EndTabBar(); // only call EndTabBar() if BeginTabBar() returns true!
@ -1062,19 +1070,9 @@ enum ImGuiTableFlags_
ImGuiTableFlags_ScrollX = 1 << 20, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Because this create a child window, ScrollY is currently generally recommended when using ScrollX. ImGuiTableFlags_ScrollX = 1 << 20, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Because this create a child window, ScrollY is currently generally recommended when using ScrollX.
ImGuiTableFlags_ScrollY = 1 << 21, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. ImGuiTableFlags_ScrollY = 1 << 21, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
ImGuiTableFlags_Scroll = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY, ImGuiTableFlags_Scroll = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY,
ImGuiTableFlags_ScrollFreezeTopRow = 1 << 22, // We can lock 1 to 3 rows (starting from the top). Use with ScrollY enabled.
ImGuiTableFlags_ScrollFreeze2Rows = 2 << 22,
ImGuiTableFlags_ScrollFreeze3Rows = 3 << 22,
ImGuiTableFlags_ScrollFreezeLeftColumn = 1 << 24, // We can lock 1 to 3 columns (starting from the left). Use with ScrollX enabled.
ImGuiTableFlags_ScrollFreeze2Columns = 2 << 24,
ImGuiTableFlags_ScrollFreeze3Columns = 3 << 24,
// [Internal] Combinations and masks // [Internal] Combinations and masks
ImGuiTableFlags_SizingPolicyMaskX_ = ImGuiTableFlags_SizingPolicyStretchX | ImGuiTableFlags_SizingPolicyFixedX, ImGuiTableFlags_SizingPolicyMaskX_ = ImGuiTableFlags_SizingPolicyStretchX | ImGuiTableFlags_SizingPolicyFixedX,
ImGuiTableFlags_ScrollFreezeRowsShift_ = 22,
ImGuiTableFlags_ScrollFreezeColumnsShift_ = 24,
ImGuiTableFlags_ScrollFreezeRowsMask_ = 0x03 << ImGuiTableFlags_ScrollFreezeRowsShift_,
ImGuiTableFlags_ScrollFreezeColumnsMask_ = 0x03 << ImGuiTableFlags_ScrollFreezeColumnsShift_
}; };
// Flags for ImGui::TableSetupColumn() // Flags for ImGui::TableSetupColumn()

View File

@ -3630,12 +3630,12 @@ static void ShowDemoWindowTables()
{ {
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."); 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.");
ImVec2 size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 7); ImVec2 size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 7);
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_ScrollFreezeTopRow | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeTopRow", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeTopRow);
if (ImGui::BeginTable("##table1", 3, flags, size)) if (ImGui::BeginTable("##table1", 3, flags, size))
{ {
ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None);
@ -3665,14 +3665,19 @@ static void ShowDemoWindowTables()
{ {
HelpMarker("When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingPolicyFixedX, as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\nAlso note that as of the current version, you will almost always want to enable ScrollY along with ScrollX, because the container window won't automatically extend vertically to fix contents (this may be improved in future versions)."); HelpMarker("When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingPolicyFixedX, as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\nAlso note that as of the current version, you will almost always want to enable ScrollY along with ScrollX, because the container window won't automatically extend vertically to fix contents (this may be improved in future versions).");
ImVec2 size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 10); ImVec2 size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 10);
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_ScrollFreezeTopRow | ImGuiTableFlags_ScrollFreezeLeftColumn | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
static int freeze_cols = 1;
static int freeze_rows = 1;
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeTopRow", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeTopRow); ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeLeftColumn", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeLeftColumn); ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
if (ImGui::BeginTable("##table1", 7, flags, size)) 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 ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
ImGui::TableSetupColumn("Line #", ImGuiTableColumnFlags_NoHide); // Make the first column not hideable to match our use of TableSetupScrollFreeze()
ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None);
ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None);
@ -3978,7 +3983,6 @@ static void ShowDemoWindowTables()
{ {
static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg; static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg;
//ImGui::CheckboxFlags("ImGuiTableFlags_Scroll", (unsigned int*)&flags, ImGuiTableFlags_Scroll); //ImGui::CheckboxFlags("ImGuiTableFlags_Scroll", (unsigned int*)&flags, ImGuiTableFlags_Scroll);
//ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeLeftColumn", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeLeftColumn);
if (ImGui::BeginTable("##3ways", 3, flags)) if (ImGui::BeginTable("##3ways", 3, flags))
{ {
@ -4187,7 +4191,7 @@ static void ShowDemoWindowTables()
static ImGuiTableFlags flags = static ImGuiTableFlags flags =
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_MultiSortable ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_MultiSortable
| ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV
| ImGuiTableFlags_ScrollY | ImGuiTableFlags_ScrollFreezeTopRow; | ImGuiTableFlags_ScrollY;
if (ImGui::BeginTable("##table", 4, flags, ImVec2(0, 250), 0.0f)) if (ImGui::BeginTable("##table", 4, flags, ImVec2(0, 250), 0.0f))
{ {
// Declare columns // Declare columns
@ -4201,6 +4205,7 @@ static void ShowDemoWindowTables()
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name);
ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action); ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action);
ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Quantity); ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Quantity);
ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible
// Sort our data if sort specs have been changed! // Sort our data if sort specs have been changed!
if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs()) if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs())
@ -4246,14 +4251,14 @@ static void ShowDemoWindowTables()
ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_MultiSortable ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_MultiSortable
| ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders
| ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
| ImGuiTableFlags_ScrollFreezeTopRow | ImGuiTableFlags_ScrollFreezeLeftColumn
| ImGuiTableFlags_SizingPolicyFixedX | ImGuiTableFlags_SizingPolicyFixedX
; ;
enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable }; enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable };
static int contents_type = CT_FillButton; static int contents_type = CT_FillButton;
const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable" }; const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable" };
static int freeze_cols = 1;
static int freeze_rows = 1;
static int items_count = IM_ARRAYSIZE(template_items_names); static int items_count = IM_ARRAYSIZE(template_items_names);
static ImVec2 outer_size_value = ImVec2(0, 250); static ImVec2 outer_size_value = ImVec2(0, 250);
static float row_min_height = 0.0f; // Auto static float row_min_height = 0.0f; // Auto
@ -4314,20 +4319,10 @@ static void ShowDemoWindowTables()
ImGui::Indent(); ImGui::Indent();
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", (unsigned int*)&flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", (unsigned int*)&flags, ImGuiTableFlags_ScrollX);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", (unsigned int*)&flags, ImGuiTableFlags_ScrollY);
// For the purpose of our "advanced" demo, we expose the 3 freezing variants on both axises instead of only exposing the most common flag.
//ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeTopRow", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeTopRow);
//ImGui::CheckboxFlags("ImGuiTableFlags_ScrollFreezeLeftColumn", (unsigned int*)&flags, ImGuiTableFlags_ScrollFreezeLeftColumn);
int freeze_row_count = (flags & ImGuiTableFlags_ScrollFreezeRowsMask_) >> ImGuiTableFlags_ScrollFreezeRowsShift_;
int freeze_col_count = (flags & ImGuiTableFlags_ScrollFreezeColumnsMask_) >> ImGuiTableFlags_ScrollFreezeColumnsShift_;
ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
if (ImGui::DragInt("ImGuiTableFlags_ScrollFreezeTopRow/2Rows/3Rows", &freeze_row_count, 0.2f, 0, 3)) ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
if (freeze_row_count >= 0 && freeze_row_count <= 3)
flags = (flags & ~ImGuiTableFlags_ScrollFreezeRowsMask_) | (freeze_row_count << ImGuiTableFlags_ScrollFreezeRowsShift_);
ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
if (ImGui::DragInt("ImGuiTableFlags_ScrollFreezeLeftColumn/2Columns/3Columns", &freeze_col_count, 0.2f, 0, 3)) ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
if (freeze_col_count >= 0 && freeze_col_count <= 3)
flags = (flags & ~ImGuiTableFlags_ScrollFreezeColumnsMask_) | (freeze_col_count << ImGuiTableFlags_ScrollFreezeColumnsShift_);
ImGui::Unindent(); ImGui::Unindent();
@ -4386,6 +4381,7 @@ static void ShowDemoWindowTables()
// Declare columns // Declare columns
// We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications. // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
// This is so our sort function can identify a column given our own identifier. We could also identify them based on their index! // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | (lock_first_column_visibility ? ImGuiTableColumnFlags_NoHide : 0), -1.0f, MyItemColumnID_ID); ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | (lock_first_column_visibility ? ImGuiTableColumnFlags_NoHide : 0), -1.0f, MyItemColumnID_ID);
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name);
ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action); ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action);

View File

@ -69,6 +69,7 @@
// | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame) // | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame)
// | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width // | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of stretch columns) from their respective width
// - TableSetupColumn() user submit columns details (optional) // - TableSetupColumn() user submit columns details (optional)
// - TableSetupScrollFreeze() user submit scroll freeze information (optional)
// - TableUpdateLayout() [Internal] automatically called by the FIRST call to TableNextRow() or Table*Header(): lock all widths, columns positions, clipping rectangles // - TableUpdateLayout() [Internal] automatically called by the FIRST call to TableNextRow() or Table*Header(): lock all widths, columns positions, clipping rectangles
// | TableUpdateDrawChannels() - setup ImDrawList channels // | TableUpdateDrawChannels() - setup ImDrawList channels
// | TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission // | TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission
@ -113,22 +114,10 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags)
if (flags & ImGuiTableFlags_Resizable) if (flags & ImGuiTableFlags_Resizable)
flags |= ImGuiTableFlags_BordersInnerV; flags |= ImGuiTableFlags_BordersInnerV;
// Adjust flags: disable top rows freezing if there's no scrolling.
// We could want to assert if ScrollFreeze was set without the corresponding scroll flag, but that would hinder demos.
if ((flags & ImGuiTableFlags_ScrollX) == 0)
flags &= ~ImGuiTableFlags_ScrollFreezeColumnsMask_;
if ((flags & ImGuiTableFlags_ScrollY) == 0)
flags &= ~ImGuiTableFlags_ScrollFreezeRowsMask_;
// Adjust flags: disable NoHostExtendY if we have any scrolling going on // Adjust flags: disable NoHostExtendY if we have any scrolling going on
if ((flags & ImGuiTableFlags_NoHostExtendY) && (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0) if ((flags & ImGuiTableFlags_NoHostExtendY) && (flags & (ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY)) != 0)
flags &= ~ImGuiTableFlags_NoHostExtendY; flags &= ~ImGuiTableFlags_NoHostExtendY;
// Adjust flags: we don't support NoClip with (FreezeColumns > 0)
// We could with some work but it doesn't appear to be worth the effort.
//if (flags & ImGuiTableFlags_ScrollFreezeColumnsMask_)
// flags &= ~ImGuiTableFlags_NoClip;
return flags; return flags;
} }
@ -290,11 +279,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->BackgroundClipRect = table->InnerClipRect; table->BackgroundClipRect = table->InnerClipRect;
table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow
table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
table->FreezeRowsRequest = (ImS8)((flags & ImGuiTableFlags_ScrollFreezeRowsMask_) >> ImGuiTableFlags_ScrollFreezeRowsShift_); table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any
table->FreezeRowsCount = (inner_window->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; table->FreezeColumnsRequest = table->FreezeColumnsCount = 0;
table->FreezeColumnsRequest = (ImS8)((flags & ImGuiTableFlags_ScrollFreezeColumnsMask_) >> ImGuiTableFlags_ScrollFreezeColumnsShift_); table->IsFreezeRowsPassed = true;
table->FreezeColumnsCount = (inner_window->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0;
table->IsFreezeRowsPassed = (table->FreezeRowsCount == 0);
table->DeclColumnsCount = 0; table->DeclColumnsCount = 0;
table->RightMostVisibleColumn = -1; table->RightMostVisibleColumn = -1;
@ -487,6 +474,22 @@ void ImGui::TableBeginUpdateColumns(ImGuiTable* table)
table->InnerWindow->SkipItems = false; table->InnerWindow->SkipItems = false;
} }
void ImGui::TableSetupScrollFreeze(int columns, int rows)
{
ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!");
IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!");
IM_ASSERT(columns >= 0 && columns < IMGUI_TABLE_MAX_COLUMNS);
IM_ASSERT(rows >= 0 && rows < 128); // Arbitrary limit
table->FreezeColumnsRequest = (table->Flags & ImGuiTableFlags_ScrollX) ? (ImS8)columns : 0;
table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0;
table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImS8)rows : 0;
table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0;
table->IsFreezeRowsPassed = (table->FreezeRowsCount == 0);
}
void ImGui::TableUpdateDrawChannels(ImGuiTable* table) void ImGui::TableUpdateDrawChannels(ImGuiTable* table)
{ {
// Allocate draw channels. // Allocate draw channels.
@ -1527,7 +1530,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags,
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!"); IM_ASSERT(table != NULL && "Need to call TableSetupColumn() after BeginTable()!");
IM_ASSERT(!table->IsLayoutLocked && "Need to call call TableSetupColumn() before first row!"); IM_ASSERT(table->IsLayoutLocked == false && "Need to call call TableSetupColumn() before first row!");
IM_ASSERT(table->DeclColumnsCount >= 0 && table->DeclColumnsCount < table->ColumnsCount && "Called TableSetupColumn() too many times!"); IM_ASSERT(table->DeclColumnsCount >= 0 && table->DeclColumnsCount < table->ColumnsCount && "Called TableSetupColumn() too many times!");
ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount]; ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount];