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

Modifying text contents of active InputText #3878

Open
wolfgang371 opened this issue Mar 4, 2021 · 2 comments
Open

Modifying text contents of active InputText #3878

wolfgang371 opened this issue Mar 4, 2021 · 2 comments

Comments

@wolfgang371
Copy link

I have a use case where I want to be able to modify the currently active InputText. You already proposed a workaround in #3290, calling ClearActiveID() (see workaround 2 below), which I think is sort of a counterpart to SetKeyboardFocusHere().
I also came up with another (ugly) workaround, just blinking a temporary InputText for the sake of switching the focus (see workaround 1 below).
I know either is currently necessary since you internally buffer the text in InputText, but nevertheless they both feel like workarounds to me. What do you think about adding an internal dirty flag to TextBuffer (comparable to the ones you have for the InputText callbacks anyway), which would be set by any TextBuffer modification and consumed on the next InputText rendering..? This might be more intuitive to use and also match better the stateless GUI philosophy.

If this is not an option to you - would you consider making the ClearActiveID() public (since it's on the same level as SetKeyboardFocusHere(), which is public)? :)

class ModifyInputText
    def initialize
        @text_buffer = ImGui::TextBuffer.new(64)
    end
    def paint
        ImGui.set_keyboard_focus_here # give permanent focus to following input_text
        if ImGui.input_text("a", @text_buffer, ImGui::ImGuiInputTextFlags::EnterReturnsTrue)
            modify # works because "enter" removes keyboard focus
        end
        if ImGui.is_item_active && ImGui.is_key_pressed(SF::Keyboard::Key::Insert.value)
            # workaround #1 - to make above input_text listen again to @text_buffer
            steal_focus

            # workaround #2
            # ImGui.clear_active_id # internal API, not exposed by crystal-imgui

            modify # works because we manually took away keyboard focus
        end
    end
    def modify
        puts(@text_buffer.to_s)
        @text_buffer.clear # if corresponding input_text has focus, this has no effect to it
        @text_buffer << "bla" # same
    end
    def steal_focus
        ImGui.set_keyboard_focus_here # this takes the focus from above input_text
        dummy = ImGui::TextBuffer.new(64)
        ImGui.input_text("b", dummy) # works but blinks; invisible_button doesn't have a keyboard focus, everything else is visible
        ImGui.set_item_allow_overlap
    end
end

(Crystal again, sorry)

@ocornut ocornut changed the title (Again) modifying InputText Modifying text contents of active InputText Mar 5, 2021
@ocornut
Copy link
Owner

ocornut commented Mar 5, 2021

Would #2890 solve your problem?
Been considering merging this but also add a InputText flags to temporary "trigger" this behavior as well.

if ImGui.is_item_active && ImGui.is_key_pressed(SF::Keyboard::Key::Insert.value)

Have you considered modifying the buffer inside the InputText callback, by using ImGuiInputTextCallbackData::InsertChars() etc?
Although not perfect this is the currently officially supported way or modifying an active buffer.
There are three callbacks: ImGuiInputTextFlags_CallbackAlways, ImGuiInputTextFlags_CallbackCompletion, ImGuiInputTextFlags_CallbackHistory, the two later ones are hardcoded to trigger on certain keys (TAB, Up/Down) while Always can be used for your own check? I think there are certainly ways to improve this system but I need to know if you tried using it.

would you consider making the ClearActiveID() public

I think this is a XY Problem. We don't need to make all internals public, but you may need to figure a path for your language bindings (generated or not) to allow you to access internals when needed.

@wolfgang371
Copy link
Author

wolfgang371 commented Mar 5, 2021

Would #2890 solve your problem?

I understand the proposal is to extend InputText by a flag to allow re-initialization. This would work for me with a but: I need a helper variable since I need to take the decision at another place in the code, not during drawing of the widget (as in my sample code). From my point of view a more elegant solution would be what I proposed: imgui keeps track transparently if the TextBuffer was modified and reinitializes InputText automatically once in this case.

Have you considered modifying the buffer inside the InputText callback, by using ImGuiInputTextCallbackData::InsertChars() etc?

Indeed this is what I've currently implemented, but this feels quite awkward for my use case since I'm not interested in the entered characters in the first place.

I think this is a XY Problem

:) I was not familiar with that term, but it also was my understanding. I really want to have a TextBuffer change have automatic effect on it's InputText, independent of its active state (this is my X). Making ClearActiveID() public is one possible Y.

ocornut added a commit that referenced this issue Feb 7, 2024
Very highly requested feature (#6962, #5219, #3290, #4627, #5054, #3878, #2881, #1506, #1216, #968).
Also useful for interactive completion/selection popups (#2057, #718)
Based on @kudaba PR. Design for Inputtext V2 should make this obsolete.
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