mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-11-03 22:51:06 +01:00 
			
		
		
		
	Combo, Slider: Improve rendering in situation when there's there's very little space available.
This commit is contained in:
		@@ -788,16 +788,19 @@ void ImGui::Scrollbar(ImGuiAxis axis)
 | 
			
		||||
    // Render background
 | 
			
		||||
    bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);
 | 
			
		||||
    float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;
 | 
			
		||||
    const ImRect window_rect = window->Rect();
 | 
			
		||||
    const ImRect host_rect = window->Rect();
 | 
			
		||||
    const float border_size = window->WindowBorderSize;
 | 
			
		||||
    ImRect bb = horizontal
 | 
			
		||||
        ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size)
 | 
			
		||||
        : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size);
 | 
			
		||||
        ? ImRect(host_rect.Min.x + border_size, host_rect.Max.y - style.ScrollbarSize, host_rect.Max.x - other_scrollbar_size_w - border_size, host_rect.Max.y - border_size)
 | 
			
		||||
        : ImRect(host_rect.Max.x - style.ScrollbarSize, host_rect.Min.y + border_size, host_rect.Max.x - border_size, host_rect.Max.y - other_scrollbar_size_w - border_size);
 | 
			
		||||
    bb.Min.x = ImMax(host_rect.Min.x, bb.Min.x); // Handle case where the host rectangle is smaller than the scrollbar
 | 
			
		||||
    bb.Min.y = ImMax(host_rect.Min.y, bb.Min.y);
 | 
			
		||||
    if (!horizontal)
 | 
			
		||||
        bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); // FIXME: InnerRect?
 | 
			
		||||
 | 
			
		||||
    const float bb_width = bb.GetWidth();
 | 
			
		||||
    const float bb_height = bb.GetHeight();
 | 
			
		||||
    if (bb.GetWidth() <= 0.0f || bb_height <= 0.0f)
 | 
			
		||||
    if (bb_width <= 0.0f || bb_height <= 0.0f)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the resize grab)
 | 
			
		||||
@@ -816,7 +819,7 @@ void ImGui::Scrollbar(ImGuiAxis axis)
 | 
			
		||||
    else
 | 
			
		||||
        window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0) | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight);
 | 
			
		||||
    window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_ScrollbarBg), window->WindowRounding, window_rounding_corners);
 | 
			
		||||
    bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f)));
 | 
			
		||||
    bb.Expand(ImVec2(-ImClamp((float)(int)((bb_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb_height - 2.0f) * 0.5f), 0.0f, 3.0f)));
 | 
			
		||||
 | 
			
		||||
    // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar)
 | 
			
		||||
    float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight();
 | 
			
		||||
@@ -887,9 +890,9 @@ void ImGui::Scrollbar(ImGuiAxis axis)
 | 
			
		||||
    const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
 | 
			
		||||
    ImRect grab_rect;
 | 
			
		||||
    if (horizontal)
 | 
			
		||||
        grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImMin(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, window_rect.Max.x), bb.Max.y);
 | 
			
		||||
        grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImMin(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, host_rect.Max.x), bb.Max.y);
 | 
			
		||||
    else
 | 
			
		||||
        grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImMin(ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels, window_rect.Max.y));
 | 
			
		||||
        grab_rect = ImRect(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, grab_v_norm), bb.Max.x, ImMin(ImLerp(bb.Min.y, bb.Max.y, grab_v_norm) + grab_h_pixels, host_rect.Max.y));
 | 
			
		||||
    window->DrawList->AddRectFilled(grab_rect.Min, grab_rect.Max, grab_col, style.ScrollbarRounding);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1361,19 +1364,19 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
 | 
			
		||||
    bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
 | 
			
		||||
    bool popup_open = IsPopupOpen(id);
 | 
			
		||||
 | 
			
		||||
    const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f));
 | 
			
		||||
    const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
 | 
			
		||||
    const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);
 | 
			
		||||
    RenderNavHighlight(frame_bb, id);
 | 
			
		||||
    if (!(flags & ImGuiComboFlags_NoPreview))
 | 
			
		||||
        window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Max.y), frame_col, style.FrameRounding, ImDrawCornerFlags_Left);
 | 
			
		||||
        window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, ImDrawCornerFlags_Left);
 | 
			
		||||
    if (!(flags & ImGuiComboFlags_NoArrowButton))
 | 
			
		||||
    {
 | 
			
		||||
        window->DrawList->AddRectFilled(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
 | 
			
		||||
        RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down);
 | 
			
		||||
        window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right);
 | 
			
		||||
        RenderArrow(ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down);
 | 
			
		||||
    }
 | 
			
		||||
    RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);
 | 
			
		||||
    if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview))
 | 
			
		||||
        RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
 | 
			
		||||
        RenderTextClipped(frame_bb.Min + style.FramePadding, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f,0.0f));
 | 
			
		||||
    if (label_size.x > 0)
 | 
			
		||||
        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
 | 
			
		||||
 | 
			
		||||
