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

Preview value for InputText #7208

Closed
eugeneko opened this issue Jan 7, 2024 · 7 comments
Closed

Preview value for InputText #7208

eugeneko opened this issue Jan 7, 2024 · 7 comments

Comments

@eugeneko
Copy link

eugeneko commented Jan 7, 2024

Version/Branch of Dear ImGui:

docking

Details:

I would like to provide preview value for InputText. What would be the simplest way to achieve that?

E.g. I have text box with "some/very/long/long/path/to/file", but I would like to show ".../path/to/file" instead as long as user is not editing the text. When user starts editing the text, the "real" value is displayed.

I feel like there should be some trick to do that with existing InputText widget. I can maybe replace text value on the fly, but I am vary of messing this up and making text box wacky.

@ocornut
Copy link
Owner

ocornut commented Jan 7, 2024

Doesn’t InputTextWithHint() do what you want ?

@eugeneko
Copy link
Author

eugeneko commented Jan 8, 2024

Doesn’t InputTextWithHint() do what you want ?

It is really close but it does not do what I want.

Currently, the hint is visible when there is no data in the buffer or internal storage, while I want my "hint" to be visible when input text is not focused regardless of the buffer contents.

Basically, I want to display different text when it's "focused and editing" and when it's not.

@ocornut
Copy link
Owner

ocornut commented Jan 8, 2024

Basically, I want to display different text when it's "focused and editing" and when it's not.

It's not possible with InputText().

A workaround may be to write a custom widget that switched to an input text on click.
Copy DragScalar() and strip it from drag behavior: (remove DataTypeGetInfo, DragBehavior, assume temp_input_allowed always true, simplify the different way of activation to keep the one you need, and rely on TempInputScalar).

bool InputTextWithPreviewValue(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0)
{
    using namespace ImGui;
    ImGuiWindow* window = GetCurrentWindow();
    if (window->SkipItems)
        return false;

    ImGuiContext& g = *GImGui;
    const ImGuiStyle& style = g.Style;
    const ImGuiID id = window->GetID(label);

    const ImVec2 label_size = CalcTextSize(label, NULL, true);
    const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(CalcItemWidth(), label_size.y + style.FramePadding.y * 2.0f));
    const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));

    ItemSize(total_bb, style.FramePadding.y);
    if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
        return false;

    const bool hovered = ItemHoverable(frame_bb, id, g.LastItemData.InFlags);
    bool make_active = false;
    if (g.ActiveId != id)
    {
        if ((hovered && IsMouseClicked(0, id)) || g.NavActivateId == id)
        {
            make_active = true;
            g.NavActivateId = id;
            g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
        }
    }

    if (g.ActiveId == id || make_active)
    {
        g.CurrentWindow->DC.CursorPos = frame_bb.Min;
        return InputText(label, buf, buf_size, flags);
    }

    // Draw frame
    const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
    RenderNavHighlight(frame_bb, id);
    RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding);

    const char* preview_value = "Click me"; // FIXME: Transform path however you want

    if (g.LogEnabled)
        LogSetNextTextDecoration("{", "}");
    RenderTextClipped(frame_bb.Min, frame_bb.Max, preview_value, NULL, NULL, ImVec2(0.5f, 0.5f));

    if (label_size.x > 0.0f)
        RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);

    IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Inputable);
    return false;
}

As your issue relate specifically to truncating a path names: both right-alignment (#1442) and different forms of text compaction (e.g. #5791 (comment)) would potentially be solution, but neither are implemented yet and I don't have ETA though I am hoping both will happen this year.

@ocornut
Copy link
Owner

ocornut commented Feb 5, 2024

Closing as answered with code (no reaction 🤷‍♂️ )

@ocornut
Copy link
Owner

ocornut commented Dec 9, 2024

On the specific of displaying the right portion of path, ImGuiInputTextFlags_ElideLeft has now been added:
#1442 (comment)

image

I believe the discussion in this topic went a bit off-rail, as in my opinion a more complicated "XY Problem" suggestion was suggested and I went along with it. For this specific case then ImGuiInputTextFlags_ElideLeft is a better solution and is now supported.

@eugeneko
Copy link
Author

eugeneko commented Dec 9, 2024

@ocornut Thanks, this specific case is indeed mitigated by ImGuiInputTextFlags_ElideLeft.

While it does not look as nice as manually compacted value (e.g. elipsis to indicate truncation), it goes from "awful" to "okay" which is big improvement. This new flag is good enough for me.

@ocornut
Copy link
Owner

ocornut commented Dec 9, 2024

I didn't add the ellipsis yet but I intend to, and it will be part of an upcoming refactor of text functions.

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

No branches or pull requests

2 participants