Skip to content

Commit

Permalink
improve sandbox_node_popup: Demonstrates a collection of patches to i…
Browse files Browse the repository at this point in the history
…mgui and imgui-node-editor
  • Loading branch information
pthom committed Oct 15, 2024
1 parent 9b592b8 commit 330c5ab
Showing 1 changed file with 92 additions and 56 deletions.
148 changes: 92 additions & 56 deletions bindings/imgui_bundle/demos_cpp/sandbox/sandbox_node_popup.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
// Test patch proposed ad https://github.com/thedmd/imgui-node-editor/issues/242
// Demonstrates a collection of patches to imgui-node-editor and imgui
// to make them work together in a smoother way.
// - Handle node width in separators
// - Handle Popups
// - Warn users if using BeginChild / EndChild
// - Handle InputTextMultiline
//
// Source for https://github.com/thedmd/imgui-node-editor/issues/310
#include "immapp/immapp.h"
#include "imgui.h"
#include "misc/cpp/imgui_stdlib.h"
#include "imgui_md_wrapper/imgui_md_wrapper.h"
#include "imgui-node-editor/imgui_node_editor.h"

namespace ed = ax::NodeEditor;

ImVec4 gColor(0.1, 0.2, 0.8, 1);
std::string gText = "Lorem ipsum dolor sit amet, consectetur adipiscing, \n"
std::string gLoremIpsum = "Lorem ipsum dolor sit amet, consectetur adipiscing, \n"
"sed do eiusmod tempor incididunt \n"
"ut labore et dolore magna aliqua. "
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \n"
Expand All @@ -20,69 +28,94 @@ void Gui()

ed::BeginNode(1);

ImGui::Text("Node 1");
ImGui::ColorEdit4("Color", &gColor.x);

static bool item_highlight = false;
int item_highlighted_idx = -1; // Here we store our highlighted data as an index.
ImGui::Checkbox("Check!", &item_highlight);

// IMGUI_API bool Combo(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int popup_max_height_in_items = -1);
// IMGUI_API bool ListBox(const char* label, int* current_item, bool (*old_callback)(void* user_data, int idx, const char** out_text), void* user_data, int items_count, int height_in_items = -1);

// IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0);
// IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true!
// IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1);
// IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0"
// IMGUI_API bool Combo(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int popup_max_height_in_items = -1);

// // Widgets: List Boxes
// // - This is essentially a thin wrapper to using BeginChild/EndChild with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
// // - You can submit contents and manage your selection state however you want it, by creating e.g. Selectable() or any other items.
// // - The simplified/old ListBox() api are helpers over BeginListBox()/EndListBox() which are kept available for convenience purpose. This is analoguous to how Combos are created.
// // - Choose frame width: size.x > 0.0f: custom / size.x < 0.0f or -FLT_MIN: right-align / size.x = 0.0f (default): use current ItemWidth
// // - Choose frame height: size.y > 0.0f: custom / size.y < 0.0f or -FLT_MIN: bottom-align / size.y = 0.0f (default): arbitrary default height which can fit ~7 items
// IMGUI_API bool BeginListBox(const char* label, const ImVec2& size = ImVec2(0, 0)); // open a framed scrolling region
// IMGUI_API void EndListBox(); // only call EndListBox() if BeginListBox() returned true!
// IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1);
// IMGUI_API bool ListBox(const char* label, int* current_item, const char* (*getter)(void* user_data, int idx), void* user_data, int items_count, int height_in_items = -1);


// {
// const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
// static int item_selected_idx = 0; // Here we store our selected data as an index.
// if (ImGui::BeginListBox("listbox 1"))
// {
// for (int n = 0; n < IM_ARRAYSIZE(items); n++)
// {
// const bool is_selected = (item_selected_idx == n);
// if (ImGui::Selectable(items[n], is_selected))
// item_selected_idx = n;
//
// if (item_highlight && ImGui::IsItemHovered())
// item_highlighted_idx = n;
//
// // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
// if (is_selected)
// ImGui::SetItemDefaultFocus();
// }
// ImGui::EndListBox();
// }
// }
ImGui::Dummy(ImVec2(500, 0));

