ocornut/imgui

ComboBox with TextInput

HaSa1002 opened this issue · 5 comments

Version/Branch of Dear ImGui:

1.64

Back-end file/Renderer/OS:

Back-ends: SFML, imgui-SFML
OS: Win10

Suggestion:
I needed a ComboBox, where you can simply enter Text and the combobox provides you with one proposal. If it doesn't fit, you simply enter the next character and get the next best fitting proposal. Besides you can click on the ComboBox Key or use the right mouse button to open the ComboBox and select an entry. The textinputcombobox.cpp.txt provides the full implementation of this widget, as well as an minimal example, which is also visible below. The solution is by far not perfect eceptionally the "backspace" (the action, if you want to delete text) support, since it uses SFML Keys, because I couldn't get this correctly done using imgui functions. Also deleting isn't always exxecuted, which could be related to my backend, since it worked when it was not in the function... I tried to use no stl container, but didn't came around one pair to pass the actual array as well as the size of this array.

Screenshots/Video
combobox

Standalone, minimal, complete and verifiable example:

ImGui::Begin("Combobox");
	static char buffer[20];
        const char* items[] = {"Item1", "Item2", "AAAA", "AAAB", "AABB", "ABBB", "ABBB"};
	ImGui::TextInputComboBox("Demo", buffer, 20, items, IM_ARRAYSIZE(items), 0);
ImGui::End();

Sourcecode:
textinputcombobox.cpp.txt

Hello @HaSa1002

Thanks for posting this!

Some feedback:

  • Providing a GIF (instead of static pictures) would make the widget much more self explanatory to users. You can use ScreenToGif to create animated GIF easily.
  • I think you could rewrite TextInputComboBox() use use InputText + BeginCombo/EndCombo instead of reimplementing Combo().
  • For your std::string wrapper, see #2006.
  • Your function bool identical(const char* buf, const char* item) is equivalent to calling strcmp(buf, item) == 0, expect identical() is much slower. Remember strlen() is doing a full iteration over the string, so you are doing 2 iterations + 1 extra iteration in the loop while iterating. You could just do a single iteration and test for the zero terminator and never call strlen.
  • ImGuiInputTextFlags_CallbackAlways doesn't provide you with a key. I think your Key testing code will never run, but I'm not even sure to understand what it is trying to do, it appears that your Backspace code tries to emulate exactly what Backspace already does?
  • You can use a normal structure instead of std::pair if you want the code to work without reliance on STL stuff or templates.

Thanks for the feedback. First of all I posted a gif (It was a bit late yesterday). Second, that could be possible, but the selection is saved using the buffer of the textinput and it depends on the sizing possiblities of the combo. Third is on the way. Fourth, I use now strncmp since it checkes the equality of the first n characters. Fifth, the custom delete is ncessary, because the user deletes the selection, but still want's to the delete on more char. If this isn't working you can't delete chars because only the proposal is selected to gurantee textinput. Six, yes, I forgot that.
I normally use a lot of the stl library, so programming it in the imgui way is sometimes a bit tricky for me.
I now tried to change the ImGuiInputTextFlags_CallbackAlways to ImGuiInputTextFlags_CallbackCharFilter, but my code always crashes, because using the charfilter callback I don't get the buffer (It is a nullptr, since the ). InputTextFilterCharacter() function has no access to it. It would be very nice if ether the key is passed when using ImGuiInputTextFlags_CallbackAlways or the buffer would be set when using ImGuiInputTextFlags_CallbackCharFilter. However a completly different solution would also be ok.

@ocornut I'm trying to implement something similar. Regarding your suggestion to use InputText + BeginCombo/EndCombo: how can I align the drop-down selectables with the left of my InputText?

May not have time to look at it, but linking this thread to #718

Thanks @ocornut. That ought to work.