Browse Source

Tables: Angled Headers: fixed TableAngledHeadersRow() incorrect background fill drawn too low. Fixed row geometry with non-small values of CellPadding. (#6917)

ocornut 1 year ago
parent
commit
6655ab2e43
3 changed files with 28 additions and 12 deletions
  1. 4 1
      docs/CHANGELOG.txt
  2. 2 2
      imgui_internal.h
  3. 22 9
      imgui_tables.cpp

+ 4 - 1
docs/CHANGELOG.txt

@@ -43,6 +43,9 @@ Breaking changes:
 
 
 Other changes:
 Other changes:
 
 
+- Tables: Angled headers: fixed TableAngledHeadersRow() incorrect background fill
+  drawn too low, particularly visible with tables that have no scrolling. (#6917)
+
 
 
 -----------------------------------------------------------------------
 -----------------------------------------------------------------------
  VERSION 1.90.3 (Released 2024-02-14)
  VERSION 1.90.3 (Released 2024-02-14)
@@ -355,7 +358,7 @@ Other changes:
     with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually.
     with ImGuiDragDropFlags_AcceptNoPreviewTooltip and submitting a tooltip manually.
 - Tables:
 - Tables:
   - Added angled headers support. You need to set ImGuiTableColumnFlags_AngledHeader on selected
   - Added angled headers support. You need to set ImGuiTableColumnFlags_AngledHeader on selected
-    columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option.
+    columns and call TableAngledHeadersRow(). Added style.TableAngledHeadersAngle style option. (#6917)
   - Added ImGuiTableFlags_HighlightHoveredColumn flag, currently highlighting column header.
   - Added ImGuiTableFlags_HighlightHoveredColumn flag, currently highlighting column header.
   - Fixed an edge-case when no columns are visible + table scrollbar is visible + user
   - Fixed an edge-case when no columns are visible + table scrollbar is visible + user
     code is always testing return value of TableSetColumnIndex() to coarse clip. With an active
     code is always testing return value of TableSetColumnIndex() to coarse clip. With an active

+ 2 - 2
imgui_internal.h

@@ -2916,7 +2916,7 @@ struct IMGUI_API ImGuiTableTempData
 {
 {
     int                         TableIndex;                 // Index in g.Tables.Buf[] pool
     int                         TableIndex;                 // Index in g.Tables.Buf[] pool
     float                       LastTimeActive;             // Last timestamp this structure was used
     float                       LastTimeActive;             // Last timestamp this structure was used
-    float                       AngledheadersExtraWidth;    // Used in EndTable()
+    float                       AngledHeadersExtraWidth;    // Used in EndTable()
 
 
     ImVec2                      UserOuterSize;              // outer_size.x passed to BeginTable()
     ImVec2                      UserOuterSize;              // outer_size.x passed to BeginTable()
     ImDrawListSplitter          DrawSplitter;
     ImDrawListSplitter          DrawSplitter;
@@ -3300,7 +3300,7 @@ namespace ImGui
     IMGUI_API float         TableGetHeaderAngledMaxLabelWidth();
     IMGUI_API float         TableGetHeaderAngledMaxLabelWidth();
     IMGUI_API void          TablePushBackgroundChannel();
     IMGUI_API void          TablePushBackgroundChannel();
     IMGUI_API void          TablePopBackgroundChannel();
     IMGUI_API void          TablePopBackgroundChannel();
-    IMGUI_API void          TableAngledHeadersRowEx(float angle, float label_width = 0.0f);
+    IMGUI_API void          TableAngledHeadersRowEx(float angle, float max_label_width = 0.0f);
 
 
     // Tables: Internals
     // Tables: Internals
     inline    ImGuiTable*   GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
     inline    ImGuiTable*   GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }

+ 22 - 9
imgui_tables.cpp

@@ -498,7 +498,7 @@ bool    ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
     table->DeclColumnsCount = table->AngledHeadersCount = 0;
     table->DeclColumnsCount = table->AngledHeadersCount = 0;
     if (previous_frame_active + 1 < g.FrameCount)
     if (previous_frame_active + 1 < g.FrameCount)
         table->IsActiveIdInTable = false;
         table->IsActiveIdInTable = false;
-    temp_data->AngledheadersExtraWidth = 0.0f;
+    temp_data->AngledHeadersExtraWidth = 0.0f;
 
 
     // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
     // Using opaque colors facilitate overlapping lines of the grid, otherwise we'd need to improve TableDrawBorders()
     table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
     table->BorderColorStrong = GetColorU32(ImGuiCol_TableBorderStrong);
@@ -1344,7 +1344,7 @@ void    ImGui::EndTable()
             max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
             max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
         if (table->ResizedColumn != -1)
         if (table->ResizedColumn != -1)
             max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
             max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
-        table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledheadersExtraWidth;
+        table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth;
     }
     }
 
 
     // Pop clipping rect
     // Pop clipping rect
@@ -1462,7 +1462,7 @@ void    ImGui::EndTable()
     }
     }
     else if (temp_data->UserOuterSize.x <= 0.0f)
     else if (temp_data->UserOuterSize.x <= 0.0f)
     {
     {
-        const float decoration_size = table->TempData->AngledheadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f);
+        const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f);
         outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x);
         outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x);
         outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
         outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
     }
     }