@@ -2223,16 +2226,16 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
 | 
			
		||||
        grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize);  // For integer sliders: if possible have the grab size represent 1 unit
 | 
			
		||||
    grab_sz = ImMin(grab_sz, slider_sz);
 | 
			
		||||
    const float slider_usable_sz = slider_sz - grab_sz;
 | 
			
		||||
    const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz*0.5f;
 | 
			
		||||
    const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz*0.5f;
 | 
			
		||||
    const float slider_usable_pos_min = bb.Min[axis] + grab_padding + grab_sz * 0.5f;
 | 
			
		||||
    const float slider_usable_pos_max = bb.Max[axis] - grab_padding - grab_sz * 0.5f;
 | 
			
		||||
 | 
			
		||||
    // For power curve sliders that cross over sign boundary we want the curve to be symmetric around 0.0f
 | 
			
		||||
    float linear_zero_pos;   // 0.0->1.0f
 | 
			
		||||
    if (is_power && v_min * v_max < 0.0f)
 | 
			
		||||
    {
 | 
			
		||||
        // Different sign
 | 
			
		||||
        const FLOATTYPE linear_dist_min_to_0 = ImPow(v_min >= 0 ? (FLOATTYPE)v_min : -(FLOATTYPE)v_min, (FLOATTYPE)1.0f/power);
 | 
			
		||||
        const FLOATTYPE linear_dist_max_to_0 = ImPow(v_max >= 0 ? (FLOATTYPE)v_max : -(FLOATTYPE)v_max, (FLOATTYPE)1.0f/power);
 | 
			
		||||
        const FLOATTYPE linear_dist_min_to_0 = ImPow(v_min >= 0 ? (FLOATTYPE)v_min : -(FLOATTYPE)v_min, (FLOATTYPE)1.0f / power);
 | 
			
		||||
        const FLOATTYPE linear_dist_max_to_0 = ImPow(v_max >= 0 ? (FLOATTYPE)v_max : -(FLOATTYPE)v_max, (FLOATTYPE)1.0f / power);
 | 
			
		||||
        linear_zero_pos = (float)(linear_dist_min_to_0 / (linear_dist_min_to_0 + linear_dist_max_to_0));
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
@@ -2355,15 +2358,22 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Output grab position so it can be displayed by the caller
 | 
			
		||||
    float grab_t = SliderCalcRatioFromValueT<TYPE,FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
 | 
			
		||||
    if (axis == ImGuiAxis_Y)
 | 
			
		||||
        grab_t = 1.0f - grab_t;
 | 
			
		||||
    const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
 | 
			
		||||
    if (axis == ImGuiAxis_X)
 | 
			
		||||
        *out_grab_bb = ImRect(grab_pos - grab_sz*0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz*0.5f, bb.Max.y - grab_padding);
 | 
			
		||||
    if (slider_sz < 1.0f)
 | 
			
		||||
    {
 | 
			
		||||
        *out_grab_bb = ImRect(bb.Min, bb.Min);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz*0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz*0.5f);
 | 
			
		||||
    {
 | 
			
		||||
        // Output grab position so it can be displayed by the caller
 | 
			
		||||
        float grab_t = SliderCalcRatioFromValueT<TYPE, FLOATTYPE>(data_type, *v, v_min, v_max, power, linear_zero_pos);
 | 
			
		||||
        if (axis == ImGuiAxis_Y)
 | 
			
		||||
            grab_t = 1.0f - grab_t;
 | 
			
		||||
        const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t);
 | 
			
		||||
        if (axis == ImGuiAxis_X)
 | 
			
		||||
            *out_grab_bb = ImRect(grab_pos - grab_sz * 0.5f, bb.Min.y + grab_padding, grab_pos + grab_sz * 0.5f, bb.Max.y - grab_padding);
 | 
			
		||||
        else
 | 
			
		||||
            *out_grab_bb = ImRect(bb.Min.x + grab_padding, grab_pos - grab_sz * 0.5f, bb.Max.x - grab_padding, grab_pos + grab_sz * 0.5f);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return value_changed;
 | 
			
		||||
}
 | 
			
		||||
@@ -2465,7 +2475,8 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* v, co
 | 
			
		||||
        MarkItemEdited(id);
 | 
			
		||||
 | 
			
		||||
    // Render grab
 | 
			
		||||
    window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
 | 
			
		||||
    if (grab_bb.Max.x > grab_bb.Min.x)
 | 
			
		||||
        window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
 | 
			
		||||
 | 
			
		||||
    // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
 | 
			
		||||
    char value_buf[64];
 | 
			
		||||
@@ -2605,7 +2616,8 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
 | 
			
		||||
        MarkItemEdited(id);
 | 
			
		||||
 | 
			
		||||
    // Render grab
 | 
			
		||||
    window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
 | 
			
		||||
    if (grab_bb.Max.y > grab_bb.Min.y)
 | 
			
		||||
        window->DrawList->AddRectFilled(grab_bb.Min, grab_bb.Max, GetColorU32(g.ActiveId == id ? ImGuiCol_SliderGrabActive : ImGuiCol_SliderGrab), style.GrabRounding);
 | 
			
		||||
 | 
			
		||||
    // Display value using user-provided display format so user can add prefix/suffix/decorations to the value.
 | 
			
		||||
    // For the vertical slider we allow centered text to overlap the frame padding
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user