1 // dear imgui, v1.53 WIP
4 // Message to the person tempted to delete this file when integrating ImGui into their code base:
5 // Don't do it! Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.
6 // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow().
7 // During development, you can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu!
8 // Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library.
9 // Note that you can #define IMGUI_DISABLE_TEST_WINDOWS in imconfig.h for the same effect.
10 // If you want to link core ImGui in your public builds but not those test windows, #define IMGUI_DISABLE_TEST_WINDOWS in imconfig.h and those functions will be empty.
11 // For any other case, if you have ImGui available you probably want this to be available for reference and execution.
13 // -Your beloved friend, imgui_demo.cpp (that you won't delete)
15 // Message to beginner C/C++ programmer about the meaning of 'static': in this demo code, we frequently we use 'static' variables inside functions.
16 // We do this as a way to gather code and data in the same place, make the demo code faster to read, faster to write, and smaller. A static variable persist across calls,
17 // so it is essentially like a global variable but declared inside the scope of the function.
18 // It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads.
19 // This may be a pattern you want to use in your code (simple is beautiful!), but most of the real data you would be editing is likely to be stored outside your function.
21 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
22 #define _CRT_SECURE_NO_WARNINGS
26 #include <ctype.h> // toupper, isprint
27 #include <math.h> // sqrtf, powf, cosf, sinf, floorf, ceilf
28 #include <stdio.h> // vsnprintf, sscanf, printf
29 #include <stdlib.h> // NULL, malloc, free, atoi
30 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
31 #include <stddef.h> // intptr_t
33 #include <stdint.h> // intptr_t
37 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
38 #define snprintf _snprintf
41 #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
42 #pragma clang diagnostic ignored "-Wdeprecated-declarations" // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
43 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
44 #pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal
45 #pragma clang diagnostic ignored "-Wexit-time-destructors" // warning : declaration requires an exit-time destructor // exit-time destruction order is undefined. if MemFree() leads to users code that has been disabled before exit it might cause problems. ImGui coding style welcomes static/globals.
46 #if __has_warning("-Wreserved-id-macro")
47 #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
49 #elif defined(__GNUC__)
50 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
51 #pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure)
52 #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
53 #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
55 #pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on github.
59 // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
61 #define IM_NEWLINE "\r\n"
63 #define IM_NEWLINE "\n"
66 #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR)))
67 #define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B))
69 //-----------------------------------------------------------------------------
71 //-----------------------------------------------------------------------------
73 #ifndef IMGUI_DISABLE_TEST_WINDOWS
75 static void ShowExampleAppConsole(bool* p_open);
76 static void ShowExampleAppLog(bool* p_open);
77 static void ShowExampleAppLayout(bool* p_open);
78 static void ShowExampleAppPropertyEditor(bool* p_open);
79 static void ShowExampleAppLongText(bool* p_open);
80 static void ShowExampleAppAutoResize(bool* p_open);
81 static void ShowExampleAppConstrainedResize(bool* p_open);
82 static void ShowExampleAppFixedOverlay(bool* p_open);
83 static void ShowExampleAppManipulatingWindowTitle(bool* p_open);
84 static void ShowExampleAppCustomRendering(bool* p_open);
85 static void ShowExampleAppMainMenuBar();
86 static void ShowExampleMenuFile();
88 static void ShowHelpMarker(const char* desc)
90 ImGui::TextDisabled("(?)");
91 if (ImGui::IsItemHovered())
93 ImGui::BeginTooltip();
94 ImGui::PushTextWrapPos(450.0f);
95 ImGui::TextUnformatted(desc);
96 ImGui::PopTextWrapPos();
101 void ImGui::ShowUserGuide()
103 ImGui::BulletText("Double-click on title bar to collapse window.");
104 ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
105 ImGui::BulletText("Click and drag on any empty space to move window.");
106 ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
107 ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
108 if (ImGui::GetIO().FontAllowUserScaling)
109 ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
110 ImGui::BulletText("Mouse Wheel to scroll.");
111 ImGui::BulletText("While editing text:\n");
113 ImGui::BulletText("Hold SHIFT or use mouse to select text.");
114 ImGui::BulletText("CTRL+Left/Right to word jump.");
115 ImGui::BulletText("CTRL+A or double-click to select all.");
116 ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
117 ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
118 ImGui::BulletText("ESCAPE to revert.");
119 ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
123 // Demonstrate most ImGui features (big function!)
124 void ImGui::ShowTestWindow(bool* p_open)
127 static bool show_app_main_menu_bar = false;
128 static bool show_app_console = false;
129 static bool show_app_log = false;
130 static bool show_app_layout = false;
131 static bool show_app_property_editor = false;
132 static bool show_app_long_text = false;
133 static bool show_app_auto_resize = false;
134 static bool show_app_constrained_resize = false;
135 static bool show_app_fixed_overlay = false;
136 static bool show_app_manipulating_window_title = false;
137 static bool show_app_custom_rendering = false;
138 static bool show_app_style_editor = false;
140 static bool show_app_metrics = false;
141 static bool show_app_about = false;
143 if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
144 if (show_app_console) ShowExampleAppConsole(&show_app_console);
145 if (show_app_log) ShowExampleAppLog(&show_app_log);
146 if (show_app_layout) ShowExampleAppLayout(&show_app_layout);
147 if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor);
148 if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text);
149 if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize);
150 if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize);
151 if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
152 if (show_app_manipulating_window_title) ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title);
153 if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering);
155 if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics);
156 if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
159 ImGui::Begin("About ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
160 ImGui::Text("dear imgui, %s", ImGui::GetVersion());
162 ImGui::Text("By Omar Cornut and all github contributors.");
163 ImGui::Text("ImGui is licensed under the MIT License, see LICENSE for more information.");
167 static bool no_titlebar = false;
168 static bool no_scrollbar = false;
169 static bool no_menu = false;
170 static bool no_move = false;
171 static bool no_resize = false;
172 static bool no_collapse = false;
174 // Demonstrate the various window flags. Typically you would just use the default.
175 ImGuiWindowFlags window_flags = 0;
176 if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
177 if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
178 if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
179 if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
180 if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
181 if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
182 ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiCond_FirstUseEver);
183 if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
185 // Early out if the window is collapsed, as an optimization.
190 //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // 2/3 of the space for widget and 1/3 for labels
191 ImGui::PushItemWidth(-140); // Right align, keep 140 pixels for labels
193 ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
196 if (ImGui::BeginMenuBar())
198 if (ImGui::BeginMenu("Menu"))
200 ShowExampleMenuFile();
203 if (ImGui::BeginMenu("Examples"))
205 ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
206 ImGui::MenuItem("Console", NULL, &show_app_console);
207 ImGui::MenuItem("Log", NULL, &show_app_log);
208 ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
209 ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
210 ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
211 ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
212 ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
213 ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay);
214 ImGui::MenuItem("Manipulating window title", NULL, &show_app_manipulating_window_title);
215 ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
218 if (ImGui::BeginMenu("Help"))
220 ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
221 ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
222 ImGui::MenuItem("About ImGui", NULL, &show_app_about);
229 if (ImGui::CollapsingHeader("Help"))
231 ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n");
232 ImGui::Text("USER GUIDE:");
233 ImGui::ShowUserGuide();
236 if (ImGui::CollapsingHeader("Window options"))
238 ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
239 ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
240 ImGui::Checkbox("No menu", &no_menu);
241 ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
242 ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
243 ImGui::Checkbox("No collapse", &no_collapse);
245 if (ImGui::TreeNode("Style"))
247 ImGui::ShowStyleEditor();
251 if (ImGui::TreeNode("Logging"))
253 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.");
259 if (ImGui::CollapsingHeader("Widgets"))
261 if (ImGui::TreeNode("Basic"))
263 static int clicked = 0;
264 if (ImGui::Button("Button"))
269 ImGui::Text("Thanks for clicking me!");
272 static bool check = true;
273 ImGui::Checkbox("checkbox", &check);
276 ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
277 ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
278 ImGui::RadioButton("radio c", &e, 2);
280 // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
281 for (int i = 0; i < 7; i++)
283 if (i > 0) ImGui::SameLine();
285 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
286 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
287 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
288 ImGui::Button("Click");
289 ImGui::PopStyleColor(3);
293 ImGui::Text("Hover over me");
294 if (ImGui::IsItemHovered())
295 ImGui::SetTooltip("I am a tooltip");
298 ImGui::Text("- or me");
299 if (ImGui::IsItemHovered())
301 ImGui::BeginTooltip();
302 ImGui::Text("I am a fancy tooltip");
303 static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
304 ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
308 // Testing ImGuiOnceUponAFrame helper.
309 //static ImGuiOnceUponAFrame once;
310 //for (int i = 0; i < 5; i++)
312 // ImGui::Text("This will be displayed only once.");
316 ImGui::LabelText("label", "Value");
319 ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Combo using values packed in a single constant string (for really quick combo)
321 const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK" };
322 static int item2 = -1;
323 ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that.
326 static char str0[128] = "Hello, world!";
328 static float f0=0.001f;
329 ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
330 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");
332 ImGui::InputInt("input int", &i0);
333 ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
335 ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
337 static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
338 ImGui::InputFloat3("input float3", vec4a);
342 static int i1=50, i2=42;
343 ImGui::DragInt("drag int", &i1, 1);
344 ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
346 ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%");
348 static float f1=1.00f, f2=0.0067f;
349 ImGui::DragFloat("drag float", &f1, 0.005f);
350 ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
355 ImGui::SliderInt("slider int", &i1, -1, 3);
356 ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
358 static float f1=0.123f, f2=0.0f;
359 ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
360 ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f);
361 static float angle = 0.0f;
362 ImGui::SliderAngle("slider angle", &angle);
365 static float col1[3] = { 1.0f,0.0f,0.2f };
366 static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
367 ImGui::ColorEdit3("color 1", col1);
368 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");
370 ImGui::ColorEdit4("color 2", col2);
372 const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
373 static int listbox_item_current = 1;
374 ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
376 //static int listbox_item_current2 = 2;
377 //ImGui::PushItemWidth(-1);
378 //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
379 //ImGui::PopItemWidth();
384 if (ImGui::TreeNode("Trees"))
386 if (ImGui::TreeNode("Basic trees"))
388 for (int i = 0; i < 5; i++)
389 if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
391 ImGui::Text("blah blah");
393 if (ImGui::SmallButton("print")) printf("Child %d pressed", i);
399 if (ImGui::TreeNode("Advanced, with Selectable nodes"))
401 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.");
402 static bool align_label_with_current_x_position = false;
403 ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
404 ImGui::Text("Hello!");
405 if (align_label_with_current_x_position)
406 ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
408 static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
409 int node_clicked = -1; // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
410 ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
411 for (int i = 0; i < 6; i++)
413 // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
414 ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
418 bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
419 if (ImGui::IsItemClicked())
423 ImGui::Text("Blah blah\nBlah Blah");
429 // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text().
430 node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
431 ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
432 if (ImGui::IsItemClicked())
436 if (node_clicked != -1)
438 // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
439 if (ImGui::GetIO().KeyCtrl)
440 selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
441 else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
442 selection_mask = (1 << node_clicked); // Click to single-select
444 ImGui::PopStyleVar();
445 if (align_label_with_current_x_position)
446 ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
452 if (ImGui::TreeNode("Collapsing Headers"))
454 static bool closable_group = true;
455 ImGui::Checkbox("Enable extra group", &closable_group);
456 if (ImGui::CollapsingHeader("Header"))
458 ImGui::Text("IsItemHovered: %d", IsItemHovered());
459 for (int i = 0; i < 5; i++)
460 ImGui::Text("Some content %d", i);
462 if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
464 ImGui::Text("IsItemHovered: %d", IsItemHovered());
465 for (int i = 0; i < 5; i++)
466 ImGui::Text("More content %d", i);
471 if (ImGui::TreeNode("Bullets"))
473 ImGui::BulletText("Bullet point 1");
474 ImGui::BulletText("Bullet point 2\nOn multiple lines");
475 ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
476 ImGui::Bullet(); ImGui::SmallButton("Button");
480 if (ImGui::TreeNode("Text"))
482 if (ImGui::TreeNode("Colored Text"))
484 // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
485 ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
486 ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
487 ImGui::TextDisabled("Disabled");
488 ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
492 if (ImGui::TreeNode("Word Wrapping"))
494 // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
495 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.");
498 static float wrap_width = 200.0f;
499 ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
501 ImGui::Text("Test paragraph 1:");
502 ImVec2 pos = ImGui::GetCursorScreenPos();
503 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));
504 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
505 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);
506 ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
507 ImGui::PopTextWrapPos();
509 ImGui::Text("Test paragraph 2:");
510 pos = ImGui::GetCursorScreenPos();
511 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));
512 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
513 ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
514 ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
515 ImGui::PopTextWrapPos();
520 if (ImGui::TreeNode("UTF-8 Text"))
522 // UTF-8 test with Japanese characters
523 // (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html)
524 // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
525 // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. Visual Studio save your file as 'UTF-8 without signature')
526 // - HOWEVER, FOR THIS DEMO FILE, BECAUSE WE WANT TO SUPPORT COMPILER, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.
527 // Instead we are encoding a few string with hexadecimal constants. Don't do this in your application!
528 // Note that characters values are preserved even by InputText() if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
529 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.");
530 ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
531 ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
532 static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; // "nihongo"
533 ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
539 if (ImGui::TreeNode("Images"))
541 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!");
542 ImGuiIO& io = ImGui::GetIO();
544 // Here we are grabbing the font texture because that's the only one we have access to inside the demo code.
545 // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure.
546 // If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID.
547 // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.)
548 // If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc.
549 // Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this.
550 // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
551 ImTextureID my_tex_id = io.Fonts->TexID;
552 float my_tex_w = (float)io.Fonts->TexWidth;
553 float my_tex_h = (float)io.Fonts->TexHeight;
555 ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
556 ImVec2 pos = ImGui::GetCursorScreenPos();
557 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));
558 if (ImGui::IsItemHovered())
560 ImGui::BeginTooltip();
561 float focus_sz = 32.0f;
562 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;
563 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;
564 ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y);
565 ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz);
566 ImVec2 uv0 = ImVec2((focus_x) / my_tex_w, (focus_y) / my_tex_h);
567 ImVec2 uv1 = ImVec2((focus_x + focus_sz) / my_tex_w, (focus_y + focus_sz) / my_tex_h);
568 ImGui::Image(my_tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
571 ImGui::TextWrapped("And now some textured buttons..");
572 static int pressed_count = 0;
573 for (int i = 0; i < 8; i++)
576 int frame_padding = -1 + i; // -1 = uses default padding
577 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)))
583 ImGui::Text("Pressed %d times.", pressed_count);
587 if (ImGui::TreeNode("Selectables"))
589 if (ImGui::TreeNode("Basic"))
591 static bool selected[4] = { false, true, false, false };
592 ImGui::Selectable("1. I am selectable", &selected[0]);
593 ImGui::Selectable("2. I am selectable", &selected[1]);
594 ImGui::Text("3. I am not selectable");
595 ImGui::Selectable("4. I am selectable", &selected[2]);
596 if (ImGui::Selectable("5. I am double clickable", selected[3], ImGuiSelectableFlags_AllowDoubleClick))
597 if (ImGui::IsMouseDoubleClicked(0))
598 selected[3] = !selected[3];
601 if (ImGui::TreeNode("Rendering more text into the same block"))
603 static bool selected[3] = { false, false, false };
604 ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
605 ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
606 ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
609 if (ImGui::TreeNode("In columns"))
611 ImGui::Columns(3, NULL, false);
612 static bool selected[16] = { 0 };
613 for (int i = 0; i < 16; i++)
615 char label[32]; sprintf(label, "Item %d", i);
616 if (ImGui::Selectable(label, &selected[i])) {}
622 if (ImGui::TreeNode("Grid"))
624 static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
625 for (int i = 0; i < 16; i++)
628 if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50)))
630 int x = i % 4, y = i / 4;
631 if (x > 0) selected[i - 1] ^= 1;
632 if (x < 3) selected[i + 1] ^= 1;
633 if (y > 0) selected[i - 4] ^= 1;
634 if (y < 3) selected[i + 4] ^= 1;
636 if ((i % 4) < 3) ImGui::SameLine();
644 if (ImGui::TreeNode("Filtered Text Input"))
646 static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
647 static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
648 static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
649 static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
650 static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
651 struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
652 static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
654 ImGui::Text("Password input");
655 static char bufpass[64] = "password123";
656 ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
657 ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
658 ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
663 if (ImGui::TreeNode("Multi-line Text Input"))
665 static bool read_only = false;
666 static char text[1024*16] =
668 " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
669 " the hexadecimal encoding of one offending instruction,\n"
670 " more formally, the invalid operand with locked CMPXCHG8B\n"
671 " instruction bug, is a design flaw in the majority of\n"
672 " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
673 " processors (all in the P5 microarchitecture).\n"
676 "\tlock cmpxchg8b eax\n";
678 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
679 ImGui::Checkbox("Read-only", &read_only);
680 ImGui::PopStyleVar();
681 ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0));
685 if (ImGui::TreeNode("Plots widgets"))
687 static bool animate = true;
688 ImGui::Checkbox("Animate", &animate);
690 static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
691 ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
693 // Create a dummy array of contiguous float values to plot
694 // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter.
695 static float values[90] = { 0 };
696 static int values_offset = 0;
697 static float refresh_time = 0.0f;
698 if (!animate || refresh_time == 0.0f)
699 refresh_time = ImGui::GetTime();
700 while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo
702 static float phase = 0.0f;
703 values[values_offset] = cosf(phase);
704 values_offset = (values_offset+1) % IM_ARRAYSIZE(values);
705 phase += 0.10f*values_offset;
706 refresh_time += 1.0f/60.0f;
708 ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
709 ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));
711 // Use functions to generate output
712 // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count.
715 static float Sin(void*, int i) { return sinf(i * 0.1f); }
716 static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
718 static int func_type = 0, display_count = 70;
720 ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
722 ImGui::SliderInt("Sample count", &display_count, 1, 400);
723 float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
724 ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
725 ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
728 // Animate a simple progress bar
729 static float progress = 0.0f, progress_dir = 1.0f;
732 progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
733 if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
734 if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
737 // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
738 ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
739 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
740 ImGui::Text("Progress Bar");
742 float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
744 sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
745 ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
749 if (ImGui::TreeNode("Color/Picker Widgets"))
751 static ImVec4 color = ImColor(114, 144, 154, 200);
753 static bool hdr = false;
754 static bool alpha_preview = true;
755 static bool alpha_half_preview = false;
756 static bool options_menu = true;
757 ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
758 ImGui::Checkbox("With Alpha Preview", &alpha_preview);
759 ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
760 ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
761 int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
763 ImGui::Text("Color widget:");
764 ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
765 ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
767 ImGui::Text("Color widget HSV with Alpha:");
768 ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
770 ImGui::Text("Color widget with Float Display:");
771 ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
773 ImGui::Text("Color button with Picker:");
774 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.");
775 ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
777 ImGui::Text("Color button with Custom Picker Popup:");
778 static bool saved_palette_inited = false;
779 static ImVec4 saved_palette[32];
780 static ImVec4 backup_color;
781 if (!saved_palette_inited)
782 for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
783 ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
784 bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
786 open_popup |= ImGui::Button("Palette");
789 ImGui::OpenPopup("mypicker");
790 backup_color = color;
792 if (ImGui::BeginPopup("mypicker"))
794 // FIXME: Adding a drag and drop example here would be perfect!
795 ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
797 ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
800 ImGui::Text("Current");
801 ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40));
802 ImGui::Text("Previous");
803 if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)))
804 color = backup_color;
806 ImGui::Text("Palette");
807 for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
811 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
812 if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20)))
813 color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
820 ImGui::Text("Color button only:");
821 ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80));
823 ImGui::Text("Color picker:");
824 static bool alpha = true;
825 static bool alpha_bar = true;
826 static bool side_preview = true;
827 static bool ref_color = false;
828 static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);
829 static int inputs_mode = 2;
830 static int picker_mode = 0;
831 ImGui::Checkbox("With Alpha", &alpha);
832 ImGui::Checkbox("With Alpha Bar", &alpha_bar);
833 ImGui::Checkbox("With Side Preview", &side_preview);
837 ImGui::Checkbox("With Ref Color", &ref_color);
841 ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
844 ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
845 ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
846 ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
847 ImGuiColorEditFlags flags = misc_flags;
848 if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
849 if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
850 if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
851 if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
852 if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
853 if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;
854 if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;
855 if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;
856 if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;
857 ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
859 ImGui::Text("Programmatically set defaults/options:");
860 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.");
861 if (ImGui::Button("Uint8 + HSV"))
862 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV);
864 if (ImGui::Button("Float + HDR"))
865 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_RGB);
870 if (ImGui::TreeNode("Range Widgets"))
872 static float begin = 10, end = 90;
873 static int begin_i = 100, end_i = 1000;
874 ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
875 ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %.0f units", "Max: %.0f units");
879 if (ImGui::TreeNode("Multi-component Widgets"))
881 static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
882 static int vec4i[4] = { 1, 5, 100, 255 };
884 ImGui::InputFloat2("input float2", vec4f);
885 ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
886 ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
887 ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
888 ImGui::InputInt2("input int2", vec4i);
889 ImGui::SliderInt2("slider int2", vec4i, 0, 255);
892 ImGui::InputFloat3("input float3", vec4f);
893 ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
894 ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
895 ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
896 ImGui::InputInt3("input int3", vec4i);
897 ImGui::SliderInt3("slider int3", vec4i, 0, 255);
900 ImGui::InputFloat4("input float4", vec4f);
901 ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
902 ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
903 ImGui::InputInt4("input int4", vec4i);
904 ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
905 ImGui::SliderInt4("slider int4", vec4i, 0, 255);
910 if (ImGui::TreeNode("Vertical Sliders"))
912 const float spacing = 4;
913 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
915 static int int_value = 0;
916 ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
919 static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
920 ImGui::PushID("set1");
921 for (int i = 0; i < 7; i++)
923 if (i > 0) ImGui::SameLine();
925 ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));
926 ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));
927 ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));
928 ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));
929 ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
930 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
931 ImGui::SetTooltip("%.3f", values[i]);
932 ImGui::PopStyleColor(4);
938 ImGui::PushID("set2");
939 static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
941 const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);
942 for (int nx = 0; nx < 4; nx++)
944 if (nx > 0) ImGui::SameLine();
946 for (int ny = 0; ny < rows; ny++)
948 ImGui::PushID(nx*rows+ny);
949 ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
950 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
951 ImGui::SetTooltip("%.3f", values2[nx]);
959 ImGui::PushID("set3");
960 for (int i = 0; i < 4; i++)
962 if (i > 0) ImGui::SameLine();
964 ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
965 ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
966 ImGui::PopStyleVar();
970 ImGui::PopStyleVar();
975 if (ImGui::CollapsingHeader("Layout"))
977 if (ImGui::TreeNode("Child regions"))
979 ImGui::Text("Without border");
980 static int line = 50;
981 bool goto_line = ImGui::Button("Goto");
983 ImGui::PushItemWidth(100);
984 goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
985 ImGui::PopItemWidth();
986 ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar);
987 for (int i = 0; i < 100; i++)
989 ImGui::Text("%04d: scrollable region", i);
990 if (goto_line && line == i)
991 ImGui::SetScrollHere();
993 if (goto_line && line >= 100)
994 ImGui::SetScrollHere();
999 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
1000 ImGui::BeginChild("Sub2", ImVec2(0,300), true);
1001 ImGui::Text("With border");
1003 for (int i = 0; i < 100; i++)
1006 ImGui::NextColumn();
1008 sprintf(buf, "%08x", i*5731);
1009 ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
1012 ImGui::PopStyleVar();
1017 if (ImGui::TreeNode("Widgets Width"))
1019 static float f = 0.0f;
1020 ImGui::Text("PushItemWidth(100)");
1021 ImGui::SameLine(); ShowHelpMarker("Fixed width.");
1022 ImGui::PushItemWidth(100);
1023 ImGui::DragFloat("float##1", &f);
1024 ImGui::PopItemWidth();
1026 ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
1027 ImGui::SameLine(); ShowHelpMarker("Half of window width.");
1028 ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
1029 ImGui::DragFloat("float##2", &f);
1030 ImGui::PopItemWidth();
1032 ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
1033 ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
1034 ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
1035 ImGui::DragFloat("float##3", &f);
1036 ImGui::PopItemWidth();
1038 ImGui::Text("PushItemWidth(-100)");
1039 ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
1040 ImGui::PushItemWidth(-100);
1041 ImGui::DragFloat("float##4", &f);
1042 ImGui::PopItemWidth();
1044 ImGui::Text("PushItemWidth(-1)");
1045 ImGui::SameLine(); ShowHelpMarker("Align to right edge");
1046 ImGui::PushItemWidth(-1);
1047 ImGui::DragFloat("float##5", &f);
1048 ImGui::PopItemWidth();
1053 if (ImGui::TreeNode("Basic Horizontal Layout"))
1055 ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1058 ImGui::Text("Two items: Hello"); ImGui::SameLine();
1059 ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1062 ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
1063 ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1066 ImGui::AlignTextToFramePadding();
1067 ImGui::Text("Normal buttons"); ImGui::SameLine();
1068 ImGui::Button("Banana"); ImGui::SameLine();
1069 ImGui::Button("Apple"); ImGui::SameLine();
1070 ImGui::Button("Corniflower");
1073 ImGui::Text("Small buttons"); ImGui::SameLine();
1074 ImGui::SmallButton("Like this one"); ImGui::SameLine();
1075 ImGui::Text("can fit within a text block.");
1077 // Aligned to arbitrary position. Easy/cheap column.
1078 ImGui::Text("Aligned");
1079 ImGui::SameLine(150); ImGui::Text("x=150");
1080 ImGui::SameLine(300); ImGui::Text("x=300");
1081 ImGui::Text("Aligned");
1082 ImGui::SameLine(150); ImGui::SmallButton("x=150");
1083 ImGui::SameLine(300); ImGui::SmallButton("x=300");
1086 static bool c1=false,c2=false,c3=false,c4=false;
1087 ImGui::Checkbox("My", &c1); ImGui::SameLine();
1088 ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
1089 ImGui::Checkbox("Is", &c3); ImGui::SameLine();
1090 ImGui::Checkbox("Rich", &c4);
1093 static float f0=1.0f, f1=2.0f, f2=3.0f;
1094 ImGui::PushItemWidth(80);
1095 const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
1096 static int item = -1;
1097 ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
1098 ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine();
1099 ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine();
1100 ImGui::SliderFloat("Z", &f2, 0.0f,5.0f);
1101 ImGui::PopItemWidth();
1103 ImGui::PushItemWidth(80);
1104 ImGui::Text("Lists:");
1105 static int selection[4] = { 0, 1, 2, 3 };
1106 for (int i = 0; i < 4; i++)
1108 if (i > 0) ImGui::SameLine();
1110 ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
1112 //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
1114 ImGui::PopItemWidth();
1118 ImGui::Button("A", sz); ImGui::SameLine();
1119 ImGui::Dummy(sz); ImGui::SameLine();
1120 ImGui::Button("B", sz);
1125 if (ImGui::TreeNode("Groups"))
1127 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.)");
1128 ImGui::BeginGroup();
1130 ImGui::BeginGroup();
1131 ImGui::Button("AAA");
1133 ImGui::Button("BBB");
1135 ImGui::BeginGroup();
1136 ImGui::Button("CCC");
1137 ImGui::Button("DDD");
1140 ImGui::Button("EEE");
1142 if (ImGui::IsItemHovered())
1143 ImGui::SetTooltip("First group hovered");
1145 // Capture the group size and create widgets using the same size
1146 ImVec2 size = ImGui::GetItemRectSize();
1147 const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
1148 ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
1150 ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
1152 ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
1156 ImGui::Button("LEVERAGE\nBUZZWORD", size);
1159 ImGui::ListBoxHeader("List", size);
1160 ImGui::Selectable("Selected", true);
1161 ImGui::Selectable("Not Selected", false);
1162 ImGui::ListBoxFooter();
1167 if (ImGui::TreeNode("Text Baseline Alignment"))
1169 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)");
1171 ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
1172 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1173 ImGui::Text("Banana");
1175 ImGui::Text("Banana"); ImGui::SameLine();
1176 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1177 ImGui::Text("One\nTwo\nThree");
1179 ImGui::Button("HOP##1"); ImGui::SameLine();
1180 ImGui::Text("Banana"); ImGui::SameLine();
1181 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1182 ImGui::Text("Banana");
1184 ImGui::Button("HOP##2"); ImGui::SameLine();
1185 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1186 ImGui::Text("Banana");
1188 ImGui::Button("TEST##1"); ImGui::SameLine();
1189 ImGui::Text("TEST"); ImGui::SameLine();
1190 ImGui::SmallButton("TEST##2");
1192 ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets.
1193 ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
1194 ImGui::Button("Widget##1"); ImGui::SameLine();
1195 ImGui::Text("Widget"); ImGui::SameLine();
1196 ImGui::SmallButton("Widget##2"); ImGui::SameLine();
1197 ImGui::Button("Widget##3");
1200 const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
1201 ImGui::Button("Button##1");
1202 ImGui::SameLine(0.0f, spacing);
1203 if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
1205 ImGui::AlignTextToFramePadding(); // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
1206 bool node_open = ImGui::TreeNode("Node##2"); // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.
1207 ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
1208 if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); } // Dummy tree data
1211 ImGui::Button("Button##3");
1212 ImGui::SameLine(0.0f, spacing);
1213 ImGui::BulletText("Bullet text");
1215 ImGui::AlignTextToFramePadding();
1216 ImGui::BulletText("Node");
1217 ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
1222 if (ImGui::TreeNode("Scrolling"))
1224 ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)");
1225 static bool track = true;
1226 static int track_line = 50, scroll_to_px = 200;
1227 ImGui::Checkbox("Track", &track);
1228 ImGui::PushItemWidth(100);
1229 ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %.0f");
1230 bool scroll_to = ImGui::Button("Scroll To Pos");
1231 ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %.0f px");
1232 ImGui::PopItemWidth();
1233 if (scroll_to) track = false;
1235 for (int i = 0; i < 5; i++)
1237 if (i > 0) ImGui::SameLine();
1238 ImGui::BeginGroup();
1239 ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
1240 ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
1242 ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
1243 for (int line = 0; line < 100; line++)
1245 if (track && line == track_line)
1247 ImGui::TextColored(ImColor(255,255,0), "Line %d", line);
1248 ImGui::SetScrollHere(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
1252 ImGui::Text("Line %d", line);
1255 float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
1257 ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
1263 if (ImGui::TreeNode("Horizontal Scrolling"))
1265 ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
1266 ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
1267 static int lines = 7;
1268 ImGui::SliderInt("Lines", &lines, 1, 15);
1269 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
1270 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
1271 ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
1272 for (int line = 0; line < lines; line++)
1274 // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off
1275 // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API)
1276 int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
1277 for (int n = 0; n < num_buttons; n++)
1279 if (n > 0) ImGui::SameLine();
1280 ImGui::PushID(n + line * 1000);
1282 const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : (sprintf(num_buf, "%d", n), num_buf);
1283 float hue = n*0.05f;
1284 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
1285 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
1286 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
1287 ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
1288 ImGui::PopStyleColor(3);
1292 float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
1294 ImGui::PopStyleVar(2);
1295 float scroll_x_delta = 0.0f;
1296 ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
1297 ImGui::Text("Scroll from code"); ImGui::SameLine();
1298 ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
1299 ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
1300 if (scroll_x_delta != 0.0f)
1302 ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window)
1303 ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
1309 if (ImGui::TreeNode("Clipping"))
1311 static ImVec2 size(100, 100), offset(50, 20);
1312 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.");
1313 ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
1314 ImGui::TextWrapped("(Click and drag)");
1315 ImVec2 pos = ImGui::GetCursorScreenPos();
1316 ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);
1317 ImGui::InvisibleButton("##dummy", size);
1318 if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
1319 ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255));
1320 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);
1325 if (ImGui::CollapsingHeader("Popups & Modal windows"))
1327 if (ImGui::TreeNode("Popups"))
1329 ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
1331 static int selected_fish = -1;
1332 const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
1333 static bool toggles[] = { true, false, false, false, false };
1335 // Simple selection popup
1336 // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
1337 if (ImGui::Button("Select.."))
1338 ImGui::OpenPopup("select");
1340 ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
1341 if (ImGui::BeginPopup("select"))
1343 ImGui::Text("Aquarium");
1345 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1346 if (ImGui::Selectable(names[i]))
1351 // Showing a menu with toggles
1352 if (ImGui::Button("Toggle.."))
1353 ImGui::OpenPopup("toggle");
1354 if (ImGui::BeginPopup("toggle"))
1356 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1357 ImGui::MenuItem(names[i], "", &toggles[i]);
1358 if (ImGui::BeginMenu("Sub-menu"))
1360 ImGui::MenuItem("Click me");
1365 ImGui::Text("Tooltip here");
1366 if (ImGui::IsItemHovered())
1367 ImGui::SetTooltip("I am a tooltip over a popup");
1369 if (ImGui::Button("Stacked Popup"))
1370 ImGui::OpenPopup("another popup");
1371 if (ImGui::BeginPopup("another popup"))
1373 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1374 ImGui::MenuItem(names[i], "", &toggles[i]);
1375 if (ImGui::BeginMenu("Sub-menu"))
1377 ImGui::MenuItem("Click me");
1385 if (ImGui::Button("Popup Menu.."))
1386 ImGui::OpenPopup("FilePopup");
1387 if (ImGui::BeginPopup("FilePopup"))
1389 ShowExampleMenuFile();
1396 if (ImGui::TreeNode("Context menus"))
1398 // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
1399 // if (IsItemHovered() && IsMouseClicked(0))
1401 // return BeginPopup(id);
1402 // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
1403 static float value = 0.5f;
1404 ImGui::Text("Value = %.3f (<-- right-click here)", value);
1405 if (ImGui::BeginPopupContextItem("item context menu"))
1407 if (ImGui::Selectable("Set to zero")) value = 0.0f;
1408 if (ImGui::Selectable("Set to PI")) value = 3.1415f;
1409 ImGui::PushItemWidth(-1);
1410 ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
1411 ImGui::PopItemWidth();
1415 static char name[32] = "Label1";
1416 char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
1418 if (ImGui::BeginPopupContextItem()) // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
1420 ImGui::Text("Edit name:");
1421 ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
1422 if (ImGui::Button("Close"))
1423 ImGui::CloseCurrentPopup();
1426 ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
1431 if (ImGui::TreeNode("Modals"))
1433 ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
1435 if (ImGui::Button("Delete.."))
1436 ImGui::OpenPopup("Delete?");
1437 if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
1439 ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
1442 //static int dummy_i = 0;
1443 //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
1445 static bool dont_ask_me_next_time = false;
1446 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
1447 ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
1448 ImGui::PopStyleVar();
1450 if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
1452 if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
1456 if (ImGui::Button("Stacked modals.."))
1457 ImGui::OpenPopup("Stacked 1");
1458 if (ImGui::BeginPopupModal("Stacked 1"))
1460 ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDarkening] for darkening.");
1461 static int item = 1;
1462 ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
1463 static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
1464 ImGui::ColorEdit4("color", color); // This is to test behavior of stacked regular popups over a modal
1466 if (ImGui::Button("Add another modal.."))
1467 ImGui::OpenPopup("Stacked 2");
1468 if (ImGui::BeginPopupModal("Stacked 2"))
1470 ImGui::Text("Hello from Stacked The Second");
1471 if (ImGui::Button("Close"))
1472 ImGui::CloseCurrentPopup();
1476 if (ImGui::Button("Close"))
1477 ImGui::CloseCurrentPopup();
1484 if (ImGui::TreeNode("Menus inside a regular window"))
1486 ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
1488 // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above.
1489 // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here
1490 // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus.
1491 ImGui::PushID("foo");
1492 ImGui::MenuItem("Menu item", "CTRL+M");
1493 if (ImGui::BeginMenu("Menu inside a regular window"))
1495 ShowExampleMenuFile();
1504 if (ImGui::CollapsingHeader("Columns"))
1506 ImGui::PushID("Columns");
1509 if (ImGui::TreeNode("Basic"))
1511 ImGui::Text("Without border:");
1512 ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border
1514 for (int n = 0; n < 14; n++)
1517 sprintf(label, "Item %d", n);
1518 if (ImGui::Selectable(label)) {}
1519 //if (ImGui::Button(label, ImVec2(-1,0))) {}
1520 ImGui::NextColumn();
1525 ImGui::Text("With border:");
1526 ImGui::Columns(4, "mycolumns"); // 4-ways, with border
1528 ImGui::Text("ID"); ImGui::NextColumn();
1529 ImGui::Text("Name"); ImGui::NextColumn();
1530 ImGui::Text("Path"); ImGui::NextColumn();
1531 ImGui::Text("Hovered"); ImGui::NextColumn();
1533 const char* names[3] = { "One", "Two", "Three" };
1534 const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
1535 static int selected = -1;
1536 for (int i = 0; i < 3; i++)
1539 sprintf(label, "%04d", i);
1540 if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
1542 bool hovered = ImGui::IsItemHovered();
1543 ImGui::NextColumn();
1544 ImGui::Text(names[i]); ImGui::NextColumn();
1545 ImGui::Text(paths[i]); ImGui::NextColumn();
1546 ImGui::Text("%d", hovered); ImGui::NextColumn();
1553 // Create multiple items in a same cell before switching to next column
1554 if (ImGui::TreeNode("Mixed items"))
1556 ImGui::Columns(3, "mixed");
1559 ImGui::Text("Hello");
1560 ImGui::Button("Banana");
1561 ImGui::NextColumn();
1563 ImGui::Text("ImGui");
1564 ImGui::Button("Apple");
1565 static float foo = 1.0f;
1566 ImGui::InputFloat("red", &foo, 0.05f, 0, 3);
1567 ImGui::Text("An extra line here.");
1568 ImGui::NextColumn();
1570 ImGui::Text("Sailor");
1571 ImGui::Button("Corniflower");
1572 static float bar = 1.0f;
1573 ImGui::InputFloat("blue", &bar, 0.05f, 0, 3);
1574 ImGui::NextColumn();
1576 if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
1577 if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
1578 if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
1585 if (ImGui::TreeNode("Word-wrapping"))
1587 ImGui::Columns(2, "word-wrapping");
1589 ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
1590 ImGui::TextWrapped("Hello Left");
1591 ImGui::NextColumn();
1592 ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
1593 ImGui::TextWrapped("Hello Right");
1599 if (ImGui::TreeNode("Borders"))
1601 // NB: Future columns API should allow automatic horizontal borders.
1602 static bool h_borders = true;
1603 static bool v_borders = true;
1604 ImGui::Checkbox("horizontal", &h_borders);
1606 ImGui::Checkbox("vertical", &v_borders);
1607 ImGui::Columns(4, NULL, v_borders);
1608 for (int i = 0; i < 4*3; i++)
1610 if (h_borders && ImGui::GetColumnIndex() == 0)
1612 ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
1613 ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
1614 ImGui::NextColumn();
1622 // Scrolling columns
1624 if (ImGui::TreeNode("Vertical Scrolling"))
1626 ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
1628 ImGui::Text("ID"); ImGui::NextColumn();
1629 ImGui::Text("Name"); ImGui::NextColumn();
1630 ImGui::Text("Path"); ImGui::NextColumn();
1634 ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
1636 for (int i = 0; i < 10; i++)
1638 ImGui::Text("%04d", i); ImGui::NextColumn();
1639 ImGui::Text("Foobar"); ImGui::NextColumn();
1640 ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
1648 if (ImGui::TreeNode("Horizontal Scrolling"))
1650 ImGui::SetNextWindowContentWidth(1500);
1651 ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
1653 int ITEMS_COUNT = 2000;
1654 ImGuiListClipper clipper(ITEMS_COUNT); // Also demonstrate using the clipper for large list
1655 while (clipper.Step())
1657 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
1658 for (int j = 0; j < 10; j++)
1660 ImGui::Text("Line %d Column %d...", i, j);
1661 ImGui::NextColumn();
1669 bool node_open = ImGui::TreeNode("Tree within single cell");
1670 ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
1673 ImGui::Columns(2, "tree items");
1675 if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
1676 if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
1684 if (ImGui::CollapsingHeader("Filtering"))
1686 static ImGuiTextFilter filter;
1687 ImGui::Text("Filter usage:\n"
1688 " \"\" display all lines\n"
1689 " \"xxx\" display lines containing \"xxx\"\n"
1690 " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
1691 " \"-xxx\" hide lines containing \"xxx\"");
1693 const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
1694 for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
1695 if (filter.PassFilter(lines[i]))
1696 ImGui::BulletText("%s", lines[i]);
1699 if (ImGui::CollapsingHeader("Inputs & Focus"))
1701 ImGuiIO& io = ImGui::GetIO();
1702 ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
1703 ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via regular GPU rendering will feel more laggy than hardware cursor, but will be more in sync with your other visuals.");
1705 ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
1706 ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
1707 ImGui::Text("WantTextInput: %d", io.WantTextInput);
1708 ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse);
1710 if (ImGui::TreeNode("Keyboard & Mouse State"))
1712 ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
1713 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]); }
1714 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); }
1715 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); }
1716 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); }
1717 ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
1719 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]); }
1720 ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
1721 ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
1722 ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
1725 ImGui::Button("Hovering me sets the\nkeyboard capture flag");
1726 if (ImGui::IsItemHovered())
1727 ImGui::CaptureKeyboardFromApp(true);
1729 ImGui::Button("Holding me clears the\nthe keyboard capture flag");
1730 if (ImGui::IsItemActive())
1731 ImGui::CaptureKeyboardFromApp(false);
1736 if (ImGui::TreeNode("Tabbing"))
1738 ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
1739 static char buf[32] = "dummy";
1740 ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
1741 ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
1742 ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
1743 ImGui::PushAllowKeyboardFocus(false);
1744 ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
1745 //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
1746 ImGui::PopAllowKeyboardFocus();
1747 ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
1751 if (ImGui::TreeNode("Focus from code"))
1753 bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
1754 bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
1755 bool focus_3 = ImGui::Button("Focus on 3");
1757 static char buf[128] = "click on a button to set focus";
1759 if (focus_1) ImGui::SetKeyboardFocusHere();
1760 ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
1761 if (ImGui::IsItemActive()) has_focus = 1;
1763 if (focus_2) ImGui::SetKeyboardFocusHere();
1764 ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
1765 if (ImGui::IsItemActive()) has_focus = 2;
1767 ImGui::PushAllowKeyboardFocus(false);
1768 if (focus_3) ImGui::SetKeyboardFocusHere();
1769 ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
1770 if (ImGui::IsItemActive()) has_focus = 3;
1771 ImGui::PopAllowKeyboardFocus();
1773 ImGui::Text("Item with focus: %d", has_focus);
1775 ImGui::Text("Item with focus: <none>");
1776 ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code.");
1780 if (ImGui::TreeNode("Hovering"))
1782 // Testing IsWindowHovered() function with its various flags (note that the flags can be combined)
1784 "IsWindowHovered() = %d\n"
1785 "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
1786 "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1787 "IsWindowHovered(_FlattenChilds) = %d\n",
1788 ImGui::IsWindowHovered(),
1789 ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1790 ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1791 ImGui::IsWindowHovered(ImGuiHoveredFlags_FlattenChilds));
1793 // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code)
1794 ImGui::Button("ITEM");
1796 "IsItemHovered() = %d\n"
1797 "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
1798 "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1799 "IsItemHovered(_AllowWhenOverlapped) = %d\n"
1800 "IsItemhovered(_RectOnly) = %d\n",
1801 ImGui::IsItemHovered(),
1802 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1803 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1804 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
1805 ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly));
1810 if (ImGui::TreeNode("Dragging"))
1812 ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
1813 ImGui::Button("Drag Me");
1814 if (ImGui::IsItemActive())
1816 // Draw a line between the button and the mouse cursor
1817 ImDrawList* draw_list = ImGui::GetWindowDrawList();
1818 draw_list->PushClipRectFullScreen();
1819 draw_list->AddLine(ImGui::CalcItemRectClosestPoint(io.MousePos, true, -2.0f), io.MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f);
1820 draw_list->PopClipRect();
1821 ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
1822 ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
1823 ImVec2 mouse_delta = io.MouseDelta;
1824 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);
1829 if (ImGui::TreeNode("Mouse cursors"))
1831 ImGui::Text("Hover to see mouse cursors:");
1832 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.");
1833 for (int i = 0; i < ImGuiMouseCursor_Count_; i++)
1836 sprintf(label, "Mouse cursor %d", i);
1837 ImGui::Bullet(); ImGui::Selectable(label, false);
1838 if (ImGui::IsItemHovered())
1839 ImGui::SetMouseCursor(i);
1848 void ImGui::ShowStyleEditor(ImGuiStyle* ref)
1850 // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
1851 ImGuiStyle& style = ImGui::GetStyle();
1852 static ImGuiStyle ref_saved_style;
1854 // Default to using internal storage as reference
1855 static bool init = true;
1856 if (init && ref == NULL)
1857 ref_saved_style = style;
1860 ref = &ref_saved_style;
1862 ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
1864 // Default Styles Selector
1865 static int style_idx = 0;
1866 if (ImGui::Combo("Colors##Selector", &style_idx, "Classic\0Dark\0Light\0"))
1870 case 0: ImGui::StyleColorsClassic(); break;
1871 case 1: ImGui::StyleColorsDark(); break;
1872 case 2: ImGui::StyleColorsLight(); break;
1874 ref_saved_style = style;
1877 // Simplified Settings
1878 if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
1879 style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
1880 { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
1882 { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
1884 { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
1886 // Save/Revert button
1887 if (ImGui::Button("Save Ref"))
1888 *ref = ref_saved_style = style;
1890 if (ImGui::Button("Revert Ref"))
1893 ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
1895 if (ImGui::TreeNode("Rendering"))
1897 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.");
1898 ImGui::Checkbox("Anti-aliased shapes", &style.AntiAliasedShapes);
1899 ImGui::PushItemWidth(100);
1900 ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);
1901 if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;
1902 ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
1903 ImGui::PopItemWidth();
1907 if (ImGui::TreeNode("Settings"))
1909 ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
1910 ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f");
1911 ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
1912 ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
1913 ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
1914 ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
1915 ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
1916 ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
1917 ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
1918 ImGui::Text("BorderSize");
1919 ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
1920 ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
1921 ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
1922 ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
1923 ImGui::Text("Rounding");
1924 ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
1925 ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
1926 ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
1927 ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
1928 ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
1929 ImGui::Text("Alignment");
1930 ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
1931 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.");
1935 if (ImGui::TreeNode("Colors"))
1937 static int output_dest = 0;
1938 static bool output_only_modified = true;
1939 if (ImGui::Button("Export Unsaved"))
1941 if (output_dest == 0)
1942 ImGui::LogToClipboard();
1945 ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
1946 for (int i = 0; i < ImGuiCol_COUNT; i++)
1948 const ImVec4& col = style.Colors[i];
1949 const char* name = ImGui::GetStyleColorName(i);
1950 if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
1951 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);
1955 ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
1956 ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
1958 ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");
1960 static ImGuiTextFilter filter;
1961 filter.Draw("Filter colors", 200);
1963 static ImGuiColorEditFlags alpha_flags = 0;
1964 ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
1965 ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
1966 ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf);
1968 ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
1969 ImGui::PushItemWidth(-160);
1970 for (int i = 0; i < ImGuiCol_COUNT; i++)
1972 const char* name = ImGui::GetStyleColorName(i);
1973 if (!filter.PassFilter(name))
1976 ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
1977 if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
1979 // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons.
1980 // Read the FAQ and extra_fonts/README.txt about using icon fonts. It's really easy and super convenient!
1981 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
1982 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
1984 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
1985 ImGui::TextUnformatted(name);
1988 ImGui::PopItemWidth();
1994 bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size);
1995 ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions.");
1998 ImFontAtlas* atlas = ImGui::GetIO().Fonts;
1999 if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
2001 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));
2004 ImGui::PushItemWidth(100);
2005 for (int i = 0; i < atlas->Fonts.Size; i++)
2007 ImFont* font = atlas->Fonts[i];
2008 ImGui::PushID(font);
2009 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);
2010 ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
2011 if (font_details_opened)
2013 ImGui::PushFont(font);
2014 ImGui::Text("The quick brown fox jumps over the lazy dog");
2016 ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font
2017 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.)");
2018 ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
2019 ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
2020 ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
2021 for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
2023 ImFontConfig* cfg = &font->ConfigData[config_i];
2024 ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
2026 if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
2028 // Display all glyphs of the fonts in separate pages of 256 characters
2029 const ImFontGlyph* glyph_fallback = font->FallbackGlyph; // Forcefully/dodgily make FindGlyph() return NULL on fallback, which isn't the default behavior.
2030 font->FallbackGlyph = NULL;
2031 for (int base = 0; base < 0x10000; base += 256)
2034 for (int n = 0; n < 256; n++)
2035 count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0;
2036 if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph"))
2038 float cell_spacing = style.ItemSpacing.y;
2039 ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1);
2040 ImVec2 base_pos = ImGui::GetCursorScreenPos();
2041 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2042 for (int n = 0; n < 256; n++)
2044 ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing));
2045 ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y);
2046 const ImFontGlyph* glyph = font->FindGlyph((ImWchar)(base+n));;
2047 draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50));
2048 font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string.
2049 if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
2051 ImGui::BeginTooltip();
2052 ImGui::Text("Codepoint: U+%04X", base+n);
2054 ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
2055 ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
2056 ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
2057 ImGui::EndTooltip();
2060 ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16));
2064 font->FallbackGlyph = glyph_fallback;
2071 static float window_scale = 1.0f;
2072 ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale only this window
2073 ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything
2074 ImGui::PopItemWidth();
2075 ImGui::SetWindowFontScale(window_scale);
2079 ImGui::PopItemWidth();
2082 // Demonstrate creating a fullscreen menu bar and populating it.
2083 static void ShowExampleAppMainMenuBar()
2085 if (ImGui::BeginMainMenuBar())
2087 if (ImGui::BeginMenu("File"))
2089 ShowExampleMenuFile();
2092 if (ImGui::BeginMenu("Edit"))
2094 if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
2095 if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
2097 if (ImGui::MenuItem("Cut", "CTRL+X")) {}
2098 if (ImGui::MenuItem("Copy", "CTRL+C")) {}
2099 if (ImGui::MenuItem("Paste", "CTRL+V")) {}
2102 ImGui::EndMainMenuBar();
2106 static void ShowExampleMenuFile()
2108 ImGui::MenuItem("(dummy menu)", NULL, false, false);
2109 if (ImGui::MenuItem("New")) {}
2110 if (ImGui::MenuItem("Open", "Ctrl+O")) {}
2111 if (ImGui::BeginMenu("Open Recent"))
2113 ImGui::MenuItem("fish_hat.c");
2114 ImGui::MenuItem("fish_hat.inl");
2115 ImGui::MenuItem("fish_hat.h");
2116 if (ImGui::BeginMenu("More.."))
2118 ImGui::MenuItem("Hello");
2119 ImGui::MenuItem("Sailor");
2120 if (ImGui::BeginMenu("Recurse.."))
2122 ShowExampleMenuFile();
2129 if (ImGui::MenuItem("Save", "Ctrl+S")) {}
2130 if (ImGui::MenuItem("Save As..")) {}
2132 if (ImGui::BeginMenu("Options"))
2134 static bool enabled = true;
2135 ImGui::MenuItem("Enabled", "", &enabled);
2136 ImGui::BeginChild("child", ImVec2(0, 60), true);
2137 for (int i = 0; i < 10; i++)
2138 ImGui::Text("Scrolling Text %d", i);
2140 static float f = 0.5f;
2142 static bool b = true;
2143 ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
2144 ImGui::InputFloat("Input", &f, 0.1f);
2145 ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
2146 ImGui::Checkbox("Check", &b);
2149 if (ImGui::BeginMenu("Colors"))
2151 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
2152 for (int i = 0; i < ImGuiCol_COUNT; i++)
2154 const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
2155 ImGui::ColorButton(name, ImGui::GetStyleColorVec4((ImGuiCol)i));
2157 ImGui::MenuItem(name);
2159 ImGui::PopStyleVar();
2162 if (ImGui::BeginMenu("Disabled", false)) // Disabled
2166 if (ImGui::MenuItem("Checked", NULL, true)) {}
2167 if (ImGui::MenuItem("Quit", "Alt+F4")) {}
2170 // Demonstrate creating a window which gets auto-resized according to its content.
2171 static void ShowExampleAppAutoResize(bool* p_open)
2173 if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
2179 static int lines = 10;
2180 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.");
2181 ImGui::SliderInt("Number of lines", &lines, 1, 20);
2182 for (int i = 0; i < lines; i++)
2183 ImGui::Text("%*sThis is line %d", i*4, "", i); // Pad with space to extend size horizontally
2187 // Demonstrate creating a window with custom resize constraints.
2188 static void ShowExampleAppConstrainedResize(bool* p_open)
2190 struct CustomConstraints // Helper functions to demonstrate programmatic constraints
2192 static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
2193 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); }
2196 static bool auto_resize = false;
2197 static int type = 0;
2198 static int display_lines = 10;
2199 if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX)); // Vertical only
2200 if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1)); // Horizontal only
2201 if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
2202 if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500
2203 if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500
2204 if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square); // Always Square
2205 if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step
2207 ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
2208 if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
2210 const char* desc[] =
2212 "Resize vertical only",
2213 "Resize horizontal only",
2214 "Width > 100, Height > 100",
2217 "Custom: Always Square",
2218 "Custom: Fixed Steps (100)",
2220 if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
2221 if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
2222 if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
2223 ImGui::PushItemWidth(200);
2224 ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
2225 ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
2226 ImGui::PopItemWidth();
2227 ImGui::Checkbox("Auto-resize", &auto_resize);
2228 for (int i = 0; i < display_lines; i++)
2229 ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
2234 // Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
2235 static void ShowExampleAppFixedOverlay(bool* p_open)
2237 const float DISTANCE = 10.0f;
2238 static int corner = 0;
2239 ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
2240 ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
2241 ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
2242 ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); // Transparent background
2243 if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings))
2245 ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)");
2247 ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
2248 if (ImGui::BeginPopupContextWindow())
2250 if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
2251 if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
2252 if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
2253 if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
2258 ImGui::PopStyleColor();
2261 // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
2262 // Read section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." about ID.
2263 static void ShowExampleAppManipulatingWindowTitle(bool*)
2265 // By default, Windows are uniquely identified by their title.
2266 // You can use the "##" and "###" markers to manipulate the display/ID.
2268 // Using "##" to display same title but have unique identifier.
2269 ImGui::SetNextWindowPos(ImVec2(100,100), ImGuiCond_FirstUseEver);
2270 ImGui::Begin("Same title as another window##1");
2271 ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
2274 ImGui::SetNextWindowPos(ImVec2(100,200), ImGuiCond_FirstUseEver);
2275 ImGui::Begin("Same title as another window##2");
2276 ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
2279 // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
2281 sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand());
2282 ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiCond_FirstUseEver);
2284 ImGui::Text("This window has a changing title.");
2288 // Demonstrate using the low-level ImDrawList to draw custom shapes.
2289 static void ShowExampleAppCustomRendering(bool* p_open)
2291 ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiCond_FirstUseEver);
2292 if (!ImGui::Begin("Example: Custom rendering", p_open))
2298 // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
2299 // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
2300 // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
2301 // In this example we are not using the maths operators!
2302 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2305 ImGui::Text("Primitives");
2306 static float sz = 36.0f;
2307 static ImVec4 col = ImVec4(1.0f,1.0f,0.4f,1.0f);
2308 ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
2309 ImGui::ColorEdit3("Color", &col.x);
2311 const ImVec2 p = ImGui::GetCursorScreenPos();
2312 const ImU32 col32 = ImColor(col);
2313 float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
2314 for (int n = 0; n < 2; n++)
2316 float thickness = (n == 0) ? 1.0f : 4.0f;
2317 draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, thickness); x += sz+spacing;
2318 draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, thickness); x += sz+spacing;
2319 draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, thickness); x += sz+spacing;
2320 draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, thickness); x += sz+spacing;
2321 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;
2322 draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y ), col32, thickness); x += sz+spacing;
2323 draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, thickness); x += sz+spacing;
2324 draw_list->AddLine(ImVec2(x, y), ImVec2(x, y+sz), col32, thickness); x += spacing;
2325 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);
2329 draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;
2330 draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
2331 draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
2332 draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;
2333 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;
2334 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));
2335 ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
2339 static ImVector<ImVec2> points;
2340 static bool adding_line = false;
2341 ImGui::Text("Canvas example");
2342 if (ImGui::Button("Clear")) points.clear();
2343 if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
2344 ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
2346 // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
2347 // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
2348 // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
2349 ImVec2 canvas_pos = ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
2350 ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available
2351 if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
2352 if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
2353 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));
2354 draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255));
2356 bool adding_preview = false;
2357 ImGui::InvisibleButton("canvas", canvas_size);
2358 ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
2361 adding_preview = true;
2362 points.push_back(mouse_pos_in_canvas);
2363 if (!ImGui::GetIO().MouseDown[0])
2364 adding_line = adding_preview = false;
2366 if (ImGui::IsItemHovered())
2368 if (!adding_line && ImGui::IsMouseClicked(0))
2370 points.push_back(mouse_pos_in_canvas);
2373 if (ImGui::IsMouseClicked(1) && !points.empty())
2375 adding_line = adding_preview = false;
2380 draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x+canvas_size.x, canvas_pos.y+canvas_size.y), true); // clip lines within the canvas (if we resize it, etc.)
2381 for (int i = 0; i < points.Size - 1; i += 2)
2382 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);
2383 draw_list->PopClipRect();
2390 // Demonstrating creating a simple console window, with scrolling, filtering, completion and history.
2391 // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
2392 struct ExampleAppConsole
2395 ImVector<char*> Items;
2396 bool ScrollToBottom;
2397 ImVector<char*> History;
2398 int HistoryPos; // -1: new line, 0..History.Size-1 browsing history.
2399 ImVector<const char*> Commands;
2404 memset(InputBuf, 0, sizeof(InputBuf));
2406 Commands.push_back("HELP");
2407 Commands.push_back("HISTORY");
2408 Commands.push_back("CLEAR");
2409 Commands.push_back("CLASSIFY"); // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
2410 AddLog("Welcome to ImGui!");
2412 ~ExampleAppConsole()
2415 for (int i = 0; i < History.Size; i++)
2420 static int Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
2421 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; }
2422 static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }
2426 for (int i = 0; i < Items.Size; i++)
2429 ScrollToBottom = true;
2432 void AddLog(const char* fmt, ...) IM_FMTARGS(2)
2437 va_start(args, fmt);
2438 vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
2439 buf[IM_ARRAYSIZE(buf)-1] = 0;
2441 Items.push_back(Strdup(buf));
2442 ScrollToBottom = true;
2445 void Draw(const char* title, bool* p_open)
2447 ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
2448 if (!ImGui::Begin(title, p_open))
2454 // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
2455 // Here we create a context menu only available from the title bar.
2456 if (ImGui::BeginPopupContextItem())
2458 if (ImGui::MenuItem("Close"))
2463 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.");
2464 ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
2466 // TODO: display items starting from the bottom
2468 if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
2469 if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
2470 if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
2471 bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine();
2472 if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
2473 //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
2477 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
2478 static ImGuiTextFilter filter;
2479 filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
2480 ImGui::PopStyleVar();
2483 ImGui::BeginChild("ScrollingRegion", ImVec2(0,-ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar);
2484 if (ImGui::BeginPopupContextWindow())
2486 if (ImGui::Selectable("Clear")) ClearLog();
2490 // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
2491 // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
2492 // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements.
2493 // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
2494 // ImGuiListClipper clipper(Items.Size);
2495 // while (clipper.Step())
2496 // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
2497 // However take note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list.
2498 // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter,
2499 // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code!
2500 // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list.
2501 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
2502 if (copy_to_clipboard)
2503 ImGui::LogToClipboard();
2504 for (int i = 0; i < Items.Size; i++)
2506 const char* item = Items[i];
2507 if (!filter.PassFilter(item))
2509 ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text.
2510 if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f);
2511 else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f);
2512 ImGui::PushStyleColor(ImGuiCol_Text, col);
2513 ImGui::TextUnformatted(item);
2514 ImGui::PopStyleColor();
2516 if (copy_to_clipboard)
2519 ImGui::SetScrollHere();
2520 ScrollToBottom = false;
2521 ImGui::PopStyleVar();
2526 if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
2528 char* input_end = InputBuf+strlen(InputBuf);
2529 while (input_end > InputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0;
2531 ExecCommand(InputBuf);
2532 strcpy(InputBuf, "");
2535 // Demonstrate keeping auto focus on the input box
2536 if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)))
2537 ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
2542 void ExecCommand(const char* command_line)
2544 AddLog("# %s\n", command_line);
2546 // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.
2548 for (int i = History.Size-1; i >= 0; i--)
2549 if (Stricmp(History[i], command_line) == 0)
2552 History.erase(History.begin() + i);
2555 History.push_back(Strdup(command_line));
2558 if (Stricmp(command_line, "CLEAR") == 0)
2562 else if (Stricmp(command_line, "HELP") == 0)
2564 AddLog("Commands:");
2565 for (int i = 0; i < Commands.Size; i++)
2566 AddLog("- %s", Commands[i]);
2568 else if (Stricmp(command_line, "HISTORY") == 0)
2570 int first = History.Size - 10;
2571 for (int i = first > 0 ? first : 0; i < History.Size; i++)
2572 AddLog("%3d: %s\n", i, History[i]);
2576 AddLog("Unknown command: '%s'\n", command_line);
2580 static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
2582 ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
2583 return console->TextEditCallback(data);
2586 int TextEditCallback(ImGuiTextEditCallbackData* data)
2588 //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
2589 switch (data->EventFlag)
2591 case ImGuiInputTextFlags_CallbackCompletion:
2593 // Example of TEXT COMPLETION
2595 // Locate beginning of current word
2596 const char* word_end = data->Buf + data->CursorPos;
2597 const char* word_start = word_end;
2598 while (word_start > data->Buf)
2600 const char c = word_start[-1];
2601 if (c == ' ' || c == '\t' || c == ',' || c == ';')
2606 // Build a list of candidates
2607 ImVector<const char*> candidates;
2608 for (int i = 0; i < Commands.Size; i++)
2609 if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
2610 candidates.push_back(Commands[i]);
2612 if (candidates.Size == 0)
2615 AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
2617 else if (candidates.Size == 1)
2619 // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
2620 data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
2621 data->InsertChars(data->CursorPos, candidates[0]);
2622 data->InsertChars(data->CursorPos, " ");
2626 // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
2627 int match_len = (int)(word_end - word_start);
2631 bool all_candidates_matches = true;
2632 for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
2634 c = toupper(candidates[i][match_len]);
2635 else if (c == 0 || c != toupper(candidates[i][match_len]))
2636 all_candidates_matches = false;
2637 if (!all_candidates_matches)
2644 data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
2645 data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
2649 AddLog("Possible matches:\n");
2650 for (int i = 0; i < candidates.Size; i++)
2651 AddLog("- %s\n", candidates[i]);
2656 case ImGuiInputTextFlags_CallbackHistory:
2658 // Example of HISTORY
2659 const int prev_history_pos = HistoryPos;
2660 if (data->EventKey == ImGuiKey_UpArrow)
2662 if (HistoryPos == -1)
2663 HistoryPos = History.Size - 1;
2664 else if (HistoryPos > 0)
2667 else if (data->EventKey == ImGuiKey_DownArrow)
2669 if (HistoryPos != -1)
2670 if (++HistoryPos >= History.Size)
2674 // A better implementation would preserve the data on the current input line along with cursor position.
2675 if (prev_history_pos != HistoryPos)
2677 data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
2678 data->BufDirty = true;
2686 static void ShowExampleAppConsole(bool* p_open)
2688 static ExampleAppConsole console;
2689 console.Draw("Example: Console", p_open);
2693 // static ExampleAppLog my_log;
2694 // my_log.AddLog("Hello %d world\n", 123);
2695 // my_log.Draw("title");
2696 struct ExampleAppLog
2698 ImGuiTextBuffer Buf;
2699 ImGuiTextFilter Filter;
2700 ImVector<int> LineOffsets; // Index to lines offset
2701 bool ScrollToBottom;
2703 void Clear() { Buf.clear(); LineOffsets.clear(); }
2705 void AddLog(const char* fmt, ...) IM_FMTARGS(2)
2707 int old_size = Buf.size();
2709 va_start(args, fmt);
2710 Buf.appendv(fmt, args);
2712 for (int new_size = Buf.size(); old_size < new_size; old_size++)
2713 if (Buf[old_size] == '\n')
2714 LineOffsets.push_back(old_size);
2715 ScrollToBottom = true;
2718 void Draw(const char* title, bool* p_open = NULL)
2720 ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver);
2721 ImGui::Begin(title, p_open);
2722 if (ImGui::Button("Clear")) Clear();
2724 bool copy = ImGui::Button("Copy");
2726 Filter.Draw("Filter", -100.0f);
2728 ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
2729 if (copy) ImGui::LogToClipboard();
2731 if (Filter.IsActive())
2733 const char* buf_begin = Buf.begin();
2734 const char* line = buf_begin;
2735 for (int line_no = 0; line != NULL; line_no++)
2737 const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
2738 if (Filter.PassFilter(line, line_end))
2739 ImGui::TextUnformatted(line, line_end);
2740 line = line_end && line_end[1] ? line_end + 1 : NULL;
2745 ImGui::TextUnformatted(Buf.begin());
2749 ImGui::SetScrollHere(1.0f);
2750 ScrollToBottom = false;
2756 // Demonstrate creating a simple log window with basic filtering.
2757 static void ShowExampleAppLog(bool* p_open)
2759 static ExampleAppLog log;
2761 // Demo: add random items (unless Ctrl is held)
2762 static float last_time = -1.0f;
2763 float time = ImGui::GetTime();
2764 if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl)
2766 const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
2767 log.AddLog("[%s] Hello, time is %.1f, rand() %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, (int)rand());
2771 log.Draw("Example: Log", p_open);
2774 // Demonstrate create a window with multiple child windows.
2775 static void ShowExampleAppLayout(bool* p_open)
2777 ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
2778 if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
2780 if (ImGui::BeginMenuBar())
2782 if (ImGui::BeginMenu("File"))
2784 if (ImGui::MenuItem("Close")) *p_open = false;
2787 ImGui::EndMenuBar();
2791 static int selected = 0;
2792 ImGui::BeginChild("left pane", ImVec2(150, 0), true);
2793 for (int i = 0; i < 100; i++)
2796 sprintf(label, "MyObject %d", i);
2797 if (ImGui::Selectable(label, selected == i))
2804 ImGui::BeginGroup();
2805 ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us
2806 ImGui::Text("MyObject: %d", selected);
2808 ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
2810 ImGui::BeginChild("buttons");
2811 if (ImGui::Button("Revert")) {}
2813 if (ImGui::Button("Save")) {}
2820 // Demonstrate create a simple property editor.
2821 static void ShowExampleAppPropertyEditor(bool* p_open)
2823 ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
2824 if (!ImGui::Begin("Example: Property editor", p_open))
2830 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.");
2832 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
2838 static void ShowDummyObject(const char* prefix, int uid)
2840 ImGui::PushID(uid); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
2841 ImGui::AlignTextToFramePadding(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
2842 bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
2843 ImGui::NextColumn();
2844 ImGui::AlignTextToFramePadding();
2845 ImGui::Text("my sailor is rich");
2846 ImGui::NextColumn();
2849 static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
2850 for (int i = 0; i < 8; i++)
2852 ImGui::PushID(i); // Use field index as identifier.
2855 ShowDummyObject("Child", 424242);
2859 ImGui::AlignTextToFramePadding();
2860 // Here we use a Selectable (instead of Text) to highlight on hover
2861 //ImGui::Text("Field_%d", i);
2863 sprintf(label, "Field_%d", i);
2865 ImGui::Selectable(label);
2866 ImGui::NextColumn();
2867 ImGui::PushItemWidth(-1);
2869 ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
2871 ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
2872 ImGui::PopItemWidth();
2873 ImGui::NextColumn();
2883 // Iterate dummy objects with dummy members (all the same data)
2884 for (int obj_i = 0; obj_i < 3; obj_i++)
2885 funcs::ShowDummyObject("Object", obj_i);
2889 ImGui::PopStyleVar();
2893 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
2894 static void ShowExampleAppLongText(bool* p_open)
2896 ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
2897 if (!ImGui::Begin("Example: Long text display", p_open))
2903 static int test_type = 0;
2904 static ImGuiTextBuffer log;
2905 static int lines = 0;
2906 ImGui::Text("Printing unusually long amount of text.");
2907 ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
2908 ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
2909 if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
2911 if (ImGui::Button("Add 1000 lines"))
2913 for (int i = 0; i < 1000; i++)
2914 log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i);
2917 ImGui::BeginChild("Log");
2921 // Single call to TextUnformatted() with a big buffer
2922 ImGui::TextUnformatted(log.begin(), log.end());
2926 // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
2927 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
2928 ImGuiListClipper clipper(lines);
2929 while (clipper.Step())
2930 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
2931 ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
2932 ImGui::PopStyleVar();
2936 // Multiple calls to Text(), not clipped (slow)
2937 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
2938 for (int i = 0; i < lines; i++)
2939 ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
2940 ImGui::PopStyleVar();
2950 void ImGui::ShowTestWindow(bool*) {}
2951 void ImGui::ShowUserGuide() {}
2952 void ImGui::ShowStyleEditor(ImGuiStyle*) {}