Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's the proper way to render custom text or custom items in the "key"/"label" of a TreeNode? #7505

Closed
kalebs-anotheraxiom opened this issue Apr 18, 2024 · 8 comments
Labels
tree tree nodes

Comments

@kalebs-anotheraxiom
Copy link

Version/Branch of Dear ImGui:

v1.90.1 WIP + docking

Back-ends:

N/A

Compiler, OS:

Windows

Full config/build information:

Dear ImGui 1.90.1 WIP (19002)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=199711
define: _WIN32
define: _WIN64
define: _MSC_VER=1929
define: _MSVC_LANG=201703
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: NULL
io.BackendRendererName: NULL
io.ConfigFlags: 0x00000041
 NavEnableKeyboard
 DockingEnable
io.ConfigViewportsNoDecoration
io.ConfigInputTextCursorBlink
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x00000000
--------------------------------
io.Fonts: 2 fonts, Flags: 0x00000000, TexSize: 1024,1024
io.DisplaySize: 2981.00,766.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 10.00,13.00
style.WindowBorderSize: 1.00
style.FramePadding: 10.00,6.00
style.FrameRounding: 2.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 12.00,7.00
style.ItemInnerSpacing: 11.00,4.00

Details:

What's the Proper way to render custom text or custom items in the body of a TreeNode :

I am creating a general Tree style console application and want to be able to do more then the standard TreeNode label that TreeNode provides.

For example id like to be able to have the Arrow, Blue text, And then a white colon
Tree Screenshot
The current solution is

ImGui::PushID(KeyVal);
bool IsOpen = ImGui::TreeNode("");
ImGui::SameLine();
ImGui::TextColored(Color, "%s", KeyVal);
ImGui::SameLine(0, 0);
ImGui::Text(": ");
if (IsOpen) 
{
	// ...
	ImGui::TreePop();
}
ImGui::PopID();

But there's one fairly glaring issue with this. Its that the Text "SubObject" Is far too close to the Arrow. When i add Text into the Label the spacing looks correct. But for some reason things behave slightly differently when you pass in a blank label. I'm aware i can probably just manually set the X Cursor position to be the start of the line + ImGui::GetTreeNodeToLabelSpacing(), Or find the magic value to indent by. But I am just wondering if there is a cleaner way to go about it.

Screenshots/Video:

UnrealEditor-Win64-DebugGame_4KYRm7E8p7 UnrealEditor-Win64-DebugGame_E3XPtNqZgO

Minimal, Complete and Verifiable Example code:

// Here's some code anyone can copy and paste to reproduce your issue
ImGui::PushID(KeyVal);
bool IsOpen = ImGui::TreeNode("");
ImGui::SameLine();
ImGui::TextColored(Color, "%s", KeyVal);
ImGui::SameLine(0, 0);
ImGui::Text(": ");
if (IsOpen) 
{
	// ...
	ImGui::TreePop();
}
ImGui::PopID();
@kalebs-anotheraxiom kalebs-anotheraxiom changed the title proper way to render custom text or custom items in the body of a TreeNode proper way to render custom text or custom items in the "key"/"label" of a TreeNode Apr 18, 2024
@kalebs-anotheraxiom kalebs-anotheraxiom changed the title proper way to render custom text or custom items in the "key"/"label" of a TreeNode What's the proper way to render custom text or custom items in the "key"/"label" of a TreeNode Apr 18, 2024
@kalebs-anotheraxiom kalebs-anotheraxiom changed the title What's the proper way to render custom text or custom items in the "key"/"label" of a TreeNode What's the proper way to render custom text or custom items in the "key"/"label" of a TreeNode? Apr 18, 2024
@GamingMinds-DanielC
Copy link
Contributor

GamingMinds-DanielC commented Apr 18, 2024

I don't think there is a "clean" way to do this. If you want to replicate the offset exactly, you can find how to calculate it in the first few lines of ImGui::TreeNodeBehavior(). Doable, but not ideal in case this implementation ever changes.

Still a hack, but maybe a bit cleaner since you won't need to replicate calculations: you could add a singular space as a label and adjust the cursor position by the width of that space. Still better (in case you want f.e. navigation rects of the correct size): you can submit a full size label with all characters replaced by spaces. and adjust the cursor position by the entire text width. That should work as long as you don't use a proportional custom font.

@ocornut ocornut added the tree tree nodes label Apr 18, 2024
@ocornut
Copy link
Owner

ocornut commented Apr 18, 2024

