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

How to get both value_changed and enter_pressed events from the same InputText widget #2034

Closed
mizvekov opened this issue Aug 22, 2018 · 7 comments

Comments

@mizvekov
Copy link

I have a need to know (and be able to discriminate) when an InputText widget has it's value changed, and also when enter is pressed.

The need is for along the lines of allowing the user to select an item among a list by typing it in full and pressing enter, but also filter that list as the user types in.

Currently you get one or the other by passing the ImGuiInputTextFlags_EnterReturnsTrue flag.

We have all the information needed by the end of InputTextEx, it's just a matter of choosing which to return because we only return a single bool.
Getting that information through other ways using the api or looking at the internal state directly looks very convoluted, if feasible at all.

So would this be a good case for changing the API to return more information, or do you have a better alternative in mind?

@ice1000
Copy link
Contributor

ice1000 commented Aug 22, 2018

be able to discriminate

I believe you can do this via passing ImGuiInputTextFlags_ReadOnly

have a need to know when an InputText widget has it's value changed

If it's me I'd make a copy of the original char* and do a strcmp check each time when any key is pressed.

@ice1000
Copy link
Contributor

ice1000 commented Aug 22, 2018

Have you considered using ImGuiTextEditCallback? I see a lot of useful information inside.

imgui/imgui.h

Lines 1417 to 1443 in 5942c08

// Shared state of InputText(), passed to callback when a ImGuiInputTextFlags_Callback* flag is used and the corresponding callback is triggered.
struct ImGuiTextEditCallbackData
{
ImGuiInputTextFlags EventFlag; // One of ImGuiInputTextFlags_Callback* // Read-only
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
void* UserData; // What user passed to InputText() // Read-only
bool ReadOnly; // Read-only mode // Read-only
// CharFilter event:
ImWchar EventChar; // Character input // Read-write (replace character or set to zero)
// Completion,History,Always events:
// If you modify the buffer contents make sure you update 'BufTextLen' and set 'BufDirty' to true.
ImGuiKey EventKey; // Key pressed (Up/Down/TAB) // Read-only
char* Buf; // Current text buffer // Read-write (pointed data only, can't replace the actual pointer)
int BufTextLen; // Current text length in bytes // Read-write
int BufSize; // Maximum text length in bytes // Read-only
bool BufDirty; // Set if you modify Buf/BufTextLen!! // Write
int CursorPos; // // Read-write
int SelectionStart; // // Read-write (== to SelectionEnd when no selection)
int SelectionEnd; // // Read-write
// NB: Helper functions for text manipulation. Calling those function loses selection.
IMGUI_API void DeleteChars(int pos, int bytes_count);
IMGUI_API void InsertChars(int pos, const char* text, const char* text_end = NULL);
bool HasSelection() const { return SelectionStart != SelectionEnd; }
};

@mizvekov
Copy link
Author

mizvekov commented Aug 22, 2018

I believe you can do this via passing ImGuiInputTextFlags_ReadOnly

What I mean is I need to be able to tell value changed from enter_pressed, in other words a solution that adds another ImGuiInputTextFlag that simply makes the return value be 'value_changed | enter_pressed' would not be enough. ImGuiInputTextFlags_ReadOnly does not help me, the widget needs to be editable.

If it's me I'd make a copy of the original char* and do a strcmp check each time when, say, any key is pressed.

That's inefficient, I was hoping a solution where I wouln't need to manage an extra copy of the string.
Also EnterReturnsTrue makes it so the user buffer is only updated when enter is pressed, I'd need to look at imgui's internal edit buffer.

Have you considered using ImGuiTextEditCallback? I see a lot of useful information inside.

Yes, but it's not easy to tell from the callback when the value has been changed, it's not simple and I'm not sure it's feasible to do without keeping an extra copy around and comparing every time.

Maybe a bettter patch for imgui here would be a new CallbackData field that has the 'value_changed' information.

@ice1000
Copy link
Contributor

ice1000 commented Aug 22, 2018

Sorry for misunderstanding your requirement.

Maybe a bettter patch for imgui here would be a new CallbackData field that has the 'value_changed' information.

This looks like the best solution, which is backward-compatible (modifying the return type will be a breaking change).

ocornut added a commit that referenced this issue Aug 22, 2018
…lags, for an hypothetical IsItemValueChanged() function. (#2034)
@ocornut
Copy link
Owner

ocornut commented Aug 22, 2018

@mizvekov

I have merged a small internal change from another branch which should make the "value_changed" data available in the internal state. I've been trying to regroup some of those state into a place that can be queried but some of them are particularly tricky to deal with either because their computation is costly (and so we wouldn't want to do it on every item unless request) either they can't be relied on if we also rely on clipping items.

At any rate, the particular information you need here is cheap to store/query so I added it now.

While it is not exposed just yet, you may create the function in your own helper file (without touching imgui.cpp)

namespace ImGui
{
    IMGUI_API bool ImGui::IsItemValueChanged();
}
#include "imgui_internal.h"
bool ImGui::IsItemValueChanged()
{
    ImGuiContext& g = *GImGui;
    return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ValueChanged) != 0;
}

I think this should solve your problem, let me know!

I will eventually expose this function in the official API as a followup to the work done in #820, #956, #1875 but I need to verify that it'll work properly in more tricky use cases.

ocornut added a commit that referenced this issue Aug 23, 2018
… was pressed). This is equivalent to the bool returned by most widgets. It is useful in some situation e.g. using InputText() with ImGuiInputTextFlags_EnterReturnsTrue. (#2034)
ocornut added a commit that referenced this issue Aug 23, 2018
…) for consistency with new IsItemEdited() API. Kept redirection function (will obsolete fast as IsItemDeactivatedAfterChange() is very recent). (#820, #956, #1875, #2034)
@ocornut
Copy link
Owner

ocornut commented Aug 23, 2018

This has been now added as IsItemEdited().

@mizvekov
Copy link
Author

Solution worked for me, thanks!

ocornut added a commit that referenced this issue May 13, 2019
…orting IsItemEdited() multiple times when the text input doesn't match the formatted output value (e.g. input "1" shows "1.000"). It wasn't much of a problem because we typically use the return value instead of IsItemEdited() here. (#1875, #2034)
ocornut added a commit that referenced this issue Jan 4, 2021
…e from Combo(). (#2034) + fix some PVS warnings, fix typo, blanks.

Amend e28b107
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

3 participants