mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-14 17:07:01 +00:00
Combo, Slider: Improve rendering in situation when there's there's very little space available.
This commit is contained in:
parent
1aeee9d40f
commit
240dddff87
@ -52,6 +52,7 @@ Other Changes:
|
||||
- PlotLines, PlotHistogram: Ignore NaN values when calculating min/max bounds. (#2485)
|
||||
- Window: Window close button is horizontally aligned with style.FramePadding.x.
|
||||
- Columns: Fixed boundary of clipping being off by 1 pixel within the left column.
|
||||
- Combo, Slider, Scrollbar: Improve rendering in situation when there's only a few pixels available (<3 pixels).
|
||||
- Misc: Added IM_MALLOC/IM_FREE macros mimicking IM_NEW/IM_DELETE so user doesn't need to revert
|
||||
to using the ImGui::MemAlloc()/MemFree() calls directly.
|
||||
- Metrics: Added "Show windows rectangles" tool to visualize the different rectangles.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user