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

Icons in the tree #282

Closed
emoon opened this issue Jul 22, 2015 · 13 comments
Closed

Icons in the tree #282

emoon opened this issue Jul 22, 2015 · 13 comments
Labels

Comments

@emoon
Copy link
Contributor

emoon commented Jul 22, 2015

Hi,

I wonder if it is currently possible to have custom icons in the tree view? (that would be infront of the text and for the folded/unfolded state)

Think of something like an explorer view/Visual Studio Workspace of files view

@ocornut
Copy link
Owner

ocornut commented Jul 22, 2015

There's a few way you can do that but the correct one will have to wait until I make a change to TreeNode - I started it but shelved it.

Currently if you do TreeNode("##hiddenlabel", ...); SameLine(0, 0); you can already add stuff.

treenode sameline

There's will several issues:

  • Tree node will only react to click over roughly the width of the label (this was intentional to allow other widgets such as buttons to be used on the same line).
  • Undesired horizontal spacing (visible here)
  • If your widget have bigger height, the tree node won't be correctly vertically aligned.

So what we need to do is:

  • Make it an option up to decide the width of the hit box for input processing (up to label or up to a certain X position, typically edge of the screen but it can be shorter also). I don't yet know what form this option can take, how it'll be specified and stored.
  • Fix the undesired horizontal spacing.
  • Fix the height issues, not sure what's the correct way here. User may want to adjust the tree node height to match other widget height in some instances (e.g. adding a bigger icon) but not in other instances (e.g. adding a tree node on the side of a very large widget), so it may be an option as well or maybe to simplify the height can be capped to widget-height by default so the two typical height will be text-height and widget-height.

You can temporarily hack around your way from those problems by passing a tree node label full of spaces to get a larger hit box, and moving the cursor SetCursorPosX(GetCursorPosX() - 20.0f) after SameLine.

@emoon
Copy link
Contributor Author

emoon commented Jul 22, 2015

Thanks for the reply.

I will go for your temporary hack for now.

@ocornut
Copy link
Owner

ocornut commented Jul 22, 2015

If you use spaces for id remember to do a prior PushId/PopId to make the full-id unique.

@emoon
Copy link
Contributor Author

emoon commented Jul 22, 2015

Will do. Thanks!

@ocornut
Copy link
Owner

ocornut commented Aug 29, 2015

I wonder if it is currently possible to have custom icons in the tree view? (that would be infront of the text and for the folded/unfolded state)

Did you mean you wanted to remove the ">" thingie and draw an icon instead?

@ocornut
Copy link
Owner

ocornut commented Aug 29, 2015

