mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-25 21:17:01 +00:00
TreeNode: Added ImGuiTreeNodeFlags_SpanAvailWidth and ImGuiTreeNodeFlags_SpanFullWidth flags (#2451, #2438, #1897)
Added demo bits.
This commit is contained in:
parent
74e01e62ce
commit
9d02ed51e3
@ -50,6 +50,13 @@ Other Changes:
|
|||||||
- SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton]
|
- SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton]
|
||||||
- DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value.
|
- DragInt, DragFloat, DragScalar: Using (v_min > v_max) allows locking any edit to the value.
|
||||||
- DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat]
|
- DragScalar: Fixed dragging of unsigned values on ARM cpu. (#2780) [@dBagrat]
|
||||||
|
- TreeNode: Added ImGuiTreeNodeFlags_SpanAvailWidth flag. (#2451, #2438, #1897) [@Melix19, @PathogenDavid]
|
||||||
|
This extends the hit-box to the right-most edge, even if the node is not framed.
|
||||||
|
(Note: this is not the default in order to allow adding other items on the same line. In the future we will
|
||||||
|
aim toward refactoring the hit-system to be front-to-back, allowing more natural overlapping of items,
|
||||||
|
and then we will be able to make this the default.)
|
||||||
|
- TreeNode: Added ImGuiTreeNodeFlags_SpanFullWidth flag. This extends the hit-box to both the left-most and
|
||||||
|
right-most edge of the working area, bypassing indentation.
|
||||||
- Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639)
|
- Style: Allow style.WindowMenuButtonPosition to be set to ImGuiDir_None to hide the collapse button. (#2634, #2639)
|
||||||
- Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly
|
- Font: Better ellipsis drawing implementation. Instead of drawing three pixel-ey dots (which was glaringly
|
||||||
unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set.
|
unfitting with many types of fonts) we first attempt to find a standard ellipsis glyphs within the loaded set.
|
||||||
|
5
imgui.h
5
imgui.h
@ -791,9 +791,10 @@ enum ImGuiTreeNodeFlags_
|
|||||||
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
|
ImGuiTreeNodeFlags_Leaf = 1 << 8, // No collapsing, no arrow (use as a convenience for leaf nodes).
|
||||||
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow
|
ImGuiTreeNodeFlags_Bullet = 1 << 9, // Display a bullet instead of arrow
|
||||||
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding().
|
ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding().
|
||||||
//ImGuiTreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed
|
ImGuiTreeNodeFlags_SpanAvailWidth = 1 << 11, // Extend hit box to the right-most edge, even if not framed. This is not the default in order to allow adding other items on the same line. In the future we may refactor the hit system to be front-to-back, allowing natural overlaps and then this can become the default.
|
||||||
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
|
ImGuiTreeNodeFlags_SpanFullWidth = 1 << 12, // Extend hit box to the left-most and right-most edges (bypass the indented area).
|
||||||
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
|
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop)
|
||||||
|
//ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 14, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible
|
||||||
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog
|
ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_NoAutoOpenOnLog
|
||||||
|
|
||||||
// Obsolete names (will be removed)
|
// Obsolete names (will be removed)
|
||||||
|
@ -608,7 +608,12 @@ static void ShowDemoWindowWidgets()
|
|||||||
if (ImGui::TreeNode("Advanced, with Selectable nodes"))
|
if (ImGui::TreeNode("Advanced, with Selectable nodes"))
|
||||||
{
|
{
|
||||||
HelpMarker("This is a more typical looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
|
HelpMarker("This is a more typical looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
|
||||||
|
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
|
||||||
static bool align_label_with_current_x_position = false;
|
static bool align_label_with_current_x_position = false;
|
||||||
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
|
||||||
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
|
||||||
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanAvailWidth);
|
||||||
|
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
|
||||||
ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
|
ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
|
||||||
ImGui::Text("Hello!");
|
ImGui::Text("Hello!");
|
||||||
if (align_label_with_current_x_position)
|
if (align_label_with_current_x_position)
|
||||||
@ -616,12 +621,12 @@ static void ShowDemoWindowWidgets()
|
|||||||
|
|
||||||
static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
|
static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
|
||||||
int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
|
int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
|
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
// Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
|
// Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
|
||||||
ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
ImGuiTreeNodeFlags node_flags = base_flags;
|
||||||
if (selection_mask & (1 << i))
|
const bool is_selected = (selection_mask & (1 << i));
|
||||||
|
if (is_selected)
|
||||||
node_flags |= ImGuiTreeNodeFlags_Selected;
|
node_flags |= ImGuiTreeNodeFlags_Selected;
|
||||||
if (i < 3)
|
if (i < 3)
|
||||||
{
|
{
|
||||||
@ -631,7 +636,7 @@ static void ShowDemoWindowWidgets()
|
|||||||
node_clicked = i;
|
node_clicked = i;
|
||||||
if (node_open)
|
if (node_open)
|
||||||
{
|
{
|
||||||
ImGui::Text("Blah blah\nBlah Blah");
|
ImGui::BulletText("Blah blah\nBlah Blah");
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -654,7 +659,6 @@ static void ShowDemoWindowWidgets()
|
|||||||
else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
|
else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
|
||||||
selection_mask = (1 << node_clicked); // Click to single-select
|
selection_mask = (1 << node_clicked); // Click to single-select
|
||||||
}
|
}
|
||||||
ImGui::PopStyleVar();
|
|
||||||
if (align_label_with_current_x_position)
|
if (align_label_with_current_x_position)
|
||||||
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
|
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
|
@ -5177,29 +5177,36 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
|||||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||||
|
|
||||||
// We vertically grow up to current line height up the typical widget height.
|
// We vertically grow up to current line height up the typical widget height.
|
||||||
const float text_base_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
|
|
||||||
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
|
const float frame_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2);
|
||||||
ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->WorkRect.Max.x, window->DC.CursorPos.y + frame_height));
|
ImRect frame_bb;
|
||||||
|
frame_bb.Min.x = (flags & ImGuiTreeNodeFlags_SpanFullWidth) ? window->WorkRect.Min.x : window->DC.CursorPos.x;
|
||||||
|
frame_bb.Min.y = window->DC.CursorPos.y;
|
||||||
|
frame_bb.Max.x = window->WorkRect.Max.x;
|
||||||
|
frame_bb.Max.y = window->DC.CursorPos.y + frame_height;
|
||||||
if (display_frame)
|
if (display_frame)
|
||||||
{
|
{
|
||||||
// Framed header expand a little outside the default padding
|
// Framed header expand a little outside the default padding, to the edge of InnerClipRect
|
||||||
|
// (FIXME: May remove this at some point and make InnerClipRect align with WindowPadding.x instead of WindowPadding.x*0.5f)
|
||||||
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f - 1.0f);
|
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f - 1.0f);
|
||||||
frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f);
|
frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing
|
const float text_offset_x = g.FontSize + (display_frame ? padding.x*3 : padding.x*2); // Collapser arrow width + Spacing
|
||||||
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
|
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
|
||||||
ItemSize(ImVec2(text_width, frame_height), text_base_offset_y);
|
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
|
||||||
|
const ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
|
||||||
|
ItemSize(ImVec2(text_width, frame_height), text_offset_y);
|
||||||
|
|
||||||
// For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
|
// For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
|
||||||
// (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not)
|
ImRect interact_bb = frame_bb;
|
||||||
const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y);
|
if (!display_frame && (flags & (ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth)) == 0)
|
||||||
bool is_open = TreeNodeBehaviorIsOpen(id, flags);
|
interact_bb.Max.x = frame_bb.Min.x + text_width + style.ItemSpacing.x * 2.0f;
|
||||||
bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
|
||||||
|
|
||||||
// Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
|
// Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child.
|
||||||
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
||||||
// This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
|
// This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
|
||||||
|
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
||||||
|
bool is_open = TreeNodeBehaviorIsOpen(id, flags);
|
||||||
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||||
window->DC.TreeStoreMayJumpToParentOnPop |= (1 << window->DC.TreeDepth);
|
window->DC.TreeStoreMayJumpToParentOnPop |= (1 << window->DC.TreeDepth);
|
||||||
|
|
||||||
@ -5273,7 +5280,6 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
|||||||
|
|
||||||
// Render
|
// Render
|
||||||
const ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
const ImU32 text_col = GetColorU32(ImGuiCol_Text);
|
||||||
const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y);
|
|
||||||
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin;
|
ImGuiNavHighlightFlags nav_highlight_flags = ImGuiNavHighlightFlags_TypeThin;
|
||||||
if (display_frame)
|
if (display_frame)
|
||||||
{
|
{
|
||||||
@ -5281,7 +5287,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
|||||||
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
|
||||||
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, true, style.FrameRounding);
|
||||||
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
||||||
RenderArrow(window->DrawList, frame_bb.Min + ImVec2(padding.x, text_base_offset_y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
|
RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
|
||||||
if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
|
if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
|
||||||
frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
|
frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
|
||||||
if (g.LogEnabled)
|
if (g.LogEnabled)
|
||||||
@ -5309,9 +5315,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & ImGuiTreeNodeFlags_Bullet)
|
if (flags & ImGuiTreeNodeFlags_Bullet)
|
||||||
RenderBullet(window->DrawList, frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y), text_col);
|
RenderBullet(window->DrawList, ImVec2(text_pos.x - text_offset_x * 0.5f, text_pos.y + g.FontSize*0.50f), text_col);
|
||||||
else if (!is_leaf)
|
else if (!is_leaf)
|
||||||
RenderArrow(window->DrawList, frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
|
RenderArrow(window->DrawList, ImVec2(text_pos.x - text_offset_x + padding.x, text_pos.y + g.FontSize*0.15f), text_col, is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f);
|
||||||
if (g.LogEnabled)
|
if (g.LogEnabled)
|
||||||
LogRenderedText(&text_pos, ">");
|
LogRenderedText(&text_pos, ">");
|
||||||
RenderText(text_pos, label, label_end, false);
|
RenderText(text_pos, label, label_end, false);
|
||||||
|
Loading…
Reference in New Issue
Block a user