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

Input textbox of arbitrary length #1008

Closed
Makinami opened this issue Feb 4, 2017 · 11 comments
Closed

Input textbox of arbitrary length #1008

Makinami opened this issue Feb 4, 2017 · 11 comments

Comments

@Makinami
Copy link

Makinami commented Feb 4, 2017

I want to implement input textbox for arbitrary length buffer that would grow when needed. I am already resizing my buffer when it approaches its capacity, but as ImGui is internally keeping a copy of original data (together with its size) as long as it is active, usable buffer size remains the same until I click somewhere else and back on the textbox to reactivate it.

Is there any way to force ImGui to synchronize/update its internal buffer with the one provided by my without the need to click, nor loosing cursor position? I wanted to try SetActiveId, but it isn't part of the public interface.

PS. I am aware that whatever the solution, pasting becomes a problem when we allow for any buffer to change size.

@ocornut
Copy link
Owner

ocornut commented Feb 4, 2017

Hello,

Sorry it is isn't supported at the moment. There's definitively a need to support that sort of patterns (to work more naturally with say, user storage in a std::string along with clipboard pasting of any size).

At some point earlier on InputText() was about to update its size but that was actually tied to a bug that really needed fixing. That code has become muddled in a series of features and needs to be rewritten. This is among the thing that will be keep in mind when doing so.

The regular workaround for now is just to provide a buffer large enough, sorry!

As you pointed out, manipulating internals or the code itself might lead to acceptable workarounds, you can always include imgui_internal.h if you want to call those functions and play with that.
It is possible that calling edit_state.Text.resize() and edit_state.InitialText.resize() could allow for it. I may dig into that later but being too busy this month to engage in this part of the code :)

( If you need a serious text editor you may attempt to integrate Scintilla:
#108 )

@Makinami
Copy link
Author

Makinami commented Feb 6, 2017

Hi, thanks for reply.

For now, even though such textbox would be useful, it's not of utmost importance so I've moved on. But it seems interesting so I will surely return to the problem.

I will post if I find any suitable, more general solution.

@Pagghiu
Copy link
Contributor

Pagghiu commented Feb 27, 2017

I have been hitting the same issue here described.
I am growing strings as needed, looking at their size vs. their capacity.

My temporary fix is to add Text.resize() inside ImGui::InputTextEx

 if (io.InputCharacters[0])
 {
            if(buf_size + 1 != edit_state.Text.Size)
            {
                edit_state.Text.resize(buf_size+1);
            }
//...
}

Could such a change make any sense to be merged in the master?

@Flix01
Copy link

Flix01 commented Feb 28, 2017

@Pagghiu: Does this work when text is copied/pasted too?

Moreover, in ImGuiTextEditState 3 buffers are present:

ImVector<ImWchar>   Text;                       // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
ImVector<char>      InitialText;                // backup of end-user buffer at the time of focus (in UTF-8, unaltered)
ImVector<char>      TempTextBuffer;

I didn't look at the code, but Is it safe to just resize one of them ?

P.S. Maybe it's possible to add an ImGui::InputText(...) overload that takes an ImGuiTextBuffer, so that it's resizable. Maybe we can add an optional last argument to ImGui::InputTextEx(...) that takes that buffer, so that we can keep most of its implementation as it is.

@Pagghiu
Copy link
Contributor

Pagghiu commented Feb 28, 2017

@Flix01 you're right, there are issues with copy&paste.
I will have a deeper look at ImGui::InputText(...) to figure out how to make copy and paste work.

@SSBMTonberry
Copy link

SSBMTonberry commented Dec 10, 2017

I was looking after a way to resize the Input textbox myself(expand when needed), and here is my solution:
Included the imgui_internal.h in the top.

Note: myText is a std::string.
I'm using a InputTextMultiline, but should be the same code:

    std::string clipText = (ImGui::GetClipboardText() != nullptr) ? ImGui::GetClipboardText() : "";
    size_t clipSize = clipText.length();
    size_t size = myText.length()+clipSize+5;
    char newText[size];
    strncpy(newText, myText.c_str(), sizeof(newText));

    ImGui::InputTextMultiline("Them characters mate", newText, size);//, ImVec2(sf::Vector2<int>(300, 300))), ImGuiInputTextFlags_::ImGuiInputTextFlags_CallbackAlways, repl_callback);

    //Allows the textbox to expand while active.
    ImGuiTextEditState& edit_state = ImGui::GetCurrentContext()->InputTextState;
    edit_state.Text.resize(size);
    edit_state.InitialText.resize(size);
    
    myText = newText;

Seems to work fine, but I just made it work, so might be something I haven't thought about.

@Flix01
Copy link

Flix01 commented Dec 10, 2017

@SSBMTonberry: Good job! (and non-intrusive) 😃

I've not tested it yet, but maybe there could be some problem when using two different instances:

Q) How can we be sure that "clipText" belongs to "Them characters mate" and not to the another input text ?
A) We don't know, but InputTextMultiline(...) can just skip it and that's OK.

