mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-04 07:01:04 +01:00 
			
		
		
		
	Merge branch 'master' into docking
# Conflicts: # imgui.cpp # imgui_internal.h # imgui_widgets.cpp
This commit is contained in:
		@@ -41,6 +41,8 @@ Other Changes:
 | 
			
		||||
- Columns: Fixed Selectable with SpanAllColumns flag from creating an extraneous draw command. (#125)
 | 
			
		||||
- Separator: Revert 1.70 "Declare its thickness (1.0f) to the layout" change. It's not incorrect
 | 
			
		||||
  but it breaks existing some layout patterns. Will return back to it when we expose Separator flags.
 | 
			
		||||
- Fixed InputScalar, InputScalarN, SliderScalarN, DragScalarN with non-visible label from inserting
 | 
			
		||||
  style.ItemInnerSpacing.x worth of trailing spacing.
 | 
			
		||||
- Fixed InputFloatX, SliderFloatX, DragFloatX functions erroneously reporting IsItemEdited() multiple
 | 
			
		||||
  times when the text input doesn't match the formatted output value (e.g. input "1" shows "1.000").
 | 
			
		||||
  It wasn't much of a problem because we typically use the return value instead of IsItemEdited() here.
 | 
			
		||||
@@ -48,6 +50,9 @@ Other Changes:
 | 
			
		||||
  after EndGroup(). (#2550, #1875)
 | 
			
		||||
- Fixed crash when appending with BeginMainMenuBar() more than once and no other window are showing. (#2567)
 | 
			
		||||
- Scrollbar: Very minor bounding box adjustment to cope with various border size.
 | 
			
		||||
- Style: Added style.WindowMenuButtonPosition (left/right, defaults to ImGuiDir_Left) to move the
 | 
			
		||||
  collapsing/docking button to the other side of the title bar.
 | 
			
		||||
- Style: Made window close button cross is slightly smaller.
 | 
			
		||||
- ImFontAtlas: FreeType: Added RasterizerFlags::Monochrome flag to disable font anti-aliasing. (#2545)
 | 
			
		||||
  Combine with RasterizerFlags::MonoHinting for best results.
 | 
			
		||||
- ImFontGlyphRangesBuilder: Fixed unnecessarily over-sized buffer, which incidentally was also not
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										88
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								imgui.cpp
									
									
									
									
									
								
							@@ -1161,6 +1161,7 @@ ImGuiStyle::ImGuiStyle()
 | 
			
		||||
    WindowBorderSize        = 1.0f;             // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
 | 
			
		||||
    WindowMinSize           = ImVec2(32,32);    // Minimum window size
 | 
			
		||||
    WindowTitleAlign        = ImVec2(0.0f,0.5f);// Alignment for title bar text
 | 
			
		||||
    WindowMenuButtonPosition= ImGuiDir_Left;    // Position of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left.
 | 
			
		||||
    ChildRounding           = 0.0f;             // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
 | 
			
		||||
    ChildBorderSize         = 1.0f;             // Thickness of border around child windows. Generally set to 0.0f or 1.0f. Other values not well tested.
 | 
			
		||||
    PopupRounding           = 0.0f;             // Radius of popup window corners rounding. Set to 0.0f to have rectangular child windows
 | 
			
		||||
@@ -3593,6 +3594,8 @@ void ImGui::NewFrame()
 | 
			
		||||
    IM_ASSERT(g.Style.CurveTessellationTol > 0.0f                       && "Invalid style setting!");
 | 
			
		||||
    IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f            && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)!");
 | 
			
		||||
    IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting.");
 | 
			
		||||
    IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGuiDir_Right);
 | 
			
		||||
 | 
			
		||||
    for (int n = 0; n < ImGuiKey_COUNT; n++)
 | 
			
		||||
        IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)");
 | 
			
		||||
 | 
			
		||||
@@ -5434,30 +5437,54 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Render title text, collapse button, close button
 | 
			
		||||
void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiStyle& style = g.Style;
 | 
			
		||||
    ImGuiWindowFlags flags = window->Flags;
 | 
			
		||||
 | 
			
		||||
    // Close & collapse button are on layer 1 (same as menus) and don't default focus
 | 
			
		||||
    const bool has_close_button = (p_open != NULL);
 | 
			
		||||
    const bool has_collapse_button = !(flags & ImGuiWindowFlags_NoCollapse);
 | 
			
		||||
 | 
			
		||||
    // Close & collapse button are on the Menu NavLayer and don't default focus (unless there's nothing else on that layer)
 | 
			
		||||
    const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
 | 
			
		||||
    window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus;
 | 
			
		||||
    window->DC.NavLayerCurrent = ImGuiNavLayer_Menu;
 | 
			
		||||
    window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Menu);
 | 
			
		||||
 | 
			
		||||
    // Collapse button
 | 
			
		||||
    if (!(flags & ImGuiWindowFlags_NoCollapse))
 | 
			
		||||
        if (CollapseButton(window->GetID("#COLLAPSE"), window->Pos, NULL))
 | 
			
		||||
            window->WantCollapseToggle = true; // Defer collapsing to next frame as we are too far in the Begin() function
 | 
			
		||||
    // Layout buttons
 | 
			
		||||
    // FIXME: Would be nice to generalize the subtleties expressed here into reusable code.
 | 
			
		||||
    float pad_l = style.FramePadding.x;
 | 
			
		||||
    float pad_r = style.FramePadding.x;
 | 
			
		||||
    float button_sz = g.FontSize;
 | 
			
		||||
    ImVec2 close_button_pos;
 | 
			
		||||
    ImVec2 collapse_button_pos;
 | 
			
		||||
    if (has_close_button)
 | 
			
		||||
    {
 | 
			
		||||
        pad_r += button_sz;
 | 
			
		||||
        close_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y);
 | 
			
		||||
    }
 | 
			
		||||
    if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Right)
 | 
			
		||||
    {
 | 
			
		||||
        pad_r += button_sz;
 | 
			
		||||
        collapse_button_pos = ImVec2(title_bar_rect.Max.x - pad_r - style.FramePadding.x, title_bar_rect.Min.y);
 | 
			
		||||
    }
 | 
			
		||||
    if (has_collapse_button && style.WindowMenuButtonPosition == ImGuiDir_Left)
 | 
			
		||||
    {
 | 
			
		||||
        collapse_button_pos = ImVec2(title_bar_rect.Min.x + pad_l - style.FramePadding.x, title_bar_rect.Min.y);
 | 
			
		||||
        pad_l += button_sz;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Collapse button (submitting first so it gets priority when choosing a navigation init fallback)
 | 
			
		||||
    if (has_collapse_button)
 | 
			
		||||
        if (CollapseButton(window->GetID("#COLLAPSE"), collapse_button_pos, NULL))
 | 
			
		||||
            window->WantCollapseToggle = true; // Defer actual collapsing to next frame as we are too far in the Begin() function
 | 
			
		||||
 | 
			
		||||
    // Close button
 | 
			
		||||
    if (p_open != NULL)
 | 
			
		||||
    {
 | 
			
		||||
        const float rad = g.FontSize * 0.5f;
 | 
			
		||||
        if (CloseButton(window->GetID("#CLOSE"), ImVec2(window->Pos.x + window->Size.x - style.FramePadding.x - rad, window->Pos.y + style.FramePadding.y + rad), rad + 1))
 | 
			
		||||
    if (has_close_button)
 | 
			
		||||
        if (CloseButton(window->GetID("#CLOSE"), close_button_pos))
 | 
			
		||||
            *p_open = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    window->DC.NavLayerCurrent = ImGuiNavLayer_Main;
 | 
			
		||||
    window->DC.NavLayerCurrentMask = (1 << ImGuiNavLayer_Main);
 | 
			
		||||
@@ -5466,23 +5493,32 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
 | 
			
		||||
    // Title bar text (with: horizontal alignment, avoiding collapse/close button, optional "unsaved document" marker)
 | 
			
		||||
    // FIXME: Refactor text alignment facilities along with RenderText helpers, this is too much code..
 | 
			
		||||
    const char* UNSAVED_DOCUMENT_MARKER = "*";
 | 
			
		||||
    float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
 | 
			
		||||
    ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
 | 
			
		||||
    ImRect text_r = title_bar_rect;
 | 
			
		||||
    float pad_left = (flags & ImGuiWindowFlags_NoCollapse) ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
 | 
			
		||||
    float pad_right = (p_open == NULL)                     ? style.FramePadding.x : (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x);
 | 
			
		||||
    if (style.WindowTitleAlign.x > 0.0f)
 | 
			
		||||
        pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x);
 | 
			
		||||
    text_r.Min.x += pad_left;
 | 
			
		||||
    text_r.Max.x -= pad_right;
 | 
			
		||||
    ImRect clip_rect = text_r;
 | 
			
		||||
    clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton()
 | 
			
		||||
    RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect);
 | 
			
		||||
    const float marker_size_x = (flags & ImGuiWindowFlags_UnsavedDocument) ? CalcTextSize(UNSAVED_DOCUMENT_MARKER, NULL, false).x : 0.0f;
 | 
			
		||||
    const ImVec2 text_size = CalcTextSize(name, NULL, true) + ImVec2(marker_size_x, 0.0f);
 | 
			
		||||
 | 
			
		||||
    // As a nice touch we try to ensure that centered title text doesn't get affected by visibility of Close/Collapse button,
 | 
			
		||||
    // while uncentered title text will still reach edges correct.
 | 
			
		||||
    if (pad_l > style.FramePadding.x)
 | 
			
		||||
        pad_l += g.Style.ItemInnerSpacing.x;
 | 
			
		||||
    if (pad_r > style.FramePadding.x)
 | 
			
		||||
        pad_r += g.Style.ItemInnerSpacing.x;
 | 
			
		||||
    if (style.WindowTitleAlign.x > 0.0f && style.WindowTitleAlign.x < 1.0f)
 | 
			
		||||
    {
 | 
			
		||||
        float centerness = ImSaturate(1.0f - ImFabs(style.WindowTitleAlign.x - 0.5f) * 2.0f); // 0.0f on either edges, 1.0f on center
 | 
			
		||||
        float pad_extend = ImMin(ImMax(pad_l, pad_r), title_bar_rect.GetWidth() - pad_l - pad_r - text_size.x);
 | 
			
		||||
        pad_l = ImMax(pad_l, pad_extend * centerness);
 | 
			
		||||
        pad_r = ImMax(pad_r, pad_extend * centerness);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ImRect layout_r(title_bar_rect.Min.x + pad_l, title_bar_rect.Min.y, title_bar_rect.Max.x - pad_r, title_bar_rect.Max.y);
 | 
			
		||||
    ImRect clip_r(layout_r.Min.x, layout_r.Min.y, layout_r.Max.x + g.Style.ItemInnerSpacing.x, layout_r.Max.y);
 | 
			
		||||
    //if (g.IO.KeyCtrl) window->DrawList->AddRect(layout_r.Min, layout_r.Max, IM_COL32(255, 128, 0, 255)); // [DEBUG]
 | 
			
		||||
    RenderTextClipped(layout_r.Min, layout_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_r);
 | 
			
		||||
    if (flags & ImGuiWindowFlags_UnsavedDocument)
 | 
			
		||||
    {
 | 
			
		||||
        ImVec2 marker_pos = ImVec2(ImMax(text_r.Min.x, text_r.Min.x + (text_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, text_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
 | 
			
		||||
        ImVec2 marker_pos = ImVec2(ImMax(layout_r.Min.x, layout_r.Min.x + (layout_r.GetWidth() - text_size.x) * style.WindowTitleAlign.x) + text_size.x, layout_r.Min.y) + ImVec2(2 - marker_size_x, 0.0f);
 | 
			
		||||
        ImVec2 off = ImVec2(0.0f, (float)(int)(-g.FontSize * 0.25f));
 | 
			
		||||
        RenderTextClipped(marker_pos + off, text_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_rect);
 | 
			
		||||
        RenderTextClipped(marker_pos + off, layout_r.Max + off, UNSAVED_DOCUMENT_MARKER, NULL, NULL, ImVec2(0, style.WindowTitleAlign.y), &clip_r);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -12479,8 +12515,8 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
 | 
			
		||||
            PushItemFlag(ImGuiItemFlags_Disabled, true);
 | 
			
		||||
            PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_Text] * ImVec4(1.0f,1.0f,1.0f,0.5f));
 | 
			
		||||
        }
 | 
			
		||||
        const float rad = g.FontSize * 0.5f;
 | 
			
		||||
        if (CloseButton(host_window->GetID("#CLOSE"), title_bar_rect.GetTR() + ImVec2(-style.FramePadding.x - rad, style.FramePadding.y + rad), rad + 1))
 | 
			
		||||
        const float button_sz = g.FontSize;
 | 
			
		||||
        if (CloseButton(host_window->GetID("#CLOSE"), title_bar_rect.GetTR() + ImVec2(-style.FramePadding.x * 2.0f - button_sz, 0.0f)))
 | 
			
		||||
            if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_bar->VisibleTabId))
 | 
			
		||||
            {
 | 
			
		||||
                node->WantCloseTabID = tab->ID;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								imgui.h
									
									
									
									
									
								
							@@ -1354,6 +1354,7 @@ struct ImGuiStyle
 | 
			
		||||
    float       WindowBorderSize;           // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
 | 
			
		||||
    ImVec2      WindowMinSize;              // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints().
 | 
			
		||||
    ImVec2      WindowTitleAlign;           // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
 | 
			
		||||
    ImGuiDir    WindowMenuButtonPosition;   // Side of the collapsing/docking button in the title bar (left/right). Defaults to ImGuiDir_Left.
 | 
			
		||||
    float       ChildRounding;              // Radius of child window corners rounding. Set to 0.0f to have rectangular windows.
 | 
			
		||||
    float       ChildBorderSize;            // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly).
 | 
			
		||||
    float       PopupRounding;              // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding)
 | 
			
		||||
 
 | 
			
		||||
@@ -3078,6 +3078,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
 | 
			
		||||
            ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
 | 
			
		||||
            ImGui::Text("Alignment");
 | 
			
		||||
            ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
 | 
			
		||||
            ImGui::Combo("WindowMenuButtonPosition", (int*)&style.WindowMenuButtonPosition, "Left\0Right\0");
 | 
			
		||||
            ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
 | 
			
		||||
            ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
 | 
			
		||||
            ImGui::Text("Safe Area Padding"); ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
 | 
			
		||||
 
 | 
			
		||||
@@ -869,7 +869,7 @@ struct ImGuiNextItemData
 | 
			
		||||
// Docking, Tabs
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
struct ImGuiTabBarSortItem
 | 
			
		||||
struct ImGuiShrinkWidthItem
 | 
			
		||||
{
 | 
			
		||||
    int             Index;
 | 
			
		||||
    float           Width;
 | 
			
		||||
@@ -1115,7 +1115,7 @@ struct ImGuiContext
 | 
			
		||||
    ImPool<ImGuiTabBar>             TabBars;
 | 
			
		||||
    ImGuiTabBar*                    CurrentTabBar;
 | 
			
		||||
    ImVector<ImGuiTabBarRef>        CurrentTabBarStack;
 | 
			
		||||
    ImVector<ImGuiTabBarSortItem>   TabSortByWidthBuffer;
 | 
			
		||||
    ImVector<ImGuiShrinkWidthItem>  ShrinkWidthBuffer;
 | 
			
		||||
 | 
			
		||||
    // Widget state
 | 
			
		||||
    ImVec2                  LastValidMousePos;
 | 
			
		||||
@@ -1678,6 +1678,7 @@ namespace ImGui
 | 
			
		||||
    IMGUI_API void          PopItemFlag();
 | 
			
		||||
    IMGUI_API bool          IsItemToggledSelection();                                           // was the last item selection toggled? (after Selectable(), TreeNode() etc. We only returns toggle _event_ in order to handle clipping correctly)
 | 
			
		||||
    IMGUI_API ImVec2        GetWorkRectMax();
 | 
			
		||||
    IMGUI_API void          ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess);
 | 
			
		||||
 | 
			
		||||
    // Logging/Capture
 | 
			
		||||
    IMGUI_API void          LogBegin(ImGuiLogType type, int auto_open_depth);   // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
 | 
			
		||||
@@ -1803,7 +1804,7 @@ namespace ImGui
 | 
			
		||||
    // Widgets
 | 
			
		||||
    IMGUI_API void          TextEx(const char* text, const char* text_end = NULL, ImGuiTextFlags flags = 0);
 | 
			
		||||
    IMGUI_API bool          ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0);
 | 
			
		||||
    IMGUI_API bool          CloseButton(ImGuiID id, const ImVec2& pos, float radius);
 | 
			
		||||
    IMGUI_API bool          CloseButton(ImGuiID id, const ImVec2& pos);
 | 
			
		||||
    IMGUI_API bool          CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_node);
 | 
			
		||||
    IMGUI_API bool          ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags);
 | 
			
		||||
    IMGUI_API void          Scrollbar(ImGuiAxis axis);
 | 
			
		||||
 
 | 
			
		||||
