Skip to content

Commit 04fb2ec

Browse files
committed
[Bundle] InputTextMultiline compatible with imgui-node-editor (cf thedmd/imgui-node-editor#242 (comment))
1 parent b3cec31 commit 04fb2ec

File tree

1 file changed

+136
-1
lines changed

1 file changed

+136
-1
lines changed

imgui_widgets.cpp

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ Index of this file:
4747
// System includes
4848
#include <stdint.h> // intptr_t
4949

50+
// [ADAPT_IMGUI_BUNDLE]
51+
// for InputTextMultiline tooltip within node editor
52+
#include <string>
53+
#include <vector>
54+
#include <sstream>
55+
// [/ADAPT_IMGUI_BUNDLE]
56+
5057
//-------------------------------------------------------------------------
5158
// Warnings
5259
//-------------------------------------------------------------------------
@@ -3926,9 +3933,137 @@ bool ImGui::InputText(const char* label, char* buf, size_t buf_size, ImGuiInputT
39263933
return InputTextEx(label, NULL, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
39273934
}
39283935

3936+
// [ADAPT_IMGUI_BUNDLE] cf
3937+
bool Priv_ImGuiNodeEditor_IsInCanvas();
3938+
// [/ADAPT_IMGUI_BUNDLE]
3939+
3940+
39293941
bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
39303942
{
3931-
return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
3943+
// [ADAPT_IMGUI_BUNDLE] cf
3944+
// When inside imgui-node-editor canvas, we cannot open child windows
3945+
// In this case, we present a one line version of the input text,
3946+
// and offer the possibility to open a popup to edit the text in a multiline widget
3947+
if (Priv_ImGuiNodeEditor_IsInCanvas())
3948+
{
3949+
// Helper function to split and format the text for a tooltip
3950+
// to show an extract of the full text when hovering the button,
3951+
auto fn_format_tooltip = [](
3952+
const char* text, size_t max_line_length, size_t max_lines) -> std::string
3953+
{
3954+
auto fn_cut_string_after_max_length = [](const std::string& text, size_t max_length) -> std::string
3955+
{
3956+
if (text.size() <= max_length)
3957+
return text;
3958+
std::string r = text.substr(0, max_length - 3) + "...";
3959+
return r;
3960+
};
3961+
auto fn_split_lines = [](const std::string& s) -> std::vector<std::string>
3962+
{
3963+
std::vector<std::string> lines;
3964+
std::istringstream f(s);
3965+
std::string line;
3966+
while (std::getline(f, line))
3967+
lines.push_back(line);
3968+
return lines;
3969+
};
3970+
std::string r = "";
3971+
auto lines = fn_split_lines(text);
3972+
size_t n = 0;
3973+
for (const auto& line : lines)
3974+
{
3975+
if (n >= max_lines)
3976+
{
3977+
r += "...\n";
3978+
break;
3979+
}
3980+
r += fn_cut_string_after_max_length(line, max_line_length) + "\n";
3981+
n++;
3982+
}
3983+
return r;
3984+
};
3985+
3986+
// Helper function to make the text color more red
3987+
auto fn_redify_color = [](const ImVec4& color) -> ImVec4
3988+
{
3989+
ImVec4 redified_color;
3990+
redified_color.x = color.x;
3991+
redified_color.y = 0.6f * color.y;
3992+
redified_color.z = 0.6f * color.z;
3993+
redified_color.w = color.w;
3994+
return redified_color;
3995+
};
3996+
3997+
// Intro
3998+
PushID(label); // make sure to use unique ids
3999+
bool changed = false;
4000+
ImGui::BeginGroup();
4001+
4002+
// A- One line version text, without the label
4003+
ImGuiStyle& style = ImGui::GetStyle();
4004+
ImVec2 pos = ImGui::GetCursorScreenPos();
4005+
float btn_additional_width = CalcTextSize("...").x + style.FramePadding.x * 2.0f;// + style.ItemInnerSpacing.x;
4006+
float one_line_widget_width = size.x > 0.f ? size.x : CalcItemWidth();
4007+
one_line_widget_width -= btn_additional_width;
4008+
ImGui::SetNextItemWidth(one_line_widget_width);
4009+
if (InputText("##hidden_label", buf, buf_size, flags, callback, user_data))
4010+
changed = true;
4011+
4012+
// B- Add a button to open a popup to edit the text
4013+
// i. First, move the cursor to the left, so that the button appears right next to the input text
4014+
//ImVec2 pos = ImGui::GetCursorScreenPos();
4015+
//pos.x = pos.x - style.ItemSpacing.x; // + style.ItemInnerSpacing.x;
4016+
pos.x += one_line_widget_width - 1.f;
4017+
ImGui::SetCursorScreenPos(pos);
4018+
// ii. Then add the button
4019+
bool shall_display_tooltip = strchr(buf, '\n') != NULL;
4020+
if (shall_display_tooltip)
4021+
{
4022+
ImVec4 color = ImGui::GetStyleColorVec4(ImGuiCol_Text);
4023+
ImGui::PushStyleColor(ImGuiCol_Text, fn_redify_color(color));
4024+
}
4025+
bool was_button_pressed = false;
4026+
if (Button("..."))
4027+
{
4028+
was_button_pressed = true;
4029+
OpenPopup("InputTextMultilinePopup");
4030+
}
4031+
if (shall_display_tooltip)
4032+
ImGui::PopStyleColor();
4033+
4034+
if (shall_display_tooltip && ! was_button_pressed)
4035+
ImGui::SetItemTooltip("%s", fn_format_tooltip(buf, 60, 3).c_str());
4036+
4037+
// C. Finally, add the label (up until "##")
4038+
const char* label_end = FindRenderedTextEnd(label);
4039+
pos.x += style.ItemInnerSpacing.x + btn_additional_width;
4040+
ImGui::SetCursorScreenPos(pos);
4041+
TextUnformatted(label, label_end);
4042+
4043+
ImGui::EndGroup();
4044+
4045+
// D. Handle the popup
4046+
if (ImGui::BeginPopup("InputTextMultilinePopup"))
4047+
{
4048+
// Note: there is no infinite recursion here, since we are not inside the canvas anymore
4049+
// (as soon as BeginPopup return true, we are outside the canvas)
4050+
// (iif the patches https://github.com/thedmd/imgui-node-editor/issues/242#issuecomment-1681806764
4051+
// and https://github.com/thedmd/imgui-node-editor/issues/242#issuecomment-2404714757 are applied)
4052+
ImVec2 size_multiline = size;
4053+
size_multiline.x = one_line_widget_width;
4054+
if (InputTextMultiline("##edit", buf, buf_size, size_multiline, flags, callback, user_data))
4055+
changed = true;
4056+
EndPopup();
4057+
}
4058+
PopID();
4059+
return changed;
4060+
}
4061+
// [/ADAPT_IMGUI_BUNDLE]
4062+
else
4063+
{
4064+
// Standard behavior outside of imgui-node-editor canvas
4065+
return InputTextEx(label, NULL, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data);
4066+
}
39324067
}
39334068

39344069
bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)

0 commit comments

Comments
 (0)