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:
		@@ -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