@@ -718,14 +718,14 @@ bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Button to close a window
 | 
			
		||||
bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius)
 | 
			
		||||
bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos)//, float size)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
    ImGuiWindow* window = g.CurrentWindow;
 | 
			
		||||
 | 
			
		||||
    // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window.
 | 
			
		||||
    // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible).
 | 
			
		||||
    const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius));
 | 
			
		||||
    const ImRect bb(pos, pos + ImVec2(g.FontSize, g.FontSize) + g.Style.FramePadding * 2.0f);
 | 
			
		||||
    bool is_clipped = !ItemAdd(bb, id);
 | 
			
		||||
 | 
			
		||||
    bool hovered, held;
 | 
			
		||||
@@ -734,11 +734,12 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius)
 | 
			
		||||
        return pressed;
 | 
			
		||||
 | 
			
		||||
    // Render
 | 
			
		||||
    ImU32 col = GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered);
 | 
			
		||||
    ImVec2 center = bb.GetCenter();
 | 
			
		||||
    if (hovered)
 | 
			
		||||
        window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), GetColorU32(held ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), 9);
 | 
			
		||||
        window->DrawList->AddCircleFilled(center, ImMax(2.0f, g.FontSize * 0.5f + 1.0f), col, 12);
 | 
			
		||||
 | 
			
		||||
    float cross_extent = (radius * 0.7071f) - 1.0f;
 | 
			
		||||
    float cross_extent = g.FontSize * 0.5f * 0.7071f - 1.0f;
 | 
			
		||||
    ImU32 cross_col = GetColorU32(ImGuiCol_Text);
 | 
			
		||||
    center -= ImVec2(0.5f, 0.5f);
 | 
			
		||||
    window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f);
 | 
			
		||||
