imgui
imgui copied to clipboard
InputText, InputInt, InputFloat: add ImGuiInputTextFlags_NoLiveEdit flag
ImGuiInputTextFlags_NoLiveEdit
(tentative name) would only apply the value when pressing Return or intentionally changing focus via Tab, as opposed to the current behaviour of applying the value as it is being edited. How about when unintentionally losing focus?
(ref. #700)
That's ok. That's how windows and OS X handles it On Thu, Jun 16, 2016 at 16:14, omar [email protected] wrote:
ImGuiInputTextFlags_NoLiveEdit (tentative name) would only apply the value when pressing Return or intentionally changing focus via Tab, as opposed to the current behaviour of applying the value as it is being edited. How about when unintentionally losing focus?
(ref. #700 https://github.com/ocornut/imgui/issues/700)
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ocornut/imgui/issues/701, or mute the thread https://github.com/notifications/unsubscribe/AAVRxqolsk47I99TmR3Z1JuP55sWPUtkks5qMa6qgaJpZM4I3w-k .
Setting the xyz values of an object is something you don't live update on, otherwise the object will be jumping about as you type :)
I think live update makes more sense for string/text values than for float/int. I am considering changing the default so that for float/int it wouldn't live update by default. Will poll people on twitter for that.
FYI started working on this but it is hard to accomplish 100% in an imgui context.
We can only write back within the InputXXX
call so it means the function needs to tell that it is being stolen focus. While it is feasible to cover the most common case (such as tabbing, or explicitly clicking outside) some other cases are harder (any code explicitly stealing ActiveId would be a problem, or user stopping to render the widget/window would allow lose the data but that is less of a problem). Looking into it.
I don't think you should have different defaults depending on the type of values (string or float etc). I think it should be consistent in the API. Maybe make live editing not the default and add a ImGuiTextEditFlags_LiveEdit?
Putting this on hold until I do a big cleanup to add UTF-8 to stb_textedit and ditch the back and forth conversions. The code before the is too risky and bug-prone.
Basically we need to store the data so that when another text widget submitted earlier steals focus and starts editing, the old data is still available for the next recently-been-editing widget to apply back to the user variable. So that means likely we'll need to have two text buffers in memory and alternate their use to avoid extra copying of data. Currently InputText() is too complex because of how it has to work-around limitation of stb_textedit while staying efficient for large text, so I am going to fix that first (not a big big change).
👍 Ran into this as well for a property editor. I was able to work around it. However, wanted to chime so I can stay up to date on this topic.
same here also for a property editor. what was your work around ? using intermediate buffer with live edit + copying into edited value when focus lost / tab / enter ?
Is #2034 / the new IsItemEdited()
relevant here?
It is relevant as being useful but it doesn't technically solve this issue #701 as the value is still always written back to the user's buffer at the moment.
+1 Having the same problem. Would be nice to achieve "normal" behavior without workarounds. Live updates are problem for property editors
Any update on this?
Hello, I have the same problem with my own property editor. Any update on this? or is there any known workaround to disable Live edit?
I recently needed this feature as well, mainly due to the usual undo/redo shenanigans where I would like to only get the updated value on enter/focus lost etc. and not edit the actual string (yet). I wasn't quite happy with the solution of preemptively copying the string into e.g. a static variable before passing it in, so I did a little digging and implemented my own little hacky NoLiveEdit flag.
Now I am well aware that implementing this feature properly while keeping edge cases, backwards compatibility etc. in mind is a huge task and I do not want to imply that my hacky solution does that AT ALL. However it required such a tiny little change that I would like to discuss is anyways. On one hand, who knows, maybe it is actually a good idea that might help with implementing the proper solution. On the other hand, if there are obvious flaws that I could not find, knowing about those would be good as well (mostly for my own benefit, I guess).
What I did is the following: In the imgui source, the only change I had to do was, of course, add the NoLiveEdit flag and if it was set, block all text changes from being written back to user buffer like so (imgui_widgets.cpp)
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
if (apply_new_text != NULL && (flags & ImGuiInputTextFlags_NoLiveEdit) == 0)
{
//...
}
(Technically there is at least one other place, that could be skipped. Where the internal buffer is compared to the user buffer to detect if any changes have been made. However I didn't bother for now). While editing the InputText we now exclusively work on the internal copy. As far as I can tell, this does not impact the behaviour of the widget at all, except for the fact that the resize callback will never be called which is what we want anyways.
Now we somehow have to access the changes, once the editing is actually finished. To accomplish that I make use of the (afaik already undesired) TextDeactivateHook feature that was added, so the internal text buffer can still be accessed after the InputText became inactive, like so
ImGui::InputText("Name", &model->Name, ImGuiInputTextFlags_NoLiveEdit);
if (ImGui::IsItemDeactivatedAfterEdit()) {
auto& state = ImGui::GetCurrentContext()->InputTextDeactivatedState;
//Do something with 'state.TextA.Data'/'state.TextA.Size'
}
In my case I neatly hid that admittedly undesired context access into a little wrapper function
std::string_view GetLastDeactivatedText()
{
auto& state = ImGui::GetCurrentContext()->InputTextDeactivatedState;
return std::string_view(state.TextA.Data, state.TextA.Size);
}
This almost works already, with the exception of pressing 'Esc' which should discard the changes. Currently 'Esc' still triggers the IsItemDeactivatedAfterEdit()
. We can easily bypass this by making use of the fact that InputText returns true on pretty much all actions except 'Esc'. That is, pressing Enter, Tab, or clicking somewhere outside the widget (including into other widgets) all return true, while pressing 'Esc' returns false.
We can then do this:
bool update = ImGui::InputText("Name", &model->Name, ImGuiInputTextFlags_NoLiveEdit);
if (ImGui::IsItemDeactivatedAfterEdit() && update) {
auto& state = ImGui::GetCurrentContext()->InputTextDeactivatedState;
//Do something with 'state.TextA.Data'/'state.TextA.Size'
}
And that's about it. While it is a little more work in user code than just adding the flag, the code "overhead" of the IsItemDeactivatedAfterEdit
seems acceptable to me. I'm not entirely sure about accessing InputTextDeactivatedState
directy. That may or may not be a bad idea.
Like I said, I do not necessarily expect this to be the one big great solution. It is quite impossible for me to judge the impact this has on the overarching code base and existing user code. I know there are also other open issue that are, in some way or another, related to this feature. However the only issue I encountered so far is a one-frame flicker when tabbing out of the widget. That being said, I didn't really check the usage of most other flags/flag-combinations. Just wanted to get it out there in case it helps, since it was such a little change.