ImGuiMd::RenderUnindented(R"(
This is a sandbox to test various patches to imgui-node-editor and imgui.
The goal is to make imgui-node-editor work smoothly with imgui.
These patches are applied inside [Dear ImGui Bundle](https://github.com/pthom/imgui_bundle).
The code for this demo is available [here](https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_cpp/sandbox/sandbox_node_popup.cpp).
)");

if (ImGui::CollapsingHeader("Handle node width in separators"))
{
// Simplified one-liner Combo() API, using values packed in a single constant string
// This is a convenience for when the selection set is small and known at compile-time.
ImGuiMd::RenderUnindented(R"(
Thanks to [this patch](https://github.com/pthom/imgui-node-editor/commit/148a06dcbddcf10a77382bff21bc168d5e518a65),
`ImGui::SeparatorText()`, `ImGui::Separator()`, and `ImGui::CollapsingHeader()` use the actual node width.
It was proposed [here](https://github.com/thedmd/imgui-node-editor/issues/298)
(The collapsing header you are looking at was fixed by this patch)
)");
ImGui::SeparatorText("SeparatorText example");
ImGui::Text("Below is a separator");
ImGui::Separator();
}

if (ImGui::CollapsingHeader("Handle Popups"))
{
ImGuiMd::RenderUnindented(R"(
[@lukaasm](https://github.com/lukaasm) proposed a patch [here](https://github.com/thedmd/imgui-node-editor/issues/242#issuecomment-1681806764),
which solves many issues with popups in the node editor (by automatically suspending the canvas, and placing popups correctly).
Example implementation for this patch:
* inside [imgui-node-editor](https://github.com/pthom/imgui-node-editor/commit/8b178424fcf7c452a7b5c14fb90b02487615ff70)
* inside [imgui](https://github.com/pthom/imgui/commit/1942772deac459210a321251bcc8857ac8170035)
With this patch, `ImGui::ColorEdit`, `ImGui::Begin/EndCombo` will work correctly.
)");
ImGui::SetNextItemWidth(200.f);
ImGui::ColorEdit4("Color", &gColor.x);

static int item_current_2 = 0;
ImGui::Combo("combo", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
}

if (ImGui::CollapsingHeader("Warn users / BeginChild"))
{
//ImGui::SetNextItemWidth(200);
ImGui::InputTextMultiline("source##truc", &gText, ImVec2(0, ImGui::GetTextLineHeight() * 16));
ImGuiMd::RenderUnindented(R"(
imgui-node-editor remains incompatible with `ImGui::BeginChild()` and `ImGui::EndChild()`.
Below is the list of ImGui widgets which are concerned (because they use BeginChild/EndChild):
* ImGui::InputTextMultiline()
* ImGui::BeginListbox() and ImGui::EndListbox()
* ImGui::BeginChild() and ImGui::EndChild()
We can warn the developer whenever they use these functions inside a node:
* patch inside [imgui](https://github.com/pthom/imgui/commit/52c093f4f259d7e99579e683b4f8c0247e2e8271)
* patch inside [imgui-node-editor](https://github.com/pthom/imgui-node-editor/commit/e4704e6a646e90f6b0df41240539261d1ede9d55)
)");

static bool showChildWindow = false;
ImGui::Text("Click to show a child window (this will trigger an IM_ASSERT!)");
ImGui::Checkbox("Show Child Window", &showChildWindow);
if (showChildWindow)
{
ImGui::BeginChild("child window", ImVec2(200, 200), true);
ImGui::Text("Hello from child window");
ImGui::EndChild();
}
}

ImGui::ColorEdit4("Color2", &gColor.x);
if (ImGui::CollapsingHeader("Handle InputTextMultiline"))
{
ImGuiMd::RenderUnindented(R"(
By default `InputTextMultiline` uses a child window, which is not compatible with the node editor.
An additional patch adapts its behavior, by showing a preview within a single line text input,
followed by a "..." button which triggers a popup with the full text edition.
To apply this, two patches are required:
* inside imgui-node-editor: A patch on top of @lukaasm's [patch](https://github.com/thedmd/imgui-node-editor/issues/242#issuecomment-1681806764):
we need to handle the "depth" of call to ImGui::Begin/End (only the first call should trigger):
it is available [here](https://github.com/pthom/imgui-node-editor/commit/3966e21ac9d43b159e6d19493e20ab5e2e8465ec)
* inside imgui: A patch for InputTextMultiline is available [here]( https://github.com/pthom/imgui/commit/b51b61346c5d7b98b960624b43a330279ccc8308)
)");
//ImGui::SetNextItemWidth(200);
ImGui::InputTextMultiline("lorem ipsum", &gLoremIpsum, ImVec2(0, ImGui::GetTextLineHeight() * 16));
}

ed::EndNode();

Expand All @@ -95,7 +128,10 @@ int main(int, char**)
HelloImGui::RunnerParams runnerParams;
ImmApp::AddOnsParams addOnsParams;
runnerParams.callbacks.ShowGui = Gui;
addOnsParams.withMarkdown = true;
addOnsParams.withNodeEditor = true;
addOnsParams.withNodeEditorConfig = ed::Config();
addOnsParams.withNodeEditorConfig->ForceWindowContentWidthToNodeWidth = true;
ImmApp::Run(runnerParams, addOnsParams);
return 0;
}

0 comments on commit 330c5ab

Please sign in to comment.