It seems like a bug to me that TreeNode("##EmptyLabel") doesn't allow for that by default.

@ocornut
Copy link
Owner

ocornut commented Apr 18, 2024

I'm sincerely surprised this has not been submitted before.

By sheer accident, with the default style settings if you do what you did (TreeNode("") + SameLine()) it looks correct, but it's only accidentally because ItemSpacing.x = FramePadding.x * 2 with default settings. This is the reason I haven't noticed that before :(

If I rewind history, the code was notably modified in 370de41, some refactor 4006fb7, split layout vs interact bb in c381d58, The later is what introduced the (label_size.x > 0.0f) test. We are talking ancient times (#282) but that specific change wasn't exactly the main point of the commit.

I'll push a fix soon.

@kalebs-anotheraxiom
Copy link
Author

kalebs-anotheraxiom commented Apr 18, 2024

:(
Well that's the beauty of open source, Eventually someone's gonna use every line of code at one point or another so stuff like this will get caught. Glad I could help out and make this project just a little bit better.

Ill probably end up going with some sort of space padded solution to maintain the ability to click on the label or just doing it via TreeNodeBehavior so i can get more finetune control on the bounding boxes

@ocornut
Copy link
Owner

ocornut commented Apr 18, 2024

Ill probably end up going with some sort of space padded solution to maintain the ability to click on the label or just doing it via TreeNodeBehavior so i can get more finetune control on the bounding boxes

You probably want to use ImGuiTreeNodeFlags_SpanAvailWidth here, and possibly ImGuiTreeNodeFlags_AllowOverlap if you also need to add e.g. SmallButton() on the same line.

ocornut added a commit that referenced this issue Apr 18, 2024
…l") may properly be used with SameLine(0,0). (#7505, #282)

Also adjust some of the interact_bb padding, arbitrary interact padding not meaningful as empty label is likely to be followed by extra item. User likely to use ImGuiTreeNodeFlags_SpanAvailWidth.
@ocornut
Copy link
Owner

ocornut commented Apr 18, 2024

I've pushed a fix 361432a however this is a breaking fix, and I need to share my reasoning.

First of all, we want TreeNode("Hello"), SameLine(), Text("World") to be unaltered since this is a frequent pattern and it works. That's for sure.

// Old code
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x * 2 : 0.0f);  // Include collapsing arrow
layout_width = text_width;

I tried two approaches:

// New 1
const float text_width = g.FontSize + label_size.x + padding.x * 2;
layout_width = text_width;

New 1 embeds the arrow padding. It's standard and doesn't look hacky. But it breaks every TreeNode(""), SameLine() use which needs to be changed into TreeNode(), SameLine(0,0).
Pros: it's fairly consistent.
Pros: it visibly breaks regardless of styling value: issue not hidden in default style.
Cons: it visibly breaks regardless of styling value: issue not hidden in default style. :)

// New 2
const float text_width = g.FontSize + label_size.x + padding.x * 2;
layout_width = text_width + (label_size.x > 0.0f ? 0.0f : -style.ItemSpacing.x);

New 2 tries to undo the effect of SameLine().
Pros: it breaks less case.
Cons: it's less consistent, it'sweird and I've learned enough about the troubles of selectable and treenode doing inconsistent hacks that I would prefer to stay clear of them.

So I went for New 1. Which is more breaking, but ultimately this idiom is not used by everyone.

treenode_padding

There's an additional quirk which is that interact_bb is altered differently when label_size.x but I think it does make sense as when you use an empty label you are likely to add an immediately neighbor item, and if that item is interactive (a button) you need to avoid tree node overlapping it. Either way as mentioned users of TreeNode("") are likely to use ImGuiTreeNodeFlags_SpanAvailWidth and ImGuiTreeNodeFlags_AllowOverlap anyhow.

PS: There are no matches for neither TreeNode("") and TreeNode("##xxx"); in the demo code.

ocornut added a commit to ocornut/imgui_test_engine that referenced this issue Apr 19, 2024
@ocornut
Copy link
Owner

ocornut commented Apr 19, 2024

Added a test ocornut/imgui_test_engine@fac000b

Closing as solved!

@ocornut ocornut closed this as completed Apr 19, 2024
@kalebs-anotheraxiom
Copy link
Author

🥳 Glad I was able to help! ImGUI is such a cool project and I love improving the tools I use

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tree tree nodes
Projects
None yet
Development

No branches or pull requests

3 participants