mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-06 04:58:47 +02:00
Merge branch 'master' into docking
# Conflicts: # examples/imgui_impl_opengl3.cpp # imgui.h
This commit is contained in:
@ -5329,30 +5329,39 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
return is_open;
|
||||
}
|
||||
|
||||
// Flags that affects opening behavior:
|
||||
// - 0 (default) .................... single-click anywhere to open
|
||||
// - OpenOnDoubleClick .............. double-click anywhere to open
|
||||
// - OpenOnArrow .................... single-click on arrow to open
|
||||
// - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open
|
||||
ImGuiButtonFlags button_flags = 0;
|
||||
ImGuiButtonFlags button_flags = ImGuiTreeNodeFlags_None;
|
||||
if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)
|
||||
button_flags |= ImGuiButtonFlags_AllowItemOverlap;
|
||||
if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
|
||||
button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0);
|
||||
else
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||
if (!is_leaf)
|
||||
button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
|
||||
|
||||
// We allow clicking on the arrow section with keyboard modifiers held, in order to easily
|
||||
// allow browsing a tree while preserving selection with code implementing multi-selection patterns.
|
||||
// When clicking on the rest of the tree node we always disallow keyboard modifiers.
|
||||
const float hit_padding_x = style.TouchExtraPadding.x;
|
||||
const float arrow_hit_x1 = (text_pos.x - text_offset_x) - hit_padding_x;
|
||||
const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + hit_padding_x;
|
||||
if (window != g.HoveredWindow || !(g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2))
|
||||
const float arrow_hit_x1 = (text_pos.x - text_offset_x) - style.TouchExtraPadding.x;
|
||||
const float arrow_hit_x2 = (text_pos.x - text_offset_x) + (g.FontSize + padding.x * 2.0f) + style.TouchExtraPadding.x;
|
||||
const bool is_mouse_x_over_arrow = (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2);
|
||||
if (window != g.HoveredWindow || !is_mouse_x_over_arrow)
|
||||
button_flags |= ImGuiButtonFlags_NoKeyModifiers;
|
||||
|
||||
// Open behaviors can be altered with the _OpenOnArrow and _OnOnDoubleClick flags.
|
||||
// Some alteration have subtle effects (e.g. toggle on MouseUp vs MouseDown events) due to requirements for multi-selection and drag and drop support.
|
||||
// - Single-click on label = Toggle on MouseUp (default)
|
||||
// - Single-click on arrow = Toggle on MouseUp (when _OpenOnArrow=0)
|
||||
// - Single-click on arrow = Toggle on MouseDown (when _OpenOnArrow=1)
|
||||
// - Double-click on label = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1)
|
||||
// - Double-click on arrow = Toggle on MouseDoubleClick (when _OpenOnDoubleClick=1 and _OpenOnArrow=0)
|
||||
// This makes _OpenOnArrow have a subtle effect on _OpenOnDoubleClick: arrow click reacts on Down rather than Up.
|
||||
// It is rather standard that arrow click react on Down rather than Up and we'd be tempted to make it the default
|
||||
// (by removing the _OpenOnArrow test below), however this would have a perhaps surprising effect on CollapsingHeader()?
|
||||
// So right now we are making this optional. May evolve later.
|
||||
if (is_mouse_x_over_arrow && (flags & ImGuiTreeNodeFlags_OpenOnArrow))
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClick;
|
||||
else if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick)
|
||||
button_flags |= ImGuiButtonFlags_PressedOnDoubleClick;
|
||||
else
|
||||
button_flags |= ImGuiButtonFlags_PressedOnClickRelease;
|
||||
|
||||
bool selected = (flags & ImGuiTreeNodeFlags_Selected) != 0;
|
||||
const bool was_selected = selected;
|
||||
|
||||
@ -5366,7 +5375,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id))
|
||||
toggled = true;
|
||||
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
|
||||
toggled |= (g.IO.MousePos.x >= arrow_hit_x1 && g.IO.MousePos.x < arrow_hit_x2) && (!g.NavDisableMouseHover); // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
|
||||
toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
|
||||
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0])
|
||||
toggled = true;
|
||||
if (g.DragDropActive && is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again.
|
||||
@ -5568,6 +5577,8 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags
|
||||
|
||||
// Tip: pass a non-visible label (e.g. "##dummy") then you can use the space to draw other text or image.
|
||||
// But you need to make sure the ID is unique, e.g. enclose calls in PushID/PopID or use ##unique_id.
|
||||
// With this scheme, ImGuiSelectableFlags_SpanAllColumns and ImGuiSelectableFlags_AllowItemOverlap are also frequently used flags.
|
||||
// FIXME: Selectable() with (size.x == 0.0f) and (SelectableTextAlign.x > 0.0f) followed by SameLine() is currently not supported.
|
||||
bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags flags, const ImVec2& size_arg)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@ -5580,44 +5591,48 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped.
|
||||
PushColumnsBackground();
|
||||
|
||||
// Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle.
|
||||
ImGuiID id = window->GetID(label);
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
pos.y += window->DC.CurrLineTextBaseOffset;
|
||||
ImRect bb_inner(pos, pos + size);
|
||||
ItemSize(size, 0.0f);
|
||||
|
||||
// Fill horizontal space.
|
||||
ImVec2 window_padding = window->WindowPadding;
|
||||
float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? GetWindowContentRegionMax().x : GetContentRegionMax().x;
|
||||
float w_draw = ImMax(label_size.x, window->Pos.x + max_x - window_padding.x - pos.x);
|
||||
ImVec2 size_draw((size_arg.x != 0 && !(flags & ImGuiSelectableFlags_DrawFillAvailWidth)) ? size_arg.x : w_draw, size_arg.y != 0.0f ? size_arg.y : size.y);
|
||||
ImRect bb(pos, pos + size_draw);
|
||||
if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_DrawFillAvailWidth))
|
||||
bb.Max.x += window_padding.x;
|
||||
// Fill horizontal space
|
||||
const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Min.x : pos.x;
|
||||
const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Max.x : GetContentRegionMaxAbs().x;
|
||||
if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth))
|
||||
size.x = ImMax(label_size.x, max_x - min_x);
|
||||
|
||||
// Selectables are tightly packed together so we extend the box to cover spacing between selectable.
|
||||
// Text stays at the submission position, but bounding box may be extended on both sides
|
||||
const ImVec2 text_min = pos;
|
||||
const ImVec2 text_max(min_x + size.x, pos.y + size.y);
|
||||
|
||||
// Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
|
||||
ImRect bb_enlarged(min_x, pos.y, text_max.x, text_max.y);
|
||||
const float spacing_x = style.ItemSpacing.x;
|
||||
const float spacing_y = style.ItemSpacing.y;
|
||||
const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
|
||||
const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
|
||||
bb.Min.x -= spacing_L;
|
||||
bb.Min.y -= spacing_U;
|
||||
bb.Max.x += (spacing_x - spacing_L);
|
||||
bb.Max.y += (spacing_y - spacing_U);
|
||||
bb_enlarged.Min.x -= spacing_L;
|
||||
bb_enlarged.Min.y -= spacing_U;
|
||||
bb_enlarged.Max.x += (spacing_x - spacing_L);
|
||||
bb_enlarged.Max.y += (spacing_y - spacing_U);
|
||||
//if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_align.Min, bb_align.Max, IM_COL32(255, 0, 0, 255)); }
|
||||
//if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_enlarged.Min, bb_enlarged.Max, IM_COL32(0, 255, 0, 255)); }
|
||||
|
||||
bool item_add;
|
||||
if (flags & ImGuiSelectableFlags_Disabled)
|
||||
{
|
||||
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags;
|
||||
window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;
|
||||
item_add = ItemAdd(bb, id);
|
||||
item_add = ItemAdd(bb_enlarged, id);
|
||||
window->DC.ItemFlags = backup_item_flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
item_add = ItemAdd(bb, id);
|
||||
item_add = ItemAdd(bb_enlarged, id);
|
||||
}
|
||||
if (!item_add)
|
||||
{
|
||||
@ -5640,7 +5655,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
|
||||
const bool was_selected = selected;
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
||||
bool pressed = ButtonBehavior(bb_enlarged, id, &hovered, &held, button_flags);
|
||||
|
||||
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
|
||||
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
|
||||
@ -5667,18 +5682,15 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
if (hovered || selected)
|
||||
{
|
||||
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||
RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
|
||||
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
|
||||
RenderFrame(bb_enlarged.Min, bb_enlarged.Max, col, false, 0.0f);
|
||||
RenderNavHighlight(bb_enlarged, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
|
||||
}
|
||||
|
||||
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns)
|
||||
{
|
||||
PopColumnsBackground();
|
||||
bb.Max.x -= (GetContentRegionMax().x - max_x);
|
||||
}
|
||||
|
||||
if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
|
||||
RenderTextClipped(bb_inner.Min, bb_inner.Max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
|
||||
RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb_enlarged);
|
||||
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
|
||||
|
||||
// Automatically close popups
|
||||
@ -6259,10 +6271,12 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
else
|
||||
{
|
||||
// Menu inside a menu
|
||||
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
|
||||
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
|
||||
popup_pos = ImVec2(pos.x, pos.y - style.WindowPadding.y);
|
||||
float w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame
|
||||
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
|
||||
pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f));
|
||||
float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, 0.0f, IM_FLOOR(g.FontSize * 1.20f)); // Feedback to next frame
|
||||
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||
pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_SpanAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(min_w, 0.0f));
|
||||
ImU32 text_col = GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled);
|
||||
RenderArrow(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), text_col, ImGuiDir_Right);
|
||||
}
|
||||
@ -6407,11 +6421,14 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
|
||||
}
|
||||
else
|
||||
{
|
||||
ImVec2 shortcut_size = shortcut ? CalcTextSize(shortcut, NULL) : ImVec2(0.0f, 0.0f);
|
||||
float w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_size.x, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame
|
||||
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w);
|
||||
pressed = Selectable(label, false, flags | ImGuiSelectableFlags_DrawFillAvailWidth, ImVec2(w, 0.0f));
|
||||
if (shortcut_size.x > 0.0f)
|
||||
// Menu item inside a vertical menu
|
||||
// (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f.
|
||||
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.
|
||||
float shortcut_w = shortcut ? CalcTextSize(shortcut, NULL).x : 0.0f;
|
||||
float min_w = window->DC.MenuColumns.DeclColumns(label_size.x, shortcut_w, IM_FLOOR(g.FontSize * 1.20f)); // Feedback for next frame
|
||||
float extra_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||
pressed = Selectable(label, false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
|
||||
if (shortcut_w > 0.0f)
|
||||
{
|
||||
PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]);
|
||||
RenderText(pos + ImVec2(window->DC.MenuColumns.Pos[1] + extra_w, 0.0f), shortcut, NULL, false);
|
||||
|
Reference in New Issue
Block a user