- added imgui
[laserbrain_demo] / src / imgui / imgui_demo.cc
1 // dear imgui, v1.53 WIP
2 // (demo code)
3
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.
12 // Thank you,
13 // -Your beloved friend, imgui_demo.cpp (that you won't delete)
14
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.
20
21 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
22 #define _CRT_SECURE_NO_WARNINGS
23 #endif
24
25 #include "imgui.h"
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
32 #else
33 #include <stdint.h>         // intptr_t
34 #endif
35
36 #ifdef _MSC_VER
37 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
38 #define snprintf _snprintf
39 #endif
40 #ifdef __clang__
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                //
48 #endif
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
54 #if (__GNUC__ >= 6)
55 #pragma GCC diagnostic ignored "-Wmisleading-indentation"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on github.
56 #endif
57 #endif
58
59 // Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n.
60 #ifdef _WIN32
61 #define IM_NEWLINE "\r\n"
62 #else
63 #define IM_NEWLINE "\n"
64 #endif
65
66 #define IM_ARRAYSIZE(_ARR)  ((int)(sizeof(_ARR)/sizeof(*_ARR)))
67 #define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))
68
69 //-----------------------------------------------------------------------------
70 // DEMO CODE
71 //-----------------------------------------------------------------------------
72
73 #ifndef IMGUI_DISABLE_TEST_WINDOWS
74
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();
87
88 static void ShowHelpMarker(const char* desc)
89 {
90     ImGui::TextDisabled("(?)");
91     if (ImGui::IsItemHovered())
92     {
93         ImGui::BeginTooltip();
94         ImGui::PushTextWrapPos(450.0f);
95         ImGui::TextUnformatted(desc);
96         ImGui::PopTextWrapPos();
97         ImGui::EndTooltip();
98     }
99 }
100
101 void ImGui::ShowUserGuide()
102 {
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");
112     ImGui::Indent();
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.");
120     ImGui::Unindent();
121 }
122
123 // Demonstrate most ImGui features (big function!)
124 void ImGui::ShowTestWindow(bool* p_open)
125 {
126     // Examples apps
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;
139
140     static bool show_app_metrics = false;
141     static bool show_app_about = false;
142
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);
154
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(); }
157     if (show_app_about)
158     {
159         ImGui::Begin("About ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
160         ImGui::Text("dear imgui, %s", ImGui::GetVersion());
161         ImGui::Separator();
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.");
164         ImGui::End();
165     }
166
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;
173
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))
184     {
185         // Early out if the window is collapsed, as an optimization.
186         ImGui::End();
187         return;
188     }
189
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
192
193     ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
194
195     // Menu
196     if (ImGui::BeginMenuBar())
197     {
198         if (ImGui::BeginMenu("Menu"))
199         {
200             ShowExampleMenuFile();
201             ImGui::EndMenu();
202         }
203         if (ImGui::BeginMenu("Examples"))
204         {
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);
216             ImGui::EndMenu();
217         }
218         if (ImGui::BeginMenu("Help"))
219         {
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);
223             ImGui::EndMenu();
224         }
225         ImGui::EndMenuBar();
226     }
227
228     ImGui::Spacing();
229     if (ImGui::CollapsingHeader("Help"))
230     {
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();
234     }
235
236     if (ImGui::CollapsingHeader("Window options"))
237     {
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);
244
245         if (ImGui::TreeNode("Style"))
246         {
247             ImGui::ShowStyleEditor();
248             ImGui::TreePop();
249         }
250
251         if (ImGui::TreeNode("Logging"))
252         {
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.");
254             ImGui::LogButtons();
255             ImGui::TreePop();
256         }
257     }
258
259     if (ImGui::CollapsingHeader("Widgets"))
260     {
261         if (ImGui::TreeNode("Basic"))
262         {
263             static int clicked = 0;
264             if (ImGui::Button("Button")) 
265                 clicked++;
266             if (clicked & 1)
267             {
268                 ImGui::SameLine();
269                 ImGui::Text("Thanks for clicking me!");
270             }
271
272             static bool check = true;
273             ImGui::Checkbox("checkbox", &check);
274
275             static int e = 0;
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);
279
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++)
282             {
283                 if (i > 0) ImGui::SameLine();
284                 ImGui::PushID(i);
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);
290                 ImGui::PopID();
291             }
292
293             ImGui::Text("Hover over me");
294             if (ImGui::IsItemHovered())
295                 ImGui::SetTooltip("I am a tooltip");
296
297             ImGui::SameLine();
298             ImGui::Text("- or me");
299             if (ImGui::IsItemHovered())
300             {
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));
305                 ImGui::EndTooltip();
306             }
307
308             // Testing ImGuiOnceUponAFrame helper.
309             //static ImGuiOnceUponAFrame once;
310             //for (int i = 0; i < 5; i++)
311             //    if (once)
312             //        ImGui::Text("This will be displayed only once.");
313
314             ImGui::Separator();
315
316             ImGui::LabelText("label", "Value");
317
318             static int item = 1;
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)
320
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.
324
325             {
326                 static char str0[128] = "Hello, world!";
327                 static int i0=123;
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");
331
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");
334
335                 ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
336
337                 static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
338                 ImGui::InputFloat3("input float3", vec4a);
339             }
340
341             {
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.");
345
346                 ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%");
347
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");
351             }
352
353             {
354                 static int i1=0;
355                 ImGui::SliderInt("slider int", &i1, -1, 3);
356                 ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
357
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);
363             }
364
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");
369
370             ImGui::ColorEdit4("color 2", col2);
371
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);
375
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();
380
381             ImGui::TreePop();
382         }
383
384         if (ImGui::TreeNode("Trees"))
385         {
386             if (ImGui::TreeNode("Basic trees"))
387             {
388                 for (int i = 0; i < 5; i++)
389                     if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
390                     {
391                         ImGui::Text("blah blah");
392                         ImGui::SameLine(); 
393                         if (ImGui::SmallButton("print")) printf("Child %d pressed", i);
394                         ImGui::TreePop();
395                     }
396                 ImGui::TreePop();
397             }
398
399             if (ImGui::TreeNode("Advanced, with Selectable nodes"))
400             {
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());
407
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++)
412                 {
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);
415                     if (i < 3)
416                     {
417                         // Node
418                         bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
419                         if (ImGui::IsItemClicked()) 
420                             node_clicked = i;
421                         if (node_open)
422                         {
423                             ImGui::Text("Blah blah\nBlah Blah");
424                             ImGui::TreePop();
425                         }
426                     }
427                     else
428                     {
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()) 
433                             node_clicked = i;
434                     }
435                 }
436                 if (node_clicked != -1)
437                 {
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
443                 }
444                 ImGui::PopStyleVar();
445                 if (align_label_with_current_x_position)
446                     ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
447                 ImGui::TreePop();
448             }
449             ImGui::TreePop();
450         }
451
452         if (ImGui::TreeNode("Collapsing Headers"))
453         {
454             static bool closable_group = true;
455             ImGui::Checkbox("Enable extra group", &closable_group);
456             if (ImGui::CollapsingHeader("Header"))
457             {
458                 ImGui::Text("IsItemHovered: %d", IsItemHovered());
459                 for (int i = 0; i < 5; i++)
460                     ImGui::Text("Some content %d", i);
461             }
462             if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
463             {
464                 ImGui::Text("IsItemHovered: %d", IsItemHovered());
465                 for (int i = 0; i < 5; i++)
466                     ImGui::Text("More content %d", i);
467             }
468             ImGui::TreePop();
469         }
470
471         if (ImGui::TreeNode("Bullets"))
472         {
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");
477             ImGui::TreePop();
478         }
479
480         if (ImGui::TreeNode("Text"))
481         {
482             if (ImGui::TreeNode("Colored Text"))
483             {
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.");
489                 ImGui::TreePop();
490             }
491
492             if (ImGui::TreeNode("Word Wrapping"))
493             {
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.");
496                 ImGui::Spacing();
497
498                 static float wrap_width = 200.0f;
499                 ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
500
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();
508
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();
516
517                 ImGui::TreePop();
518             }
519
520             if (ImGui::TreeNode("UTF-8 Text"))
521             {
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));
534                 ImGui::TreePop();
535             }
536             ImGui::TreePop();
537         }
538
539         if (ImGui::TreeNode("Images"))
540         {
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();
543
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;
554
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())
559             {
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));
569                 ImGui::EndTooltip();
570             }
571             ImGui::TextWrapped("And now some textured buttons..");
572             static int pressed_count = 0;
573             for (int i = 0; i < 8; i++)
574             {
575                 ImGui::PushID(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)))
578                     pressed_count += 1;
579                 ImGui::PopID();
580                 ImGui::SameLine();
581             }
582             ImGui::NewLine();
583             ImGui::Text("Pressed %d times.", pressed_count);
584             ImGui::TreePop();
585         }
586
587         if (ImGui::TreeNode("Selectables"))
588         {
589             if (ImGui::TreeNode("Basic"))
590             {
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];
599                 ImGui::TreePop();
600             }
601             if (ImGui::TreeNode("Rendering more text into the same block"))
602             {
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");
607                 ImGui::TreePop();
608             }
609             if (ImGui::TreeNode("In columns"))
610             {
611                 ImGui::Columns(3, NULL, false);
612                 static bool selected[16] = { 0 };
613                 for (int i = 0; i < 16; i++)
614                 {
615                     char label[32]; sprintf(label, "Item %d", i);
616                     if (ImGui::Selectable(label, &selected[i])) {}
617                     ImGui::NextColumn();
618                 }
619                 ImGui::Columns(1);
620                 ImGui::TreePop();
621             }
622             if (ImGui::TreeNode("Grid"))
623             {
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++)
626                 {
627                     ImGui::PushID(i);
628                     if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50)))
629                     {
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;
635                     }
636                     if ((i % 4) < 3) ImGui::SameLine();
637                     ImGui::PopID();
638                 }
639                 ImGui::TreePop();
640             }
641             ImGui::TreePop();
642         }
643
644         if (ImGui::TreeNode("Filtered Text Input"))
645         {
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);
653
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);
659
660             ImGui::TreePop();
661         }
662
663         if (ImGui::TreeNode("Multi-line Text Input"))
664         {
665             static bool read_only = false;
666             static char text[1024*16] =
667                 "/*\n"
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"
674                 "*/\n\n"
675                 "label:\n"
676                 "\tlock cmpxchg8b eax\n";
677
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));
682             ImGui::TreePop();
683         }
684
685         if (ImGui::TreeNode("Plots widgets"))
686         {
687             static bool animate = true;
688             ImGui::Checkbox("Animate", &animate);
689
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));
692
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
701             {
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;
707             }
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));
710
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.
713             struct Funcs
714             {
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; }
717             };
718             static int func_type = 0, display_count = 70;
719             ImGui::Separator();
720             ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
721             ImGui::SameLine();
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));
726             ImGui::Separator();
727
728             // Animate a simple progress bar
729             static float progress = 0.0f, progress_dir = 1.0f;
730             if (animate)
731             {
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; }
735             }
736
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");
741
742             float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
743             char buf[32];
744             sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
745             ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
746             ImGui::TreePop();
747         }
748
749         if (ImGui::TreeNode("Color/Picker Widgets"))
750         {
751             static ImVec4 color = ImColor(114, 144, 154, 200);
752
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);
762
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);
766
767             ImGui::Text("Color widget HSV with Alpha:");
768             ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
769
770             ImGui::Text("Color widget with Float Display:");
771             ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
772
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);
776
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);
785             ImGui::SameLine();
786             open_popup |= ImGui::Button("Palette");
787             if (open_popup)
788             {
789                 ImGui::OpenPopup("mypicker");
790                 backup_color = color;
791             }
792             if (ImGui::BeginPopup("mypicker"))
793             {
794                 // FIXME: Adding a drag and drop example here would be perfect!
795                 ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
796                 ImGui::Separator();
797                 ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
798                 ImGui::SameLine();
799                 ImGui::BeginGroup();
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;
805                 ImGui::Separator();
806                 ImGui::Text("Palette");
807                 for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
808                 {
809                     ImGui::PushID(n);
810                     if ((n % 8) != 0)
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!
814                     ImGui::PopID();
815                 }
816                 ImGui::EndGroup();
817                 ImGui::EndPopup();
818             }
819
820             ImGui::Text("Color button only:");
821             ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80));
822
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);
834             if (side_preview)
835             {
836                 ImGui::SameLine();
837                 ImGui::Checkbox("With Ref Color", &ref_color);
838                 if (ref_color)
839                 {
840                     ImGui::SameLine();
841                     ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
842                 }
843             }
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);
858
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);
863             ImGui::SameLine();
864             if (ImGui::Button("Float + HDR"))
865                 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_RGB);
866
867             ImGui::TreePop();
868         }
869
870         if (ImGui::TreeNode("Range Widgets"))
871         {
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");
876             ImGui::TreePop();
877         }
878
879         if (ImGui::TreeNode("Multi-component Widgets"))
880         {
881             static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
882             static int vec4i[4] = { 1, 5, 100, 255 };
883
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);
890             ImGui::Spacing();
891
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);
898             ImGui::Spacing();
899
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);
906
907             ImGui::TreePop();
908         }
909
910         if (ImGui::TreeNode("Vertical Sliders"))
911         {
912             const float spacing = 4;
913             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
914
915             static int int_value = 0;
916             ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
917             ImGui::SameLine();
918
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++)
922             {
923                 if (i > 0) ImGui::SameLine();
924                 ImGui::PushID(i);
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);
933                 ImGui::PopID();
934             }
935             ImGui::PopID();
936
937             ImGui::SameLine();
938             ImGui::PushID("set2");
939             static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
940             const int rows = 3;
941             const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);
942             for (int nx = 0; nx < 4; nx++)
943             {
944                 if (nx > 0) ImGui::SameLine();
945                 ImGui::BeginGroup();
946                 for (int ny = 0; ny < rows; ny++)
947                 {
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]);
952                     ImGui::PopID();
953                 }
954                 ImGui::EndGroup();
955             }
956             ImGui::PopID();
957
958             ImGui::SameLine();
959             ImGui::PushID("set3");
960             for (int i = 0; i < 4; i++)
961             {
962                 if (i > 0) ImGui::SameLine();
963                 ImGui::PushID(i);
964                 ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
965                 ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
966                 ImGui::PopStyleVar();
967                 ImGui::PopID();
968             }
969             ImGui::PopID();
970             ImGui::PopStyleVar();
971             ImGui::TreePop();
972         }
973     }
974
975     if (ImGui::CollapsingHeader("Layout"))
976     {
977         if (ImGui::TreeNode("Child regions"))
978         {
979             ImGui::Text("Without border");
980             static int line = 50;
981             bool goto_line = ImGui::Button("Goto");
982             ImGui::SameLine();
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++)
988             {
989                 ImGui::Text("%04d: scrollable region", i);
990                 if (goto_line && line == i)
991                     ImGui::SetScrollHere();
992             }
993             if (goto_line && line >= 100)
994                 ImGui::SetScrollHere();
995             ImGui::EndChild();
996
997             ImGui::SameLine();
998
999             ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
1000             ImGui::BeginChild("Sub2", ImVec2(0,300), true);
1001             ImGui::Text("With border");
1002             ImGui::Columns(2);
1003             for (int i = 0; i < 100; i++)
1004             {
1005                 if (i == 50)
1006                     ImGui::NextColumn();
1007                 char buf[32];
1008                 sprintf(buf, "%08x", i*5731);
1009                 ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
1010             }
1011             ImGui::EndChild();
1012             ImGui::PopStyleVar();
1013
1014             ImGui::TreePop();
1015         }
1016
1017         if (ImGui::TreeNode("Widgets Width"))
1018         {
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();
1025
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();
1031
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();
1037
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();
1043
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();
1049
1050             ImGui::TreePop();
1051         }
1052
1053         if (ImGui::TreeNode("Basic Horizontal Layout"))
1054         {
1055             ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1056
1057             // Text
1058             ImGui::Text("Two items: Hello"); ImGui::SameLine();
1059             ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1060
1061             // Adjust spacing
1062             ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
1063             ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1064
1065             // Button
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");
1071
1072             // Button
1073             ImGui::Text("Small buttons"); ImGui::SameLine();
1074             ImGui::SmallButton("Like this one"); ImGui::SameLine();
1075             ImGui::Text("can fit within a text block.");
1076
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");
1084
1085             // Checkbox
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);
1091
1092             // Various
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();
1102
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++)
1107             {
1108                 if (i > 0) ImGui::SameLine();
1109                 ImGui::PushID(i);
1110                 ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
1111                 ImGui::PopID();
1112                 //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
1113             }
1114             ImGui::PopItemWidth();
1115
1116             // Dummy
1117             ImVec2 sz(30,30);
1118             ImGui::Button("A", sz); ImGui::SameLine();
1119             ImGui::Dummy(sz); ImGui::SameLine();
1120             ImGui::Button("B", sz);
1121
1122             ImGui::TreePop();
1123         }
1124
1125         if (ImGui::TreeNode("Groups"))
1126         {
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();
1129             {
1130                 ImGui::BeginGroup();
1131                 ImGui::Button("AAA");
1132                 ImGui::SameLine();
1133                 ImGui::Button("BBB");
1134                 ImGui::SameLine();
1135                 ImGui::BeginGroup();
1136                 ImGui::Button("CCC");
1137                 ImGui::Button("DDD");
1138                 ImGui::EndGroup();
1139                 ImGui::SameLine();
1140                 ImGui::Button("EEE");
1141                 ImGui::EndGroup();
1142                 if (ImGui::IsItemHovered())
1143                     ImGui::SetTooltip("First group hovered");
1144             }
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);
1149
1150             ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
1151             ImGui::SameLine();
1152             ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
1153             ImGui::EndGroup();
1154             ImGui::SameLine();
1155
1156             ImGui::Button("LEVERAGE\nBUZZWORD", size);
1157             ImGui::SameLine();
1158
1159             ImGui::ListBoxHeader("List", size);
1160             ImGui::Selectable("Selected", true);
1161             ImGui::Selectable("Not Selected", false);
1162             ImGui::ListBoxFooter();
1163
1164             ImGui::TreePop();
1165         }
1166
1167         if (ImGui::TreeNode("Text Baseline Alignment"))
1168         {
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)");
1170
1171             ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
1172             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1173             ImGui::Text("Banana");
1174
1175             ImGui::Text("Banana"); ImGui::SameLine();
1176             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1177             ImGui::Text("One\nTwo\nThree");
1178
1179             ImGui::Button("HOP##1"); ImGui::SameLine();
1180             ImGui::Text("Banana"); ImGui::SameLine();
1181             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1182             ImGui::Text("Banana");
1183
1184             ImGui::Button("HOP##2"); ImGui::SameLine();
1185             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1186             ImGui::Text("Banana");
1187
1188             ImGui::Button("TEST##1"); ImGui::SameLine();
1189             ImGui::Text("TEST"); ImGui::SameLine();
1190             ImGui::SmallButton("TEST##2");
1191
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");
1198
1199             // Tree
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
1204
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
1209
1210             // Bullet
1211             ImGui::Button("Button##3");
1212             ImGui::SameLine(0.0f, spacing);
1213             ImGui::BulletText("Bullet text");
1214
1215             ImGui::AlignTextToFramePadding();
1216             ImGui::BulletText("Node");
1217             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
1218
1219             ImGui::TreePop();
1220         }
1221
1222         if (ImGui::TreeNode("Scrolling"))
1223         {
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;
1234
1235             for (int i = 0; i < 5; i++)
1236             {
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);
1241                 if (scroll_to)
1242                     ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
1243                 for (int line = 0; line < 100; line++)
1244                 {
1245                     if (track && line == track_line)
1246                     {
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
1249                     }
1250                     else
1251                     {
1252                         ImGui::Text("Line %d", line);
1253                     }
1254                 }
1255                 float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
1256                 ImGui::EndChild();
1257                 ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
1258                 ImGui::EndGroup();
1259             }
1260             ImGui::TreePop();
1261         }
1262
1263         if (ImGui::TreeNode("Horizontal Scrolling"))
1264         {
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++)
1273             {
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++)
1278                 {
1279                     if (n > 0) ImGui::SameLine();
1280                     ImGui::PushID(n + line * 1000);
1281                     char num_buf[16];
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);
1289                     ImGui::PopID();
1290                 }
1291             }
1292             float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
1293             ImGui::EndChild();
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)
1301             {
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);
1304                 ImGui::End();
1305             }
1306             ImGui::TreePop();
1307         }
1308
1309         if (ImGui::TreeNode("Clipping"))
1310         {
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);
1321             ImGui::TreePop();
1322         }
1323     }
1324
1325     if (ImGui::CollapsingHeader("Popups & Modal windows"))
1326     {
1327         if (ImGui::TreeNode("Popups"))
1328         {
1329             ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
1330
1331             static int selected_fish = -1;
1332             const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
1333             static bool toggles[] = { true, false, false, false, false };
1334
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");
1339             ImGui::SameLine();
1340             ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
1341             if (ImGui::BeginPopup("select"))
1342             {
1343                 ImGui::Text("Aquarium");
1344                 ImGui::Separator();
1345                 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1346                     if (ImGui::Selectable(names[i]))
1347                         selected_fish = i;
1348                 ImGui::EndPopup();
1349             }
1350
1351             // Showing a menu with toggles
1352             if (ImGui::Button("Toggle.."))
1353                 ImGui::OpenPopup("toggle");
1354             if (ImGui::BeginPopup("toggle"))
1355             {
1356                 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1357                     ImGui::MenuItem(names[i], "", &toggles[i]);
1358                 if (ImGui::BeginMenu("Sub-menu"))
1359                 {
1360                     ImGui::MenuItem("Click me");
1361                     ImGui::EndMenu();
1362                 }
1363
1364                 ImGui::Separator();
1365                 ImGui::Text("Tooltip here");
1366                 if (ImGui::IsItemHovered())
1367                     ImGui::SetTooltip("I am a tooltip over a popup");
1368
1369                 if (ImGui::Button("Stacked Popup"))
1370                     ImGui::OpenPopup("another popup");
1371                 if (ImGui::BeginPopup("another popup"))
1372                 {
1373                     for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1374                         ImGui::MenuItem(names[i], "", &toggles[i]);
1375                     if (ImGui::BeginMenu("Sub-menu"))
1376                     {
1377                         ImGui::MenuItem("Click me");
1378                         ImGui::EndMenu();
1379                     }
1380                     ImGui::EndPopup();
1381                 }
1382                 ImGui::EndPopup();
1383             }
1384
1385             if (ImGui::Button("Popup Menu.."))
1386                 ImGui::OpenPopup("FilePopup");
1387             if (ImGui::BeginPopup("FilePopup"))
1388             {
1389                 ShowExampleMenuFile();
1390                 ImGui::EndPopup();
1391             }
1392
1393             ImGui::TreePop();
1394         }
1395
1396         if (ImGui::TreeNode("Context menus"))
1397         {
1398             // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
1399             //    if (IsItemHovered() && IsMouseClicked(0))
1400             //       OpenPopup(id);
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"))
1406             {
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();
1412                 ImGui::EndPopup();
1413             }
1414
1415             static char name[32] = "Label1";
1416             char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
1417             ImGui::Button(buf);
1418             if (ImGui::BeginPopupContextItem()) // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
1419             {
1420                 ImGui::Text("Edit name:");
1421                 ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
1422                 if (ImGui::Button("Close"))
1423                     ImGui::CloseCurrentPopup();
1424                 ImGui::EndPopup();
1425             }
1426             ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
1427
1428             ImGui::TreePop();
1429         }
1430
1431         if (ImGui::TreeNode("Modals"))
1432         {
1433             ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
1434
1435             if (ImGui::Button("Delete.."))
1436                 ImGui::OpenPopup("Delete?");
1437             if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
1438             {
1439                     ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
1440                 ImGui::Separator();
1441
1442                 //static int dummy_i = 0;
1443                 //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
1444
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();
1449
1450                 if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
1451                 ImGui::SameLine();
1452                 if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
1453                 ImGui::EndPopup();
1454             }
1455
1456             if (ImGui::Button("Stacked modals.."))
1457                 ImGui::OpenPopup("Stacked 1");
1458             if (ImGui::BeginPopupModal("Stacked 1"))
1459             {
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
1465
1466                 if (ImGui::Button("Add another modal.."))
1467                     ImGui::OpenPopup("Stacked 2");
1468                 if (ImGui::BeginPopupModal("Stacked 2"))
1469                 {
1470                     ImGui::Text("Hello from Stacked The Second");
1471                     if (ImGui::Button("Close"))
1472                         ImGui::CloseCurrentPopup();
1473                     ImGui::EndPopup();
1474                 }
1475
1476                 if (ImGui::Button("Close"))
1477                     ImGui::CloseCurrentPopup();
1478                 ImGui::EndPopup();
1479             }
1480
1481             ImGui::TreePop();
1482         }
1483
1484         if (ImGui::TreeNode("Menus inside a regular window"))
1485         {
1486             ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
1487             ImGui::Separator();
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"))
1494             {
1495                 ShowExampleMenuFile();
1496                 ImGui::EndMenu();
1497             }
1498             ImGui::PopID();
1499             ImGui::Separator();
1500             ImGui::TreePop();
1501         }
1502     }
1503
1504     if (ImGui::CollapsingHeader("Columns"))
1505     {
1506         ImGui::PushID("Columns");
1507
1508         // Basic columns
1509         if (ImGui::TreeNode("Basic"))
1510         {
1511             ImGui::Text("Without border:");
1512             ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
1513             ImGui::Separator();
1514             for (int n = 0; n < 14; n++)
1515             {
1516                 char label[32];
1517                 sprintf(label, "Item %d", n);
1518                 if (ImGui::Selectable(label)) {}
1519                 //if (ImGui::Button(label, ImVec2(-1,0))) {}
1520                 ImGui::NextColumn();
1521             }
1522             ImGui::Columns(1);
1523             ImGui::Separator();
1524
1525             ImGui::Text("With border:");
1526             ImGui::Columns(4, "mycolumns"); // 4-ways, with border
1527             ImGui::Separator();
1528             ImGui::Text("ID"); ImGui::NextColumn();
1529             ImGui::Text("Name"); ImGui::NextColumn();
1530             ImGui::Text("Path"); ImGui::NextColumn();
1531             ImGui::Text("Hovered"); ImGui::NextColumn();
1532             ImGui::Separator();
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++)
1537             {
1538                 char label[32];
1539                 sprintf(label, "%04d", i);
1540                 if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
1541                     selected = i;
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();
1547             }
1548             ImGui::Columns(1);
1549             ImGui::Separator();
1550             ImGui::TreePop();
1551         }
1552
1553         // Create multiple items in a same cell before switching to next column
1554         if (ImGui::TreeNode("Mixed items"))
1555         {
1556             ImGui::Columns(3, "mixed");
1557             ImGui::Separator();
1558
1559             ImGui::Text("Hello");
1560             ImGui::Button("Banana");
1561             ImGui::NextColumn();
1562
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();
1569
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();
1575
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();
1579             ImGui::Columns(1);
1580             ImGui::Separator();
1581             ImGui::TreePop();
1582         }
1583
1584         // Word wrapping
1585         if (ImGui::TreeNode("Word-wrapping"))
1586         {
1587             ImGui::Columns(2, "word-wrapping");
1588             ImGui::Separator();
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");
1594             ImGui::Columns(1);
1595             ImGui::Separator();
1596             ImGui::TreePop();
1597         }
1598
1599         if (ImGui::TreeNode("Borders"))
1600         {
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);
1605             ImGui::SameLine();
1606             ImGui::Checkbox("vertical", &v_borders);
1607             ImGui::Columns(4, NULL, v_borders);
1608             for (int i = 0; i < 4*3; i++)
1609             {
1610                 if (h_borders && ImGui::GetColumnIndex() == 0)
1611                     ImGui::Separator();
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();
1615             }
1616             ImGui::Columns(1);
1617             if (h_borders)
1618                 ImGui::Separator();
1619             ImGui::TreePop();
1620         }
1621
1622         // Scrolling columns
1623         /*
1624         if (ImGui::TreeNode("Vertical Scrolling"))
1625         {
1626             ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
1627             ImGui::Columns(3);
1628             ImGui::Text("ID"); ImGui::NextColumn();
1629             ImGui::Text("Name"); ImGui::NextColumn();
1630             ImGui::Text("Path"); ImGui::NextColumn();
1631             ImGui::Columns(1);
1632             ImGui::Separator();
1633             ImGui::EndChild();
1634             ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
1635             ImGui::Columns(3);
1636             for (int i = 0; i < 10; i++)
1637             {
1638                 ImGui::Text("%04d", i); ImGui::NextColumn();
1639                 ImGui::Text("Foobar"); ImGui::NextColumn();
1640                 ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
1641             }
1642             ImGui::Columns(1);
1643             ImGui::EndChild();
1644             ImGui::TreePop();
1645         }
1646         */
1647
1648         if (ImGui::TreeNode("Horizontal Scrolling"))
1649         {
1650             ImGui::SetNextWindowContentWidth(1500);
1651             ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
1652             ImGui::Columns(10);
1653             int ITEMS_COUNT = 2000;
1654             ImGuiListClipper clipper(ITEMS_COUNT);  // Also demonstrate using the clipper for large list
1655             while (clipper.Step())
1656             {
1657                 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
1658                     for (int j = 0; j < 10; j++)
1659                     {
1660                         ImGui::Text("Line %d Column %d...", i, j);
1661                         ImGui::NextColumn();
1662                     }
1663             }
1664             ImGui::Columns(1);
1665             ImGui::EndChild();
1666             ImGui::TreePop();
1667         }
1668
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.");
1671         if (node_open)
1672         {
1673             ImGui::Columns(2, "tree items");
1674             ImGui::Separator();
1675             if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
1676             if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
1677             ImGui::Columns(1);
1678             ImGui::Separator();
1679             ImGui::TreePop();
1680         }
1681         ImGui::PopID();
1682     }
1683
1684     if (ImGui::CollapsingHeader("Filtering"))
1685     {
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\"");
1692         filter.Draw();
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]);
1697     }
1698
1699     if (ImGui::CollapsingHeader("Inputs & Focus"))
1700     {
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.");
1704
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);
1709
1710         if (ImGui::TreeNode("Keyboard & Mouse State"))
1711         {
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);
1718
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 " : "");
1723
1724
1725             ImGui::Button("Hovering me sets the\nkeyboard capture flag");
1726             if (ImGui::IsItemHovered())
1727                 ImGui::CaptureKeyboardFromApp(true);
1728             ImGui::SameLine();
1729             ImGui::Button("Holding me clears the\nthe keyboard capture flag");
1730             if (ImGui::IsItemActive())
1731                 ImGui::CaptureKeyboardFromApp(false);
1732
1733             ImGui::TreePop();
1734         }
1735
1736         if (ImGui::TreeNode("Tabbing"))
1737         {
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));
1748             ImGui::TreePop();
1749         }
1750
1751         if (ImGui::TreeNode("Focus from code"))
1752         {
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");
1756             int has_focus = 0;
1757             static char buf[128] = "click on a button to set focus";
1758
1759             if (focus_1) ImGui::SetKeyboardFocusHere();
1760             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
1761             if (ImGui::IsItemActive()) has_focus = 1;
1762
1763             if (focus_2) ImGui::SetKeyboardFocusHere();
1764             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
1765             if (ImGui::IsItemActive()) has_focus = 2;
1766
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();
1772             if (has_focus)
1773                 ImGui::Text("Item with focus: %d", has_focus);
1774             else
1775                 ImGui::Text("Item with focus: <none>");
1776             ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code.");
1777             ImGui::TreePop();
1778         }
1779
1780         if (ImGui::TreeNode("Hovering"))
1781         {
1782             // Testing IsWindowHovered() function with its various flags (note that the flags can be combined)
1783             ImGui::BulletText(
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));
1792
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");
1795             ImGui::BulletText(
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));
1806
1807             ImGui::TreePop();
1808         }
1809
1810         if (ImGui::TreeNode("Dragging"))
1811         {
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())
1815             {
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);
1825             }
1826             ImGui::TreePop();
1827         }
1828
1829         if (ImGui::TreeNode("Mouse cursors"))
1830         {
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++)
1834             {
1835                 char label[32];
1836                 sprintf(label, "Mouse cursor %d", i);
1837                 ImGui::Bullet(); ImGui::Selectable(label, false);
1838                 if (ImGui::IsItemHovered())
1839                     ImGui::SetMouseCursor(i);
1840             }
1841             ImGui::TreePop();
1842         }
1843     }
1844
1845     ImGui::End();
1846 }
1847
1848 void ImGui::ShowStyleEditor(ImGuiStyle* ref)
1849 {
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;
1853
1854     // Default to using internal storage as reference
1855     static bool init = true;
1856     if (init && ref == NULL)
1857         ref_saved_style = style;
1858     init = false;
1859     if (ref == NULL)
1860         ref = &ref_saved_style;
1861
1862     ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
1863
1864     // Default Styles Selector
1865     static int style_idx = 0;
1866     if (ImGui::Combo("Colors##Selector", &style_idx, "Classic\0Dark\0Light\0"))
1867     {
1868         switch (style_idx)
1869         {
1870         case 0: ImGui::StyleColorsClassic(); break;
1871         case 1: ImGui::StyleColorsDark(); break;
1872         case 2: ImGui::StyleColorsLight(); break;
1873         }
1874         ref_saved_style = style;
1875     }
1876
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; }
1881     ImGui::SameLine();
1882     { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
1883     ImGui::SameLine();
1884     { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
1885
1886     // Save/Revert button
1887     if (ImGui::Button("Save Ref"))
1888         *ref = ref_saved_style = style;
1889     ImGui::SameLine();
1890     if (ImGui::Button("Revert Ref"))
1891         style = *ref;
1892     ImGui::SameLine();
1893     ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
1894
1895     if (ImGui::TreeNode("Rendering"))
1896     {
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();
1904         ImGui::TreePop();
1905     }
1906
1907     if (ImGui::TreeNode("Settings"))
1908     {
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.");
1932         ImGui::TreePop();
1933     }
1934
1935     if (ImGui::TreeNode("Colors"))
1936     {
1937         static int output_dest = 0;
1938         static bool output_only_modified = true;
1939         if (ImGui::Button("Export Unsaved"))
1940         {
1941             if (output_dest == 0)
1942                 ImGui::LogToClipboard();
1943             else
1944                 ImGui::LogToTTY();
1945             ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
1946             for (int i = 0; i < ImGuiCol_COUNT; i++)
1947             {
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);
1952             }
1953             ImGui::LogFinish();
1954         }
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);
1957
1958         ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");
1959
1960         static ImGuiTextFilter filter;
1961         filter.Draw("Filter colors", 200);
1962
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);
1967
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++)
1971         {
1972             const char* name = ImGui::GetStyleColorName(i);
1973             if (!filter.PassFilter(name))
1974                 continue;
1975             ImGui::PushID(i);
1976             ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
1977             if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
1978             {
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];
1983             }
1984             ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
1985             ImGui::TextUnformatted(name);
1986             ImGui::PopID();
1987         }
1988         ImGui::PopItemWidth();
1989         ImGui::EndChild();
1990
1991         ImGui::TreePop();
1992     }
1993
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.");
1996     if (fonts_opened)
1997     {
1998         ImFontAtlas* atlas = ImGui::GetIO().Fonts;
1999         if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
2000         {
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));
2002             ImGui::TreePop();
2003         }
2004         ImGui::PushItemWidth(100);
2005         for (int i = 0; i < atlas->Fonts.Size; i++)
2006         {
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)
2012             {
2013                 ImGui::PushFont(font);
2014                 ImGui::Text("The quick brown fox jumps over the lazy dog");
2015                 ImGui::PopFont();
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++)
2022                 {
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);
2025                 }
2026                 if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
2027                 {
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)
2032                     {
2033                         int count = 0;
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"))
2037                         {
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++)
2043                             {
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))
2050                                 {
2051                                     ImGui::BeginTooltip();
2052                                     ImGui::Text("Codepoint: U+%04X", base+n);
2053                                     ImGui::Separator();
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();
2058                                 }
2059                             }
2060                             ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16));
2061                             ImGui::TreePop();
2062                         }
2063                     }
2064                     font->FallbackGlyph = glyph_fallback;
2065                     ImGui::TreePop();
2066                 }
2067                 ImGui::TreePop();
2068             }
2069             ImGui::PopID();
2070         }
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);
2076         ImGui::TreePop();
2077     }
2078
2079     ImGui::PopItemWidth();
2080 }
2081
2082 // Demonstrate creating a fullscreen menu bar and populating it.
2083 static void ShowExampleAppMainMenuBar()
2084 {
2085     if (ImGui::BeginMainMenuBar())
2086     {
2087         if (ImGui::BeginMenu("File"))
2088         {
2089             ShowExampleMenuFile();
2090             ImGui::EndMenu();
2091         }
2092         if (ImGui::BeginMenu("Edit"))
2093         {
2094             if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
2095             if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
2096             ImGui::Separator();
2097             if (ImGui::MenuItem("Cut", "CTRL+X")) {}
2098             if (ImGui::MenuItem("Copy", "CTRL+C")) {}
2099             if (ImGui::MenuItem("Paste", "CTRL+V")) {}
2100             ImGui::EndMenu();
2101         }
2102         ImGui::EndMainMenuBar();
2103     }
2104 }
2105
2106 static void ShowExampleMenuFile()
2107 {
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"))
2112     {
2113         ImGui::MenuItem("fish_hat.c");
2114         ImGui::MenuItem("fish_hat.inl");
2115         ImGui::MenuItem("fish_hat.h");
2116         if (ImGui::BeginMenu("More.."))
2117         {
2118             ImGui::MenuItem("Hello");
2119             ImGui::MenuItem("Sailor");
2120             if (ImGui::BeginMenu("Recurse.."))
2121             {
2122                 ShowExampleMenuFile();
2123                 ImGui::EndMenu();
2124             }
2125             ImGui::EndMenu();
2126         }
2127         ImGui::EndMenu();
2128     }
2129     if (ImGui::MenuItem("Save", "Ctrl+S")) {}
2130     if (ImGui::MenuItem("Save As..")) {}
2131     ImGui::Separator();
2132     if (ImGui::BeginMenu("Options"))
2133     {
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);
2139         ImGui::EndChild();
2140         static float f = 0.5f;
2141         static int n = 0;
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);
2147         ImGui::EndMenu();
2148     }
2149     if (ImGui::BeginMenu("Colors"))
2150     {
2151         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
2152         for (int i = 0; i < ImGuiCol_COUNT; i++)
2153         {
2154             const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
2155             ImGui::ColorButton(name, ImGui::GetStyleColorVec4((ImGuiCol)i));
2156             ImGui::SameLine();
2157             ImGui::MenuItem(name);
2158         }
2159         ImGui::PopStyleVar();
2160         ImGui::EndMenu();
2161     }
2162     if (ImGui::BeginMenu("Disabled", false)) // Disabled
2163     {
2164         IM_ASSERT(0);
2165     }
2166     if (ImGui::MenuItem("Checked", NULL, true)) {}
2167     if (ImGui::MenuItem("Quit", "Alt+F4")) {}
2168 }
2169
2170 // Demonstrate creating a window which gets auto-resized according to its content.
2171 static void ShowExampleAppAutoResize(bool* p_open)
2172 {
2173     if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
2174     {
2175         ImGui::End();
2176         return;
2177     }
2178
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
2184     ImGui::End();
2185 }
2186
2187 // Demonstrate creating a window with custom resize constraints.
2188 static void ShowExampleAppConstrainedResize(bool* p_open)
2189 {
2190     struct CustomConstraints // Helper functions to demonstrate programmatic constraints
2191     {
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); }
2194     };
2195
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
2206
2207     ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
2208     if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
2209     {
2210         const char* desc[] = 
2211         {
2212             "Resize vertical only",
2213             "Resize horizontal only",
2214             "Width > 100, Height > 100",
2215             "Width 400-500",
2216             "Height 400-500",
2217             "Custom: Always Square",
2218             "Custom: Fixed Steps (100)",
2219         };
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, "");
2230     }
2231     ImGui::End();
2232 }
2233
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)
2236 {
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))
2244     {
2245         ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)");
2246         ImGui::Separator();
2247         ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
2248         if (ImGui::BeginPopupContextWindow())
2249         {
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;
2254             ImGui::EndPopup();
2255         }
2256         ImGui::End();
2257     }
2258     ImGui::PopStyleColor();
2259 }
2260
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*)
2264 {
2265     // By default, Windows are uniquely identified by their title.
2266     // You can use the "##" and "###" markers to manipulate the display/ID.
2267
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.");
2272     ImGui::End();
2273
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.");
2277     ImGui::End();
2278
2279     // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
2280     char buf[128];
2281     sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand());
2282     ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiCond_FirstUseEver);
2283     ImGui::Begin(buf);
2284     ImGui::Text("This window has a changing title.");
2285     ImGui::End();
2286 }
2287
2288 // Demonstrate using the low-level ImDrawList to draw custom shapes. 
2289 static void ShowExampleAppCustomRendering(bool* p_open)
2290 {
2291     ImGui::SetNextWindowSize(ImVec2(350,560), ImGuiCond_FirstUseEver);
2292     if (!ImGui::Begin("Example: Custom rendering", p_open))
2293     {
2294         ImGui::End();
2295         return;
2296     }
2297
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();
2303
2304     // Primitives
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);
2310     {
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++)
2315         {
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);
2326             x = p.x + 4;
2327             y += sz+spacing;
2328         }
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));
2336     }
2337     ImGui::Separator();
2338     {
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");
2345
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));
2355
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);
2359         if (adding_line)
2360         {
2361             adding_preview = true;
2362             points.push_back(mouse_pos_in_canvas);
2363             if (!ImGui::GetIO().MouseDown[0])
2364                 adding_line = adding_preview = false;
2365         }
2366         if (ImGui::IsItemHovered())
2367         {
2368             if (!adding_line && ImGui::IsMouseClicked(0))
2369             {
2370                 points.push_back(mouse_pos_in_canvas);
2371                 adding_line = true;
2372             }
2373             if (ImGui::IsMouseClicked(1) && !points.empty())
2374             {
2375                 adding_line = adding_preview = false;
2376                 points.pop_back();
2377                 points.pop_back();
2378             }
2379         }
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();
2384         if (adding_preview)
2385             points.pop_back();
2386     }
2387     ImGui::End();
2388 }
2389
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
2393 {
2394     char                  InputBuf[256];
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;
2400
2401     ExampleAppConsole()
2402     {
2403         ClearLog();
2404         memset(InputBuf, 0, sizeof(InputBuf));
2405         HistoryPos = -1;
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!");
2411     }
2412     ~ExampleAppConsole()
2413     {
2414         ClearLog();
2415         for (int i = 0; i < History.Size; i++)
2416             free(History[i]);
2417     }
2418
2419     // Portable helpers
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); }
2423
2424     void    ClearLog()
2425     {
2426         for (int i = 0; i < Items.Size; i++)
2427             free(Items[i]);
2428         Items.clear();
2429         ScrollToBottom = true;
2430     }
2431
2432     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
2433     {
2434         // FIXME-OPT
2435         char buf[1024];
2436         va_list args;
2437         va_start(args, fmt);
2438         vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
2439         buf[IM_ARRAYSIZE(buf)-1] = 0;
2440         va_end(args);
2441         Items.push_back(Strdup(buf));
2442         ScrollToBottom = true;
2443     }
2444
2445     void    Draw(const char* title, bool* p_open)
2446     {
2447         ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
2448         if (!ImGui::Begin(title, p_open))
2449         {
2450             ImGui::End();
2451             return;
2452         }
2453
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())
2457         {
2458             if (ImGui::MenuItem("Close"))
2459                 *p_open = false;
2460             ImGui::EndPopup();
2461         }
2462
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.");
2465
2466         // TODO: display items starting from the bottom
2467
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); }
2474
2475         ImGui::Separator();
2476
2477         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
2478         static ImGuiTextFilter filter;
2479         filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
2480         ImGui::PopStyleVar();
2481         ImGui::Separator();
2482
2483         ImGui::BeginChild("ScrollingRegion", ImVec2(0,-ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar);
2484         if (ImGui::BeginPopupContextWindow())
2485         {
2486             if (ImGui::Selectable("Clear")) ClearLog();
2487             ImGui::EndPopup();
2488         }
2489
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++)
2505         {
2506             const char* item = Items[i];
2507             if (!filter.PassFilter(item))
2508                 continue;
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();
2515         }
2516         if (copy_to_clipboard)
2517             ImGui::LogFinish();
2518         if (ScrollToBottom)
2519             ImGui::SetScrollHere();
2520         ScrollToBottom = false;
2521         ImGui::PopStyleVar();
2522         ImGui::EndChild();
2523         ImGui::Separator();
2524
2525         // Command-line
2526         if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
2527         {
2528             char* input_end = InputBuf+strlen(InputBuf);
2529             while (input_end > InputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0;
2530             if (InputBuf[0])
2531                 ExecCommand(InputBuf);
2532             strcpy(InputBuf, "");
2533         }
2534
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
2538
2539         ImGui::End();
2540     }
2541
2542     void    ExecCommand(const char* command_line)
2543     {
2544         AddLog("# %s\n", command_line);
2545
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.
2547         HistoryPos = -1;
2548         for (int i = History.Size-1; i >= 0; i--)
2549             if (Stricmp(History[i], command_line) == 0)
2550             {
2551                 free(History[i]);
2552                 History.erase(History.begin() + i);
2553                 break;
2554             }
2555         History.push_back(Strdup(command_line));
2556
2557         // Process command
2558         if (Stricmp(command_line, "CLEAR") == 0)
2559         {
2560             ClearLog();
2561         }
2562         else if (Stricmp(command_line, "HELP") == 0)
2563         {
2564             AddLog("Commands:");
2565             for (int i = 0; i < Commands.Size; i++)
2566                 AddLog("- %s", Commands[i]);
2567         }
2568         else if (Stricmp(command_line, "HISTORY") == 0)
2569         {
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]);
2573         }
2574         else
2575         {
2576             AddLog("Unknown command: '%s'\n", command_line);
2577         }
2578     }
2579
2580     static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
2581     {
2582         ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
2583         return console->TextEditCallback(data);
2584     }
2585
2586     int     TextEditCallback(ImGuiTextEditCallbackData* data)
2587     {
2588         //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
2589         switch (data->EventFlag)
2590         {
2591         case ImGuiInputTextFlags_CallbackCompletion:
2592             {
2593                 // Example of TEXT COMPLETION
2594
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)
2599                 {
2600                     const char c = word_start[-1];
2601                     if (c == ' ' || c == '\t' || c == ',' || c == ';')
2602                         break;
2603                     word_start--;
2604                 }
2605
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]);
2611
2612                 if (candidates.Size == 0)
2613                 {
2614                     // No match
2615                     AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
2616                 }
2617                 else if (candidates.Size == 1)
2618                 {
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, " ");
2623                 }
2624                 else
2625                 {
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);
2628                     for (;;)
2629                     {
2630                         int c = 0;
2631                         bool all_candidates_matches = true;
2632                         for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
2633                             if (i == 0)
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)
2638                             break;
2639                         match_len++;
2640                     }
2641
2642                     if (match_len > 0)
2643                     {
2644                         data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
2645                         data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
2646                     }
2647
2648                     // List matches
2649                     AddLog("Possible matches:\n");
2650                     for (int i = 0; i < candidates.Size; i++)
2651                         AddLog("- %s\n", candidates[i]);
2652                 }
2653
2654                 break;
2655             }
2656         case ImGuiInputTextFlags_CallbackHistory:
2657             {
2658                 // Example of HISTORY
2659                 const int prev_history_pos = HistoryPos;
2660                 if (data->EventKey == ImGuiKey_UpArrow)
2661                 {
2662                     if (HistoryPos == -1)
2663                         HistoryPos = History.Size - 1;
2664                     else if (HistoryPos > 0)
2665                         HistoryPos--;
2666                 }
2667                 else if (data->EventKey == ImGuiKey_DownArrow)
2668                 {
2669                     if (HistoryPos != -1)
2670                         if (++HistoryPos >= History.Size)
2671                             HistoryPos = -1;
2672                 }
2673
2674                 // A better implementation would preserve the data on the current input line along with cursor position.
2675                 if (prev_history_pos != HistoryPos)
2676                 {
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;
2679                 }
2680             }
2681         }
2682         return 0;
2683     }
2684 };
2685
2686 static void ShowExampleAppConsole(bool* p_open)
2687 {
2688     static ExampleAppConsole console;
2689     console.Draw("Example: Console", p_open);
2690 }
2691
2692 // Usage:
2693 //  static ExampleAppLog my_log;
2694 //  my_log.AddLog("Hello %d world\n", 123);
2695 //  my_log.Draw("title");
2696 struct ExampleAppLog
2697 {
2698     ImGuiTextBuffer     Buf;
2699     ImGuiTextFilter     Filter;
2700     ImVector<int>       LineOffsets;        // Index to lines offset
2701     bool                ScrollToBottom;
2702
2703     void    Clear()     { Buf.clear(); LineOffsets.clear(); }
2704
2705     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
2706     {
2707         int old_size = Buf.size();
2708         va_list args;
2709         va_start(args, fmt);
2710         Buf.appendv(fmt, args);
2711         va_end(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;
2716     }
2717
2718     void    Draw(const char* title, bool* p_open = NULL)
2719     {
2720         ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver);
2721         ImGui::Begin(title, p_open);
2722         if (ImGui::Button("Clear")) Clear();
2723         ImGui::SameLine();
2724         bool copy = ImGui::Button("Copy");
2725         ImGui::SameLine();
2726         Filter.Draw("Filter", -100.0f);
2727         ImGui::Separator();
2728         ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
2729         if (copy) ImGui::LogToClipboard();
2730
2731         if (Filter.IsActive())
2732         {
2733             const char* buf_begin = Buf.begin();
2734             const char* line = buf_begin;
2735             for (int line_no = 0; line != NULL; line_no++)
2736             {
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;
2741             }
2742         }
2743         else
2744         {
2745             ImGui::TextUnformatted(Buf.begin());
2746         }
2747
2748         if (ScrollToBottom)
2749             ImGui::SetScrollHere(1.0f);
2750         ScrollToBottom = false;
2751         ImGui::EndChild();
2752         ImGui::End();
2753     }
2754 };
2755
2756 // Demonstrate creating a simple log window with basic filtering.
2757 static void ShowExampleAppLog(bool* p_open)
2758 {
2759     static ExampleAppLog log;
2760
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)
2765     {
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());
2768         last_time = time;
2769     }
2770
2771     log.Draw("Example: Log", p_open);
2772 }
2773
2774 // Demonstrate create a window with multiple child windows.
2775 static void ShowExampleAppLayout(bool* p_open)
2776 {
2777     ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
2778     if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
2779     {
2780         if (ImGui::BeginMenuBar())
2781         {
2782             if (ImGui::BeginMenu("File"))
2783             {
2784                 if (ImGui::MenuItem("Close")) *p_open = false;
2785                 ImGui::EndMenu();
2786             }
2787             ImGui::EndMenuBar();
2788         }
2789
2790         // left
2791         static int selected = 0;
2792         ImGui::BeginChild("left pane", ImVec2(150, 0), true);
2793         for (int i = 0; i < 100; i++)
2794         {
2795             char label[128];
2796             sprintf(label, "MyObject %d", i);
2797             if (ImGui::Selectable(label, selected == i))
2798                 selected = i;
2799         }
2800         ImGui::EndChild();
2801         ImGui::SameLine();
2802
2803         // right
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);
2807                 ImGui::Separator();
2808                 ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
2809             ImGui::EndChild();
2810             ImGui::BeginChild("buttons");
2811                 if (ImGui::Button("Revert")) {}
2812                 ImGui::SameLine();
2813                 if (ImGui::Button("Save")) {}
2814             ImGui::EndChild();
2815         ImGui::EndGroup();
2816     }
2817     ImGui::End();
2818 }
2819
2820 // Demonstrate create a simple property editor.
2821 static void ShowExampleAppPropertyEditor(bool* p_open)
2822 {
2823     ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
2824     if (!ImGui::Begin("Example: Property editor", p_open))
2825     {
2826         ImGui::End();
2827         return;
2828     }
2829
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.");
2831
2832     ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
2833     ImGui::Columns(2);
2834     ImGui::Separator();
2835
2836     struct funcs
2837     {
2838         static void ShowDummyObject(const char* prefix, int uid)
2839         {
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();
2847             if (node_open)
2848             {
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++)
2851                 {
2852                     ImGui::PushID(i); // Use field index as identifier.
2853                     if (i < 2)
2854                     {
2855                         ShowDummyObject("Child", 424242);
2856                     }
2857                     else
2858                     {
2859                         ImGui::AlignTextToFramePadding();
2860                         // Here we use a Selectable (instead of Text) to highlight on hover
2861                         //ImGui::Text("Field_%d", i);
2862                         char label[32];
2863                         sprintf(label, "Field_%d", i);
2864                         ImGui::Bullet();
2865                         ImGui::Selectable(label);
2866                         ImGui::NextColumn();
2867                         ImGui::PushItemWidth(-1);
2868                         if (i >= 5)
2869                             ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
2870                         else
2871                             ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
2872                         ImGui::PopItemWidth();
2873                         ImGui::NextColumn();
2874                     }
2875                     ImGui::PopID();
2876                 }
2877                 ImGui::TreePop();
2878             }
2879             ImGui::PopID();
2880         }
2881     };
2882
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);
2886
2887     ImGui::Columns(1);
2888     ImGui::Separator();
2889     ImGui::PopStyleVar();
2890     ImGui::End();
2891 }
2892
2893 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
2894 static void ShowExampleAppLongText(bool* p_open)
2895 {
2896     ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
2897     if (!ImGui::Begin("Example: Long text display", p_open))
2898     {
2899         ImGui::End();
2900         return;
2901     }
2902
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; }
2910     ImGui::SameLine();
2911     if (ImGui::Button("Add 1000 lines"))
2912     {
2913         for (int i = 0; i < 1000; i++)
2914             log.append("%i The quick brown fox jumps over the lazy dog\n", lines+i);
2915         lines += 1000;
2916     }
2917     ImGui::BeginChild("Log");
2918     switch (test_type)
2919     {
2920     case 0:
2921         // Single call to TextUnformatted() with a big buffer
2922         ImGui::TextUnformatted(log.begin(), log.end());
2923         break;
2924     case 1:
2925         {
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();
2933             break;
2934         }
2935     case 2:
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();
2941         break;
2942     }
2943     ImGui::EndChild();
2944     ImGui::End();
2945 }
2946
2947 // End of Demo code
2948 #else
2949
2950 void ImGui::ShowTestWindow(bool*) {}
2951 void ImGui::ShowUserGuide() {}
2952 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
2953
2954 #endif