Q) Does ImGui::GetCurrentContext()->InputTextState always point to the input text in the previous line (or only if it's focused) ?

Q) [Optimization] Would it be possible to just append some '\0' chars to the string, instead of deep copying it every frame?

However basically I think this kind of solution can actually work, since the only question I can think that can break it is the second. 😃

@SSBMTonberry
Copy link

SSBMTonberry commented Dec 10, 2017

@Flix01: To be honest, I started tinkering with ImGui for the first time yesterday, so there is naturally a lot of things I don't know for sure yet. What I have figured, though, is that the code I posted is causing issues for other code parts when used. For instance, I get a crash when simply selecting the bottom textbox (the one displaying the hex value of the color) of ColorPicker4 which is in another popup.
Great questions you've asked, but I don't think I'm in the position to answer them, yet 😛

My idea of the code though, was to make the InputTextMultiline field expand to a size that made sure you always could paste in values as well as typing, but as I have figured my code has issues. Works fine when "isolated", but can cause crashes when using controls added later.

EDIT:
I solved the crashes, it seems, by altering this part of the code(adding IsWindowFocused() check)

if(ImGui::IsWindowFocused())
 {
     ImGuiTextEditState &edit_state = ImGui::GetCurrentContext()->InputTextState;
     edit_state.Text.resize(size);
     edit_state.InitialText.resize(size);

     myText = newText;
 }

@Flix01
Copy link

Flix01 commented Dec 11, 2017

I solved the crashes, it seems, by altering this part of the code(adding IsWindowFocused() check)

I can't test it yet, but maybe something like: if (ImGui::IsItemActive()) is a more robust solution (it should return true when the last used ImGui widget is active).

From imgui.h:

IMGUI_API bool          IsItemActive();                                                     
// is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false)

Can you please try and see if it still works ?

@Flix01
Copy link

Flix01 commented Dec 12, 2017

Made a small gist here, mostly for testing purposes.

But if the ImGui::InputText(...) internals are going to change in the future, maybe it's a wise choice to wait... 😕

@ocornut
Copy link
Owner

ocornut commented Aug 22, 2018

I have pushed a solution for this problem, described in #2006.
Closing this topic. feel free to comment in #2006 to state if it works for you or if you have other feedback.

@ocornut ocornut closed this as completed Aug 22, 2018
ocornut added a commit that referenced this issue Aug 22, 2018
…h Escape key. Avoid over-allocating for InitialText storage. (#2006, #1443, #1008)
ocornut added a commit that referenced this issue Aug 22, 2018
ocornut added a commit that referenced this issue Oct 12, 2018
ocornut added a commit that referenced this issue Mar 12, 2019
ocornut added a commit that referenced this issue Dec 25, 2019
ocornut added a commit that referenced this issue Feb 4, 2020
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

5 participants