@@ -1567,6 +1567,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
     }
     }
 
 
     // Store name (append with zero-terminator in contiguous buffer)
     // Store name (append with zero-terminator in contiguous buffer)
+    // FIXME: If we recorded the number of \n in names we could compute header row height
     column->NameOffset = -1;
     column->NameOffset = -1;
     if (label != NULL && label[0] != 0)
     if (label != NULL && label[0] != 0)
     {
     {
@@ -2154,6 +2155,8 @@ void ImGui::TableEndCell(ImGuiTable* table)
 // - TableSetColumnWidthAutoAll() [Internal]
 // - TableSetColumnWidthAutoAll() [Internal]
 // - TableUpdateColumnsWeightFromWidth() [Internal]
 // - TableUpdateColumnsWeightFromWidth() [Internal]
 //-------------------------------------------------------------------------
 //-------------------------------------------------------------------------
+// Note that actual columns widths are computed in TableUpdateLayout().
+//-------------------------------------------------------------------------
 
 
 // Maximum column content width given current layout. Use column->MinX so this value on a per-column basis.
 // Maximum column content width given current layout. Use column->MinX so this value on a per-column basis.
 float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
 float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
@@ -2927,6 +2930,7 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
 // [SECTION] Tables: Headers
 // [SECTION] Tables: Headers
 //-------------------------------------------------------------------------
 //-------------------------------------------------------------------------
 // - TableGetHeaderRowHeight() [Internal]
 // - TableGetHeaderRowHeight() [Internal]
+// - TableGetHeaderAngledMaxLabelWidth() [Internal]
 // - TableHeadersRow()
 // - TableHeadersRow()
 // - TableHeader()
 // - TableHeader()
 // - TableAngledHeadersRow()
 // - TableAngledHeadersRow()
@@ -3180,25 +3184,25 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
 
 
     // Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow()
     // Calculate our base metrics and set angled headers data _before_ the first call to TableNextRow()
     // FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other.
     // FIXME-STYLE: Would it be better for user to submit 'max_label_width' or 'row_height' ? One can be derived from the other.
-    const float header_height = table->RowCellPaddingY * 2.0f + g.FontSize;
+    const float header_height = g.FontSize + g.Style.CellPadding.x * 2.0f;
     const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y);
     const float row_height = ImFabs(ImRotate(ImVec2(max_label_width, flip_label ? +header_height : -header_height), cos_a, sin_a).y);
-    const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a);
     table->AngledHeadersHeight = row_height;
     table->AngledHeadersHeight = row_height;
     table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f;
     table->AngledHeadersSlope = (sin_a != 0.0f) ? (cos_a / sin_a) : 0.0f;
+    const ImVec2 header_angled_vector = unit_right * (row_height / -sin_a); // vector from bottom-left to top-left, and from bottom-right to top-right
 
 
     // Declare row, override and draw our own background
     // Declare row, override and draw our own background
     TableNextRow(ImGuiTableRowFlags_Headers, row_height);
     TableNextRow(ImGuiTableRowFlags_Headers, row_height);
     TableNextColumn();
     TableNextColumn();
+    const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, table->RowPosY2);
     table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0);
     table->DrawSplitter->SetCurrentChannel(draw_list, TABLE_DRAW_CHANNEL_BG0);
     float clip_rect_min_x = table->BgClipRect.Min.x;
     float clip_rect_min_x = table->BgClipRect.Min.x;
     if (table->FreezeColumnsCount > 0)
     if (table->FreezeColumnsCount > 0)
         clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX);
         clip_rect_min_x = ImMax(clip_rect_min_x, table->Columns[table->FreezeColumnsCount - 1].MaxX);
     TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel
     TableSetBgColor(ImGuiTableBgTarget_RowBg0, 0); // Cancel
     PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns
     PushClipRect(table->BgClipRect.Min, table->BgClipRect.Max, false); // Span all columns
