mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-23 21:09:01 +08:00
Tables: Fixed incorrect border height used for logic when resizing one of several synchronized instance of a same table ID, when instances have a different height. (#3955, #3565)
This commit is contained in:
parent
6315716f23
commit
0f14933577
@ -55,6 +55,8 @@ Other Changes:
|
||||
clipper instance. High-level languages (Lua,Rust etc.) would typically be affected. (#4822)
|
||||
- IsItemHovered(): added ImGuiHoveredFlags_NoNavOverride to disable the behavior where the
|
||||
return value is overriden by focus when gamepad/keyboard navigation is active.
|
||||
- Tables: Fixed incorrect border height used for logic when resizing one of several synchronized
|
||||
instance of a same table ID, when instances have a different height. (#3955).
|
||||
- Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate.
|
||||
- ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label.
|
||||
- Stack Tool: Added option to copy item path to clipboard. (#4631)
|
||||
|
11
imgui.cpp
11
imgui.cpp
@ -12173,19 +12173,20 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
{
|
||||
static ImRect GetTableRect(ImGuiTable* table, int rect_type, int n)
|
||||
{
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent); // Always using last submitted instance
|
||||
if (rect_type == TRT_OuterRect) { return table->OuterRect; }
|
||||
else if (rect_type == TRT_InnerRect) { return table->InnerRect; }
|
||||
else if (rect_type == TRT_WorkRect) { return table->WorkRect; }
|
||||
else if (rect_type == TRT_HostClipRect) { return table->HostClipRect; }
|
||||
else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; }
|
||||
else if (rect_type == TRT_BackgroundClipRect) { return table->BgClipRect; }
|
||||
else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); }
|
||||
else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table_instance->LastOuterHeight); }
|
||||
else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); }
|
||||
else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; }
|
||||
else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // Note: y1/y2 not always accurate
|
||||
else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); }
|
||||
else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); } // Note: y1/y2 not always accurate
|
||||
else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXFrozen, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight); }
|
||||
else if (rect_type == TRT_ColumnsContentUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y + table_instance->LastFirstRowHeight, c->ContentMaxXUnfrozen, table->InnerClipRect.Max.y); }
|
||||
IM_ASSERT(0);
|
||||
return ImRect();
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ struct ImGuiTabBar; // Storage for a tab bar
|
||||
struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
|
||||
struct ImGuiTable; // Storage for a table
|
||||
struct ImGuiTableColumn; // Storage for one column of a table
|
||||
struct ImGuiTableInstanceData; // Storage for one instance of a same table
|
||||
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
|
||||
struct ImGuiTableSettings; // Storage for a table .ini settings
|
||||
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
|
||||
@ -2290,6 +2291,15 @@ struct ImGuiTableCellData
|
||||
ImGuiTableColumnIdx Column; // Column number
|
||||
};
|
||||
|
||||
// Per-instance data that needs preserving across frames (seemingly most others do not need to be preserved aside from debug needs, does that needs they could be moved to ImGuiTableTempData ?)
|
||||
struct ImGuiTableInstanceData
|
||||
{
|
||||
float LastOuterHeight; // Outer height from last frame // FIXME: multi-instance issue (#3955)
|
||||
float LastFirstRowHeight; // Height of first row from last frame // FIXME: possible multi-instance issue?
|
||||
|
||||
ImGuiTableInstanceData() { LastOuterHeight = LastFirstRowHeight = 0.0f; }
|
||||
};
|
||||
|
||||
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
|
||||
struct IMGUI_API ImGuiTable
|
||||
{
|
||||
@ -2332,8 +2342,6 @@ struct IMGUI_API ImGuiTable
|
||||
float CellPaddingY;
|
||||
float CellSpacingX1; // Spacing between non-bordered cells
|
||||
float CellSpacingX2;
|
||||
float LastOuterHeight; // Outer height from last frame
|
||||
float LastFirstRowHeight; // Height of first row from last frame
|
||||
float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details.
|
||||
float ColumnsGivenWidth; // Sum of current column width
|
||||
float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window
|
||||
@ -2353,6 +2361,8 @@ struct IMGUI_API ImGuiTable
|
||||
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
|
||||
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
|
||||
ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
|
||||
ImGuiTableInstanceData InstanceDataFirst;
|
||||
ImVector<ImGuiTableInstanceData> InstanceDataExtra; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
ImGuiTableColumnSortSpecs SortSpecsSingle;
|
||||
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
|
||||
@ -2708,6 +2718,7 @@ namespace ImGui
|
||||
IMGUI_API void TableDrawBorders(ImGuiTable* table);
|
||||
IMGUI_API void TableDrawContextMenu(ImGuiTable* table);
|
||||
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
|
||||
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
|
||||
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
|
||||
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
|
||||
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
|
||||
|
@ -361,6 +361,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
table->IsLayoutLocked = false;
|
||||
table->InnerWidth = inner_width;
|
||||
temp_data->UserOuterSize = outer_size;
|
||||
if (instance_no > 0 && table->InstanceDataExtra.Size < instance_no)
|
||||
table->InstanceDataExtra.push_back(ImGuiTableInstanceData());
|
||||
|
||||
// When not using a child window, WorkRect.Max will grow as we append contents.
|
||||
if (use_child_window)
|
||||
@ -933,9 +935,10 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
width_remaining_for_stretched_columns -= 1.0f;
|
||||
}
|
||||
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
table->HoveredColumnBody = -1;
|
||||
table->HoveredColumnBorder = -1;
|
||||
const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table->LastOuterHeight));
|
||||
const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table_instance->LastOuterHeight));
|
||||
const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0);
|
||||
|
||||
// [Part 6] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
|
||||
@ -1096,7 +1099,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
// [Part 10] Hit testing on borders
|
||||
if (table->Flags & ImGuiTableFlags_Resizable)
|
||||
TableUpdateBorders(table);
|
||||
table->LastFirstRowHeight = 0.0f;
|
||||
table_instance->LastFirstRowHeight = 0.0f;
|
||||
table->IsLayoutLocked = true;
|
||||
table->IsUsingHeaders = false;
|
||||
|
||||
@ -1141,10 +1144,11 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
|
||||
// use the final height from last frame. Because this is only affecting _interaction_ with columns, it is not
|
||||
// really problematic (whereas the actual visual will be displayed in EndTable() and using the current frame height).
|
||||
// Actual columns highlight/render will be performed in EndTable() and not be affected.
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
const float hit_half_width = TABLE_RESIZE_SEPARATOR_HALF_THICKNESS;
|
||||
const float hit_y1 = table->OuterRect.Min.y;
|
||||
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table->LastOuterHeight);
|
||||
const float hit_y2_head = hit_y1 + table->LastFirstRowHeight;
|
||||
const float hit_y2_body = ImMax(table->OuterRect.Max.y, hit_y1 + table_instance->LastOuterHeight);
|
||||
const float hit_y2_head = hit_y1 + table_instance->LastFirstRowHeight;
|
||||
|
||||
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
||||
{
|
||||
@ -1223,6 +1227,7 @@ void ImGui::EndTable()
|
||||
TableOpenContextMenu((int)table->HoveredColumnBody);
|
||||
|
||||
// Finalize table height
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize;
|
||||
inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize;
|
||||
inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos;
|
||||
@ -1233,7 +1238,7 @@ void ImGui::EndTable()
|
||||
else if (!(flags & ImGuiTableFlags_NoHostExtendY))
|
||||
table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height
|
||||
table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y);
|
||||
table->LastOuterHeight = table->OuterRect.GetHeight();
|
||||
table_instance->LastOuterHeight = table->OuterRect.GetHeight();
|
||||
|
||||
// Setup inner scrolling range
|
||||
// FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y,
|
||||
@ -1749,7 +1754,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
const bool unfreeze_rows_actual = (table->CurrentRow + 1 == table->FreezeRowsCount);
|
||||
const bool unfreeze_rows_request = (table->CurrentRow + 1 == table->FreezeRowsRequest);
|
||||
if (table->CurrentRow == 0)
|
||||
table->LastFirstRowHeight = bg_y2 - bg_y1;
|
||||
TableGetInstanceData(table, table->InstanceCurrent)->LastFirstRowHeight = bg_y2 - bg_y1;
|
||||
|
||||
const bool is_visible = (bg_y2 >= table->InnerClipRect.Min.y && bg_y1 <= table->InnerClipRect.Max.y);
|
||||
if (is_visible)
|
||||
@ -2502,10 +2507,11 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
|
||||
|
||||
// Draw inner border and resizing feedback
|
||||
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
|
||||
const float border_size = TABLE_BORDER_SIZE;
|
||||
const float draw_y1 = table->InnerRect.Min.y;
|
||||
const float draw_y2_body = table->InnerRect.Max.y;
|
||||
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1;
|
||||
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastFirstRowHeight) : draw_y1;
|
||||
if (table->Flags & ImGuiTableFlags_BordersInnerV)
|
||||
{
|
||||
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
|
||||
@ -3536,6 +3542,8 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
|
||||
GetForegroundDrawList()->AddRect(GetItemRectMin(), GetItemRectMax(), IM_COL32(255, 255, 0, 255));
|
||||
if (!open)
|
||||
return;
|
||||
if (table->InstanceCurrent > 0)
|
||||
ImGui::Text("** %d instances of same table! Some data below will refer to last instance.", table->InstanceCurrent + 1);
|
||||
bool clear_settings = SmallButton("Clear settings");
|
||||
BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
|
||||
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
|
||||
|
@ -3533,6 +3533,9 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f
|
||||
// - InputText()
|
||||
// - InputTextWithHint()
|
||||
// - InputTextMultiline()
|
||||
// - InputTextGetCharInfo() [Internal]
|
||||
// - InputTextReindexLines() [Internal]
|
||||
// - InputTextReindexLinesRange() [Internal]
|
||||
// - InputTextEx() [Internal]
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user