-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New Tables API (alpha available for testing) #2957
Comments
Basic Usage (Edited Jan 8, 2021)
Main API // Tables
// [BETA API] API may evolve!
// - Full-featured replacement for old Columns API.
// - See Demo->Tables for details.
// - See ImGuiTableFlags_ and ImGuiTableColumnFlags_ 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 TableHeadersRow() to submit a header row (names will be pulled from data submitted to TableSetupColumns)
// - 5. Populate contents
// - In most situations you can use TableNextRow() + TableSetColumnIndex(N) 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 TableNextColumn() instead of TableNextRow() + TableSetColumnIndex().
// TableNextColumn() will automatically wrap-around into the next row if needed.
// - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column!
// - Both TableSetColumnIndex() and TableNextColumn() return true when the column is visible or performing
// width measurements. Otherwise, you may skip submitting the contents of a cell/column, BUT ONLY if you know
// it is not going to contribute to row height.
// In many situations, you may skip submitting contents for every columns but one (e.g. the first one).
// - Summary of possible call flow:
// ----------------------------------------------------------------------------------------------------------
// TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK
// TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK
// TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row!
// TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear!
// ----------------------------------------------------------------------------------------------------------
// - 5. Call EndTable()
bool BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
void EndTable(); // only call EndTable() if BeginTable() returns true!
void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row.
bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible.
bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.
int TableGetColumnIndex(); // return current column index.
int TableGetRowIndex(); // return current row index.
// Tables: Headers & Columns declaration
// - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc.
// Important: this will not display anything! The name passed to TableSetupColumn() is used by TableHeadersRow() and context-menus.
// - Use TableHeadersRow() to create a row and automatically submit a TableHeader() for each column.
// Headers are required to perform: reordering, sorting, and opening the context menu (but context menu can also be available in columns body using ImGuiTableFlags_ContextMenuInBody).
// - 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).
// - Use TableSetupScrollFreeze() to lock columns (from the right) or rows (from the top) so they stay visible when scrolled.
void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = -1.0f, ImU32 user_id = 0);
void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu
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().
int TableGetColumnCount(); // return number of columns (value passed to BeginTable)
const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column.
ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags.
ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting).
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. // Basic use of tables using TableNextRow() to create a new row, and TableSetColumnIndex() to select the column.
// In many situations, this is the most flexible and easy to use pattern.
HelpMarker("Using TableNextRow() + calling TableSetColumnIndex() _before_ each cell, in a loop.");
if (ImGui::BeginTable("##table1", 3))
{
for (int row = 0; row < 4; row++)
{
ImGui::TableNextRow();
for (int column = 0; column < 3; column++)
{
ImGui::TableSetColumnIndex(column);
ImGui::Text("Row %d Column %d", row, column);
}
}
ImGui::EndTable();
}
// This essentially the same as above, except instead of using a for loop we call TableSetColumnIndex() manually.
// Sometimes this makes more sense.
HelpMarker("Using TableNextRow() + calling TableNextColumn() _before_ each cell, manually.");
if (ImGui::BeginTable("##table2", 3))
{
for (int row = 0; row < 4; row++)
{
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("Row %d", row);
ImGui::TableNextColumn();
ImGui::Text("Some contents");
ImGui::TableNextColumn();
ImGui::Text("123.456");
}
ImGui::EndTable();
}
// Another subtle variant, we call TableNextColumn() _before_ each cell. At the end of a row, TableNextColumn() will create a new row.
// Note that we never TableNextRow() here!
HelpMarker(
"Only using TableNextColumn(), which tends to be convenient for tables where every cells contains the same type of contents.\n"
"This is also more similar to the old NextColumn() function of the Columns API, and provided to facilitate the Columns->Tables API transition.");
if (ImGui::BeginTable("##table4", 3))
{
for (int item = 0; item < 14; item++)
{
ImGui::TableNextColumn();
ImGui::Text("Item %d", item);
}
ImGui::EndTable();
}
TODO: add details here In particular, API as of October 2020Provided a rough references here, // Flags for ImGui::BeginTable()
// - Important! Sizing policies have particularly complex and subtle side effects, more so than you would expect.
// Read comments/demos carefully + experiment with live demos to get acquainted with them.
// - The default sizing policy for columns depends on whether the ScrollX flag is set on the table:
// When ScrollX is off:
// - Table defaults to ImGuiTableFlags_ColumnsWidthStretch -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch.
// - Columns sizing policy allowed: Stretch (default) or Fixed/Auto.
// - Stretch Columns will share the width available in table.
// - Fixed Columns will generally obtain their requested width unless the Table cannot fit them all.
// When ScrollX is on:
// - Table defaults to ImGuiTableFlags_ColumnsWidthFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed.
// - Columns sizing policy allowed: Fixed/Auto mostly!
// - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed.
// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable().
// - Mixing up columns with different sizing policy is possible BUT can be tricky and has some side-effects and restrictions.
// (their visible order and the scrolling state have subtle but necessary effects on how they can be manually resized).
// The typical use of mixing sizing policies is to have ScrollX disabled, one or two Stretch Column and many Fixed Columns.
enum ImGuiTableFlags_
{
// Features
ImGuiTableFlags_None = 0,
ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file.
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
// Decorations
ImGuiTableFlags_RowBg = 1 << 6, // Set each RowBg color with ImGuiCol_TableRowBg or ImGuiCol_TableRowBgAlt (equivalent of calling TableSetBgColor with ImGuiTableBgFlags_RowBg0 on each row manually)
ImGuiTableFlags_BordersInnerH = 1 << 7, // Draw horizontal borders between rows.
ImGuiTableFlags_BordersOuterH = 1 << 8, // Draw horizontal borders at the top and bottom.
ImGuiTableFlags_BordersInnerV = 1 << 9, // Draw vertical borders between columns.
ImGuiTableFlags_BordersOuterV = 1 << 10, // Draw vertical borders on the left and right sides.
ImGuiTableFlags_BordersH = ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_BordersOuterH, // Draw horizontal borders.
ImGuiTableFlags_BordersV = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersOuterV, // Draw vertical borders.
ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders.
ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders.
ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders.
ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appears in Headers). -> May move to style
ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). -> May move to style
// Sizing Policy (read above for defaults)
ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width.
ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible.
ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths.
ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overriden by TableSetupColumn().
// Sizing Extra Options
ImGuiTableFlags_NoHostExtendY = 1 << 16, // Disable extending table past the limit set by outer_size.y. Only meaningful when neither ScrollX nor ScrollY are set (data below the limit will be clipped and not visible)
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable.
ImGuiTableFlags_PreciseWidths = 1 << 18, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.
// Clipping
ImGuiTableFlags_NoClip = 1 << 19, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze().
// Padding
ImGuiTableFlags_PadOuterX = 1 << 20, // Default if BordersOuterV is on. Enable outer-most padding.
ImGuiTableFlags_NoPadOuterX = 1 << 21, // Default if BordersOuterV is off. Disable outer-most padding.
ImGuiTableFlags_NoPadInnerX = 1 << 22, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off).
// Scrolling
ImGuiTableFlags_ScrollX = 1 << 23, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this create a child window, ScrollY is currently generally recommended when using ScrollX.
ImGuiTableFlags_ScrollY = 1 << 24, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
// Sorting
ImGuiTableFlags_SortMulti = 1 << 25, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
ImGuiTableFlags_SortTristate = 1 << 26, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
};
// Flags for ImGui::TableSetupColumn()
enum ImGuiTableColumnFlags_
{
// Input configuration flags
ImGuiTableColumnFlags_None = 0,
ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column.
ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column.
ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).
ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).
ImGuiTableColumnFlags_WidthAuto = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _SizingFixedFit and table is not resizable, or policy is _SizingFixedSame). Generally compatible with using right-most fitting widgets (e.g. SetNextItemWidth(-FLT_MIN))
ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.
ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.
ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.
ImGuiTableColumnFlags_NoClip = 1 << 8, // Disable clipping for this column (all NoClip columns will render in a same draw command).
ImGuiTableColumnFlags_NoSort = 1 << 9, // Disable ability to sort on this field (even if ImGuiTableFlags_Sortable is set on the table).
ImGuiTableColumnFlags_NoSortAscending = 1 << 10, // Disable ability to sort in the ascending direction.
ImGuiTableColumnFlags_NoSortDescending = 1 << 11, // Disable ability to sort in the descending direction.
ImGuiTableColumnFlags_NoHeaderWidth = 1 << 12, // Disable header text width contribution to automatic column width.
ImGuiTableColumnFlags_PreferSortAscending = 1 << 13, // Make the initial sort direction Ascending when first sorting on this column (default).
ImGuiTableColumnFlags_PreferSortDescending = 1 << 14, // Make the initial sort direction Descending when first sorting on this column.
ImGuiTableColumnFlags_IndentEnable = 1 << 15, // Use current Indent value when entering cell (default for column 0).
ImGuiTableColumnFlags_IndentDisable = 1 << 16, // Ignore current Indent value when entering cell (default for columns > 0). Indentation changes _within_ the cell will still be honored.
// Output status flags, read-only via TableGetColumnFlags()
ImGuiTableColumnFlags_IsEnabled = 1 << 20, // Status: is enabled == not hidden by user/api (referred to as "Hide" in _DefaultHide and _NoHide) flags.
ImGuiTableColumnFlags_IsVisible = 1 << 21, // Status: is visible == is enabled AND not clipped by scrolling.
ImGuiTableColumnFlags_IsSorted = 1 << 22, // Status: is currently part of the sort specs
ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse
};
// Flags for ImGui::TableNextRow()
enum ImGuiTableRowFlags_
{
ImGuiTableRowFlags_None = 0,
ImGuiTableRowFlags_Headers = 1 << 0 // Identify header row (set default background color + width of its contents accounted different for auto column width)
};
// Enum for ImGui::TableSetBgColor()
// Background colors are rendering in 3 layers:
// - Layer 0: draw with RowBg0 color if set, otherwise draw with ColumnBg0 if set.
// - Layer 1: draw with RowBg1 color if set, otherwise draw with ColumnBg1 if set.
// - Layer 2: draw with CellBg color if set.
// The purpose of the two row/columns layers is to let you decide if a background color changes should override or blend with the existing color.
// When using ImGuiTableFlags_RowBg on the table, each row has the RowBg0 color automatically set for odd/even rows.
// If you set the color of RowBg0 target, your color will override the existing RowBg0 color.
// If you set the color of RowBg1 or ColumnBg1 target, your color will blend over the RowBg0 color.
enum ImGuiTableBgTarget_
{
ImGuiTableBgTarget_None = 0,
ImGuiTableBgTarget_RowBg0 = 1, // Set row background color 0 (generally used for background, automatically set when ImGuiTableFlags_RowBg is used)
ImGuiTableBgTarget_RowBg1 = 2, // Set row background color 1 (generally used for selection marking)
ImGuiTableBgTarget_CellBg = 3 // Set cell background color (top-most color)
}; |
Issues / Todo listSome of the stuff remaining in my current todo list
Sizing behaviors
Render, clipping, borders, background color
Keyboard/Gamepad Navigation
Headers, context menu
Sorting
Documentation
Demo
|
What do you think would be the best way to implement a table tree view with this API? Something like, say, QTreeView. |
It's entirely possible to use |
…ellRect() include expected paddings. Add demo code. Comments. (#2957) Remove misleading commented-out flags for now.
@soulthreads I am working on a Tree view demo right now. I think there may be currently some problems with how indentation is handled accross multiple columns. Will post when I have a demo.
That's a good idea, thought not inherently a table feature. I'll add something in my todo list about the possibility for child windows to forward scroll requests to their parent when already at a limit. (EDIT: there's a
Will be working on selection patterns in the upcoming months. You can already use
I personally don't think it does as I modelled it after Windows Explorer which shows this list in default order. I think it has the advantage of highlighting important columns. I'd be curious to know if other OS/toolkits uses a different scheme.
I don't it as a table-specific feature but we should generally aim to provide ellipsis/clipping settings to e.g. Text functions. When we have this features we could imagine that table columns should store and forward this setting as a convenience. I think when we start refactoring text functions we will work on low-level features to enable this.
It's a lot more complicated than you'd imagine as they are lots of rules depending on the order and number of columns of each sizing policy. So you'll probably stumble on cases where it behave differently than this too. There are generally good reasons for it but they are very unobvious to the user :/
I will experiment with this. I also had code to smoothly move the columns but it was incredibly complicated and eventually decided to ditch/stash it (was requiring z-ordering of elements, with side-effects on inputs, alpha blending, draw channels etc.). Surprisingly, alpha blending was the trickiest issue to solve. Comment in my stashed code says: // To handle smooth reordering of columns, initially we tried to offset the entire column (headers + row).
// This is possible but we ran into a problem where it is difficult to draw the correct background color for the front-most column,
// because 1) we don't know what the actual background color was, 2) we don't want to be overlaying the same transparent color twice.
// Instead we decided to only offset the header row, for which we control what the background is, and can make it non-transparent.
// The complications involved with offsetting only the header rows are simpler to handle.
Thanks, will look at this! EDIT: Fixed
Will see when it happens, we might want to add dedicated context menu hints. |
…to never be larger than scrolling visible rect width. (#2957)
…from BackupXXX to HostXXX. Comments. (#2957)
…xtBaseOffset in EndCell of inactive column). (#2957)
I haven't used the new tables API yet, but hopefully I have some useful feedback as I implemented tables with a bunch of similar features to this a while back using the old columns API. While a lot of table features look great with a trivial/nice/small examples data and you can do a lot of cool stuff, once I connected it to some real data into it and tried to interact / understand the table/data a lot of features became useless almost immediately when the number of table rows was 50+, nevermind 500+. Put simply, features like sorting were only useful in tables where the sorting by a column happens to put the thing your looking for at the top of the list in the first ~10 item. Anyway. long story short, I'm not sure if it's in your plans to build in directly, but the feature that made the tables usable for me was putting basic per column filtering based on data type directly in the table. So in your example, my IDs columns (number data type) could filter for all items > 12 (comparison operator could changable) There's a few more filter types you can implement like for enums, but you get the idea. Only in a trivial example does it seems a bit pointless, but the goal when I was implementing this pretty much went from implementing the table features you've made to be able to find / filter for as many subsets of data in a dataset into a trivial/nice/small sizes so that "last mile" features like sorting by column were much more usable. |
That makes sense of course, if you have tables with 100+ you want some sort of search going on. That's perfectly implementable already with what you have available. I'm not sure what you expect Dear ImGui to provide here, there are an infinite ways of filtering things (math ops, all kind of regexps). There's no concept of "data type in the table", tables are layout helper where you output your own data and that can be anything. I agree we could provide more elaborate demo/examples code of doing things like that, adding that to my list. |
Yeah it was pretty easy to implement simple/generic filters, the issues (besides columns api constraints/bugs) were pretty minor but mostly being space constrained to fit a filter in the column space and getting the look/interaction mechanics somewhat acceptable. I wouldn't expect imgui to do much, if you've implemented native support for regexes things have probably gone very wrong. It would be as if Valve had implemented regexes to help find the games you own in your steam library for those 0.01% of users. However I think there is compromise, I've not had much time to think about what the interface/implementation inside imgui would look like, but maybe you could optionally define some filtering flag for a given column for basic operations, trying to get you 95% there with little effort and not trying to hunt the last 5%. But like you say, it might also be better done in just a demo/example. |
…api) and exposed flags. Added simple Tree demo. (#2957)
…api) and exposed flags. Added simple Tree demo. (#2957)
@joeslay You are right and will definitively work on this at some point. The optimal way to handle coarse clipping along with filtering requires sorting e.g. a filtered list of index anyway, so it would be good to provide a demo. This is very similar to the data structure ideally required for large range-multi-selection patterns (see Speaking of which I have fixed the indentation issue and added a simple Tree View demo now (cc: @soulthreads @Folling) The ultimate target is to get large tree view with clipping, multi-select, range-select. This should currently be possible if merging both tables and rangeselect features but requires some work on a demo. I have a feeling those branches may converge soon. |
Could a ImGuiTableFlags_ScrollFreezeBottomRow be added? Sometimes it is nice to have a row of totals at the bottom of a table. Also, is there any intended functionality for cells to span columns or rows? |
@raegnar
Ouch, I didn't think of that. Adding to todo list but it may not be easy right now (though you should be able to create second table with same id right below the first one)
Spanning multiple columns I will consider looking into but not too easy (will look after reworking all the border drawing code). Spanning multiple rows is much weirder/trickier but also less useful maybe? Because we don't know row height ahead it'd be difficult to implement. |
Is there a way to query the column widths from the first table? I've tried the second table with the same id, but it seems to override the column width sizing. |
The sizes should be synchronized so you shouldn't not have query any width. If you do two successives BeginTable()/EndTable() with same id they are normally synchronized. If you can't get it to work please open a separate issue for it, thanks! |
This is looking very nice - so much more flexible than the columns API! I'm still missing the ability to select table rows, specifically when the table is paired with interactive widgets such as buttons or tree nodes. Adding the following to the demo:
basically works, but is not at all pretty, since the Selectable "disappears" when the TreeNode is hovered. This is generally a problem with Selectables over interactive widgets, and it would be very nice to see this addressed by the table selection mechanics you are working on. |
Hi, I deleted my posts earlier to attempt a new way to find the row height. In my earlier post I tried to edit internal table code but now I added the code to my ImGuiEx Library. If you can add the code or use the idea to find the row height it would be great. What I would like to have is a method that will tell the height of a row. If any cell content change its height it will update the row height value. This example shows it in action along with my Layout lib solution that align the "A0 Cell 1" text. To try it out you can download the c++ files from
The tableEx methods used are Thanks |
Fantastic job with new tables! On the subject of alignment - why not add header alignment? ` enum ImGuiTableColumnFlags_ { ImGuiTableColumnFlags_AlignLeft = 1 << 29, // left align cell content ImGuiTableColumnFlags_AlignCenter = 1 << 30, // center align cell content ImGuiTableColumnFlags_AlignRight = 1 << 31 // right align cell content }; ` imgui_widgets.cpp ` void ImGui::TableHeader(const char* label) { if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) { if (column->SortOrder != -1) { w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x); // w_arrow is calculated only for sorting column } } ... if (column->Flags & ImGuiTableColumnFlags_AlignCenter) label_pos.x += (column->WidthGiven - label_size.x - g.Style.CellPadding.x) / 2; else if (column->Flags & ImGuiTableColumnFlags_AlignRight) label_pos.x += column->WidthGiven - label_size.x - g.Style.CellPadding.x - w_arrow; RenderTextEllipsis(...) } ` It does seem to behave nicely and is very easy to implement. Please correct me if i am missing something. |
What would be the best way to implement tooltips for the header? TableHeader (actual_label); If (IsItemHovered ()) { show_something(); } TableNextCell (); Am i doing it right or is there better solution to tackle the problem? |
About row selection, TreeNode, Selectable @j-zeppenfeld Please open a dedicated issue for it. This is at the cross-over of several features. On one hand, I'm going to add internal api to make it easy to colorize row/lines/cells so that will be used for selection visuals. The wider issue is that the reach and features scope of Selectable vs TreeNode have been overlapping and confusing because none of them provide all the features we want. I think there's more general table-agnostic rework to do on them, maybe a new, better widget that covers the desirable feature set of both. Note in the meanwhile that TreeNode has a Since the canonical use case of Tables will be to provide e.g. large selectable trees we will aim to provide such demo and implement whatever is needed. I think the features/rangeselect branch will probably also converge into Tables. About row height @xpenatan: You can't calculcate a guaranted row height for the current frame before the full row (all cells) have been submitted. It's just not possible since any cell can extend the row height. Possible workaround are:
-> If you want to discuss the topic of Tables Row Height please open a dedicated issue for it. About horizontal alignment of headers
@eRabbit0 I had those exact flags during earlier work but removed them. We can only align 1 item over 1 line, anything else won't work and proper multi-item multi-line alignment wouldn't be a table feature per se. If we offer the option only for Headers, we make it harder for people to use the option with custom headers (multi-item or multi-lines, say the user wants to have a checkbox before the TableHeader call). That said, if we restrict it to single-line header and rely on temporal coherency I could re-enable the feature. Selectable() are a bit tricky here they were initially designed to cover half of the spacing between each others to avoid leaving any visual and mouse-hover gaps, but we can solve this. TableHeader()+IsItemHovered() should work I am not sure what you are asking. |
@marinjurjevic Please post this in a new issue as instructed above and delete message here, thank you! |
Recent changes to Tables:
Before shipping 1.80 the things I would like to solve are:
|
BREAKING CHANGES (NOV 2020)Everyone, I have pushed a few "major" breaking changes yesterday. I think they may be the final batch of breaking changes going in before going to master.
Sorry for the disturbance, hopefully this is for the good! |
Is the plan to obsolete the old Column API completely or are both approaches sharing the same set of flags... |
@frink the public columns API have no flags, only internal api has, see: |
I stand corrected. I misread your post on #125 this morning. |
Hello, After some internal monologue, I have undid this specific change mentioned two days ago:
Effectively nuked top-most commit 694f6cb from tables/ history. |
I realized that one essential feature of tables was not demonstrated anywhere in the demo, and poorly documented. Tables with the same identifier share all settings (width, visibility, order, etc) This is also de-facto a sensible workaround for creating contents that span an entire row (aka #3565) + ref #2136. |
BREAKING CHANGES (DEC 2020)
INCOMING RELEASETables have been merged into master today. |
Hi, is there going to be a summary of the tables branch (and I guess it might be the new thread you mentioned in the above comment)? |
Yes I'm going to open a new threads when ready, but the top posts here + demo are giving a good summary already. I found one niggle with sizing policy which I want to settle before tagging 1.80 hence the delay. Related to table, since last week:
BREAKING CHANGES (DEC 2020)
|
BREAKING CHANGES (DEC 2020)To support #3605 I made a little change to the default value and handling of the
The new meaning of Effectively this is unlikely to break much code as |
Just a positive note. Tables work well and are very functional, I especially like fixed row and column headers and fast display of even large tables. The architecture is clean and understandable. During the last months, judging by GitHub updates, the development in this area has been fast, now I am looking forward to the next stable version to test. Thank you:) |
BREAKING CHANGES (JAN 2021)I know the joke is getting old now :) but last month while looking at a totally unrelated thing (#1149) I came up with a few realization and situations where the sizing policies were inadequate, which eventually got me into a larger/deeper exploration of various sizing-related ideas and a mild refactor of the exposed policilies. As a result I've again broken the API (but only in a minor way and only if you specified a table sizing policy explicitly). TL;DR: If you are using Tables I would appreciate if you could update to latest to make sure everything's alright. And then hopefully we can tag 1.80.... Here's a run down of table sizing policies: // Sizing Policy (read above for defaults)
ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width.
ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible.
ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths.
ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overriden by TableSetupColumn(). New section in the demo: e.g. a use of There are many details under the hood which I don't have the energy to explain right now (most you don't really need to know until you hit very specific use cases) but added variety of comments and added myself more notes. Also, previously default table policy in an auto-resizing window (e.g. a tooltip) would lead to stretching columns with same weight which was wholly inadequate, we're now using One last thing I'd like to do is clarify per-column Auto vs Fixed policies and the effect of some of the internals unexposed api to override current width (not default width). Bonus fact: Our regression tests are now covering 97% lines of imgui_tables.cpp, aka 61 uncovered and many are asserts/error handlers. |
Quick test Dear ImGui, 9.1.2021 docking branch, commit tag 70703da I switched to use this version, all started working quickly. Notes:
Based on the quick test, all good with the newest table code. |
Note that the old
Post above says:
Yes I think we'll support it eventually.
|
Thank you for help and advice. When I work with ImGui, it feels like it is
on the verge of break though to much wider use. Recent docking and table
features extended the application area to office, database and data
manipulation. It is good, fast and clean, and provides "game like"
immediate response to the end user. It is open source, can be integrated
easily to any application project and be adopted to run on practically any
modern hardware. And most of all, it is ready and reliable. Many thanks,
tables are great!
…On Mon, Jan 11, 2021 at 1:24 PM omar ***@***.***> wrote:
@iocafe <https://github.com/iocafe>
ImGuiTableFlags_SizingPolicyStretchX -> ImGuiTableFlags_SizingStretchProp
Note that the old ImGuiTableFlags_SizingPolicyStretchX is ==
ImGuiTableFlags_SizingStretchSame. ImGuiTableFlags_SizingStretchProp is a
slightly different behavior.
TableGetHoveredColumn() now internal, included "imgui_internal.h". (I need
to look for better way to do this some point).
Post above says:
"Removed TableGetHoveredColumn() in favor of using TableGetColumnFlags() &
ImGuiTableColumnFlags_IsHovered."
I hit to 64 columns limit but decided to live with this for now. Support
to more columns maybe in future, the original code has preparation for more
columns (typedef ImGuiTableColumnIdx and draw channels). I hope for a real
tested version sometime in the future (much preferred over my own quick and
dirty patches).
Yes I think we'll support it eventually.
- The ImU64 mask will be changed to something like ImBitArray or
ImBitVector. Neither are currently satisfactory as one would require a
worst-case limit and the other would heap-allocate. Instead we will
allocate everything we need for the 4 masks inside the RawData single-alloc
and call the lower-level ImBitArrayXXX functions directly. The MAIN purpose
of all those packed masks is to avoid touching unnecessary cache-lines for
non-visible columns (otherwise we could naively move all those flags as
bool stored into each columns, but that would defeat their purpose).
- I would like to move ImDrawSplitter and some other transient data
out of ImGuiTable and into a structure shared by all tables for a given
recursion level, that will alleviate the recurrent cost of high-columns
tables.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#2957 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/ANCVOSGWHRVRE7EO6NPYHZ3SZM64NANCNFSM4KBOCHAQ>
.
|
… prevent columns output flags from having ImGuiTableColumnFlags_IsHovered set. (#2957)
… prevent columns output flags from having ImGuiTableColumnFlags_IsHovered set. (ocornut#2957)
… prevent columns output flags from having ImGuiTableColumnFlags_IsHovered set. (ocornut#2957)
…ledHeader, ImGui::TableHeadersAngledRow(), style.TableAngledHeadersAngle. (#2957)
TABLES ARE NOW MERGED, MOVING THIS TO #3740
I have pushed an experimental
tables
branch:https://github.com/ocornut/imgui/tree/tables
Providing a long awaited full-featured replacement to the old "Columns" API (#125).
I have been working on this for an embarassingly looong time.. What seemingly started as "let's refactor columns" became a multi-month thing with many rewrites/iterations. A large portion of this work been sponsored by Blizzard Entertainment. Several internal changes pushed to 1.71-1.74 were in preparation for this as I often try to have changes trickle down to master whenever possible to reduce complication of branching.
Please read <3
(this post will be occasionally updated)
Basic Usage:
#2957 (comment)
TODO List:
#2957 (comment)
WIP API breaking changes Sept 2020
#2957 (comment)
Question? Feedback? Bug report? Feature request? Please create a NEW ISSUE!
Status
Looking for early testers
Git Flow
tables
(https://github.com/ocornut/imgui/tree/tables).Features
Some screenshots
The text was updated successfully, but these errors were encountered: