Created
December 12, 2017 13:23
-
-
Save Flix01/cb292384c82c4196f0d1dfc327bfba9c to your computer and use it in GitHub Desktop.
Experimental attempt to create an ImGui::InputTextMultiline(...) for std::strings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// EXPERIMENTAL (ALMOST UNTESTED) InputTextMultiline(...) for std::strings. | |
// USE IT AT YOUR OWN RISK! | |
// Example usage: | |
/* | |
static std::string text = "Dear ImGui lacks InputTextMultiline(...) for std::string."; | |
static bool isTextBoxActive = false; // A better implementation should remove this | |
ImGui::InputTextMultiline("###ADummyLabelForMe",text,isTextBoxActive); | |
*/ | |
// .h file | |
#include <imgui.h> | |
#include <string> | |
namespace ImGui { | |
IMGUI_API bool InputTextMultiline(const char* label,std::string& text,bool& staticItemActiveInOut, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiTextEditCallback callback = NULL, void* user_data = NULL); | |
} | |
// .cpp file (needs imgui_internal.h) | |
namespace ImGui { | |
inline static void StdStringNonStdResize(std::string& s,int size) { | |
IM_ASSERT(size>=0); | |
const int oldLength = s.length(); | |
if (size<oldLength) s = s.substr(0,size); | |
else if (size>oldLength) for (int i=0,icnt=size-oldLength;i<icnt;i++) s+='\0'; | |
} | |
// Ideally we should remove "staticItemActiveInOut" and find a way to query the active state BEFORE calling the default InputTextMultiline(...) version | |
// Also I'm not sure this works well with Undo/Redo | |
// And I've only tested it in a single instance | |
bool InputTextMultiline(const char* label,std::string& text,bool& staticItemActiveInOut, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiTextEditCallback callback, void* user_data) { | |
bool rv = false; | |
const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; | |
if (staticItemActiveInOutForID && is_editable) { | |
const ImGuiIO& io = ImGui::GetIO(); | |
ImGuiTextEditState &edit_state = ImGui::GetCurrentContext()->InputTextState; // Hope this always points to the active InputText... | |
const char* clipText = (io.KeyMap[ImGuiKey_V] && io.KeyCtrl) ? ImGui::GetClipboardText() : ""; | |
const size_t clipSize = strlen(clipText); | |
size_t sizeToAdd = clipSize+((io.InputCharacters[0] && (!(io.KeyCtrl && !io.KeyAlt)))?(5*IM_ARRAYSIZE(io.InputCharacters)):0); | |
if (IsKeyPressedMap(ImGuiKey_Enter) || IsKeyPressedMap(ImGuiKey_Tab)) sizeToAdd+=5; | |
size_t cnt = 0; | |
if (sizeToAdd>0) { | |
// Note that this happens only on a few frames | |
sizeToAdd+=1; // Trailing '\0' | |
const size_t oldTextLen = (size_t)text.length(); | |
const size_t newTextLen = oldTextLen+sizeToAdd; | |
StdStringNonStdResize(text,newTextLen); // See its code: it sets text[i]='\0' too | |
edit_state.Text.resize(text.length()+1); | |
edit_state.InitialText.resize(text.length()+1); | |
rv = ImGui::InputTextMultiline(label,&text[0],newTextLen,flags,callback,user_data); | |
// Remove all trailing '\0's and resize all strings back to save memory (a bit slow) | |
for (int i=(int)text.length()-1;i>=0;i--) { | |
if (text[i]!='\0') break; | |
++cnt; | |
} | |
StdStringNonStdResize(text,text.length()-cnt); | |
staticItemActiveInOutForID = ImGui::IsItemActive(); | |
if (staticItemActiveInOutForID) // Otherwise maybe edit_state points to something else | |
{ | |
//Allows the textbox to expand while active. | |
edit_state.Text.resize(text.length()+1); | |
edit_state.InitialText.resize(text.length()+1); | |
} | |
} | |
else { | |
rv = ImGui::InputTextMultiline(label,&text[0],text.length(),flags,callback,user_data); | |
staticItemActiveInOutForID = ImGui::IsItemActive(); | |
} | |
// Dbg only: (to remove) | |
if (ImGui::IsItemHovered()) ImGui::SetTooltip("text.length():%d (%s) cnt:%d sizeToAdd:%d\n",text.length(),staticItemActiveInOutForID?"active":"inactive",cnt,(int)sizeToAdd); | |
} | |
else { | |
rv = ImGui::InputTextMultiline(label,&text[0],text.length(),flags,callback,user_data); | |
staticItemActiveInOutForID = ImGui::IsItemActive(); | |
} | |
return rv; | |
} | |
} // namespace ImGui |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Intended for ImGui version 1.52.
Please see: ocornut/imgui#1008 and ocornut/imgui#1443