-    draw_list->AddRectFilled(table->BgClipRect.Min, table->BgClipRect.Max, GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
+    draw_list->AddRectFilled(ImVec2(table->BgClipRect.Min.x, row_r.Min.y), ImVec2(table->BgClipRect.Max.x, row_r.Max.y), GetColorU32(ImGuiCol_TableHeaderBg, 0.25f)); // FIXME-STYLE: Change row background with an arbitrary color.
     PushClipRect(ImVec2(clip_rect_min_x, table->BgClipRect.Min.y), table->BgClipRect.Max, true); // Span all columns
     PushClipRect(ImVec2(clip_rect_min_x, table->BgClipRect.Min.y), table->BgClipRect.Max, true); // Span all columns
 
 
-    const ImRect row_r(table->WorkRect.Min.x, table->BgClipRect.Min.y, table->WorkRect.Max.x, window->DC.CursorPos.y + row_height);
     const ImGuiID row_id = GetID("##AngledHeaders");
     const ImGuiID row_id = GetID("##AngledHeaders");
     ButtonBehavior(row_r, row_id, NULL, NULL);
     ButtonBehavior(row_r, row_id, NULL, NULL);
     KeepAliveID(row_id);
     KeepAliveID(row_id);
@@ -3209,6 +3213,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
         if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
         if (table_instance->HoveredRowLast == 0 && table->HoveredColumnBorder == -1 && (g.ActiveId == 0 || g.ActiveId == row_id || (table->IsActiveIdInTable || g.DragDropActive)))
             highlight_column_n = table->HoveredColumnBody;
             highlight_column_n = table->HoveredColumnBody;
 
 
+    // Draw background and labels in first pass, then all borders.
     float max_x = 0.0f;
     float max_x = 0.0f;
     for (int pass = 0; pass < 2; pass++)
     for (int pass = 0; pass < 2; pass++)
         for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
         for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
@@ -3243,13 +3248,21 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
                 ImVec2 label_off = ImVec2(flip_label ? ImMax(0.0f, max_label_width - label_size.x - table->CellPaddingX) : table->CellPaddingX, table->RowCellPaddingY);
                 ImVec2 label_off = ImVec2(flip_label ? ImMax(0.0f, max_label_width - label_size.x - table->CellPaddingX) : table->CellPaddingX, table->RowCellPaddingY);
                 int vtx_idx_begin = draw_list->_VtxCurrentIdx;
                 int vtx_idx_begin = draw_list->_VtxCurrentIdx;
                 RenderTextEllipsis(draw_list, label_r.Min + label_off, label_r.Max, label_r.Max.x, label_r.Max.x, label_name, NULL, &label_size);
                 RenderTextEllipsis(draw_list, label_r.Min + label_off, label_r.Max, label_r.Max.x, label_r.Max.x, label_name, NULL, &label_size);
-                //if (g.IO.KeyShift) { draw_list->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f); }
                 int vtx_idx_end = draw_list->_VtxCurrentIdx;
                 int vtx_idx_end = draw_list->_VtxCurrentIdx;
 
 
                 // Rotate and offset label
                 // Rotate and offset label
                 ImVec2 pivot_in = label_r.GetBL();
                 ImVec2 pivot_in = label_r.GetBL();
                 ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y) + (flip_label ? (unit_right * clip_width) : ImVec2(header_height, 0.0f));
                 ImVec2 pivot_out = ImVec2(column->WorkMinX, row_r.Max.y) + (flip_label ? (unit_right * clip_width) : ImVec2(header_height, 0.0f));
                 ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset
                 ShadeVertsTransformPos(draw_list, vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset
+
+                // Debug draw
+                /*if (g.IO.KeyShift)
+                {
+                    vtx_idx_begin = GetForegroundDrawList()->_VtxCurrentIdx;
+                    GetForegroundDrawList()->AddRect(label_r.Min, label_r.Max, IM_COL32(0, 255, 0, 255), 0.0f, 0, 2.0f);
+                    vtx_idx_end = GetForegroundDrawList()->_VtxCurrentIdx;
+                    ShadeVertsTransformPos(GetForegroundDrawList(), vtx_idx_begin, vtx_idx_end, pivot_in, label_cos_a, label_sin_a, pivot_out); // Rotate and offset
+                }*/
             }
             }
             if (pass == 1)
             if (pass == 1)
             {
             {
@@ -3259,7 +3272,7 @@ void ImGui::TableAngledHeadersRowEx(float angle, float max_label_width)
         }
         }
     PopClipRect();
     PopClipRect();
     PopClipRect();
     PopClipRect();
-    table->TempData->AngledheadersExtraWidth = ImMax(0.0f, max_x - table->Columns[table->RightMostEnabledColumn].MaxX);
+    table->TempData->AngledHeadersExtraWidth = ImMax(0.0f, max_x - table->Columns[table->RightMostEnabledColumn].MaxX);
 }
 }
 
 
 //-------------------------------------------------------------------------
 //-------------------------------------------------------------------------