Btw you can rewrite a pretty much feature-identical custom tree node this way.
The main problem with that approach is that it is probably 10+ times slower than the version that pokes at data structure directly. (haven't measure, just guessed). Because of going through those public apis. Using imgui_internal.h would be beneficial.

ImGui::Begin("Custom Tree Node");

bool MyTreeNode(const char* label)
{
    const ImGuiStyle& style = ImGui::GetStyle();
    ImGuiStorage* storage = ImGui::GetStateStorage();

    ImU32 id = ImGui::GetID(label);
    int opened = storage->GetInt(id, 0);
    float x = ImGui::GetCursorPosX();
    ImGui::BeginGroup();
    if (ImGui::InvisibleButton(label, ImVec2(-1, ImGui::GetWindowFontSize()+style.FramePadding.y*2)))
    {
        int* p_opened = storage->GetIntRef(id, 0);
        opened = *p_opened = !*p_opened;
    }
    bool hovered = ImGui::IsItemHovered();
    bool active = ImGui::IsItemActive();
    if (hovered || active)
        ImGui::GetWindowDrawList()->AddRectFilled(ImGui::GetItemBoxMin(), ImGui::GetItemBoxMax(), ImColor(ImGui::GetStyle().Colors[active ? ImGuiCol_HeaderActive : ImGuiCol_HeaderHovered]));

    // Icon, text
    ImGui::SameLine(x);
    ImGui::ColorButton(opened ? ImColor(255,0,0) : ImColor(0,255,0));
    ImGui::SameLine();
    ImGui::Text(label);
    ImGui::EndGroup();
    if (opened)
        ImGui::TreePush(label);
    return opened != 0;
};

if (MyTreeNode("Hello"))
{
    ImGui::Text("blah");
    if (mytreenode("blah"))
    {
        ImGui::Text("Hello");
        ImGui::TreePop();
    }
    ImGui::Text("blah");
    ImGui::TreePop();
}

ImGui::End();

(gifcam is creating undesired transparent color in the GIF, the color square should be green when it's not red)
custom tree node

@ocornut
Copy link
Owner

ocornut commented Aug 29, 2015

And that's the exact same feature but using some internal data structure.

#include <imgui_internal.h>
bool MyTreeNode(const char* label)
{
    ImGuiState& g = *GImGui;
    ImGuiWindow* window = g.CurrentWindow;

    ImU32 id = window->GetID(label);
    int opened = window->StateStorage.GetInt(id, 0);
    ImVec2 pos = window->DC.CursorPos;
    if (ImGui::InvisibleButton(label, ImVec2(-1, g.FontSize + g.Style.FramePadding.y*2)))
    {
        int* p_opened = window->StateStorage.GetIntRef(id, 0);
        opened = *p_opened = !*p_opened;
    }
    bool hovered = ImGui::IsItemHovered();
    bool active = ImGui::IsItemActive();
    if (hovered || active)
        window->DrawList->AddRectFilled(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max, window->Color(active ? ImGuiCol_HeaderActive : ImGuiCol_HeaderHovered));

    // Icon, text
    float button_sz = g.FontSize + g.Style.FramePadding.y*2;
    window->DrawList->AddRectFilled(pos, ImVec2(pos.x+button_sz, pos.y+button_sz), opened ? ImColor(255,0,0) : ImColor(0,255,0));
    ImGui::RenderText(ImVec2(pos.x + button_sz + g.Style.ItemInnerSpacing.x, pos.y + g.Style.FramePadding.y), label);
    if (opened)
        ImGui::TreePush(label);
    return opened != 0;
}

@ocornut
Copy link
Owner

ocornut commented Aug 29, 2015

Perhaps I can turn part of this, or actually the underlying behavior which does a little more, into a TreeNodeBehavior().

@ocornut
Copy link
Owner

ocornut commented Aug 29, 2015

Made some change so you can write a custom tree node that is more accurate in term of honoring Auto-Expand-Node-On-Logging and SetNextTreeNode** calls.

#include <imgui_internal.h>

bool MyTreeNode(const char* label)
{
    ImGuiState& g = *GImGui;
    ImGuiWindow* window = g.CurrentWindow;

    ImU32 id = window->GetID(label);
    ImVec2 pos = window->DC.CursorPos;
    ImRect bb(pos, ImVec2(pos.x + ImGui::GetContentRegionAvail().x, pos.y + g.FontSize + g.Style.FramePadding.y*2));
    bool opened = ImGui::TreeNodeBehaviorIsOpened(id);
    bool hovered, held;
    if (ImGui::ButtonBehavior(bb, id, &hovered, &held, true))
        window->DC.StateStorage->SetInt(id, opened ? 0 : 1);
    if (hovered || held)
        window->DrawList->AddRectFilled(bb.Min, bb.Max, window->Color(held ? ImGuiCol_HeaderActive : ImGuiCol_HeaderHovered));

    // Icon, text
    float button_sz = g.FontSize + g.Style.FramePadding.y*2;
    window->DrawList->AddRectFilled(pos, ImVec2(pos.x+button_sz, pos.y+button_sz), opened ? ImColor(255,0,0) : ImColor(0,255,0));
    ImGui::RenderText(ImVec2(pos.x + button_sz + g.Style.ItemInnerSpacing.x, pos.y + g.Style.FramePadding.y), label);

    ImGui::ItemSize(bb, g.Style.FramePadding.y);
    ImGui::ItemAdd(bb, &id);

    if (opened)
        ImGui::TreePush(label);
    return opened;
}

Until I add a mechanism to parametrize how far the hit-rectangle of a treenode.should reach, this is probably the best way to just make something fully custom, Not particularly great looking but it's not the type of code you would often look back at.

@emoon
Copy link
Contributor Author

emoon commented Aug 30, 2015

Neat :) Thanks!

ocornut added a commit that referenced this issue Nov 29, 2015
ocornut added a commit that referenced this issue Dec 13, 2015
…ly for widget sized line height). (followup to #414, #282)
@ocornut
Copy link
Owner

ocornut commented Dec 25, 2015

Closing this afaik the original post is answered. Ideally we'd simplify the code for MyTreeNode() further and improve forward compatibility, but it's not too bad now.

(EDIT adding midly related attachment after the fact so I can link to it from another forum)
layers

@tuket
Copy link

tuket commented Jan 20, 2024

This is very old... ImGui API has changed and this code doesn't work any more. Is there any more up to date sample code around?

@UnfinishedBusiness
Copy link

UnfinishedBusiness commented Feb 26, 2024

@tuket - Here is his function ported to version 1.90 WIP. You should be able to modify it to your needs

#include <imgui_internal.h>
    bool MyTreeNode(const char* label)
    {
        ImGuiContext& g = *ImGui::GetCurrentContext();
        ImGuiWindow* window = g.CurrentWindow;

        ImGuiID id = window->GetID(label);
        ImVec2 pos = window->DC.CursorPos;
        ImRect bb(pos, ImVec2(pos.x + ImGui::GetContentRegionAvail().x, pos.y + g.FontSize + g.Style.FramePadding.y*2));
        bool opened = ImGui::TreeNodeBehaviorIsOpen(id, ImGuiTreeNodeFlags_None);
        bool hovered, held;
        if (ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_PressedOnClick))
            window->DC.StateStorage->SetInt(id, opened ? 0 : 1);
        if (hovered || held)
            window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(held ? ImGuiCol_HeaderActive : ImGuiCol_HeaderHovered));

        // Icon, text
        float button_sz = g.FontSize + g.Style.FramePadding.y*2;
        window->DrawList->AddRectFilled(pos, ImVec2(pos.x+button_sz, pos.y+button_sz), ImGui::GetColorU32(opened ? IM_COL32(255,0,0,255) : IM_COL32(0,255,0,255)));
        ImGui::RenderText(ImVec2(pos.x + button_sz + g.Style.ItemInnerSpacing.x, pos.y + g.Style.FramePadding.y), label);

        ImGui::ItemSize(bb, g.Style.FramePadding.y);
        ImGui::ItemAdd(bb, id);

        if (opened)
            ImGui::TreePush(label);
        return opened;
    }

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 added a commit that referenced this issue Oct 15, 2024
…TreeNodeBehaviorIsOpen() (#4814, #5423, #282, #2958, #924)

+ Removed obsolete header checks for IMGUI_DISABLE_METRICS_WINDOW.
idbrii added a commit to idbrii/cpp-imgui that referenced this issue Mar 24, 2025
Includes my merged PRs and everything in my dev branch. Haven't tested
with it yet.

Changelog:
Test case for clip rect
HACK: more recent Windows SDK and VS2017; disable graph
Set size to amount of space required
Merge pull request ocornut#349 from maksw2/master
Merge pull request ocornut#347 from mgerhardy/341
Merge pull request ocornut#348 from mgerhardy/fixed-warning
Merge pull request ocornut#346 from mgerhardy/280
Merge pull request ocornut#345 from mgerhardy/322
Merge pull request ocornut#344 from rherilier/fix-gcc-warnings
Merge pull request ocornut#336 from rherilier/add-isusingviewmanipulate
Merge pull request ocornut#335 from RedSkittleFox/alternative_window
Merge pull request ocornut#334 from ocornut/fix-beginchildframe
dear imgui update and small fixes
Merge pull request ocornut#316 from Batres3/2DSupport
Merge pull request ocornut#326 from Sayama3/use-push-pop-id
Merge pull request ocornut#328 from georgeto/master
Merge pull request ocornut#330 from maritim/master
Merge pull request ocornut#331 from GiovanyH/patch-1
Merge pull request ocornut#318 from dougbinks/imgui_math_operators
Merge pull request ocornut#312 from kimidaisuki22/master
div 0 fixed
Merge pull request ocornut#301 from ZingBallyhoo/using-any
Merge pull request ocornut#300 from Clog41200/Configurable-limits
Merge pull request ocornut#298 from xDUDSSx/fix/rotation_circles
Merge pull request ocornut#297 from xDUDSSx/fix/vertical-aspect-scaling
Merge pull request ocornut#289 from ComputationalBiomechanicsLab/fix_isusing-ignores-setid
Merge pull request ocornut#291 from ocornut/fix_math_operators_include
Merge pull request ocornut#282 from MohitSethi99/master
Merge pull request ocornut#276 from pthom/virtual_destructors
Merge pull request ocornut#271 from idbrii/clip-parent
Merge pull request ocornut#270 from idbrii/btn-behaviour
Merge pull request ocornut#265 from mgerhardy/pr/fix-minor-formatting
Merge pull request ocornut#264 from mgerhardy/pr/div0
Merge pull request ocornut#269 from peter1745/hatched-line-thickness-enhancement
Merge pull request ocornut#259 from miyanyan/master
Merge branch 'master' of https://github.com/CedricGuillemet/ImGuizmo
update dear imgui
Merge pull request ocornut#256 from Aidiakapi/patch-1
Merge pull request ocornut#252 from aaronkirkham/master
Merge pull request ocornut#249 from rokups/rk/mouse-capture
Merge pull request ocornut#246 from mgerhardy/pr/viewmanipulate
removed commented code
fix click view cube
Merge pull request ocornut#231 from mgerhardy/master
Merge pull request ocornut#230 from mgerhardy/master
Merge pull request ocornut#228 from longod/master
Merge pull request ocornut#227 from madeso/master
AddBezierCubic
Merge pull request ocornut#226 from sherief/master
revert culling test commit
Merge pull request ocornut#203 from rokups/rk/misc-fixes
Merge pull request ocornut#212 from zhaijialong/fix-behind-camera-cull
Merge pull request ocornut#209 from VictorFouquet/fix_normalize
scale is always local
Merge pull request ocornut#202 from pezy/master
imguizmo namespace
Merge pull request ocornut#194 from JonathanHiggs/vcpkg-example
1.84 WIP
Merge pull request ocornut#197 from idbrii/seq-btn-color
Merge pull request ocornut#196 from idbrii/seq-big-handles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants