#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
#endif
#include "imgui.h"
#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(_MSC_VER) && _MSC_VER <= 1500
#include <stddef.h>
#else
#include <stdint.h>
#endif
#ifdef _MSC_VER
#pragma warning (disable: 4996)
#define snprintf _snprintf
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"
#pragma clang diagnostic ignored "-Wformat-security"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#if __has_warning("-Wreserved-id-macro")
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#endif
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
#pragma GCC diagnostic ignored "-Wformat-security"
#pragma GCC diagnostic ignored "-Wdouble-promotion"
#pragma GCC diagnostic ignored "-Wconversion"
#if (__GNUC__ >= 6)
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
#endif
#endif
#ifdef _WIN32
#define IM_NEWLINE "\r\n"
#else
#define IM_NEWLINE "\n"
#endif
#define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B))
#if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS)
#define IMGUI_DISABLE_DEMO_WINDOWS
#endif
#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
static void ShowExampleAppConsole(bool* p_open);
static void ShowExampleAppLog(bool* p_open);
static void ShowExampleAppLayout(bool* p_open);
static void ShowExampleAppPropertyEditor(bool* p_open);
static void ShowExampleAppLongText(bool* p_open);
static void ShowExampleAppAutoResize(bool* p_open);
static void ShowExampleAppConstrainedResize(bool* p_open);
static void ShowExampleAppFixedOverlay(bool* p_open);
static void ShowExampleAppWindowTitles(bool* p_open);
static void ShowExampleAppCustomRendering(bool* p_open);
static void ShowExampleAppMainMenuBar();
static void ShowExampleMenuFile();
static void ShowHelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(450.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
void ImGui::ShowUserGuide()
{
ImGui::BulletText("Double-click on title bar to collapse window.");
ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
ImGui::BulletText("Click and drag on any empty space to move window.");
ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
if (ImGui::GetIO().FontAllowUserScaling)
ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
ImGui::BulletText("Mouse Wheel to scroll.");
ImGui::BulletText("While editing text:\n");
ImGui::Indent();
ImGui::BulletText("Hold SHIFT or use mouse to select text.");
ImGui::BulletText("CTRL+Left/Right to word jump.");
ImGui::BulletText("CTRL+A or double-click to select all.");
ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
ImGui::BulletText("ESCAPE to revert.");
ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
ImGui::Unindent();
}
void ImGui::ShowDemoWindow(bool* p_open)
{
static bool show_app_main_menu_bar = false;
static bool show_app_console = false;
static bool show_app_log = false;
static bool show_app_layout = false;
static bool show_app_property_editor = false;
static bool show_app_long_text = false;
static bool show_app_auto_resize = false;
static bool show_app_constrained_resize = false;
static bool show_app_fixed_overlay = false;
static bool show_app_window_titles = false;
static bool show_app_custom_rendering = false;
static bool show_app_style_editor = false;
static bool show_app_metrics = false;
static bool show_app_about = false;
if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
if (show_app_console) ShowExampleAppConsole(&show_app_console);
if (show_app_log) ShowExampleAppLog(&show_app_log);
if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles);
if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); }
if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
if (show_app_about)
{
ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
ImGui::Text("dear imgui, %s", ImGui::GetVersion());
ImGui::Separator();
ImGui::Text("By Omar Cornut and all dear imgui contributors.");
ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
ImGui::End();
}
static bool no_titlebar = false;
static bool no_scrollbar = false;
static bool no_menu = false;
static bool no_move = false;
static bool no_resize = false;
static bool no_collapse = false;
static bool no_close = false;
ImGuiWindowFlags window_flags = 0;
if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
if (no_close) p_open = NULL;
ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
{
ImGui::End();
return;
}
ImGui::PushItemWidth(-140);
ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Menu"))
{
ShowExampleMenuFile();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Examples"))
{
ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
ImGui::MenuItem("Console", NULL, &show_app_console);
ImGui::MenuItem("Log", NULL, &show_app_log);
ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay);
ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Help"))
{
ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
ImGui::Spacing();
if (ImGui::CollapsingHeader("Help"))
{
ImGui::TextWrapped("This window is being created by the ShowDemoWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n");
ImGui::Text("USER GUIDE:");
ImGui::ShowUserGuide();
}
if (ImGui::CollapsingHeader("Window options"))
{
ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
ImGui::Checkbox("No menu", &no_menu);
ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
ImGui::Checkbox("No collapse", &no_collapse);
ImGui::Checkbox("No close", &no_close);
if (ImGui::TreeNode("Style"))
{
ImGui::ShowStyleEditor();
ImGui::TreePop();
}
if (ImGui::TreeNode("Capture/Logging"))
{
ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output.");
ImGui::LogButtons();
ImGui::TreePop();
}
}
if (ImGui::CollapsingHeader("Widgets"))
{
if (ImGui::TreeNode("Basic"))
{
static int clicked = 0;
if (ImGui::Button("Button"))
clicked++;
if (clicked & 1)
{
ImGui::SameLine();
ImGui::Text("Thanks for clicking me!");
}
static bool check = true;
ImGui::Checkbox("checkbox", &check);
static int e = 0;
ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
ImGui::RadioButton("radio c", &e, 2);
for (int i = 0; i < 7; i++)
{
if (i > 0) ImGui::SameLine();
ImGui::PushID(i);
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
ImGui::Button("Click");
ImGui::PopStyleColor(3);
ImGui::PopID();
}
ImGui::Text("Hover over me");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip");
ImGui::SameLine();
ImGui::Text("- or me");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::Text("I am a fancy tooltip");
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
ImGui::EndTooltip();
}
ImGui::Separator();
ImGui::LabelText("label", "Value");
{
static int current_item_1 = 1;
ImGui::Combo("combo", ¤t_item_1, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO", "PPPP", "QQQQQQQQQQ", "RRR", "SSSS" };
static const char* current_item_2 = NULL;
if (ImGui::BeginCombo("combo 2", current_item_2)) {
for (int n = 0; n < IM_ARRAYSIZE(items); n++)
{
bool is_selected = (current_item_2 == items[n]); if (ImGui::Selectable(items[n], is_selected))
current_item_2 = items[n];
if (is_selected)
ImGui::SetItemDefaultFocus(); }
ImGui::EndCombo();
}
}
{
static char str0[128] = "Hello, world!";
static int i0=123;
static float f0=0.001f;
ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n");
ImGui::InputInt("input int", &i0);
ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
ImGui::InputFloat3("input float3", vec4a);
}
{
static int i1=50, i2=42;
ImGui::DragInt("drag int", &i1, 1);
ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%");
static float f1=1.00f, f2=0.0067f;
ImGui::DragFloat("drag float", &f1, 0.005f);
ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
}
{
static int i1=0;
ImGui::SliderInt("slider int", &i1, -1, 3);
ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
static float f1=0.123f, f2=0.0f;
ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f);
static float angle = 0.0f;
ImGui::SliderAngle("slider angle", &angle);
}
static float col1[3] = { 1.0f,0.0f,0.2f };
static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
ImGui::ColorEdit3("color 1", col1);
ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
ImGui::ColorEdit4("color 2", col2);
const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
static int listbox_item_current = 1;
ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
ImGui::TreePop();
}
if (ImGui::TreeNode("Trees"))
{
if (ImGui::TreeNode("Basic trees"))
{
for (int i = 0; i < 5; i++)
if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
{
ImGui::Text("blah blah");
ImGui::SameLine();
if (ImGui::SmallButton("print")) printf("Child %d pressed", i);
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Advanced, with Selectable nodes"))
{
ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
static bool align_label_with_current_x_position = false;
ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
ImGui::Text("Hello!");
if (align_label_with_current_x_position)
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
static int selection_mask = (1 << 2); int node_clicked = -1; ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); for (int i = 0; i < 6; i++)
{
ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
if (i < 3)
{
bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
if (ImGui::IsItemClicked())
node_clicked = i;
if (node_open)
{
ImGui::Text("Blah blah\nBlah Blah");
ImGui::TreePop();
}
}
else
{
node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
if (ImGui::IsItemClicked())
node_clicked = i;
}
}
if (node_clicked != -1)
{
if (ImGui::GetIO().KeyCtrl)
selection_mask ^= (1 << node_clicked); else selection_mask = (1 << node_clicked); }
ImGui::PopStyleVar();
if (align_label_with_current_x_position)
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Collapsing Headers"))
{
static bool closable_group = true;
ImGui::Checkbox("Enable extra group", &closable_group);
if (ImGui::CollapsingHeader("Header"))
{
ImGui::Text("IsItemHovered: %d", IsItemHovered());
for (int i = 0; i < 5; i++)
ImGui::Text("Some content %d", i);
}
if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
{
ImGui::Text("IsItemHovered: %d", IsItemHovered());
for (int i = 0; i < 5; i++)
ImGui::Text("More content %d", i);
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Bullets"))
{
ImGui::BulletText("Bullet point 1");
ImGui::BulletText("Bullet point 2\nOn multiple lines");
ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
ImGui::Bullet(); ImGui::SmallButton("Button");
ImGui::TreePop();
}
if (ImGui::TreeNode("Text"))
{
if (ImGui::TreeNode("Colored Text"))
{
ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
ImGui::TextDisabled("Disabled");
ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
ImGui::TreePop();
}
if (ImGui::TreeNode("Word Wrapping"))
{
ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages.");
ImGui::Spacing();
static float wrap_width = 200.0f;
ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
ImGui::Text("Test paragraph 1:");
ImVec2 pos = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
ImGui::PopTextWrapPos();
ImGui::Text("Test paragraph 2:");
pos = ImGui::GetCursorScreenPos();
ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));
ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
ImGui::PopTextWrapPos();
ImGui::TreePop();
}
if (ImGui::TreeNode("UTF-8 Text"))
{
ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges.");
ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Images"))
{
ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!");
ImGuiIO& io = ImGui::GetIO();
ImTextureID my_tex_id = io.Fonts->TexID;
float my_tex_w = (float)io.Fonts->TexWidth;
float my_tex_h = (float)io.Fonts->TexHeight;
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
ImVec2 pos = ImGui::GetCursorScreenPos();
ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
float focus_sz = 32.0f;
float focus_x = io.MousePos.x - pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > my_tex_w - focus_sz) focus_x = my_tex_w - focus_sz;
float focus_y = io.MousePos.y - pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > my_tex_h - focus_sz) focus_y = my_tex_h - focus_sz;
ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y);
ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz);
ImVec2 uv0 = ImVec2((focus_x) / my_tex_w, (focus_y) / my_tex_h);
ImVec2 uv1 = ImVec2((focus_x + focus_sz) / my_tex_w, (focus_y + focus_sz) / my_tex_h);
ImGui::Image(my_tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
ImGui::EndTooltip();
}
ImGui::TextWrapped("And now some textured buttons..");
static int pressed_count = 0;
for (int i = 0; i < 8; i++)
{
ImGui::PushID(i);
int frame_padding = -1 + i; if (ImGui::ImageButton(my_tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/my_tex_w,32/my_tex_h), frame_padding, ImColor(0,0,0,255)))
pressed_count += 1;
ImGui::PopID();
ImGui::SameLine();
}
ImGui::NewLine();
ImGui::Text("Pressed %d times.", pressed_count);
ImGui::TreePop();
}
if (ImGui::TreeNode("Selectables"))
{
if (ImGui::TreeNode("Basic"))
{
static bool selected[4] = { false, true, false, false };
ImGui::Selectable("1. I am selectable", &selected[0]);
ImGui::Selectable("2. I am selectable", &selected[1]);
ImGui::Text("3. I am not selectable");
ImGui::Selectable("4. I am selectable", &selected[2]);
if (ImGui::Selectable("5. I am double clickable", selected[3], ImGuiSelectableFlags_AllowDoubleClick))
if (ImGui::IsMouseDoubleClicked(0))
selected[3] = !selected[3];
ImGui::TreePop();
}
if (ImGui::TreeNode("Rendering more text into the same block"))
{
static bool selected[3] = { false, false, false };
ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
ImGui::TreePop();
}
if (ImGui::TreeNode("In columns"))
{
ImGui::Columns(3, NULL, false);
static bool selected[16] = { 0 };
for (int i = 0; i < 16; i++)
{
char label[32]; sprintf(label, "Item %d", i);
if (ImGui::Selectable(label, &selected[i])) {}
ImGui::NextColumn();
}
ImGui::Columns(1);
ImGui::TreePop();
}
if (ImGui::TreeNode("Grid"))
{
static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
for (int i = 0; i < 16; i++)
{
ImGui::PushID(i);
if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50)))
{
int x = i % 4, y = i / 4;
if (x > 0) selected[i - 1] ^= 1;
if (x < 3) selected[i + 1] ^= 1;
if (y > 0) selected[i - 4] ^= 1;
if (y < 3) selected[i + 4] ^= 1;
}
if ((i % 4) < 3) ImGui::SameLine();
ImGui::PopID();
}
ImGui::TreePop();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Filtered Text Input"))
{
static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
ImGui::Text("Password input");
static char bufpass[64] = "password123";
ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
ImGui::TreePop();
}
if (ImGui::TreeNode("Multi-line Text Input"))
{
static bool read_only = false;
static char text[1024*16] =
"/*\n"
" The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
" the hexadecimal encoding of one offending instruction,\n"
" more formally, the invalid operand with locked CMPXCHG8B\n"
" instruction bug, is a design flaw in the majority of\n"
" Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
" processors (all in the P5 microarchitecture).\n"
"*/\n\n"
"label:\n"
"\tlock cmpxchg8b eax\n";
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
ImGui::Checkbox("Read-only", &read_only);
ImGui::PopStyleVar();
ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0));
ImGui::TreePop();
}
if (ImGui::TreeNode("Plots widgets"))
{
static bool animate = true;
ImGui::Checkbox("Animate", &animate);
static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
static float values[90] = { 0 };
static int values_offset = 0;
static float refresh_time = 0.0f;
if (!animate || refresh_time == 0.0f)
refresh_time = ImGui::GetTime();
while (refresh_time < ImGui::GetTime()) {
static float phase = 0.0f;
values[values_offset] = cosf(phase);
values_offset = (values_offset+1) % IM_ARRAYSIZE(values);
phase += 0.10f*values_offset;
refresh_time += 1.0f/60.0f;
}
ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));
struct Funcs
{
static float Sin(void*, int i) { return sinf(i * 0.1f); }
static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
};
static int func_type = 0, display_count = 70;
ImGui::Separator();
ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
ImGui::SameLine();
ImGui::SliderInt("Sample count", &display_count, 1, 400);
float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
ImGui::Separator();
static float progress = 0.0f, progress_dir = 1.0f;
if (animate)
{
progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
}
ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::Text("Progress Bar");
float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
char buf[32];
sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
ImGui::TreePop();
}
if (ImGui::TreeNode("Color/Picker Widgets"))
{
static ImVec4 color = ImColor(114, 144, 154, 200);
static bool hdr = false;
static bool alpha_preview = true;
static bool alpha_half_preview = false;
static bool options_menu = true;
ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
ImGui::Checkbox("With Alpha Preview", &alpha_preview);
ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
ImGui::Text("Color widget:");
ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
ImGui::Text("Color widget HSV with Alpha:");
ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
ImGui::Text("Color widget with Float Display:");
ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
ImGui::Text("Color button with Picker:");
ImGui::SameLine(); ShowHelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.");
ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
ImGui::Text("Color button with Custom Picker Popup:");
static bool saved_palette_inited = false;
static ImVec4 saved_palette[32];
if (!saved_palette_inited)
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
{
ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
saved_palette[n].w = 1.0f; }
saved_palette_inited = true;
static ImVec4 backup_color;
bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
ImGui::SameLine();
open_popup |= ImGui::Button("Palette");
if (open_popup)
{
ImGui::OpenPopup("mypicker");
backup_color = color;
}
if (ImGui::BeginPopup("mypicker"))
{
ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
ImGui::Separator();
ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Text("Current");
ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40));
ImGui::Text("Previous");
if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)))
color = backup_color;
ImGui::Separator();
ImGui::Text("Palette");
for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
{
ImGui::PushID(n);
if ((n % 8) != 0)
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20)))
color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w);
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
EndDragDropTarget();
}
ImGui::PopID();
}
ImGui::EndGroup();
ImGui::EndPopup();
}
ImGui::Text("Color button only:");
ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80));
ImGui::Text("Color picker:");
static bool alpha = true;
static bool alpha_bar = true;
static bool side_preview = true;
static bool ref_color = false;
static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);
static int inputs_mode = 2;
static int picker_mode = 0;
ImGui::Checkbox("With Alpha", &alpha);
ImGui::Checkbox("With Alpha Bar", &alpha_bar);
ImGui::Checkbox("With Side Preview", &side_preview);
if (side_preview)
{
ImGui::SameLine();
ImGui::Checkbox("With Ref Color", &ref_color);
if (ref_color)
{
ImGui::SameLine();
ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
}
}
ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
ImGuiColorEditFlags flags = misc_flags;
if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;
if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;
if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;
if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;
ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
ImGui::Text("Programmatically set defaults/options:");
ImGui::SameLine(); ShowHelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.");
if (ImGui::Button("Uint8 + HSV"))
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV);
ImGui::SameLine();
if (ImGui::Button("Float + HDR"))
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_RGB);
ImGui::TreePop();
}
if (ImGui::TreeNode("Range Widgets"))
{
static float begin = 10, end = 90;
static int begin_i = 100, end_i = 1000;
ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %.0f units", "Max: %.0f units");
ImGui::TreePop();
}
if (ImGui::TreeNode("Multi-component Widgets"))
{
static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
static int vec4i[4] = { 1, 5, 100, 255 };
ImGui::InputFloat2("input float2", vec4f);
ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
ImGui::InputInt2("input int2", vec4i);
ImGui::SliderInt2("slider int2", vec4i, 0, 255);
ImGui::Spacing();
ImGui::InputFloat3("input float3", vec4f);
ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
ImGui::InputInt3("input int3", vec4i);
ImGui::SliderInt3("slider int3", vec4i, 0, 255);
ImGui::Spacing();
ImGui::InputFloat4("input float4", vec4f);
ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
ImGui::InputInt4("input int4", vec4i);
ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
ImGui::SliderInt4("slider int4", vec4i, 0, 255);
ImGui::TreePop();
}
if (ImGui::TreeNode("Vertical Sliders"))
{
const float spacing = 4;
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
static int int_value = 0;
ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
ImGui::SameLine();
static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
ImGui::PushID("set1");
for (int i = 0; i < 7; i++)
{
if (i > 0) ImGui::SameLine();
ImGui::PushID(i);
ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));
ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));
ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));
ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
if (ImGui::IsItemActive() || ImGui::IsItemHovered())
ImGui::SetTooltip("%.3f", values[i]);
ImGui::PopStyleColor(4);
ImGui::PopID();
}
ImGui::PopID();
ImGui::SameLine();
ImGui::PushID("set2");
static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
const int rows = 3;
const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);
for (int nx = 0; nx < 4; nx++)
{
if (nx > 0) ImGui::SameLine();
ImGui::BeginGroup();
for (int ny = 0; ny < rows; ny++)
{
ImGui::PushID(nx*rows+ny);
ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
if (ImGui::IsItemActive() || ImGui::IsItemHovered())
ImGui::SetTooltip("%.3f", values2[nx]);
ImGui::PopID();
}
ImGui::EndGroup();
}
ImGui::PopID();
ImGui::SameLine();
ImGui::PushID("set3");
for (int i = 0; i < 4; i++)
{
if (i > 0) ImGui::SameLine();
ImGui::PushID(i);
ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
ImGui::PopStyleVar();
ImGui::PopID();
}
ImGui::PopID();
ImGui::PopStyleVar();
ImGui::TreePop();
}
}
if (ImGui::CollapsingHeader("Layout"))
{
if (ImGui::TreeNode("Child regions"))
{
static bool disable_mouse_wheel = false;
ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
ImGui::Text("Without border");
static int line = 50;
bool goto_line = ImGui::Button("Goto");
ImGui::SameLine();
ImGui::PushItemWidth(100);
goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
ImGui::PopItemWidth();
ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0));
for (int i = 0; i < 100; i++)
{
ImGui::Text("%04d: scrollable region", i);
if (goto_line && line == i)
ImGui::SetScrollHere();
}
if (goto_line && line >= 100)
ImGui::SetScrollHere();
ImGui::EndChild();
ImGui::SameLine();
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
ImGui::BeginChild("Sub2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0));
ImGui::Text("With border");
ImGui::Columns(2);
for (int i = 0; i < 100; i++)
{
if (i == 50)
ImGui::NextColumn();
char buf[32];
sprintf(buf, "%08x", i*5731);
ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
}
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::TreePop();
}
if (ImGui::TreeNode("Widgets Width"))
{
static float f = 0.0f;
ImGui::Text("PushItemWidth(100)");
ImGui::SameLine(); ShowHelpMarker("Fixed width.");
ImGui::PushItemWidth(100);
ImGui::DragFloat("float##1", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
ImGui::SameLine(); ShowHelpMarker("Half of window width.");
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
ImGui::DragFloat("float##2", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
ImGui::DragFloat("float##3", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(-100)");
ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
ImGui::PushItemWidth(-100);
ImGui::DragFloat("float##4", &f);
ImGui::PopItemWidth();
ImGui::Text("PushItemWidth(-1)");
ImGui::SameLine(); ShowHelpMarker("Align to right edge");
ImGui::PushItemWidth(-1);
ImGui::DragFloat("float##5", &f);
ImGui::PopItemWidth();
ImGui::TreePop();
}
if (ImGui::TreeNode("Basic Horizontal Layout"))
{
ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
ImGui::Text("Two items: Hello"); ImGui::SameLine();
ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
ImGui::AlignTextToFramePadding();
ImGui::Text("Normal buttons"); ImGui::SameLine();
ImGui::Button("Banana"); ImGui::SameLine();
ImGui::Button("Apple"); ImGui::SameLine();
ImGui::Button("Corniflower");
ImGui::Text("Small buttons"); ImGui::SameLine();
ImGui::SmallButton("Like this one"); ImGui::SameLine();
ImGui::Text("can fit within a text block.");
ImGui::Text("Aligned");
ImGui::SameLine(150); ImGui::Text("x=150");
ImGui::SameLine(300); ImGui::Text("x=300");
ImGui::Text("Aligned");
ImGui::SameLine(150); ImGui::SmallButton("x=150");
ImGui::SameLine(300); ImGui::SmallButton("x=300");
static bool c1=false,c2=false,c3=false,c4=false;
ImGui::Checkbox("My", &c1); ImGui::SameLine();
ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
ImGui::Checkbox("Is", &c3); ImGui::SameLine();
ImGui::Checkbox("Rich", &c4);
static float f0=1.0f, f1=2.0f, f2=3.0f;
ImGui::PushItemWidth(80);
const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
static int item = -1;
ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine();
ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine();
ImGui::SliderFloat("Z", &f2, 0.0f,5.0f);
ImGui::PopItemWidth();
ImGui::PushItemWidth(80);
ImGui::Text("Lists:");
static int selection[4] = { 0, 1, 2, 3 };
for (int i = 0; i < 4; i++)
{
if (i > 0) ImGui::SameLine();
ImGui::PushID(i);
ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
ImGui::PopID();
}
ImGui::PopItemWidth();
ImVec2 sz(30,30);
ImGui::Button("A", sz); ImGui::SameLine();
ImGui::Dummy(sz); ImGui::SameLine();
ImGui::Button("B", sz);
ImGui::TreePop();
}
if (ImGui::TreeNode("Groups"))
{
ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)");
ImGui::BeginGroup();
{
ImGui::BeginGroup();
ImGui::Button("AAA");
ImGui::SameLine();
ImGui::Button("BBB");
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Button("CCC");
ImGui::Button("DDD");
ImGui::EndGroup();
ImGui::SameLine();
ImGui::Button("EEE");
ImGui::EndGroup();
if (ImGui::IsItemHovered())
ImGui::SetTooltip("First group hovered");
}
ImVec2 size = ImGui::GetItemRectSize();
const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
ImGui::SameLine();
ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
ImGui::EndGroup();
ImGui::SameLine();
ImGui::Button("LEVERAGE\nBUZZWORD", size);
ImGui::SameLine();
ImGui::ListBoxHeader("List", size);
ImGui::Selectable("Selected", true);
ImGui::Selectable("Not Selected", false);
ImGui::ListBoxFooter();
ImGui::TreePop();
}
if (ImGui::TreeNode("Text Baseline Alignment"))
{
ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)");
ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
ImGui::Text("Hello\nWorld"); ImGui::SameLine();
ImGui::Text("Banana");
ImGui::Text("Banana"); ImGui::SameLine();
ImGui::Text("Hello\nWorld"); ImGui::SameLine();
ImGui::Text("One\nTwo\nThree");
ImGui::Button("HOP##1"); ImGui::SameLine();
ImGui::Text("Banana"); ImGui::SameLine();
ImGui::Text("Hello\nWorld"); ImGui::SameLine();
ImGui::Text("Banana");
ImGui::Button("HOP##2"); ImGui::SameLine();
ImGui::Text("Hello\nWorld"); ImGui::SameLine();
ImGui::Text("Banana");
ImGui::Button("TEST##1"); ImGui::SameLine();
ImGui::Text("TEST"); ImGui::SameLine();
ImGui::SmallButton("TEST##2");
ImGui::AlignTextToFramePadding(); ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
ImGui::Button("Widget##1"); ImGui::SameLine();
ImGui::Text("Widget"); ImGui::SameLine();
ImGui::SmallButton("Widget##2"); ImGui::SameLine();
ImGui::Button("Widget##3");
const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
ImGui::Button("Button##1");
ImGui::SameLine(0.0f, spacing);
if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }
ImGui::AlignTextToFramePadding(); bool node_open = ImGui::TreeNode("Node##2"); ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }
ImGui::Button("Button##3");
ImGui::SameLine(0.0f, spacing);
ImGui::BulletText("Bullet text");
ImGui::AlignTextToFramePadding();
ImGui::BulletText("Node");
ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
ImGui::TreePop();
}
if (ImGui::TreeNode("Scrolling"))
{
ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)");
static bool track = true;
static int track_line = 50, scroll_to_px = 200;
ImGui::Checkbox("Track", &track);
ImGui::PushItemWidth(100);
ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %.0f");
bool scroll_to = ImGui::Button("Scroll To Pos");
ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %.0f px");
ImGui::PopItemWidth();
if (scroll_to) track = false;
for (int i = 0; i < 5; i++)
{
if (i > 0) ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
if (scroll_to)
ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
for (int line = 0; line < 100; line++)
{
if (track && line == track_line)
{
ImGui::TextColored(ImColor(255,255,0), "Line %d", line);
ImGui::SetScrollHere(i * 0.25f); }
else
{
ImGui::Text("Line %d", line);
}
}
float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
ImGui::EndChild();
ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
ImGui::EndGroup();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Horizontal Scrolling"))
{
ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
static int lines = 7;
ImGui::SliderInt("Lines", &lines, 1, 15);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
for (int line = 0; line < lines; line++)
{
int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
for (int n = 0; n < num_buttons; n++)
{
if (n > 0) ImGui::SameLine();
ImGui::PushID(n + line * 1000);
char num_buf[16];
sprintf(num_buf, "%d", n);
const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf;
float hue = n*0.05f;
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
ImGui::PopStyleColor(3);
ImGui::PopID();
}
}
float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
ImGui::EndChild();
ImGui::PopStyleVar(2);
float scroll_x_delta = 0.0f;
ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
ImGui::Text("Scroll from code"); ImGui::SameLine();
ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
if (scroll_x_delta != 0.0f)
{
ImGui::BeginChild("scrolling"); ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
ImGui::End();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Clipping"))
{
static ImVec2 size(100, 100), offset(50, 20);
ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
ImGui::TextWrapped("(Click and drag)");
ImVec2 pos = ImGui::GetCursorScreenPos();
ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);
ImGui::InvisibleButton("##dummy", size);
if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));
ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
ImGui::TreePop();
}
}
if (ImGui::CollapsingHeader("Popups & Modal windows"))
{
if (ImGui::TreeNode("Popups"))
{
ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
static int selected_fish = -1;
const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
static bool toggles[] = { true, false, false, false, false };
if (ImGui::Button("Select.."))
ImGui::OpenPopup("select");
ImGui::SameLine();
ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
if (ImGui::BeginPopup("select"))
{
ImGui::Text("Aquarium");
ImGui::Separator();
for (int i = 0; i < IM_ARRAYSIZE(names); i++)
if (ImGui::Selectable(names[i]))
selected_fish = i;
ImGui::EndPopup();
}
if (ImGui::Button("Toggle.."))
ImGui::OpenPopup("toggle");
if (ImGui::BeginPopup("toggle"))
{
for (int i = 0; i < IM_ARRAYSIZE(names); i++)
ImGui::MenuItem(names[i], "", &toggles[i]);
if (ImGui::BeginMenu("Sub-menu"))
{
ImGui::MenuItem("Click me");
ImGui::EndMenu();
}
ImGui::Separator();
ImGui::Text("Tooltip here");
if (ImGui::IsItemHovered())
ImGui::SetTooltip("I am a tooltip over a popup");
if (ImGui::Button("Stacked Popup"))
ImGui::OpenPopup("another popup");
if (ImGui::BeginPopup("another popup"))
{
for (int i = 0; i < IM_ARRAYSIZE(names); i++)
ImGui::MenuItem(names[i], "", &toggles[i]);
if (ImGui::BeginMenu("Sub-menu"))
{
ImGui::MenuItem("Click me");
ImGui::EndMenu();
}
ImGui::EndPopup();
}
ImGui::EndPopup();
}
if (ImGui::Button("Popup Menu.."))
ImGui::OpenPopup("FilePopup");
if (ImGui::BeginPopup("FilePopup"))
{
ShowExampleMenuFile();
ImGui::EndPopup();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Context menus"))
{
static float value = 0.5f;
ImGui::Text("Value = %.3f (<-- right-click here)", value);
if (ImGui::BeginPopupContextItem("item context menu"))
{
if (ImGui::Selectable("Set to zero")) value = 0.0f;
if (ImGui::Selectable("Set to PI")) value = 3.1415f;
ImGui::PushItemWidth(-1);
ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
ImGui::PopItemWidth();
ImGui::EndPopup();
}
static char name[32] = "Label1";
char buf[64]; sprintf(buf, "Button: %s###Button", name); ImGui::Button(buf);
if (ImGui::BeginPopupContextItem()) {
ImGui::Text("Edit name:");
ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
if (ImGui::Button("Close"))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
ImGui::TreePop();
}
if (ImGui::TreeNode("Modals"))
{
ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
if (ImGui::Button("Delete.."))
ImGui::OpenPopup("Delete?");
if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
ImGui::Separator();
static bool dont_ask_me_next_time = false;
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
ImGui::PopStyleVar();
if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
ImGui::EndPopup();
}
if (ImGui::Button("Stacked modals.."))
ImGui::OpenPopup("Stacked 1");
if (ImGui::BeginPopupModal("Stacked 1"))
{
ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDarkening] for darkening.");
static int item = 1;
ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
ImGui::ColorEdit4("color", color);
if (ImGui::Button("Add another modal.."))
ImGui::OpenPopup("Stacked 2");
if (ImGui::BeginPopupModal("Stacked 2"))
{
ImGui::Text("Hello from Stacked The Second");
if (ImGui::Button("Close"))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
if (ImGui::Button("Close"))
ImGui::CloseCurrentPopup();
ImGui::EndPopup();
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Menus inside a regular window"))
{
ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
ImGui::Separator();
ImGui::PushID("foo");
ImGui::MenuItem("Menu item", "CTRL+M");
if (ImGui::BeginMenu("Menu inside a regular window"))
{
ShowExampleMenuFile();
ImGui::EndMenu();
}
ImGui::PopID();
ImGui::Separator();
ImGui::TreePop();
}
}
if (ImGui::CollapsingHeader("Columns"))
{
ImGui::PushID("Columns");
if (ImGui::TreeNode("Basic"))
{
ImGui::Text("Without border:");
ImGui::Columns(3, "mycolumns3", false); ImGui::Separator();
for (int n = 0; n < 14; n++)
{
char label[32];
sprintf(label, "Item %d", n);
if (ImGui::Selectable(label)) {}
ImGui::NextColumn();
}
ImGui::Columns(1);
ImGui::Separator();
ImGui::Text("With border:");
ImGui::Columns(4, "mycolumns"); ImGui::Separator();
ImGui::Text("ID"); ImGui::NextColumn();
ImGui::Text("Name"); ImGui::NextColumn();
ImGui::Text("Path"); ImGui::NextColumn();
ImGui::Text("Hovered"); ImGui::NextColumn();
ImGui::Separator();
const char* names[3] = { "One", "Two", "Three" };
const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
static int selected = -1;
for (int i = 0; i < 3; i++)
{
char label[32];
sprintf(label, "%04d", i);
if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
selected = i;
bool hovered = ImGui::IsItemHovered();
ImGui::NextColumn();
ImGui::Text(names[i]); ImGui::NextColumn();
ImGui::Text(paths[i]); ImGui::NextColumn();
ImGui::Text("%d", hovered); ImGui::NextColumn();
}
ImGui::Columns(1);
ImGui::Separator();
ImGui::TreePop();
}
if (ImGui::TreeNode("Mixed items"))
{
ImGui::Columns(3, "mixed");
ImGui::Separator();
ImGui::Text("Hello");
ImGui::Button("Banana");
ImGui::NextColumn();
ImGui::Text("ImGui");
ImGui::Button("Apple");
static float foo = 1.0f;
ImGui::InputFloat("red", &foo, 0.05f, 0, 3);
ImGui::Text("An extra line here.");
ImGui::NextColumn();
ImGui::Text("Sailor");
ImGui::Button("Corniflower");
static float bar = 1.0f;
ImGui::InputFloat("blue", &bar, 0.05f, 0, 3);
ImGui::NextColumn();
if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
ImGui::Columns(1);
ImGui::Separator();
ImGui::TreePop();
}
if (ImGui::TreeNode("Word-wrapping"))
{
ImGui::Columns(2, "word-wrapping");
ImGui::Separator();
ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
ImGui::TextWrapped("Hello Left");
ImGui::NextColumn();
ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
ImGui::TextWrapped("Hello Right");
ImGui::Columns(1);
ImGui::Separator();
ImGui::TreePop();
}
if (ImGui::TreeNode("Borders"))
{
static bool h_borders = true;
static bool v_borders = true;
ImGui::Checkbox("horizontal", &h_borders);
ImGui::SameLine();
ImGui::Checkbox("vertical", &v_borders);
ImGui::Columns(4, NULL, v_borders);
for (int i = 0; i < 4*3; i++)
{
if (h_borders && ImGui::GetColumnIndex() == 0)
ImGui::Separator();
ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
ImGui::NextColumn();
}
ImGui::Columns(1);
if (h_borders)
ImGui::Separator();
ImGui::TreePop();
}
if (ImGui::TreeNode("Horizontal Scrolling"))
{
ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
ImGui::Columns(10);
int ITEMS_COUNT = 2000;
ImGuiListClipper clipper(ITEMS_COUNT); while (clipper.Step())
{
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
for (int j = 0; j < 10; j++)
{
ImGui::Text("Line %d Column %d...", i, j);
ImGui::NextColumn();
}
}
ImGui::Columns(1);
ImGui::EndChild();
ImGui::TreePop();
}
bool node_open = ImGui::TreeNode("Tree within single cell");
ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
if (node_open)
{
ImGui::Columns(2, "tree items");
ImGui::Separator();
if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
ImGui::Columns(1);
ImGui::Separator();
ImGui::TreePop();
}
ImGui::PopID();
}
if (ImGui::CollapsingHeader("Filtering"))
{
static ImGuiTextFilter filter;
ImGui::Text("Filter usage:\n"
" \"\" display all lines\n"
" \"xxx\" display lines containing \"xxx\"\n"
" \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
" \"-xxx\" hide lines containing \"xxx\"");
filter.Draw();
const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
if (filter.PassFilter(lines[i]))
ImGui::BulletText("%s", lines[i]);
}
if (ImGui::CollapsingHeader("Inputs & Focus"))
{
ImGuiIO& io = ImGui::GetIO();
ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
ImGui::Text("WantTextInput: %d", io.WantTextInput);
ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse);
if (ImGui::TreeNode("Keyboard & Mouse State"))
{
if (ImGui::IsMousePosValid())
ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
else
ImGui::Text("Mouse pos: <INVALID>");
ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }
ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Button("Hovering me sets the\nkeyboard capture flag");
if (ImGui::IsItemHovered())
ImGui::CaptureKeyboardFromApp(true);
ImGui::SameLine();
ImGui::Button("Holding me clears the\nthe keyboard capture flag");
if (ImGui::IsItemActive())
ImGui::CaptureKeyboardFromApp(false);
ImGui::TreePop();
}
if (ImGui::TreeNode("Tabbing"))
{
ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
static char buf[32] = "dummy";
ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
ImGui::PushAllowKeyboardFocus(false);
ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
ImGui::PopAllowKeyboardFocus();
ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
ImGui::TreePop();
}
if (ImGui::TreeNode("Focus from code"))
{
bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
bool focus_3 = ImGui::Button("Focus on 3");
int has_focus = 0;
static char buf[128] = "click on a button to set focus";
if (focus_1) ImGui::SetKeyboardFocusHere();
ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
if (ImGui::IsItemActive()) has_focus = 1;
if (focus_2) ImGui::SetKeyboardFocusHere();
ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
if (ImGui::IsItemActive()) has_focus = 2;
ImGui::PushAllowKeyboardFocus(false);
if (focus_3) ImGui::SetKeyboardFocusHere();
ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
if (ImGui::IsItemActive()) has_focus = 3;
ImGui::PopAllowKeyboardFocus();
if (has_focus)
ImGui::Text("Item with focus: %d", has_focus);
else
ImGui::Text("Item with focus: <none>");
ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code.");
ImGui::TreePop();
}
if (ImGui::TreeNode("Focused & Hovered Test"))
{
static bool embed_all_inside_a_child_window = false;
ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
if (embed_all_inside_a_child_window)
ImGui::BeginChild("embeddingchild", ImVec2(0, ImGui::GetFontSize() * 25), true);
ImGui::BulletText(
"IsWindowFocused() = %d\n"
"IsWindowFocused(_ChildWindows) = %d\n"
"IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
"IsWindowFocused(_RootWindow) = %d\n",
ImGui::IsWindowFocused(),
ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows),
ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
ImGui::IsWindowFocused(ImGuiHoveredFlags_RootWindow));
ImGui::BulletText(
"IsWindowHovered() = %d\n"
"IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
"IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
"IsWindowHovered(_ChildWindows) = %d\n"
"IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
"IsWindowHovered(_RootWindow) = %d\n",
ImGui::IsWindowHovered(),
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow));
ImGui::Button("ITEM");
ImGui::BulletText(
"IsItemHovered() = %d\n"
"IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
"IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
"IsItemHovered(_AllowWhenOverlapped) = %d\n"
"IsItemhovered(_RectOnly) = %d\n",
ImGui::IsItemHovered(),
ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly));
ImGui::BeginChild("child", ImVec2(0,50), true);
ImGui::Text("This is another child window for testing IsWindowHovered() flags.");
ImGui::EndChild();
if (embed_all_inside_a_child_window)
EndChild();
ImGui::TreePop();
}
if (ImGui::TreeNode("Dragging"))
{
ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
for (int button = 0; button < 3; button++)
ImGui::Text("IsMouseDragging(%d):\n w/ default threshold: %d,\n w/ zero threshold: %d\n w/ large threshold: %d",
button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
ImGui::Button("Drag Me");
if (ImGui::IsItemActive())
{
ImDrawList* draw_list = ImGui::GetWindowDrawList();
draw_list->PushClipRectFullScreen();
draw_list->AddLine(ImGui::CalcItemRectClosestPoint(io.MousePos, true, -2.0f), io.MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f);
draw_list->PopClipRect();
ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
ImVec2 mouse_delta = io.MouseDelta;
ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y);
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Mouse cursors"))
{
const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE" };
IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_Count_);
ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
ImGui::Text("Hover to see mouse cursors:");
ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
for (int i = 0; i < ImGuiMouseCursor_Count_; i++)
{
char label[32];
sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
ImGui::Bullet(); ImGui::Selectable(label, false);
if (ImGui::IsItemHovered())
ImGui::SetMouseCursor(i);
}
ImGui::TreePop();
}
}
ImGui::End();
}
bool ImGui::ShowStyleSelector(const char* label)
{
static int style_idx = 0;
if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
{
switch (style_idx)
{
case 0: ImGui::StyleColorsClassic(); break;
case 1: ImGui::StyleColorsDark(); break;
case 2: ImGui::StyleColorsLight(); break;
}
return true;
}
return false;
}
void ImGui::ShowFontSelector(const char* label)
{
ImGuiIO& io = ImGui::GetIO();
ImFont* font_current = ImGui::GetFont();
if (ImGui::BeginCombo(label, font_current->GetDebugName()))
{
for (int n = 0; n < io.Fonts->Fonts.Size; n++)
if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current))
io.FontDefault = io.Fonts->Fonts[n];
ImGui::EndCombo();
}
ImGui::SameLine();
ShowHelpMarker(
"- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
"- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
"- Read FAQ and documentation in extra_fonts/ for more details.\n"
"- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
}
void ImGui::ShowStyleEditor(ImGuiStyle* ref)
{
ImGuiStyle& style = ImGui::GetStyle();
static ImGuiStyle ref_saved_style;
static bool init = true;
if (init && ref == NULL)
ref_saved_style = style;
init = false;
if (ref == NULL)
ref = &ref_saved_style;
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
if (ImGui::ShowStyleSelector("Colors##Selector"))
ref_saved_style = style;
ImGui::ShowFontSelector("Fonts##Selector");
if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
style.GrabRounding = style.FrameRounding; { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
ImGui::SameLine();
{ bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
ImGui::SameLine();
{ bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
if (ImGui::Button("Save Ref"))
*ref = ref_saved_style = style;
ImGui::SameLine();
if (ImGui::Button("Revert Ref"))
style = *ref;
ImGui::SameLine();
ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
if (ImGui::TreeNode("Rendering"))
{
ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
ImGui::PushItemWidth(100);
ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);
if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;
ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); ImGui::PopItemWidth();
ImGui::TreePop();
}
if (ImGui::TreeNode("Settings"))
{
ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f");
ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
ImGui::Text("BorderSize");
ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
ImGui::Text("Rounding");
ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
ImGui::Text("Alignment");
ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
ImGui::TreePop();
}
if (ImGui::TreeNode("Colors"))
{
static int output_dest = 0;
static bool output_only_modified = true;
if (ImGui::Button("Export Unsaved"))
{
if (output_dest == 0)
ImGui::LogToClipboard();
else
ImGui::LogToTTY();
ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
for (int i = 0; i < ImGuiCol_COUNT; i++)
{
const ImVec4& col = style.Colors[i];
const char* name = ImGui::GetStyleColorName(i);
if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 23-(int)strlen(name), "", col.x, col.y, col.z, col.w);
}
ImGui::LogFinish();
}
ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");
static ImGuiTextFilter filter;
filter.Draw("Filter colors", 200);
static ImGuiColorEditFlags alpha_flags = 0;
ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf);
ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
ImGui::PushItemWidth(-160);
for (int i = 0; i < ImGuiCol_COUNT; i++)
{
const char* name = ImGui::GetStyleColorName(i);
if (!filter.PassFilter(name))
continue;
ImGui::PushID(i);
ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
{
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
}
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
ImGui::TextUnformatted(name);
ImGui::PopID();
}
ImGui::PopItemWidth();
ImGui::EndChild();
ImGui::TreePop();
}
bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size);
if (fonts_opened)
{
ImFontAtlas* atlas = ImGui::GetIO().Fonts;
if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
{
ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
ImGui::TreePop();
}
ImGui::PushItemWidth(100);
for (int i = 0; i < atlas->Fonts.Size; i++)
{
ImFont* font = atlas->Fonts[i];
ImGui::PushID(font);
bool font_details_opened = ImGui::TreeNode(font, "Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
if (font_details_opened)
{
ImGui::PushFont(font);
ImGui::Text("The quick brown fox jumps over the lazy dog");
ImGui::PopFont();
ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
{
ImFontConfig* cfg = &font->ConfigData[config_i];
ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
}
if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
{
const ImFontGlyph* glyph_fallback = font->FallbackGlyph; font->FallbackGlyph = NULL;
for (int base = 0; base < 0x10000; base += 256)
{
int count = 0;
for (int n = 0; n < 256; n++)
count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0;
if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph"))
{
float cell_spacing = style.ItemSpacing.y;
ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1);
ImVec2 base_pos = ImGui::GetCursorScreenPos();
ImDrawList* draw_list = ImGui::GetWindowDrawList();
for (int n = 0; n < 256; n++)
{
ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing));
ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y);
const ImFontGlyph* glyph = font->FindGlyph((ImWchar)(base+n));;
draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50));
font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
{
ImGui::BeginTooltip();
ImGui::Text("Codepoint: U+%04X", base+n);
ImGui::Separator();
ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
ImGui::EndTooltip();
}
}
ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16));
ImGui::TreePop();
}
}
font->FallbackGlyph = glyph_fallback;
ImGui::TreePop();
}
ImGui::TreePop();
}
ImGui::PopID();
}
static float window_scale = 1.0f;
ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); ImGui::PopItemWidth();
ImGui::SetWindowFontScale(window_scale);
ImGui::TreePop();
}
ImGui::PopItemWidth();
}
static void ShowExampleAppMainMenuBar()
{
if (ImGui::BeginMainMenuBar())
{
if (ImGui::BeginMenu("File"))
{
ShowExampleMenuFile();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Edit"))
{
if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} ImGui::Separator();
if (ImGui::MenuItem("Cut", "CTRL+X")) {}
if (ImGui::MenuItem("Copy", "CTRL+C")) {}
if (ImGui::MenuItem("Paste", "CTRL+V")) {}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
}
static void ShowExampleMenuFile()
{
ImGui::MenuItem("(dummy menu)", NULL, false, false);
if (ImGui::MenuItem("New")) {}
if (ImGui::MenuItem("Open", "Ctrl+O")) {}
if (ImGui::BeginMenu("Open Recent"))
{
ImGui::MenuItem("fish_hat.c");
ImGui::MenuItem("fish_hat.inl");
ImGui::MenuItem("fish_hat.h");
if (ImGui::BeginMenu("More.."))
{
ImGui::MenuItem("Hello");
ImGui::MenuItem("Sailor");
if (ImGui::BeginMenu("Recurse.."))
{
ShowExampleMenuFile();
ImGui::EndMenu();
}
ImGui::EndMenu();
}
ImGui::EndMenu();
}
if (ImGui::MenuItem("Save", "Ctrl+S")) {}
if (ImGui::MenuItem("Save As..")) {}
ImGui::Separator();
if (ImGui::BeginMenu("Options"))
{
static bool enabled = true;
ImGui::MenuItem("Enabled", "", &enabled);
ImGui::BeginChild("child", ImVec2(0, 60), true);
for (int i = 0; i < 10; i++)
ImGui::Text("Scrolling Text %d", i);
ImGui::EndChild();
static float f = 0.5f;
static int n = 0;
static bool b = true;
ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
ImGui::InputFloat("Input", &f, 0.1f);
ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
ImGui::Checkbox("Check", &b);
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Colors"))
{
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
for (int i = 0; i < ImGuiCol_COUNT; i++)
{
const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
ImGui::ColorButton(name, ImGui::GetStyleColorVec4((ImGuiCol)i));
ImGui::SameLine();
ImGui::MenuItem(name);
}
ImGui::PopStyleVar();
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Disabled", false)) {
IM_ASSERT(0);
}
if (ImGui::MenuItem("Checked", NULL, true)) {}
if (ImGui::MenuItem("Quit", "Alt+F4")) {}
}
static void ShowExampleAppAutoResize(bool* p_open)
{
if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
{
ImGui::End();
return;
}
static int lines = 10;
ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop.");
ImGui::SliderInt("Number of lines", &lines, 1, 20);
for (int i = 0; i < lines; i++)
ImGui::Text("%*sThis is line %d", i*4, "", i); ImGui::End();
}
static void ShowExampleAppConstrainedResize(bool* p_open)
{
struct CustomConstraints {
static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
};
static bool auto_resize = false;
static int type = 0;
static int display_lines = 10;
if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);
ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
{
const char* desc[] =
{
"Resize vertical only",
"Resize horizontal only",
"Width > 100, Height > 100",
"Width 400-500",
"Height 400-500",
"Custom: Always Square",
"Custom: Fixed Steps (100)",
};
if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
ImGui::PushItemWidth(200);
ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
ImGui::PopItemWidth();
ImGui::Checkbox("Auto-resize", &auto_resize);
for (int i = 0; i < display_lines; i++)
ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
}
ImGui::End();
}
static void ShowExampleAppFixedOverlay(bool* p_open)
{
const float DISTANCE = 10.0f;
static int corner = 0;
ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings))
{
ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)");
ImGui::Separator();
ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
if (ImGui::BeginPopupContextWindow())
{
if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
ImGui::EndPopup();
}
ImGui::End();
}
ImGui::PopStyleColor();
}
static void ShowExampleAppWindowTitles(bool*)
{
ImGui::SetNextWindowPos(ImVec2(100,100), ImGuiCond_FirstUseEver);
ImGui::Begin("Same title as another window##1");
ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
ImGui::End();
ImGui::SetNextWindowPos(ImVec2(100,200), ImGuiCond_FirstUseEver);
ImGui::Begin("Same title as another window##2");
ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
ImGui::End();
char buf[128];
sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], ImGui::GetFrameCount());
ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiCond_FirstUseEver);
ImGui::Begin(buf);
ImGui::Text("This window has a changing title.");
ImGui::End();
}
static void ShowExampleAppCustomRendering(bool* p_open)
{
ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Example: Custom rendering", p_open))
{
ImGui::End();
return;
}
ImDrawList* draw_list = ImGui::GetWindowDrawList();
ImGui::Text("Primitives");
static float sz = 36.0f;
static ImVec4 col = ImVec4(1.0f,1.0f,0.4f,1.0f);
ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
ImGui::ColorEdit3("Color", &col.x);
{
const ImVec2 p = ImGui::GetCursorScreenPos();
const ImU32 col32 = ImColor(col);
float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
for (int n = 0; n < 2; n++)
{
float thickness = (n == 0) ? 1.0f : 4.0f;
draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, thickness); x += sz+spacing;
draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, thickness); x += sz+spacing;
draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, thickness); x += sz+spacing;
draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, thickness); x += sz+spacing;
draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, thickness); x += sz+spacing;
draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, thickness); x += sz+spacing;
draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, thickness); x += sz+spacing;
draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, thickness); x += spacing;
draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, thickness);
x = p.x + 4;
y += sz+spacing;
}
draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;
draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing;
draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0));
ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
}
ImGui::Separator();
{
static ImVector<ImVec2> points;
static bool adding_line = false;
ImGui::Text("Canvas example");
if (ImGui::Button("Clear")) points.clear();
if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); ImVec2 canvas_size = ImGui::GetContentRegionAvail(); if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(50,50,50), ImColor(50,50,60), ImColor(60,60,70), ImColor(50,50,60));
draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255));
bool adding_preview = false;
ImGui::InvisibleButton("canvas", canvas_size);
ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
if (adding_line)
{
adding_preview = true;
points.push_back(mouse_pos_in_canvas);
if (!ImGui::GetIO().MouseDown[0])
adding_line = adding_preview = false;
}
if (ImGui::IsItemHovered())
{
if (!adding_line && ImGui::IsMouseClicked(0))
{
points.push_back(mouse_pos_in_canvas);
adding_line = true;
}
if (ImGui::IsMouseClicked(1) && !points.empty())
{
adding_line = adding_preview = false;
points.pop_back();
points.pop_back();
}
}
draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y), true); for (int i = 0; i < points.Size - 1; i += 2)
draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i+1].x, canvas_pos.y + points[i+1].y), IM_COL32(255,255,0,255), 2.0f);
draw_list->PopClipRect();
if (adding_preview)
points.pop_back();
}
ImGui::End();
}
struct ExampleAppConsole
{
char InputBuf[256];
ImVector<char*> Items;
bool ScrollToBottom;
ImVector<char*> History;
int HistoryPos; ImVector<const char*> Commands;
ExampleAppConsole()
{
ClearLog();
memset(InputBuf, 0, sizeof(InputBuf));
HistoryPos = -1;
Commands.push_back("HELP");
Commands.push_back("HISTORY");
Commands.push_back("CLEAR");
Commands.push_back("CLASSIFY"); AddLog("Welcome to ImGui!");
}
~ExampleAppConsole()
{
ClearLog();
for (int i = 0; i < History.Size; i++)
free(History[i]);
}
static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
static int Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; }
static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }
void ClearLog()
{
for (int i = 0; i < Items.Size; i++)
free(Items[i]);
Items.clear();
ScrollToBottom = true;
}
void AddLog(const char* fmt, ...) IM_FMTARGS(2)
{
char buf[1024];
va_list args;
va_start(args, fmt);
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf)-1] = 0;
va_end(args);
Items.push_back(Strdup(buf));
ScrollToBottom = true;
}
void Draw(const char* title, bool* p_open)
{
ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, p_open))
{
ImGui::End();
return;
}
if (ImGui::BeginPopupContextItem())
{
if (ImGui::MenuItem("Close"))
*p_open = false;
ImGui::EndPopup();
}
ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine();
if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
ImGui::Separator();
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
static ImGuiTextFilter filter;
filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
ImGui::PopStyleVar();
ImGui::Separator();
const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); if (ImGui::BeginPopupContextWindow())
{
if (ImGui::Selectable("Clear")) ClearLog();
ImGui::EndPopup();
}
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); if (copy_to_clipboard)
ImGui::LogToClipboard();
for (int i = 0; i < Items.Size; i++)
{
const char* item = Items[i];
if (!filter.PassFilter(item))
continue;
ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f);
else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f);
ImGui::PushStyleColor(ImGuiCol_Text, col);
ImGui::TextUnformatted(item);
ImGui::PopStyleColor();
}
if (copy_to_clipboard)
ImGui::LogFinish();
if (ScrollToBottom)
ImGui::SetScrollHere();
ScrollToBottom = false;
ImGui::PopStyleVar();
ImGui::EndChild();
ImGui::Separator();
if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
{
char* input_end = InputBuf+strlen(InputBuf);
while (input_end > InputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0;
if (InputBuf[0])
ExecCommand(InputBuf);
strcpy(InputBuf, "");
}
if (ImGui::IsItemHovered() || (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)))
ImGui::SetKeyboardFocusHere(-1);
ImGui::End();
}
void ExecCommand(const char* command_line)
{
AddLog("# %s\n", command_line);
HistoryPos = -1;
for (int i = History.Size-1; i >= 0; i--)
if (Stricmp(History[i], command_line) == 0)
{
free(History[i]);
History.erase(History.begin() + i);
break;
}
History.push_back(Strdup(command_line));
if (Stricmp(command_line, "CLEAR") == 0)
{
ClearLog();
}
else if (Stricmp(command_line, "HELP") == 0)
{
AddLog("Commands:");
for (int i = 0; i < Commands.Size; i++)
AddLog("- %s", Commands[i]);
}
else if (Stricmp(command_line, "HISTORY") == 0)
{
int first = History.Size - 10;
for (int i = first > 0 ? first : 0; i < History.Size; i++)
AddLog("%3d: %s\n", i, History[i]);
}
else
{
AddLog("Unknown command: '%s'\n", command_line);
}
}
static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) {
ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
return console->TextEditCallback(data);
}
int TextEditCallback(ImGuiTextEditCallbackData* data)
{
switch (data->EventFlag)
{
case ImGuiInputTextFlags_CallbackCompletion:
{
const char* word_end = data->Buf + data->CursorPos;
const char* word_start = word_end;
while (word_start > data->Buf)
{
const char c = word_start[-1];
if (c == ' ' || c == '\t' || c == ',' || c == ';')
break;
word_start--;
}
ImVector<const char*> candidates;
for (int i = 0; i < Commands.Size; i++)
if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
candidates.push_back(Commands[i]);
if (candidates.Size == 0)
{
AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
}
else if (candidates.Size == 1)
{
data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
data->InsertChars(data->CursorPos, candidates[0]);
data->InsertChars(data->CursorPos, " ");
}
else
{
int match_len = (int)(word_end - word_start);
for (;;)
{
int c = 0;
bool all_candidates_matches = true;
for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
if (i == 0)
c = toupper(candidates[i][match_len]);
else if (c == 0 || c != toupper(candidates[i][match_len]))
all_candidates_matches = false;
if (!all_candidates_matches)
break;
match_len++;
}
if (match_len > 0)
{
data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
}
AddLog("Possible matches:\n");
for (int i = 0; i < candidates.Size; i++)
AddLog("- %s\n", candidates[i]);
}
break;
}
case ImGuiInputTextFlags_CallbackHistory:
{
const int prev_history_pos = HistoryPos;
if (data->EventKey == ImGuiKey_UpArrow)
{
if (HistoryPos == -1)
HistoryPos = History.Size - 1;
else if (HistoryPos > 0)
HistoryPos--;
}
else if (data->EventKey == ImGuiKey_DownArrow)
{
if (HistoryPos != -1)
if (++HistoryPos >= History.Size)
HistoryPos = -1;
}
if (prev_history_pos != HistoryPos)
{
data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
data->BufDirty = true;
}
}
}
return 0;
}
};
static void ShowExampleAppConsole(bool* p_open)
{
static ExampleAppConsole console;
console.Draw("Example: Console", p_open);
}
struct ExampleAppLog
{
ImGuiTextBuffer Buf;
ImGuiTextFilter Filter;
ImVector<int> LineOffsets; bool ScrollToBottom;
void Clear() { Buf.clear(); LineOffsets.clear(); }
void AddLog(const char* fmt, ...) IM_FMTARGS(2)
{
int old_size = Buf.size();
va_list args;
va_start(args, fmt);
Buf.appendfv(fmt, args);
va_end(args);
for (int new_size = Buf.size(); old_size < new_size; old_size++)
if (Buf[old_size] == '\n')
LineOffsets.push_back(old_size);
ScrollToBottom = true;
}
void Draw(const char* title, bool* p_open = NULL)
{
ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver);
ImGui::Begin(title, p_open);
if (ImGui::Button("Clear")) Clear();
ImGui::SameLine();
bool copy = ImGui::Button("Copy");
ImGui::SameLine();
Filter.Draw("Filter", -100.0f);
ImGui::Separator();
ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
if (copy) ImGui::LogToClipboard();
if (Filter.IsActive())
{
const char* buf_begin = Buf.begin();
const char* line = buf_begin;
for (int line_no = 0; line != NULL; line_no++)
{
const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
if (Filter.PassFilter(line, line_end))
ImGui::TextUnformatted(line, line_end);
line = line_end && line_end[1] ? line_end + 1 : NULL;
}
}
else
{
ImGui::TextUnformatted(Buf.begin());
}
if (ScrollToBottom)
ImGui::SetScrollHere(1.0f);
ScrollToBottom = false;
ImGui::EndChild();
ImGui::End();
}
};
static void ShowExampleAppLog(bool* p_open)
{
static ExampleAppLog log;
static float last_time = -1.0f;
float time = ImGui::GetTime();
if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl)
{
const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
log.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, ImGui::GetFrameCount());
last_time = time;
}
log.Draw("Example: Log", p_open);
}
static void ShowExampleAppLayout(bool* p_open)
{
ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
{
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("File"))
{
if (ImGui::MenuItem("Close")) *p_open = false;
ImGui::EndMenu();
}
ImGui::EndMenuBar();
}
static int selected = 0;
ImGui::BeginChild("left pane", ImVec2(150, 0), true);
for (int i = 0; i < 100; i++)
{
char label[128];
sprintf(label, "MyObject %d", i);
if (ImGui::Selectable(label, selected == i))
selected = i;
}
ImGui::EndChild();
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); ImGui::Text("MyObject: %d", selected);
ImGui::Separator();
ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
ImGui::EndChild();
if (ImGui::Button("Revert")) {}
ImGui::SameLine();
if (ImGui::Button("Save")) {}
ImGui::EndGroup();
}
ImGui::End();
}
static void ShowExampleAppPropertyEditor(bool* p_open)
{
ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Example: Property editor", p_open))
{
ImGui::End();
return;
}
ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
ImGui::Columns(2);
ImGui::Separator();
struct funcs
{
static void ShowDummyObject(const char* prefix, int uid)
{
ImGui::PushID(uid); ImGui::AlignTextToFramePadding(); bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
ImGui::NextColumn();
ImGui::AlignTextToFramePadding();
ImGui::Text("my sailor is rich");
ImGui::NextColumn();
if (node_open)
{
static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
for (int i = 0; i < 8; i++)
{
ImGui::PushID(i); if (i < 2)
{
ShowDummyObject("Child", 424242);
}
else
{
ImGui::AlignTextToFramePadding();
char label[32];
sprintf(label, "Field_%d", i);
ImGui::Bullet();
ImGui::Selectable(label);
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
if (i >= 5)
ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
else
ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
ImGui::PopItemWidth();
ImGui::NextColumn();
}
ImGui::PopID();
}
ImGui::TreePop();
}
ImGui::PopID();
}
};
for (int obj_i = 0; obj_i < 3; obj_i++)
funcs::ShowDummyObject("Object", obj_i);
ImGui::Columns(1);
ImGui::Separator();
ImGui::PopStyleVar();
ImGui::End();
}
static void ShowExampleAppLongText(bool* p_open)
{
ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Example: Long text display", p_open))
{
ImGui::End();
return;
}
static int test_type = 0;
static ImGuiTextBuffer log;
static int lines = 0;
ImGui::Text("Printing unusually long amount of text.");
ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
ImGui::SameLine();
if (ImGui::Button("Add 1000 lines"))
{
for (int i = 0; i < 1000; i++)
log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
lines += 1000;
}
ImGui::BeginChild("Log");
switch (test_type)
{
case 0:
ImGui::TextUnformatted(log.begin(), log.end());
break;
case 1:
{
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
ImGuiListClipper clipper(lines);
while (clipper.Step())
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
ImGui::PopStyleVar();
break;
}
case 2:
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
for (int i = 0; i < lines; i++)
ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
ImGui::PopStyleVar();
break;
}
ImGui::EndChild();
ImGui::End();
}
#else
void ImGui::ShowDemoWindow(bool*) {}
void ImGui::ShowUserGuide() {}
void ImGui::ShowStyleEditor(ImGuiStyle*) {}
#endif