@@ -758,11 +759,13 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos, ImGuiDockNode* dock_no
 | 
			
		||||
    bool hovered, held;
 | 
			
		||||
    bool pressed = ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_None);
 | 
			
		||||
 | 
			
		||||
    // Render
 | 
			
		||||
    //bool is_dock_menu = (window->DockNodeAsHost && !window->Collapsed);
 | 
			
		||||
    ImVec2 off = dock_node ? ImVec2((float)(int)(-g.Style.ItemInnerSpacing.x * 0.5f) + 0.5f, 0.0f) : ImVec2(0.0f, 0.0f);
 | 
			
		||||
    ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
 | 
			
		||||
    ImVec2 center = bb.GetCenter();
 | 
			
		||||
    if (hovered || held)
 | 
			
		||||
        window->DrawList->AddCircleFilled(bb.GetCenter() + off + ImVec2(0,-0.5f), g.FontSize * 0.5f + 1.0f, col, 9);
 | 
			
		||||
        window->DrawList->AddCircleFilled(center + off + ImVec2(0,-0.5f), g.FontSize * 0.5f + 1.0f, col, 12);
 | 
			
		||||
 | 
			
		||||
    if (dock_node)
 | 
			
		||||
        RenderArrowDockMenu(window->DrawList, bb.Min + g.Style.FramePadding, g.FontSize, GetColorU32(ImGuiCol_Text));
 | 
			
		||||
