Browse Source

Tables: (Breaking change) Sorting: Made it users responsability to clear SpecsDirty back to false, so TableGetSortSpecs() doesn't have side-effect any more. + comments

pull/3657/head
omar 4 years ago
committed by ocornut
parent
commit
931829f701
  1. 28
      imgui.h
  2. 15
      imgui_demo.cpp
  3. 1
      imgui_internal.h
  4. 9
      imgui_tables.cpp

28
imgui.h

@ -688,17 +688,19 @@ namespace ImGui
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. 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 // Tables: Headers & Columns declaration
// - Use TableSetupColumn() to specify label, resizing policy, default width, id, various other flags etc. // - Use TableSetupColumn() to specify label, resizing policy, default width, id, various other flags etc.
// - The name passed to TableSetupColumn() is used by TableAutoHeaders() and by the context-menu // Important: this will not display anything! The name passed to TableSetupColumn() is used by TableAutoHeaders() and context-menus.
// - Use TableAutoHeaders() to submit the whole header row, otherwise you may treat the header row as a regular row, manually call TableHeader() and other widgets. // - 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!) // 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 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 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. IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
// Tables: Sorting // Tables: Sorting
// - Call TableGetSortSpecs() to retrieve latest sort specs for the table. Return value will be NULL if no 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. // - 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()! // - 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). 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
@ -1890,15 +1892,17 @@ struct ImGuiTableSortSpecsColumn
}; };
// Sorting specifications for a table (often handling sort specs for a single column, occasionally more) // Sorting specifications for a table (often handling sort specs for a single column, occasionally more)
// Obtained by calling TableGetSortSpecs() // Obtained by calling TableGetSortSpecs().
// 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!
struct ImGuiTableSortSpecs struct ImGuiTableSortSpecs
{ {
const ImGuiTableSortSpecsColumn* Specs; // Pointer to sort spec array. const ImGuiTableSortSpecsColumn* Specs; // Pointer to sort spec array.
int SpecsCount; // Sort spec count. Most often 1 unless e.g. ImGuiTableFlags_MultiSortable is enabled. int SpecsCount; // Sort spec count. Most often 1 unless e.g. ImGuiTableFlags_MultiSortable is enabled.
bool SpecsChanged; // Set to true by TableGetSortSpecs() call if the specs have changed since the previous call. Use this to sort again! bool SpecsDirty; // Set to true when specs have changed since last time! Use this to sort again, then clear the flag.
ImU64 ColumnsMask; // Set to the mask of column indexes included in the Specs array. e.g. (1 << N) when column N is sorted. ImU64 ColumnsMask; // Set to the mask of column indexes included in the Specs array. e.g. (1 << N) when column N is sorted.
ImGuiTableSortSpecs() { Specs = NULL; SpecsCount = 0; SpecsChanged = false; ColumnsMask = 0x00; } ImGuiTableSortSpecs() { Specs = NULL; SpecsCount = 0; SpecsDirty = false; ColumnsMask = 0x00; }
}; };
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

15
imgui_demo.cpp

@ -3250,6 +3250,8 @@ struct MyItem
// however qsort doesn't allow passing user data to comparing function. // however qsort doesn't allow passing user data to comparing function.
// As a workaround, we are storing the sort specs in a static/global for the comparing function to access. // As a workaround, we are storing the sort specs in a static/global for the comparing function to access.
// In your own use case you would probably pass the sort specs to your sorting/comparing functions directly and not use a global. // In your own use case you would probably pass the sort specs to your sorting/comparing functions directly and not use a global.
// We could technically call ImGui::TableGetSortSpecs() in CompareWithSortSpecs(), but considering that this function is called
// very often by the sorting algorithm it would be a little wasteful.
static const ImGuiTableSortSpecs* s_current_sort_specs; static const ImGuiTableSortSpecs* s_current_sort_specs;
// Compare function to be used by qsort() // Compare function to be used by qsort()
@ -4201,12 +4203,14 @@ static void ShowDemoWindowTables()
ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Quantity); ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Quantity);
// Sort our data if sort specs have been changed! // Sort our data if sort specs have been changed!
if (const ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs()) if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs())
if (sorts_specs->SpecsChanged && items.Size > 1) if (sorts_specs->SpecsDirty)
{ {
MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function. MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function.
qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs); if (items.Size > 1)
qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs);
MyItem::s_current_sort_specs = NULL; MyItem::s_current_sort_specs = NULL;
sorts_specs->SpecsDirty = false;
} }
// Display data // Display data
@ -4389,14 +4393,15 @@ static void ShowDemoWindowTables()
ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort); ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort);
// Sort our data if sort specs have been changed! // Sort our data if sort specs have been changed!
const ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs(); ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs();
if (sorts_specs && sorts_specs->SpecsChanged) if (sorts_specs && sorts_specs->SpecsDirty)
items_need_sort = true; items_need_sort = true;
if (sorts_specs && items_need_sort && items.Size > 1) if (sorts_specs && items_need_sort && items.Size > 1)
{ {
MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function. MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function.
qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs); qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs);
MyItem::s_current_sort_specs = NULL; MyItem::s_current_sort_specs = NULL;
sorts_specs->SpecsDirty = false;
} }
items_need_sort = false; items_need_sort = false;

1
imgui_internal.h

@ -2033,7 +2033,6 @@ struct ImGuiTable
bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow(). bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow().
bool IsInitializing; bool IsInitializing;
bool IsSortSpecsDirty; bool IsSortSpecsDirty;
bool IsSortSpecsChangedForUser; // Reported to end-user via TableGetSortSpecs()->SpecsChanged and then clear.
bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag. bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted). bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
bool IsSettingsRequestLoad; bool IsSettingsRequestLoad;

9
imgui_tables.cpp

@ -2298,7 +2298,7 @@ void ImGui::TableSortSpecsClickColumn(ImGuiTable* table, ImGuiTableColumn* click
// You can sort your data again when 'SpecsChanged == true'. It will be true with sorting specs have changed since // 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. // last call, or the first time.
// Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()! // Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable()!
const ImGuiTableSortSpecs* ImGui::TableGetSortSpecs() ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
ImGuiTable* table = g.CurrentTable; ImGuiTable* table = g.CurrentTable;
@ -2310,8 +2310,6 @@ const ImGuiTableSortSpecs* ImGui::TableGetSortSpecs()
if (table->IsSortSpecsDirty) if (table->IsSortSpecsDirty)
TableSortSpecsBuild(table); TableSortSpecsBuild(table);
table->SortSpecs.SpecsChanged = table->IsSortSpecsChangedForUser;
table->IsSortSpecsChangedForUser = false;
return table->SortSpecs.SpecsCount ? &table->SortSpecs : NULL; return table->SortSpecs.SpecsCount ? &table->SortSpecs : NULL;
} }
@ -2466,9 +2464,8 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
} }
table->SortSpecs.Specs = table->SortSpecsData.Data; table->SortSpecs.Specs = table->SortSpecsData.Data;
table->SortSpecs.SpecsCount = table->SortSpecsData.Size; table->SortSpecs.SpecsCount = table->SortSpecsData.Size;
table->SortSpecs.SpecsDirty = true; // Mark as dirty for user
table->IsSortSpecsDirty = false; table->IsSortSpecsDirty = false; // Mark as not dirty for us
table->IsSortSpecsChangedForUser = true;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------

Loading…
Cancel
Save