diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3849c5e9..b54b23b0 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -126,9 +126,10 @@ Other Changes: - TabBar: Fixed unfocused tab bar separator color (was using ImGuiCol_Tab, should use ImGuiCol_TabUnfocusedActive). - Columns: Fixed a regression from 1.71 where the right-side of the contents rectangle within each column would wrongly use a WindowPadding.x instead of ItemSpacing.x like it always did. (#125, #2666) -- Columns: Improved honoring left-most and right-most alignment with various values of ItemSpacing.x and - WindowPadding.x. In particular, the right-most edge now reaches up to the clipping rectangle while - ensuring that the right-most column clipping width matches others. (#125, #2666) +- Columns: Made the right-most edge reaches up to the clipping rectangle (removing half of WindowPadding.x + worth of asymmetrical/extraneous padding, note that there's another half that conservatively has to offset + the right-most column, otherwise it's clipping width won't match the other column). (#125, #2666) +- Columns: Improved honoring alignment with various values of ItemSpacing.x and WindowPadding.x. (#125, #2666) - Word-wrapping: Fixed overzealous word-wrapping when glyph edge lands exactly on the limit. Because of this, auto-fitting exactly unwrapped text would make it wrap. (fixes initial 1.15 commit, 78645a7d). - Scrolling: Added SetScrollHereX(), SetScrollFromPosX() for completeness. (#1580) [@kevreco] diff --git a/imconfig.h b/imconfig.h index 16f8c827..2b771298 100644 --- a/imconfig.h +++ b/imconfig.h @@ -80,6 +80,9 @@ // Use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging. //#define IM_DEBUG_BREAK IM_ASSERT(0) //#define IM_DEBUG_BREAK __debugbreak() +// Have the Item Picker break in the ItemAdd() function instead of ItemHoverable() - which is earlier in the code, will catch a few extra items, allow picking items other than Hovered one. +// This adds a small runtime cost which is why it is not enabled by default. +//#define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. /* diff --git a/imgui.cpp b/imgui.cpp index f12a75ca..113bca25 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2919,16 +2919,6 @@ void ImGui::SetHoveredID(ImGuiID id) g.HoveredIdAllowOverlap = false; if (id != 0 && g.HoveredIdPreviousFrame != id) g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; - - // [DEBUG] Item Picker tool! - // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making - // the cost of this tool near-zero. We would get slightly better call-stack if we made the test in ItemAdd() - // but that would incur a slightly higher cost and may require us to hide this feature behind a define. - if (id != 0 && id == g.DebugBreakItemId) - { - IM_DEBUG_BREAK(); - g.DebugBreakItemId = 0; - } } ImGuiID ImGui::GetHoveredID() @@ -3042,6 +3032,15 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); + + // [DEBUG] Item Picker tool, when enabling the "extended" version we perform the check in ItemAdd() +#ifdef IMGUI_DEBUG_TOOL_ITEM_PICKER_EX + if (id == g.DebugItemPickerBreakID) + { + IM_DEBUG_BREAK(); + g.DebugItemPickerBreakID = 0; + } +#endif } window->DC.LastItemId = id; @@ -3130,6 +3129,17 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) return false; SetHoveredID(id); + + // [DEBUG] Item Picker tool! + // We perform the check here because SetHoveredID() is not frequently called (1~ time a frame), making + // the cost of this tool near-zero. We can get slightly better call-stack and support picking non-hovered + // items if we perform the test in ItemAdd(), but that would incur a small runtime cost. + // #define IMGUI_DEBUG_TOOL_ITEM_PICKER_EX in imconfig.h if you want this check to also be performed in ItemAdd(). + if (g.DebugItemPickerActive && g.HoveredIdPreviousFrame == id) + GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(255, 255, 0, 255)); + if (g.DebugItemPickerBreakID == id) + IM_DEBUG_BREAK(); + return true; } @@ -3998,6 +4008,27 @@ void ImGui::NewFrame() g.BeginPopupStack.resize(0); ClosePopupsOverWindow(g.NavWindow, false); + // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visually select an item and break into its call-stack. + g.DebugItemPickerBreakID = 0; + if (g.DebugItemPickerActive) + { + const ImGuiID hovered_id = g.HoveredIdPreviousFrame; + ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); + if (ImGui::IsKeyPressedMap(ImGuiKey_Escape)) + g.DebugItemPickerActive = false; + if (ImGui::IsMouseClicked(0) && hovered_id) + { + g.DebugItemPickerBreakID = hovered_id; + g.DebugItemPickerActive = false; + } + ImGui::SetNextWindowBgAlpha(0.60f); + ImGui::BeginTooltip(); + ImGui::Text("HoveredId: 0x%08X", hovered_id); + ImGui::Text("Press ESC to abort picking."); + ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); + ImGui::EndTooltip(); + } + // Docking DockContextUpdateDocking(&g); @@ -14581,27 +14612,9 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (ImGui::TreeNode("Tools")) { - static bool picking_enabled = false; + // The Item Picker tool is super useful to visually select an item and break into the call-stack of where it was submitted. if (ImGui::Button("Item Picker..")) - picking_enabled = true; - if (picking_enabled) - { - const ImGuiID hovered_id = g.HoveredIdPreviousFrame; - ImGui::SetMouseCursor(ImGuiMouseCursor_Hand); - if (ImGui::IsKeyPressedMap(ImGuiKey_Escape)) - picking_enabled = false; - if (ImGui::IsMouseClicked(0) && hovered_id) - { - g.DebugBreakItemId = hovered_id; - picking_enabled = false; - } - ImGui::SetNextWindowBgAlpha(0.5f); - ImGui::BeginTooltip(); - ImGui::Text("HoveredId: 0x%08X", hovered_id); - ImGui::Text("Press ESC to abort picking."); - ImGui::TextColored(GetStyleColorVec4(hovered_id ? ImGuiCol_Text : ImGuiCol_TextDisabled), "Click to break in debugger!"); - ImGui::EndTooltip(); - } + ImGui::DebugStartItemPicker(); ImGui::Checkbox("Show windows begin order", &show_windows_begin_order); ImGui::Checkbox("Show windows rectangles", &show_windows_rects); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d1937edc..e9fa90fb 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2648,11 +2648,16 @@ static void ShowDemoWindowColumns() // NB: Future columns API should allow automatic horizontal borders. static bool h_borders = true; static bool v_borders = true; + static int columns_count = 4; + const int lines_count = 3; + ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8); + ImGui::DragInt("##columns_count", &columns_count, 0.1f, 1, 10, "%d columns"); + ImGui::SameLine(); ImGui::Checkbox("horizontal", &h_borders); ImGui::SameLine(); ImGui::Checkbox("vertical", &v_borders); - ImGui::Columns(4, NULL, v_borders); - for (int i = 0; i < 4 * 3; i++) + ImGui::Columns(columns_count, NULL, v_borders); + for (int i = 0; i < columns_count * lines_count; i++) { if (h_borders && ImGui::GetColumnIndex() == 0) ImGui::Separator(); diff --git a/imgui_internal.h b/imgui_internal.h index aba530ec..da83467d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1179,7 +1179,8 @@ struct ImGuiContext int LogDepthToExpandDefault; // Default/stored value for LogDepthMaxExpand if not specified in the LogXXX function call. // Debug Tools - ImGuiID DebugBreakItemId; + bool DebugItemPickerActive; + ImGuiID DebugItemPickerBreakID; // Will call IM_DEBUG_BREAK() when encountering this id // Misc float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds. @@ -1314,7 +1315,8 @@ struct ImGuiContext LogDepthRef = 0; LogDepthToExpand = LogDepthToExpandDefault = 2; - DebugBreakItemId = 0; + DebugItemPickerActive = false; + DebugItemPickerBreakID = 0; memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame)); FramerateSecPerFrameIdx = 0; @@ -1889,6 +1891,9 @@ namespace ImGui IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); IMGUI_API void ShadeVertsLinearUV(ImDrawList* draw_list, int vert_start_idx, int vert_end_idx, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); + // Debug Tools + inline void DebugStartItemPicker() { GImGui->DebugItemPickerActive = true; } + } // namespace ImGui // ImFontAtlas internals diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 0aede3b0..228c9ac2 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7355,6 +7355,8 @@ void ImGui::PushColumnsBackground() { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiColumns* columns = window->DC.CurrentColumns; + if (columns->Count == 1) + return; window->DrawList->ChannelsSetCurrent(0); int cmd_size = window->DrawList->CmdBuffer.Size; PushClipRect(columns->HostClipRect.Min, columns->HostClipRect.Max, false); @@ -7366,6 +7368,8 @@ void ImGui::PopColumnsBackground() { ImGuiWindow* window = GetCurrentWindowRead(); ImGuiColumns* columns = window->DC.CurrentColumns; + if (columns->Count == 1) + return; window->DrawList->ChannelsSetCurrent(columns->Current + 1); PopClipRect(); } @@ -7422,9 +7426,10 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect const float column_padding = g.Style.ItemSpacing.x; const float half_clip_extend_x = ImFloor(ImMax(window->WindowPadding.x * 0.5f, window->WindowBorderSize)); + const float max_1 = window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f); + const float max_2 = window->WorkRect.Max.x + half_clip_extend_x; columns->OffMinX = window->DC.Indent.x - column_padding + ImMax(column_padding - window->WindowPadding.x, 0.0f); - columns->OffMaxX = ImMin(window->WorkRect.Max.x + column_padding - ImMax(column_padding - window->WindowPadding.x, 0.0f), window->WorkRect.Max.x + half_clip_extend_x) - window->Pos.x; - columns->OffMaxX = ImMax(columns->OffMaxX, columns->OffMinX + 1.0f); + columns->OffMaxX = ImMax(ImMin(max_1, max_2) - window->Pos.x, columns->OffMinX + 1.0f); columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; // Clear data if columns count changed @@ -7461,11 +7466,12 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag PushColumnClipRect(0); } + // We don't generally store Indent.x inside ColumnsOffset because it may be manipulated by the user. float offset_0 = GetColumnOffset(columns->Current); float offset_1 = GetColumnOffset(columns->Current + 1); float width = offset_1 - offset_0; PushItemWidth(width * 0.65f); - window->DC.ColumnsOffset.x = columns->OffMinX - window->DC.Indent.x + column_padding; + window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x); window->WorkRect.Max.x = window->Pos.x + offset_1 - column_padding; } @@ -7501,7 +7507,7 @@ void ImGui::NextColumn() { // New row/line // Column 0 honor IndentX - window->DC.ColumnsOffset.x = columns->OffMinX - window->DC.Indent.x + column_padding; + window->DC.ColumnsOffset.x = ImMax(column_padding - window->WindowPadding.x, 0.0f); window->DrawList->ChannelsSetCurrent(1); columns->Current = 0; columns->LineMinY = columns->LineMaxY;