@@ -1180,6 +1183,7 @@ void ImGui::Bullet()
 | 
			
		||||
// - SeparatorEx() [Internal]
 | 
			
		||||
// - Separator()
 | 
			
		||||
// - SplitterBehavior() [Internal]
 | 
			
		||||
// - ShrinkWidths() [Internal]
 | 
			
		||||
//-------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
void ImGui::Spacing()
 | 
			
		||||
@@ -1361,6 +1365,33 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float
 | 
			
		||||
    return held;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int IMGUI_CDECL ShrinkWidthItemComparer(const void* lhs, const void* rhs)
 | 
			
		||||
{
 | 
			
		||||
    const ImGuiShrinkWidthItem* a = (const ImGuiShrinkWidthItem*)lhs;
 | 
			
		||||
    const ImGuiShrinkWidthItem* b = (const ImGuiShrinkWidthItem*)rhs;
 | 
			
		||||
    if (int d = (int)(b->Width - a->Width))
 | 
			
		||||
        return d;
 | 
			
		||||
    return (b->Index - a->Index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Shrink excess width from a set of item, by removing width from the larger items first.
 | 
			
		||||
void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess)
 | 
			
		||||
{
 | 
			
		||||
    if (count > 1)
 | 
			
		||||
        ImQsort(items, (size_t)count, sizeof(ImGuiShrinkWidthItem), ShrinkWidthItemComparer);
 | 
			
		||||
    int count_same_width = 1;
 | 
			
		||||
    while (width_excess > 0.0f && count_same_width < count)
 | 
			
		||||
    {
 | 
			
		||||
        while (count_same_width < count && items[0].Width == items[count_same_width].Width)
 | 
			
		||||
            count_same_width++;
 | 
			
		||||
        float width_to_remove_per_item_max = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f);
 | 
			
		||||
        float width_to_remove_per_item = ImMin(width_excess / count_same_width, width_to_remove_per_item_max);
 | 
			
		||||
        for (int item_n = 0; item_n < count_same_width; item_n++)
 | 
			
		||||
            items[item_n].Width -= width_to_remove_per_item;
 | 
			
		||||
        width_excess -= width_to_remove_per_item * count_same_width;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//-------------------------------------------------------------------------
 | 
			
		||||
// [SECTION] Widgets: ComboBox
 | 
			
		||||
//-------------------------------------------------------------------------
 | 
			
		||||
@@ -2099,15 +2130,22 @@ bool ImGui::DragScalarN(const char* label, ImGuiDataType data_type, void* v, int
 | 
			
		||||
    for (int i = 0; i < components; i++)
 | 
			
		||||
    {
 | 
			
		||||
        PushID(i);
 | 
			
		||||
        if (i > 0)
 | 
			
		||||
            SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        value_changed |= DragScalar("", data_type, v, v_speed, v_min, v_max, format, power);
 | 
			
		||||
        SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        PopID();
 | 
			
		||||
        PopItemWidth();
 | 
			
		||||
        v = (void*)((char*)v + type_size);
 | 
			
		||||
    }
 | 
			
		||||
    PopID();
 | 
			
		||||
 | 
			
		||||
    TextEx(label, FindRenderedTextEnd(label));
 | 
			
		||||
    const char* label_end = FindRenderedTextEnd(label);
 | 
			
		||||
    if (label != label_end)
 | 
			
		||||
    {
 | 
			
		||||
        SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        TextEx(label, label_end);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EndGroup();
 | 
			
		||||
    return value_changed;
 | 
			
		||||
}
 | 
			
		||||
@@ -2547,15 +2585,22 @@ bool ImGui::SliderScalarN(const char* label, ImGuiDataType data_type, void* v, i
 | 
			
		||||
    for (int i = 0; i < components; i++)
 | 
			
		||||
    {
 | 
			
		||||
        PushID(i);
 | 
			
		||||
        if (i > 0)
 | 
			
		||||
            SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        value_changed |= SliderScalar("", data_type, v, v_min, v_max, format, power);
 | 
			
		||||
        SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        PopID();
 | 
			
		||||
        PopItemWidth();
 | 
			
		||||
        v = (void*)((char*)v + type_size);
 | 
			
		||||
    }
 | 
			
		||||
    PopID();
 | 
			
		||||
 | 
			
		||||
    TextEx(label, FindRenderedTextEnd(label));
 | 
			
		||||
    const char* label_end = FindRenderedTextEnd(label);
 | 
			
		||||
    if (label != label_end)
 | 
			
		||||
    {
 | 
			
		||||
        SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        TextEx(label, label_end);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EndGroup();
 | 
			
		||||
    return value_changed;
 | 
			
		||||
}
 | 
			
		||||
@@ -2858,8 +2903,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* data_p
 | 
			
		||||
            DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast ? step_fast : step);
 | 
			
		||||
            value_changed = true;
 | 
			
		||||
        }
 | 
			
		||||
        SameLine(0, style.ItemInnerSpacing.x);
 | 
			
		||||
        TextEx(label, FindRenderedTextEnd(label));
 | 
			
		||||
 | 
			
		||||
        const char* label_end = FindRenderedTextEnd(label);
 | 
			
		||||
        if (label != label_end)
 | 
			
		||||
        {
 | 
			
		||||
            SameLine(0, style.ItemInnerSpacing.x);
 | 
			
		||||
            TextEx(label, label_end);
 | 
			
		||||
        }
 | 
			
		||||
        style.FramePadding = backup_frame_padding;
 | 
			
		||||
 | 
			
		||||
        PopID();
 | 
			
		||||
@@ -2891,15 +2941,22 @@ bool ImGui::InputScalarN(const char* label, ImGuiDataType data_type, void* v, in
 | 
			
		||||
    for (int i = 0; i < components; i++)
 | 
			
		||||
    {
 | 
			
		||||
        PushID(i);
 | 
			
		||||
        if (i > 0)
 | 
			
		||||
            SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        value_changed |= InputScalar("", data_type, v, step, step_fast, format, flags);
 | 
			
		||||
        SameLine(0, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        PopID();
 | 
			
		||||
        PopItemWidth();
 | 
			
		||||
        v = (void*)((char*)v + type_size);
 | 
			
		||||
    }
 | 
			
		||||
    PopID();
 | 
			
		||||
 | 
			
		||||
    TextEx(label, FindRenderedTextEnd(label));
 | 
			
		||||
    const char* label_end = FindRenderedTextEnd(label);
 | 
			
		||||
    if (label != label_end)
 | 
			
		||||
    {
 | 
			
		||||
        SameLine(0.0f, g.Style.ItemInnerSpacing.x);
 | 
			
		||||
        TextEx(label, label_end);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    EndGroup();
 | 
			
		||||
    return value_changed;
 | 
			
		||||
}
 | 
			
		||||
@@ -5335,12 +5392,14 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags
 | 
			
		||||
    bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label);
 | 
			
		||||
    if (p_open)
 | 
			
		||||
    {
 | 
			
		||||
        // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
 | 
			
		||||
        // Create a small overlapping close button
 | 
			
		||||
        // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc.
 | 
			
		||||
        // FIXME: CloseButton can overlap into text, need find a way to clip the text somehow.
 | 
			
		||||
        ImGuiContext& g = *GImGui;
 | 
			
		||||
        ImGuiItemHoveredDataBackup last_item_backup;
 | 
			
		||||
        float button_radius = g.FontSize * 0.5f;
 | 
			
		||||
        ImVec2 button_center = ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_radius, window->DC.LastItemRect.GetCenter().y);
 | 
			
		||||
        if (CloseButton(window->GetID((void*)((intptr_t)id+1)), button_center, button_radius))
 | 
			
		||||
        float button_size = g.FontSize;
 | 
			
		||||
        ImVec2 button_pos = ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x * 2.0f - button_size, window->DC.LastItemRect.Min.y);
 | 
			
		||||
        if (CloseButton(window->GetID((void*)((intptr_t)id + 1)), button_pos))
 | 
			
		||||
            *p_open = false;
 | 
			
		||||
        last_item_backup.Restore();
 | 
			
		||||
    }
 | 
			
		||||
@@ -6231,15 +6290,6 @@ static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const voi
 | 
			
		||||
    return (int)(a->Offset - b->Offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int IMGUI_CDECL TabBarSortItemComparer(const void* lhs, const void* rhs)
 | 
			
		||||
{
 | 
			
		||||
    const ImGuiTabBarSortItem* a = (const ImGuiTabBarSortItem*)lhs;
 | 
			
		||||
    const ImGuiTabBarSortItem* b = (const ImGuiTabBarSortItem*)rhs;
 | 
			
		||||
    if (int d = (int)(b->Width - a->Width))
 | 
			
		||||
        return d;
 | 
			
		||||
    return (b->Index - a->Index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiTabBarRef& ref)
 | 
			
		||||
{
 | 
			
		||||
    ImGuiContext& g = *GImGui;
 | 
			
		||||
@@ -6420,10 +6470,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
 | 
			
		||||
        if (ImGuiTabItem* tab_to_select = TabBarTabListPopupButton(tab_bar)) // NB: Will alter BarRect.Max.x!
 | 
			
		||||
            scroll_track_selected_tab_id = tab_bar->SelectedTabId = tab_to_select->ID;
 | 
			
		||||
 | 
			
		||||
    ImVector<ImGuiTabBarSortItem>& width_sort_buffer = g.TabSortByWidthBuffer;
 | 
			
		||||
    width_sort_buffer.resize(tab_bar->Tabs.Size);
 | 
			
		||||
 | 
			
		||||
    // Compute ideal widths
 | 
			
		||||
    g.ShrinkWidthBuffer.resize(tab_bar->Tabs.Size);
 | 
			
		||||
    float width_total_contents = 0.0f;
 | 
			
		||||
    ImGuiTabItem* most_recently_selected_tab = NULL;
 | 
			
		||||
    bool found_selected_tab_id = false;
 | 
			
		||||
@@ -6447,8 +6495,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
 | 
			
		||||
        width_total_contents += (tab_n > 0 ? g.Style.ItemInnerSpacing.x : 0.0f) + tab->WidthContents;
 | 
			
		||||
 | 
			
		||||
        // Store data so we can build an array sorted by width if we need to shrink tabs down
 | 
			
		||||
        width_sort_buffer[tab_n].Index = tab_n;
 | 
			
		||||
        width_sort_buffer[tab_n].Width = tab->WidthContents;
 | 
			
		||||
        g.ShrinkWidthBuffer[tab_n].Index = tab_n;
 | 
			
		||||
        g.ShrinkWidthBuffer[tab_n].Width = tab->WidthContents;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Compute width
 | 
			
		||||
@@ -6457,21 +6505,9 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
 | 
			
		||||
    if (width_excess > 0.0f && (tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyResizeDown))
 | 
			
		||||
    {
 | 
			
		||||
        // If we don't have enough room, resize down the largest tabs first
 | 
			
		||||
        if (tab_bar->Tabs.Size > 1)
 | 
			
		||||
            ImQsort(width_sort_buffer.Data, (size_t)width_sort_buffer.Size, sizeof(ImGuiTabBarSortItem), TabBarSortItemComparer);
 | 
			
		||||
        int tab_count_same_width = 1;
 | 
			
		||||
        while (width_excess > 0.0f && tab_count_same_width < tab_bar->Tabs.Size)
 | 
			
		||||
        {
 | 
			
		||||
            while (tab_count_same_width < tab_bar->Tabs.Size && width_sort_buffer[0].Width == width_sort_buffer[tab_count_same_width].Width)
 | 
			
		||||
                tab_count_same_width++;
 | 
			
		||||
            float width_to_remove_per_tab_max = (tab_count_same_width < tab_bar->Tabs.Size) ? (width_sort_buffer[0].Width - width_sort_buffer[tab_count_same_width].Width) : (width_sort_buffer[0].Width - 1.0f);
 | 
			
		||||
            float width_to_remove_per_tab = ImMin(width_excess / tab_count_same_width, width_to_remove_per_tab_max);
 | 
			
		||||
            for (int tab_n = 0; tab_n < tab_count_same_width; tab_n++)
 | 
			
		||||
                width_sort_buffer[tab_n].Width -= width_to_remove_per_tab;
 | 
			
		||||
            width_excess -= width_to_remove_per_tab * tab_count_same_width;
 | 
			
		||||
        }
 | 
			
		||||
        ShrinkWidths(g.ShrinkWidthBuffer.Data, g.ShrinkWidthBuffer.Size, width_excess);
 | 
			
		||||
        for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
 | 
			
		||||
            tab_bar->Tabs[width_sort_buffer[tab_n].Index].Width = (float)(int)width_sort_buffer[tab_n].Width;
 | 
			
		||||
            tab_bar->Tabs[g.ShrinkWidthBuffer[tab_n].Index].Width = (float)(int)g.ShrinkWidthBuffer[tab_n].Width;
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
    {
 | 
			
		||||
@@ -7151,16 +7187,18 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
 | 
			
		||||
    if (close_button_visible)
 | 
			
		||||
    {
 | 
			
		||||
        ImGuiItemHoveredDataBackup last_item_backup;
 | 
			
		||||
        const float close_button_sz = g.FontSize * 0.5f;
 | 
			
		||||
        if (CloseButton(close_button_id, ImVec2(bb.Max.x - frame_padding.x - close_button_sz, bb.Min.y + frame_padding.y + close_button_sz), close_button_sz))
 | 
			
		||||
        const float close_button_sz = g.FontSize;
 | 
			
		||||
        PushStyleVar(ImGuiStyleVar_FramePadding, frame_padding);
 | 
			
		||||
        if (CloseButton(close_button_id, ImVec2(bb.Max.x - frame_padding.x * 2.0f - close_button_sz, bb.Min.y)))
 | 
			
		||||
            close_button_pressed = true;
 | 
			
		||||
        PopStyleVar();
 | 
			
		||||
        last_item_backup.Restore();
 | 
			
		||||
 | 
			
		||||
        // Close with middle mouse button
 | 
			
		||||
        if (!(flags & ImGuiTabItemFlags_NoCloseWithMiddleMouseButton) && IsMouseClicked(2))
 | 
			
		||||
            close_button_pressed = true;
 | 
			
		||||
 | 
			
		||||
        text_pixel_clip_bb.Max.x -= close_button_sz * 2.0f;
 | 
			
		||||
        text_pixel_clip_bb.Max.x -= close_button_sz;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Label with ellipsis
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user