Tables: added ImGuiTableFlags_HighlightHoveredColumn.

This commit is contained in:
ocornut
2023-10-12 14:43:34 +02:00
parent be1311cfc1
commit 9f851ebfe4
5 changed files with 52 additions and 24 deletions

View File

@ -346,7 +346,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
flags = TableFixFlags(flags, outer_window);
// Initialize
const int instance_no = (table->LastFrameActive != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
const int previous_frame_active = table->LastFrameActive;
const int instance_no = (previous_frame_active != g.FrameCount) ? 0 : table->InstanceCurrent + 1;
table->ID = id;
table->Flags = flags;
table->LastFrameActive = g.FrameCount;
@ -478,6 +479,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->FreezeColumnsRequest = table->FreezeColumnsCount = 0;
table->IsUnfrozenRows = true;
table->DeclColumnsCount = 0;
if (previous_frame_active + 1 < g.FrameCount)
table->IsActiveIdInTable = false;
// Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
@ -974,8 +977,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
table_instance->HoveredRowLast = table_instance->HoveredRowNext;
table_instance->HoveredRowNext = -1;
table->HoveredColumnBody = -1;
table->HoveredColumnBorder = -1;
table->HoveredColumnBody = 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_instance->LastOuterHeight));
const ImGuiID backup_active_id = g.ActiveId;
g.ActiveId = 0;
@ -1122,13 +1124,13 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// because of using _WidthAuto/_WidthStretch). This will hide the resizing option from the context menu.
const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x);
if (is_hovering_table && table->HoveredColumnBody == -1)
{
if (g.IO.MousePos.x >= unused_x1)
table->HoveredColumnBody = (ImGuiTableColumnIdx)table->ColumnsCount;
}
if (has_resizable == false && (table->Flags & ImGuiTableFlags_Resizable))
table->Flags &= ~ImGuiTableFlags_Resizable;
table->IsActiveIdAliveBeforeTable = (g.ActiveIdIsAlive != 0);
// [Part 8] Lock actual OuterRect/WorkRect right-most position.
// This is done late to handle the case of fixed-columns tables not claiming more widths that they need.
// Because of this we are careful with uses of WorkRect and InnerClipRect before this point.
@ -1161,6 +1163,14 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->IsLayoutLocked = true;
table->IsUsingHeaders = false;
// Highlight header
table->HighlightColumnHeader = -1;
if (table->IsContextPopupOpen && table->ContextPopupColumn != -1 && table->InstanceInteracted == table->InstanceCurrent)
table->HighlightColumnHeader = table->ContextPopupColumn;
else if ((table->Flags & ImGuiTableFlags_HighlightHoveredColumn) && table->HoveredColumnBody != -1 && table->HoveredColumnBody != table->ColumnsCount && table->HoveredColumnBorder == -1)
if (g.ActiveId == 0 || (table->IsActiveIdInTable || g.DragDropActive))
table->HighlightColumnHeader = table->HoveredColumnBody;
// [Part 11] Context menu
if (TableBeginContextMenuPopup(table))
{
@ -1382,6 +1392,8 @@ void ImGui::EndTable()
table->ResizedColumnNextWidth = new_width;
}
table->IsActiveIdInTable = (g.ActiveIdIsAlive != 0 && table->IsActiveIdAliveBeforeTable == false);
// Pop from id stack
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table_instance->TableInstanceID, "Mismatching PushID/PopID!");
IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= temp_data->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
@ -2301,6 +2313,7 @@ void ImGui::TableUpdateColumnsWeightFromWidth(ImGuiTable* table)
// - TablePopBackgroundChannel() [Internal]
// - TableSetupDrawChannels() [Internal]
// - TableMergeDrawChannels() [Internal]
// - TableGetColumnBorderCol() [Internal]
// - TableDrawBorders() [Internal]
//-------------------------------------------------------------------------
@ -2584,6 +2597,18 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
}
}
static ImU32 TableGetColumnBorderCol(ImGuiTable* table, int order_n, int column_n)
{
const bool is_hovered = (table->HoveredColumnBorder == column_n);
const bool is_resized = (table->ResizedColumn == column_n) && (table->InstanceInteracted == table->InstanceCurrent);
const bool is_frozen_separator = (table->FreezeColumnsCount == order_n + 1);
if (is_resized || is_hovered)
return ImGui::GetColorU32(is_resized ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered);
if (is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)))
return table->BorderColorStrong;
return table->BorderColorLight;
}
// FIXME-TABLE: This is a mess, need to redesign how we render borders (as some are also done in TableEndRow)
void ImGui::TableDrawBorders(ImGuiTable* table)
{
@ -2626,21 +2651,9 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
// Draw in outer window so right-most column won't be clipped
// Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling.
ImU32 col;
float draw_y2;
if (is_hovered || is_resized || is_frozen_separator)
{
draw_y2 = draw_y2_body;
col = is_resized ? GetColorU32(ImGuiCol_SeparatorActive) : is_hovered ? GetColorU32(ImGuiCol_SeparatorHovered) : table->BorderColorStrong;
}
else
{
draw_y2 = (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) ? draw_y2_head : draw_y2_body;
col = (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) ? table->BorderColorStrong : table->BorderColorLight;
}
float draw_y2 = (is_hovered || is_resized || is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) == 0) ? draw_y2_body : draw_y2_head;
if (draw_y2 > draw_y1)
inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), col, border_size);
inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size);
}
}
@ -2994,7 +3007,6 @@ void ImGui::TableHeader(const char* label)
column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x);
// Keep header highlighted when context menu is open.
const bool selected = (table->IsContextPopupOpen && table->ContextPopupColumn == column_n && table->InstanceInteracted == table->InstanceCurrent);
ImGuiID id = window->GetID(label);
ImRect bb(cell_r.Min.x, cell_r.Min.y, cell_r.Max.x, ImMax(cell_r.Max.y, cell_r.Min.y + label_height + g.Style.CellPadding.y * 2.0f));
ItemSize(ImVec2(0.0f, label_height)); // Don't declare unclipped width, it'll be fed ContentMaxPosHeadersIdeal
@ -3005,9 +3017,10 @@ void ImGui::TableHeader(const char* label)
//GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 0, 0, 255)); // [DEBUG]
// Using AllowOverlap mode because we cover the whole cell, and we want user to be able to submit subsequent items.
const bool highlight = (table->HighlightColumnHeader == column_n);
bool hovered, held;
bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_AllowOverlap);
if (held || hovered || selected)
if (held || hovered || highlight)
{
const ImU32 col = GetColorU32(held ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
//RenderFrame(bb.Min, bb.Max, col, false, 0.0f);