1 // dear imgui, v1.66 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::ShowDemoWindow().
7 // During development, you can call ImGui::ShowDemoWindow() 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_DEMO_WINDOWS in imconfig.h for the same effect.
10 // If you want to link core ImGui in your final builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty.
11 // In other situation, when 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++ programmers about the meaning of the 'static' keyword: in this demo code, we frequently we use 'static' variables inside functions.
16 // A static variable persist across calls, so it is essentially like a global variable but declared inside the scope of the function.
17 // We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code.
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 might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your functions.
20 
21 /*
22 
23 Index of this file:
24 
25 // [SECTION] Forward Declarations, Helpers
26 // [SECTION] Demo Window / ShowDemoWindow()
27 // [SECTION] Style Editor / ShowStyleEditor()
28 // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
29 // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
30 // [SECTION] Example App: Debug Log / ShowExampleAppLog()
31 // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
32 // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
33 // [SECTION] Example App: Long Text / ShowExampleAppLongText()
34 // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
35 // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
36 // [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
37 // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
38 // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
39 
40 */
41 
42 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
43 #define _CRT_SECURE_NO_WARNINGS
44 #endif
45 
46 #include "imgui.h"
47 #include <ctype.h>          // toupper, isprint
48 #include <limits.h>         // INT_MIN, INT_MAX
49 #include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
50 #include <stdio.h>          // vsnprintf, sscanf, printf
51 #include <stdlib.h>         // NULL, malloc, free, atoi
52 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
53 #include <stddef.h>         // intptr_t
54 #else
55 #include <stdint.h>         // intptr_t
56 #endif
57 
58 #ifdef _MSC_VER
59 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
60 #define vsnprintf _vsnprintf
61 #endif
62 #ifdef __clang__
63 #pragma clang diagnostic ignored "-Wold-style-cast"             // warning : use of old-style cast                              // yes, they are more terse.
64 #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)
65 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"   // warning : cast to 'void *' from smaller integer type 'int'
66 #pragma clang diagnostic ignored "-Wformat-security"            // warning : warning: format string is not a string literal
67 #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.
68 #if __has_warning("-Wreserved-id-macro")
69 #pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                //
70 #endif
71 #elif defined(__GNUC__)
72 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"          // warning: cast to pointer from integer of different size
73 #pragma GCC diagnostic ignored "-Wformat-security"              // warning : format string is not a string literal (potentially insecure)
74 #pragma GCC diagnostic ignored "-Wdouble-promotion"             // warning: implicit conversion from 'float' to 'double' when passing argument to function
75 #pragma GCC diagnostic ignored "-Wconversion"                   // warning: conversion to 'xxxx' from 'xxxx' may alter its value
76 #if (__GNUC__ >= 6)
77 #pragma GCC diagnostic ignored "-Wmisleading-indentation"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
78 #endif
79 #endif
80 
81 // Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n.
82 #ifdef _WIN32
83 #define IM_NEWLINE "\r\n"
84 #else
85 #define IM_NEWLINE "\n"
86 #endif
87 
88 #define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))
89 
90 //-----------------------------------------------------------------------------
91 // [SECTION] Forward Declarations, Helpers
92 //-----------------------------------------------------------------------------
93 
94 #if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS)   // Obsolete name since 1.53, TEST->DEMO
95 #define IMGUI_DISABLE_DEMO_WINDOWS
96 #endif
97 
98 #if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
99 
100 // Forward Declarations
101 static void ShowExampleAppMainMenuBar();
102 static void ShowExampleAppConsole(bool* p_open);
103 static void ShowExampleAppLog(bool* p_open);
104 static void ShowExampleAppLayout(bool* p_open);
105 static void ShowExampleAppPropertyEditor(bool* p_open);
106 static void ShowExampleAppLongText(bool* p_open);
107 static void ShowExampleAppAutoResize(bool* p_open);
108 static void ShowExampleAppConstrainedResize(bool* p_open);
109 static void ShowExampleAppSimpleOverlay(bool* p_open);
110 static void ShowExampleAppWindowTitles(bool* p_open);
111 static void ShowExampleAppCustomRendering(bool* p_open);
112 static void ShowExampleMenuFile();
113 
114 // Helper to display a little (?) mark which shows a tooltip when hovered.
ShowHelpMarker(const char * desc)115 static void ShowHelpMarker(const char* desc)
116 {
117     ImGui::TextDisabled("(?)");
118     if (ImGui::IsItemHovered())
119     {
120         ImGui::BeginTooltip();
121         ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
122         ImGui::TextUnformatted(desc);
123         ImGui::PopTextWrapPos();
124         ImGui::EndTooltip();
125     }
126 }
127 
128 // Helper to display basic user controls.
ShowUserGuide()129 void ImGui::ShowUserGuide()
130 {
131     ImGui::BulletText("Double-click on title bar to collapse window.");
132     ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
133     ImGui::BulletText("Click and drag on any empty space to move window.");
134     ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
135     ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
136     if (ImGui::GetIO().FontAllowUserScaling)
137         ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
138     ImGui::BulletText("Mouse Wheel to scroll.");
139     ImGui::BulletText("While editing text:\n");
140     ImGui::Indent();
141     ImGui::BulletText("Hold SHIFT or use mouse to select text.");
142     ImGui::BulletText("CTRL+Left/Right to word jump.");
143     ImGui::BulletText("CTRL+A or double-click to select all.");
144     ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
145     ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
146     ImGui::BulletText("ESCAPE to revert.");
147     ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
148     ImGui::Unindent();
149 }
150 
151 //-----------------------------------------------------------------------------
152 // [SECTION] Demo Window / ShowDemoWindow()
153 //-----------------------------------------------------------------------------
154 
155 // Demonstrate most Dear ImGui features (this is big function!)
156 // You may execute this function to experiment with the UI and understand what it does. You may then search for keywords in the code when you are interested by a specific feature.
ShowDemoWindow(bool * p_open)157 void ImGui::ShowDemoWindow(bool* p_open)
158 {
159     // Examples Apps (accessible from the "Examples" menu)
160     static bool show_app_main_menu_bar = false;
161     static bool show_app_console = false;
162     static bool show_app_log = false;
163     static bool show_app_layout = false;
164     static bool show_app_property_editor = false;
165     static bool show_app_long_text = false;
166     static bool show_app_auto_resize = false;
167     static bool show_app_constrained_resize = false;
168     static bool show_app_simple_overlay = false;
169     static bool show_app_window_titles = false;
170     static bool show_app_custom_rendering = false;
171 
172     if (show_app_main_menu_bar)       ShowExampleAppMainMenuBar();
173     if (show_app_console)             ShowExampleAppConsole(&show_app_console);
174     if (show_app_log)                 ShowExampleAppLog(&show_app_log);
175     if (show_app_layout)              ShowExampleAppLayout(&show_app_layout);
176     if (show_app_property_editor)     ShowExampleAppPropertyEditor(&show_app_property_editor);
177     if (show_app_long_text)           ShowExampleAppLongText(&show_app_long_text);
178     if (show_app_auto_resize)         ShowExampleAppAutoResize(&show_app_auto_resize);
179     if (show_app_constrained_resize)  ShowExampleAppConstrainedResize(&show_app_constrained_resize);
180     if (show_app_simple_overlay)      ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
181     if (show_app_window_titles)       ShowExampleAppWindowTitles(&show_app_window_titles);
182     if (show_app_custom_rendering)    ShowExampleAppCustomRendering(&show_app_custom_rendering);
183 
184     // Dear ImGui Apps (accessible from the "Help" menu)
185     static bool show_app_metrics = false;
186     static bool show_app_style_editor = false;
187     static bool show_app_about = false;
188 
189     if (show_app_metrics)             { ImGui::ShowMetricsWindow(&show_app_metrics); }
190     if (show_app_style_editor)        { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
191     if (show_app_about)
192     {
193         ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
194         ImGui::Text("Dear ImGui, %s", ImGui::GetVersion());
195         ImGui::Separator();
196         ImGui::Text("By Omar Cornut and all dear imgui contributors.");
197         ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
198         ImGui::End();
199     }
200 
201     // Demonstrate the various window flags. Typically you would just use the default!
202     static bool no_titlebar = false;
203     static bool no_scrollbar = false;
204     static bool no_menu = false;
205     static bool no_move = false;
206     static bool no_resize = false;
207     static bool no_collapse = false;
208     static bool no_close = false;
209     static bool no_nav = false;
210     static bool no_background = false;
211     static bool no_bring_to_front = false;
212 
213     ImGuiWindowFlags window_flags = 0;
214     if (no_titlebar)        window_flags |= ImGuiWindowFlags_NoTitleBar;
215     if (no_scrollbar)       window_flags |= ImGuiWindowFlags_NoScrollbar;
216     if (!no_menu)           window_flags |= ImGuiWindowFlags_MenuBar;
217     if (no_move)            window_flags |= ImGuiWindowFlags_NoMove;
218     if (no_resize)          window_flags |= ImGuiWindowFlags_NoResize;
219     if (no_collapse)        window_flags |= ImGuiWindowFlags_NoCollapse;
220     if (no_nav)             window_flags |= ImGuiWindowFlags_NoNav;
221     if (no_background)      window_flags |= ImGuiWindowFlags_NoBackground;
222     if (no_bring_to_front)  window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
223     if (no_close)           p_open = NULL; // Don't pass our bool* to Begin
224 
225     // We specify a default position/size in case there's no data in the .ini file. Typically this isn't required! We only do it to make the Demo applications a little more welcoming.
226     ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver);
227     ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
228 
229     // Main body of the Demo window starts here.
230     if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
231     {
232         // Early out if the window is collapsed, as an optimization.
233         ImGui::End();
234         return;
235     }
236     ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
237 
238     // Most "big" widgets share a common width settings by default.
239     //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);    // Use 2/3 of the space for widgets and 1/3 for labels (default)
240     ImGui::PushItemWidth(ImGui::GetFontSize() * -12);           // Use fixed width for labels (by passing a negative value), the rest goes to widgets. We choose a width proportional to our font size.
241 
242     // Menu
243     if (ImGui::BeginMenuBar())
244     {
245         if (ImGui::BeginMenu("Menu"))
246         {
247             ShowExampleMenuFile();
248             ImGui::EndMenu();
249         }
250         if (ImGui::BeginMenu("Examples"))
251         {
252             ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
253             ImGui::MenuItem("Console", NULL, &show_app_console);
254             ImGui::MenuItem("Log", NULL, &show_app_log);
255             ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
256             ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
257             ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
258             ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
259             ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
260             ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
261             ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
262             ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
263             ImGui::EndMenu();
264         }
265         if (ImGui::BeginMenu("Help"))
266         {
267             ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
268             ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
269             ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
270             ImGui::EndMenu();
271         }
272         ImGui::EndMenuBar();
273     }
274 
275     ImGui::Spacing();
276     if (ImGui::CollapsingHeader("Help"))
277     {
278         ImGui::Text("PROGRAMMER GUIDE:");
279         ImGui::BulletText("Please see the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
280         ImGui::BulletText("Please see the comments in imgui.cpp.");
281         ImGui::BulletText("Please see the examples/ in application.");
282         ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
283         ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
284         ImGui::Separator();
285 
286         ImGui::Text("USER GUIDE:");
287         ImGui::ShowUserGuide();
288     }
289 
290     if (ImGui::CollapsingHeader("Configuration"))
291     {
292         ImGuiIO& io = ImGui::GetIO();
293 
294         if (ImGui::TreeNode("Configuration##2"))
295         {
296             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
297             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
298             ImGui::SameLine(); ShowHelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
299             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
300             ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
301             ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
302             if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) // Create a way to restore this flag otherwise we could be stuck completely!
303             {
304                 if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
305                 {
306                     ImGui::SameLine();
307                     ImGui::Text("<<PRESS SPACE TO DISABLE>>");
308                 }
309                 if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
310                     io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
311             }
312             ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
313             ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
314             ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
315             ImGui::SameLine(); ShowHelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
316             ImGui::Checkbox("io.ConfigResizeWindowsFromEdges [beta]", &io.ConfigResizeWindowsFromEdges);
317             ImGui::SameLine(); ShowHelpMarker("Enable resizing of windows from their edges and from the lower-left corner.\nThis requires (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors) because it needs mouse cursor feedback.");
318             ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
319             ImGui::SameLine(); ShowHelpMarker("Instruct Dear ImGui to render a mouse cursor for you. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something).");
320             ImGui::TreePop();
321             ImGui::Separator();
322         }
323 
324         if (ImGui::TreeNode("Backend Flags"))
325         {
326             ImGuiBackendFlags backend_flags = io.BackendFlags; // Make a local copy to avoid modifying the back-end flags.
327             ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasGamepad);
328             ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
329             ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasSetMousePos);
330             ImGui::TreePop();
331             ImGui::Separator();
332         }
333 
334         if (ImGui::TreeNode("Style"))
335         {
336             ImGui::ShowStyleEditor();
337             ImGui::TreePop();
338             ImGui::Separator();
339         }
340 
341         if (ImGui::TreeNode("Capture/Logging"))
342         {
343             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.");
344             ShowHelpMarker("Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
345             ImGui::LogButtons();
346             ImGui::TextWrapped("You can also call ImGui::LogText() to output directly to the log without a visual output.");
347             if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
348             {
349                 ImGui::LogToClipboard();
350                 ImGui::LogText("Hello, world!");
351                 ImGui::LogFinish();
352             }
353             ImGui::TreePop();
354         }
355     }
356 
357     if (ImGui::CollapsingHeader("Window options"))
358     {
359         ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
360         ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
361         ImGui::Checkbox("No menu", &no_menu);
362         ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
363         ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
364         ImGui::Checkbox("No collapse", &no_collapse);
365         ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150);
366         ImGui::Checkbox("No nav", &no_nav); ImGui::SameLine(300);
367         ImGui::Checkbox("No background", &no_background);
368         ImGui::Checkbox("No bring to front", &no_bring_to_front);
369     }
370 
371     if (ImGui::CollapsingHeader("Widgets"))
372     {
373         if (ImGui::TreeNode("Basic"))
374         {
375             static int clicked = 0;
376             if (ImGui::Button("Button"))
377                 clicked++;
378             if (clicked & 1)
379             {
380                 ImGui::SameLine();
381                 ImGui::Text("Thanks for clicking me!");
382             }
383 
384             static bool check = true;
385             ImGui::Checkbox("checkbox", &check);
386 
387             static int e = 0;
388             ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
389             ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
390             ImGui::RadioButton("radio c", &e, 2);
391 
392             // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
393             for (int i = 0; i < 7; i++)
394             {
395                 if (i > 0)
396                     ImGui::SameLine();
397                 ImGui::PushID(i);
398                 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
399                 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
400                 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
401                 ImGui::Button("Click");
402                 ImGui::PopStyleColor(3);
403                 ImGui::PopID();
404             }
405 
406             // Use AlignTextToFramePadding() to align text baseline to the baseline of framed elements (otherwise a Text+SameLine+Button sequence will have the text a little too high by default)
407             ImGui::AlignTextToFramePadding();
408             ImGui::Text("Hold to repeat:");
409             ImGui::SameLine();
410 
411             // Arrow buttons with Repeater
412             static int counter = 0;
413             float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
414             ImGui::PushButtonRepeat(true);
415             if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
416             ImGui::SameLine(0.0f, spacing);
417             if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
418             ImGui::PopButtonRepeat();
419             ImGui::SameLine();
420             ImGui::Text("%d", counter);
421 
422             ImGui::Text("Hover over me");
423             if (ImGui::IsItemHovered())
424                 ImGui::SetTooltip("I am a tooltip");
425 
426             ImGui::SameLine();
427             ImGui::Text("- or me");
428             if (ImGui::IsItemHovered())
429             {
430                 ImGui::BeginTooltip();
431                 ImGui::Text("I am a fancy tooltip");
432                 static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
433                 ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
434                 ImGui::EndTooltip();
435             }
436 
437             ImGui::Separator();
438 
439             ImGui::LabelText("label", "Value");
440 
441             {
442                 // Using the _simplified_ one-liner Combo() api here
443                 // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
444                 const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
445                 static int item_current = 0;
446                 ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
447                 ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
448             }
449 
450             {
451                 static char str0[128] = "Hello, world!";
452                 static int i0 = 123;
453                 ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
454                 ImGui::SameLine(); ShowHelpMarker("USER:\nHold 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\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp).");
455 
456                 ImGui::InputInt("input int", &i0);
457                 ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n  e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
458 
459                 static float f0 = 0.001f;
460                 ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
461 
462                 static double d0 = 999999.00000001;
463                 ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
464 
465                 static float f1 = 1.e10f;
466                 ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
467                 ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n  e.g. \"1e+8\" becomes \"100000000\".\n");
468 
469                 static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
470                 ImGui::InputFloat3("input float3", vec4a);
471             }
472 
473             {
474                 static int i1 = 50, i2 = 42;
475                 ImGui::DragInt("drag int", &i1, 1);
476                 ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
477 
478                 ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%");
479 
480                 static float f1=1.00f, f2=0.0067f;
481                 ImGui::DragFloat("drag float", &f1, 0.005f);
482                 ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
483             }
484 
485             {
486                 static int i1=0;
487                 ImGui::SliderInt("slider int", &i1, -1, 3);
488                 ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
489 
490                 static float f1=0.123f, f2=0.0f;
491                 ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
492                 ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f);
493                 static float angle = 0.0f;
494                 ImGui::SliderAngle("slider angle", &angle);
495             }
496 
497             {
498                 static float col1[3] = { 1.0f,0.0f,0.2f };
499                 static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
500                 ImGui::ColorEdit3("color 1", col1);
501                 ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nClick and hold to use drag and drop.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
502 
503                 ImGui::ColorEdit4("color 2", col2);
504             }
505 
506             {
507                 // List box
508                 const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
509                 static int listbox_item_current = 1;
510                 ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
511 
512                 //static int listbox_item_current2 = 2;
513                 //ImGui::PushItemWidth(-1);
514                 //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
515                 //ImGui::PopItemWidth();
516             }
517 
518             ImGui::TreePop();
519         }
520 
521         // Testing ImGuiOnceUponAFrame helper.
522         //static ImGuiOnceUponAFrame once;
523         //for (int i = 0; i < 5; i++)
524         //    if (once)
525         //        ImGui::Text("This will be displayed only once.");
526 
527         if (ImGui::TreeNode("Trees"))
528         {
529             if (ImGui::TreeNode("Basic trees"))
530             {
531                 for (int i = 0; i < 5; i++)
532                     if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
533                     {
534                         ImGui::Text("blah blah");
535                         ImGui::SameLine();
536                         if (ImGui::SmallButton("button")) { };
537                         ImGui::TreePop();
538                     }
539                 ImGui::TreePop();
540             }
541 
542             if (ImGui::TreeNode("Advanced, with Selectable nodes"))
543             {
544                 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.");
545                 static bool align_label_with_current_x_position = false;
546                 ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
547                 ImGui::Text("Hello!");
548                 if (align_label_with_current_x_position)
549                     ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
550 
551                 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.
552                 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.
553                 ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
554                 for (int i = 0; i < 6; i++)
555                 {
556                     // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
557                     ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
558                     if (i < 3)
559                     {
560                         // Node
561                         bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
562                         if (ImGui::IsItemClicked())
563                             node_clicked = i;
564                         if (node_open)
565                         {
566                             ImGui::Text("Blah blah\nBlah Blah");
567                             ImGui::TreePop();
568                         }
569                     }
570                     else
571                     {
572                         // 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().
573                         node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
574                         ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
575                         if (ImGui::IsItemClicked())
576                             node_clicked = i;
577                     }
578                 }
579                 if (node_clicked != -1)
580                 {
581                     // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
582                     if (ImGui::GetIO().KeyCtrl)
583                         selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
584                     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
585                         selection_mask = (1 << node_clicked);           // Click to single-select
586                 }
587                 ImGui::PopStyleVar();
588                 if (align_label_with_current_x_position)
589                     ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
590                 ImGui::TreePop();
591             }
592             ImGui::TreePop();
593         }
594 
595         if (ImGui::TreeNode("Collapsing Headers"))
596         {
597             static bool closable_group = true;
598             ImGui::Checkbox("Enable extra group", &closable_group);
599             if (ImGui::CollapsingHeader("Header"))
600             {
601                 ImGui::Text("IsItemHovered: %d", IsItemHovered());
602                 for (int i = 0; i < 5; i++)
603                     ImGui::Text("Some content %d", i);
604             }
605             if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
606             {
607                 ImGui::Text("IsItemHovered: %d", IsItemHovered());
608                 for (int i = 0; i < 5; i++)
609                     ImGui::Text("More content %d", i);
610             }
611             ImGui::TreePop();
612         }
613 
614         if (ImGui::TreeNode("Bullets"))
615         {
616             ImGui::BulletText("Bullet point 1");
617             ImGui::BulletText("Bullet point 2\nOn multiple lines");
618             ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
619             ImGui::Bullet(); ImGui::SmallButton("Button");
620             ImGui::TreePop();
621         }
622 
623         if (ImGui::TreeNode("Text"))
624         {
625             if (ImGui::TreeNode("Colored Text"))
626             {
627                 // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
628                 ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
629                 ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
630                 ImGui::TextDisabled("Disabled");
631                 ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
632                 ImGui::TreePop();
633             }
634 
635             if (ImGui::TreeNode("Word Wrapping"))
636             {
637                 // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
638                 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.");
639                 ImGui::Spacing();
640 
641                 static float wrap_width = 200.0f;
642                 ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
643 
644                 ImGui::Text("Test paragraph 1:");
645                 ImVec2 pos = ImGui::GetCursorScreenPos();
646                 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));
647                 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
648                 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);
649                 ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
650                 ImGui::PopTextWrapPos();
651 
652                 ImGui::Text("Test paragraph 2:");
653                 pos = ImGui::GetCursorScreenPos();
654                 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));
655                 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
656                 ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
657                 ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
658                 ImGui::PopTextWrapPos();
659 
660                 ImGui::TreePop();
661             }
662 
663             if (ImGui::TreeNode("UTF-8 Text"))
664             {
665                 // UTF-8 test with Japanese characters
666                 // (Needs a suitable font, try Noto, or Arial Unicode, or M+ fonts. Read misc/fonts/README.txt for details.)
667                 // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
668                 // - 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')
669                 // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.
670                 //   Instead we are encoding a few strings with hexadecimal constants. Don't do this in your application!
671                 //   Please use u8"text in any language" in your application!
672                 // 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.
673                 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. Read misc/fonts/README.txt for details.");
674                 ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
675                 ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
676                 static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
677                 //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
678                 ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
679                 ImGui::TreePop();
680             }
681             ImGui::TreePop();
682         }
683 
684         if (ImGui::TreeNode("Images"))
685         {
686             ImGuiIO& io = ImGui::GetIO();
687             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!");
688 
689             // Here we are grabbing the font texture because that's the only one we have access to inside the demo code.
690             // 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.
691             // 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.
692             // (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.)
693             // 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.
694             // 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.
695             // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
696             ImTextureID my_tex_id = io.Fonts->TexID;
697             float my_tex_w = (float)io.Fonts->TexWidth;
698             float my_tex_h = (float)io.Fonts->TexHeight;
699 
700             ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
701             ImVec2 pos = ImGui::GetCursorScreenPos();
702             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));
703             if (ImGui::IsItemHovered())
704             {
705                 ImGui::BeginTooltip();
706                 float region_sz = 32.0f;
707                 float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; if (region_x < 0.0f) region_x = 0.0f; else if (region_x > my_tex_w - region_sz) region_x = my_tex_w - region_sz;
708                 float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; if (region_y < 0.0f) region_y = 0.0f; else if (region_y > my_tex_h - region_sz) region_y = my_tex_h - region_sz;
709                 float zoom = 4.0f;
710                 ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
711                 ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
712                 ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
713                 ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
714                 ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
715                 ImGui::EndTooltip();
716             }
717             ImGui::TextWrapped("And now some textured buttons..");
718             static int pressed_count = 0;
719             for (int i = 0; i < 8; i++)
720             {
721                 ImGui::PushID(i);
722                 int frame_padding = -1 + i;     // -1 = uses default padding
723                 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)))
724                     pressed_count += 1;
725                 ImGui::PopID();
726                 ImGui::SameLine();
727             }
728             ImGui::NewLine();
729             ImGui::Text("Pressed %d times.", pressed_count);
730             ImGui::TreePop();
731         }
732 
733         if (ImGui::TreeNode("Combo"))
734         {
735             // Expose flags as checkbox for the demo
736             static ImGuiComboFlags flags = 0;
737             ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
738             if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
739                 flags &= ~ImGuiComboFlags_NoPreview;     // Clear the other flag, as we cannot combine both
740             if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
741                 flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both
742 
743             // General BeginCombo() API, you have full control over your selection data and display type.
744             // (your selection data could be an index, a pointer to the object, an id for the object, a flag stored in the object itself, etc.)
745             const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
746             static const char* item_current = items[0];            // Here our selection is a single pointer stored outside the object.
747             if (ImGui::BeginCombo("combo 1", item_current, flags)) // The second parameter is the label previewed before opening the combo.
748             {
749                 for (int n = 0; n < IM_ARRAYSIZE(items); n++)
750                 {
751                     bool is_selected = (item_current == items[n]);
752                     if (ImGui::Selectable(items[n], is_selected))
753                         item_current = items[n];
754                     if (is_selected)
755                         ImGui::SetItemDefaultFocus();   // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
756                 }
757                 ImGui::EndCombo();
758             }
759 
760             // Simplified one-liner Combo() API, using values packed in a single constant string
761             static int item_current_2 = 0;
762             ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
763 
764             // Simplified one-liner Combo() using an array of const char*
765             static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
766             ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
767 
768             // Simplified one-liner Combo() using an accessor function
769             struct FuncHolder { static bool ItemGetter(void* data, int idx, const char** out_str) { *out_str = ((const char**)data)[idx]; return true; } };
770             static int item_current_4 = 0;
771             ImGui::Combo("combo 4 (function)", &item_current_4, &FuncHolder::ItemGetter, items, IM_ARRAYSIZE(items));
772 
773             ImGui::TreePop();
774         }
775 
776         if (ImGui::TreeNode("Selectables"))
777         {
778             // Selectable() has 2 overloads:
779             // - The one taking "bool selected" as a read-only selection information. When Selectable() has been clicked is returns true and you can alter selection state accordingly.
780             // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
781             // The earlier is more flexible, as in real application your selection may be stored in a different manner (in flags within objects, as an external list, etc).
782             if (ImGui::TreeNode("Basic"))
783             {
784                 static bool selection[5] = { false, true, false, false, false };
785                 ImGui::Selectable("1. I am selectable", &selection[0]);
786                 ImGui::Selectable("2. I am selectable", &selection[1]);
787                 ImGui::Text("3. I am not selectable");
788                 ImGui::Selectable("4. I am selectable", &selection[3]);
789                 if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
790                     if (ImGui::IsMouseDoubleClicked(0))
791                         selection[4] = !selection[4];
792                 ImGui::TreePop();
793             }
794             if (ImGui::TreeNode("Selection State: Single Selection"))
795             {
796                 static int selected = -1;
797                 for (int n = 0; n < 5; n++)
798                 {
799                     char buf[32];
800                     sprintf(buf, "Object %d", n);
801                     if (ImGui::Selectable(buf, selected == n))
802                         selected = n;
803                 }
804                 ImGui::TreePop();
805             }
806             if (ImGui::TreeNode("Selection State: Multiple Selection"))
807             {
808                 ShowHelpMarker("Hold CTRL and click to select multiple items.");
809                 static bool selection[5] = { false, false, false, false, false };
810                 for (int n = 0; n < 5; n++)
811                 {
812                     char buf[32];
813                     sprintf(buf, "Object %d", n);
814                     if (ImGui::Selectable(buf, selection[n]))
815                     {
816                         if (!ImGui::GetIO().KeyCtrl)    // Clear selection when CTRL is not held
817                             memset(selection, 0, sizeof(selection));
818                         selection[n] ^= 1;
819                     }
820                 }
821                 ImGui::TreePop();
822             }
823             if (ImGui::TreeNode("Rendering more text into the same line"))
824             {
825                 // Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically.
826                 static bool selected[3] = { false, false, false };
827                 ImGui::Selectable("main.c",    &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
828                 ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
829                 ImGui::Selectable("Hello.h",   &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
830                 ImGui::TreePop();
831             }
832             if (ImGui::TreeNode("In columns"))
833             {
834                 ImGui::Columns(3, NULL, false);
835                 static bool selected[16] = { 0 };
836                 for (int i = 0; i < 16; i++)
837                 {
838                     char label[32]; sprintf(label, "Item %d", i);
839                     if (ImGui::Selectable(label, &selected[i])) {}
840                     ImGui::NextColumn();
841                 }
842                 ImGui::Columns(1);
843                 ImGui::TreePop();
844             }
845             if (ImGui::TreeNode("Grid"))
846             {
847                 static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
848                 for (int i = 0; i < 16; i++)
849                 {
850                     ImGui::PushID(i);
851                     if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50)))
852                     {
853                         int x = i % 4, y = i / 4;
854                         if (x > 0) selected[i - 1] ^= 1;
855                         if (x < 3) selected[i + 1] ^= 1;
856                         if (y > 0) selected[i - 4] ^= 1;
857                         if (y < 3) selected[i + 4] ^= 1;
858                     }
859                     if ((i % 4) < 3) ImGui::SameLine();
860                     ImGui::PopID();
861                 }
862                 ImGui::TreePop();
863             }
864             ImGui::TreePop();
865         }
866 
867         if (ImGui::TreeNode("Filtered Text Input"))
868         {
869             static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
870             static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
871             static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
872             static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
873             static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
874             struct TextFilters { static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
875             static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
876 
877             ImGui::Text("Password input");
878             static char bufpass[64] = "password123";
879             ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
880             ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
881             ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
882 
883             ImGui::TreePop();
884         }
885 
886         if (ImGui::TreeNode("Multi-line Text Input"))
887         {
888             static bool read_only = false;
889             static char text[1024*16] =
890                 "/*\n"
891                 " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
892                 " the hexadecimal encoding of one offending instruction,\n"
893                 " more formally, the invalid operand with locked CMPXCHG8B\n"
894                 " instruction bug, is a design flaw in the majority of\n"
895                 " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
896                 " processors (all in the P5 microarchitecture).\n"
897                 "*/\n\n"
898                 "label:\n"
899                 "\tlock cmpxchg8b eax\n";
900 
901             ShowHelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp)");
902             ImGui::Checkbox("Read-only", &read_only);
903             ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0);
904             ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), flags);
905             ImGui::TreePop();
906         }
907 
908         if (ImGui::TreeNode("Plots Widgets"))
909         {
910             static bool animate = true;
911             ImGui::Checkbox("Animate", &animate);
912 
913             static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
914             ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
915 
916             // Create a dummy array of contiguous float values to plot
917             // 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.
918             static float values[90] = { 0 };
919             static int values_offset = 0;
920             static double refresh_time = 0.0;
921             if (!animate || refresh_time == 0.0f)
922                 refresh_time = ImGui::GetTime();
923             while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo
924             {
925                 static float phase = 0.0f;
926                 values[values_offset] = cosf(phase);
927                 values_offset = (values_offset+1) % IM_ARRAYSIZE(values);
928                 phase += 0.10f*values_offset;
929                 refresh_time += 1.0f/60.0f;
930             }
931             ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
932             ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));
933 
934             // Use functions to generate output
935             // 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.
936             struct Funcs
937             {
938                 static float Sin(void*, int i) { return sinf(i * 0.1f); }
939                 static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
940             };
941             static int func_type = 0, display_count = 70;
942             ImGui::Separator();
943             ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
944             ImGui::SameLine();
945             ImGui::SliderInt("Sample count", &display_count, 1, 400);
946             float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
947             ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
948             ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
949             ImGui::Separator();
950 
951             // Animate a simple progress bar
952             static float progress = 0.0f, progress_dir = 1.0f;
953             if (animate)
954             {
955                 progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
956                 if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
957                 if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
958             }
959 
960             // 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.
961             ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
962             ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
963             ImGui::Text("Progress Bar");
964 
965             float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
966             char buf[32];
967             sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
968             ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
969             ImGui::TreePop();
970         }
971 
972         if (ImGui::TreeNode("Color/Picker Widgets"))
973         {
974             static ImVec4 color = ImColor(114, 144, 154, 200);
975 
976             static bool alpha_preview = true;
977             static bool alpha_half_preview = false;
978             static bool drag_and_drop = true;
979             static bool options_menu = true;
980             static bool hdr = false;
981             ImGui::Checkbox("With Alpha Preview", &alpha_preview);
982             ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
983             ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
984             ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
985             ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
986             int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (drag_and_drop ? 0 : ImGuiColorEditFlags_NoDragDrop) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
987 
988             ImGui::Text("Color widget:");
989             ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
990             ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
991 
992             ImGui::Text("Color widget HSV with Alpha:");
993             ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
994 
995             ImGui::Text("Color widget with Float Display:");
996             ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
997 
998             ImGui::Text("Color button with Picker:");
999             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.");
1000             ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
1001 
1002             ImGui::Text("Color button with Custom Picker Popup:");
1003 
1004             // Generate a dummy palette
1005             static bool saved_palette_inited = false;
1006             static ImVec4 saved_palette[32];
1007             if (!saved_palette_inited)
1008                 for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1009                 {
1010                     ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
1011                     saved_palette[n].w = 1.0f; // Alpha
1012                 }
1013             saved_palette_inited = true;
1014 
1015             static ImVec4 backup_color;
1016             bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
1017             ImGui::SameLine();
1018             open_popup |= ImGui::Button("Palette");
1019             if (open_popup)
1020             {
1021                 ImGui::OpenPopup("mypicker");
1022                 backup_color = color;
1023             }
1024             if (ImGui::BeginPopup("mypicker"))
1025             {
1026                 // FIXME: Adding a drag and drop example here would be perfect!
1027                 ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
1028                 ImGui::Separator();
1029                 ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
1030                 ImGui::SameLine();
1031                 ImGui::BeginGroup();
1032                 ImGui::Text("Current");
1033                 ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40));
1034                 ImGui::Text("Previous");
1035                 if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)))
1036                     color = backup_color;
1037                 ImGui::Separator();
1038                 ImGui::Text("Palette");
1039                 for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1040                 {
1041                     ImGui::PushID(n);
1042                     if ((n % 8) != 0)
1043                         ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
1044                     if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20)))
1045                         color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
1046 
1047                     if (ImGui::BeginDragDropTarget())
1048                     {
1049                         if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
1050                             memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
1051                         if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
1052                             memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
1053                         EndDragDropTarget();
1054                     }
1055 
1056                     ImGui::PopID();
1057                 }
1058                 ImGui::EndGroup();
1059                 ImGui::EndPopup();
1060             }
1061 
1062             ImGui::Text("Color button only:");
1063             ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80));
1064 
1065             ImGui::Text("Color picker:");
1066             static bool alpha = true;
1067             static bool alpha_bar = true;
1068             static bool side_preview = true;
1069             static bool ref_color = false;
1070             static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);
1071             static int inputs_mode = 2;
1072             static int picker_mode = 0;
1073             ImGui::Checkbox("With Alpha", &alpha);
1074             ImGui::Checkbox("With Alpha Bar", &alpha_bar);
1075             ImGui::Checkbox("With Side Preview", &side_preview);
1076             if (side_preview)
1077             {
1078                 ImGui::SameLine();
1079                 ImGui::Checkbox("With Ref Color", &ref_color);
1080                 if (ref_color)
1081                 {
1082                     ImGui::SameLine();
1083                     ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
1084                 }
1085             }
1086             ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
1087             ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
1088             ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
1089             ImGuiColorEditFlags flags = misc_flags;
1090             if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
1091             if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
1092             if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
1093             if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
1094             if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
1095             if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;
1096             if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;
1097             if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;
1098             if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;
1099             ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
1100 
1101             ImGui::Text("Programmatically set defaults:");
1102             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.");
1103             if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
1104                 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV | ImGuiColorEditFlags_PickerHueBar);
1105             if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
1106                 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
1107 
1108             ImGui::TreePop();
1109         }
1110 
1111         if (ImGui::TreeNode("Range Widgets"))
1112         {
1113             static float begin = 10, end = 90;
1114             static int begin_i = 100, end_i = 1000;
1115             ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
1116             ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
1117             ImGui::TreePop();
1118         }
1119 
1120         if (ImGui::TreeNode("Data Types"))
1121         {
1122             // The DragScalar/InputScalar/SliderScalar functions allow various data types: signed/unsigned int/long long and float/double
1123             // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type,
1124             // and passing all arguments by address.
1125             // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
1126             // In practice, if you frequently use a given type that is not covered by the normal API entry points, you can wrap it
1127             // yourself inside a 1 line function which can take typed argument as value instead of void*, and then pass their address
1128             // to the generic function. For example:
1129             //   bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
1130             //   {
1131             //      return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
1132             //   }
1133 
1134             // Limits (as helper variables that we can take the address of)
1135             // Note that the SliderScalar function has a maximum usable range of half the natural type maximum, hence the /2 below.
1136             #ifndef LLONG_MIN
1137             ImS64 LLONG_MIN = -9223372036854775807LL - 1;
1138             ImS64 LLONG_MAX = 9223372036854775807LL;
1139             ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
1140             #endif
1141             const ImS32   s32_zero = 0,   s32_one = 1,   s32_fifty = 50, s32_min = INT_MIN/2,   s32_max = INT_MAX/2,    s32_hi_a = INT_MAX/2 - 100,    s32_hi_b = INT_MAX/2;
1142             const ImU32   u32_zero = 0,   u32_one = 1,   u32_fifty = 50, u32_min = 0,           u32_max = UINT_MAX/2,   u32_hi_a = UINT_MAX/2 - 100,   u32_hi_b = UINT_MAX/2;
1143             const ImS64   s64_zero = 0,   s64_one = 1,   s64_fifty = 50, s64_min = LLONG_MIN/2, s64_max = LLONG_MAX/2,  s64_hi_a = LLONG_MAX/2 - 100,  s64_hi_b = LLONG_MAX/2;
1144             const ImU64   u64_zero = 0,   u64_one = 1,   u64_fifty = 50, u64_min = 0,           u64_max = ULLONG_MAX/2, u64_hi_a = ULLONG_MAX/2 - 100, u64_hi_b = ULLONG_MAX/2;
1145             const float   f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
1146             const double  f64_zero = 0.,  f64_one = 1.,  f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
1147 
1148             // State
1149             static ImS32  s32_v = -1;
1150             static ImU32  u32_v = (ImU32)-1;
1151             static ImS64  s64_v = -1;
1152             static ImU64  u64_v = (ImU64)-1;
1153             static float  f32_v = 0.123f;
1154             static double f64_v = 90000.01234567890123456789;
1155 
1156             const float drag_speed = 0.2f;
1157             static bool drag_clamp = false;
1158             ImGui::Text("Drags:");
1159             ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); ImGui::SameLine(); ShowHelpMarker("As with every widgets in dear imgui, we never modify values unless there is a user interaction.\nYou can override the clamping limits by using CTRL+Click to input a value.");
1160             ImGui::DragScalar("drag s32",       ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
1161             ImGui::DragScalar("drag u32",       ImGuiDataType_U32,    &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
1162             ImGui::DragScalar("drag s64",       ImGuiDataType_S64,    &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
1163             ImGui::DragScalar("drag u64",       ImGuiDataType_U64,    &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
1164             ImGui::DragScalar("drag float",     ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", 1.0f);
1165             ImGui::DragScalar("drag float ^2",  ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", 2.0f); ImGui::SameLine(); ShowHelpMarker("You can use the 'power' parameter to increase tweaking precision on one side of the range.");
1166             ImGui::DragScalar("drag double",    ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL,     "%.10f grams", 1.0f);
1167             ImGui::DragScalar("drag double ^2", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", 2.0f);
1168 
1169             ImGui::Text("Sliders");
1170             ImGui::SliderScalar("slider s32 low",     ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty,"%d");
1171             ImGui::SliderScalar("slider s32 high",    ImGuiDataType_S32,    &s32_v, &s32_hi_a, &s32_hi_b, "%d");
1172             ImGui::SliderScalar("slider s32 full",    ImGuiDataType_S32,    &s32_v, &s32_min,  &s32_max,  "%d");
1173             ImGui::SliderScalar("slider u32 low",     ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u");
1174             ImGui::SliderScalar("slider u32 high",    ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u");
1175             ImGui::SliderScalar("slider u32 full",    ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u");
1176             ImGui::SliderScalar("slider s64 low",     ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%I64d");
1177             ImGui::SliderScalar("slider s64 high",    ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%I64d");
1178             ImGui::SliderScalar("slider s64 full",    ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%I64d");
1179             ImGui::SliderScalar("slider u64 low",     ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%I64u ms");
1180             ImGui::SliderScalar("slider u64 high",    ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms");
1181             ImGui::SliderScalar("slider u64 full",    ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%I64u ms");
1182             ImGui::SliderScalar("slider float low",   ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one);
1183             ImGui::SliderScalar("slider float low^2", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", 2.0f);
1184             ImGui::SliderScalar("slider float high",  ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e");
1185             ImGui::SliderScalar("slider double low",  ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f grams", 1.0f);
1186             ImGui::SliderScalar("slider double low^2",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", 2.0f);
1187             ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams", 1.0f);
1188 
1189             static bool inputs_step = true;
1190             ImGui::Text("Inputs");
1191             ImGui::Checkbox("Show step buttons", &inputs_step);
1192             ImGui::InputScalar("input s32",     ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
1193             ImGui::InputScalar("input s32 hex", ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1194             ImGui::InputScalar("input u32",     ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
1195             ImGui::InputScalar("input u32 hex", ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1196             ImGui::InputScalar("input s64",     ImGuiDataType_S64,    &s64_v, inputs_step ? &s64_one : NULL);
1197             ImGui::InputScalar("input u64",     ImGuiDataType_U64,    &u64_v, inputs_step ? &u64_one : NULL);
1198             ImGui::InputScalar("input float",   ImGuiDataType_Float,  &f32_v, inputs_step ? &f32_one : NULL);
1199             ImGui::InputScalar("input double",  ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
1200 
1201             ImGui::TreePop();
1202         }
1203 
1204         if (ImGui::TreeNode("Multi-component Widgets"))
1205         {
1206             static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
1207             static int vec4i[4] = { 1, 5, 100, 255 };
1208 
1209             ImGui::InputFloat2("input float2", vec4f);
1210             ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
1211             ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
1212             ImGui::InputInt2("input int2", vec4i);
1213             ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
1214             ImGui::SliderInt2("slider int2", vec4i, 0, 255);
1215             ImGui::Spacing();
1216 
1217             ImGui::InputFloat3("input float3", vec4f);
1218             ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
1219             ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
1220             ImGui::InputInt3("input int3", vec4i);
1221             ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
1222             ImGui::SliderInt3("slider int3", vec4i, 0, 255);
1223             ImGui::Spacing();
1224 
1225             ImGui::InputFloat4("input float4", vec4f);
1226             ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
1227             ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
1228             ImGui::InputInt4("input int4", vec4i);
1229             ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
1230             ImGui::SliderInt4("slider int4", vec4i, 0, 255);
1231 
1232             ImGui::TreePop();
1233         }
1234 
1235         if (ImGui::TreeNode("Vertical Sliders"))
1236         {
1237             const float spacing = 4;
1238             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1239 
1240             static int int_value = 0;
1241             ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
1242             ImGui::SameLine();
1243 
1244             static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
1245             ImGui::PushID("set1");
1246             for (int i = 0; i < 7; i++)
1247             {
1248                 if (i > 0) ImGui::SameLine();
1249                 ImGui::PushID(i);
1250                 ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));
1251                 ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));
1252                 ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));
1253                 ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));
1254                 ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
1255                 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1256                     ImGui::SetTooltip("%.3f", values[i]);
1257                 ImGui::PopStyleColor(4);
1258                 ImGui::PopID();
1259             }
1260             ImGui::PopID();
1261 
1262             ImGui::SameLine();
1263             ImGui::PushID("set2");
1264             static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
1265             const int rows = 3;
1266             const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);
1267             for (int nx = 0; nx < 4; nx++)
1268             {
1269                 if (nx > 0) ImGui::SameLine();
1270                 ImGui::BeginGroup();
1271                 for (int ny = 0; ny < rows; ny++)
1272                 {
1273                     ImGui::PushID(nx*rows+ny);
1274                     ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
1275                     if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1276                         ImGui::SetTooltip("%.3f", values2[nx]);
1277                     ImGui::PopID();
1278                 }
1279                 ImGui::EndGroup();
1280             }
1281             ImGui::PopID();
1282 
1283             ImGui::SameLine();
1284             ImGui::PushID("set3");
1285             for (int i = 0; i < 4; i++)
1286             {
1287                 if (i > 0) ImGui::SameLine();
1288                 ImGui::PushID(i);
1289                 ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
1290                 ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
1291                 ImGui::PopStyleVar();
1292                 ImGui::PopID();
1293             }
1294             ImGui::PopID();
1295             ImGui::PopStyleVar();
1296             ImGui::TreePop();
1297         }
1298 
1299         if (ImGui::TreeNode("Drag and Drop"))
1300         {
1301             {
1302                 // ColorEdit widgets automatically act as drag source and drag target.
1303                 // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets
1304                 // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo.
1305                 ImGui::BulletText("Drag and drop in standard widgets");
1306                 ImGui::Indent();
1307                 static float col1[3] = { 1.0f,0.0f,0.2f };
1308                 static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
1309                 ImGui::ColorEdit3("color 1", col1);
1310                 ImGui::ColorEdit4("color 2", col2);
1311                 ImGui::Unindent();
1312             }
1313 
1314             {
1315                 ImGui::BulletText("Drag and drop to copy/swap items");
1316                 ImGui::Indent();
1317                 enum Mode
1318                 {
1319                     Mode_Copy,
1320                     Mode_Move,
1321                     Mode_Swap
1322                 };
1323                 static int mode = 0;
1324                 if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
1325                 if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
1326                 if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
1327                 static const char* names[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", "Bibi", "Blaine", "Bryn" };
1328                 for (int n = 0; n < IM_ARRAYSIZE(names); n++)
1329                 {
1330                     ImGui::PushID(n);
1331                     if ((n % 3) != 0)
1332                         ImGui::SameLine();
1333                     ImGui::Button(names[n], ImVec2(60,60));
1334 
1335                     // Our buttons are both drag sources and drag targets here!
1336                     if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
1337                     {
1338                         ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));        // Set payload to carry the index of our item (could be anything)
1339                         if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }        // Display preview (could be anything, e.g. when dragging an image we could decide to display the filename and a small preview of the image, etc.)
1340                         if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
1341                         if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
1342                         ImGui::EndDragDropSource();
1343                     }
1344                     if (ImGui::BeginDragDropTarget())
1345                     {
1346                         if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
1347                         {
1348                             IM_ASSERT(payload->DataSize == sizeof(int));
1349                             int payload_n = *(const int*)payload->Data;
1350                             if (mode == Mode_Copy)
1351                             {
1352                                 names[n] = names[payload_n];
1353                             }
1354                             if (mode == Mode_Move)
1355                             {
1356                                 names[n] = names[payload_n];
1357                                 names[payload_n] = "";
1358                             }
1359                             if (mode == Mode_Swap)
1360                             {
1361                                 const char* tmp = names[n];
1362                                 names[n] = names[payload_n];
1363                                 names[payload_n] = tmp;
1364                             }
1365                         }
1366                         ImGui::EndDragDropTarget();
1367                     }
1368                     ImGui::PopID();
1369                 }
1370                 ImGui::Unindent();
1371             }
1372 
1373             ImGui::TreePop();
1374         }
1375 
1376         if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)"))
1377         {
1378             // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined.
1379             // (because BulletText is an item itself and that would affect the output of IsItemHovered() we pass all state in a single call to simplify the code).
1380             static int item_type = 1;
1381             static bool b = false;
1382             static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
1383             ImGui::RadioButton("Text", &item_type, 0);
1384             ImGui::RadioButton("Button", &item_type, 1);
1385             ImGui::RadioButton("CheckBox", &item_type, 2);
1386             ImGui::RadioButton("SliderFloat", &item_type, 3);
1387             ImGui::RadioButton("ColorEdit4", &item_type, 4);
1388             ImGui::RadioButton("ListBox", &item_type, 5);
1389             ImGui::Separator();
1390             bool ret = false;
1391             if (item_type == 0) { ImGui::Text("ITEM: Text"); }                                              // Testing text items with no identifier/interaction
1392             if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); }                                    // Testing button
1393             if (item_type == 2) { ret = ImGui::Checkbox("ITEM: CheckBox", &b); }                            // Testing checkbox
1394             if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
1395             if (item_type == 4) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
1396             if (item_type == 5) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
1397             ImGui::BulletText(
1398                 "Return value = %d\n"
1399                 "IsItemFocused() = %d\n"
1400                 "IsItemHovered() = %d\n"
1401                 "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
1402                 "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1403                 "IsItemHovered(_AllowWhenOverlapped) = %d\n"
1404                 "IsItemHovered(_RectOnly) = %d\n"
1405                 "IsItemActive() = %d\n"
1406                 "IsItemEdited() = %d\n"
1407                 "IsItemDeactivated() = %d\n"
1408                 "IsItemDeactivatedEdit() = %d\n"
1409                 "IsItemVisible() = %d\n"
1410                 "GetItemRectMin() = (%.1f, %.1f)\n"
1411                 "GetItemRectMax() = (%.1f, %.1f)\n"
1412                 "GetItemRectSize() = (%.1f, %.1f)",
1413                 ret,
1414                 ImGui::IsItemFocused(),
1415                 ImGui::IsItemHovered(),
1416                 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1417                 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1418                 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
1419                 ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
1420                 ImGui::IsItemActive(),
1421                 ImGui::IsItemEdited(),
1422                 ImGui::IsItemDeactivated(),
1423                 ImGui::IsItemDeactivatedAfterEdit(),
1424                 ImGui::IsItemVisible(),
1425                 ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
1426                 ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
1427                 ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
1428             );
1429 
1430             static bool embed_all_inside_a_child_window = false;
1431             ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
1432             if (embed_all_inside_a_child_window)
1433                 ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true);
1434 
1435             // Testing IsWindowFocused() function with its various flags. Note that the flags can be combined.
1436             ImGui::BulletText(
1437                 "IsWindowFocused() = %d\n"
1438                 "IsWindowFocused(_ChildWindows) = %d\n"
1439                 "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
1440                 "IsWindowFocused(_RootWindow) = %d\n"
1441                 "IsWindowFocused(_AnyWindow) = %d\n",
1442                 ImGui::IsWindowFocused(),
1443                 ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
1444                 ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
1445                 ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
1446                 ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
1447 
1448             // Testing IsWindowHovered() function with its various flags. Note that the flags can be combined.
1449             ImGui::BulletText(
1450                 "IsWindowHovered() = %d\n"
1451                 "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
1452                 "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1453                 "IsWindowHovered(_ChildWindows) = %d\n"
1454                 "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
1455                 "IsWindowHovered(_RootWindow) = %d\n"
1456                 "IsWindowHovered(_AnyWindow) = %d\n",
1457                 ImGui::IsWindowHovered(),
1458                 ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1459                 ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1460                 ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
1461                 ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
1462                 ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
1463                 ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
1464 
1465             ImGui::BeginChild("child", ImVec2(0, 50), true);
1466             ImGui::Text("This is another child window for testing with the _ChildWindows flag.");
1467             ImGui::EndChild();
1468             if (embed_all_inside_a_child_window)
1469                 EndChild();
1470 
1471             // Calling IsItemHovered() after begin returns the hovered status of the title bar.
1472             // This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window.
1473             static bool test_window = false;
1474             ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
1475             if (test_window)
1476             {
1477                 ImGui::Begin("Title bar Hovered/Active tests", &test_window);
1478                 if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
1479                 {
1480                     if (ImGui::MenuItem("Close")) { test_window = false; }
1481                     ImGui::EndPopup();
1482                 }
1483                 ImGui::Text(
1484                     "IsItemHovered() after begin = %d (== is title bar hovered)\n"
1485                     "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
1486                     ImGui::IsItemHovered(), ImGui::IsItemActive());
1487                 ImGui::End();
1488             }
1489 
1490             ImGui::TreePop();
1491         }
1492     }
1493 
1494     if (ImGui::CollapsingHeader("Layout"))
1495     {
1496         if (ImGui::TreeNode("Child regions"))
1497         {
1498             static bool disable_mouse_wheel = false;
1499             static bool disable_menu = false;
1500             ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
1501             ImGui::Checkbox("Disable Menu", &disable_menu);
1502 
1503             static int line = 50;
1504             bool goto_line = ImGui::Button("Goto");
1505             ImGui::SameLine();
1506             ImGui::PushItemWidth(100);
1507             goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
1508             ImGui::PopItemWidth();
1509 
1510             // Child 1: no border, enable horizontal scrollbar
1511             {
1512                 ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0));
1513                 for (int i = 0; i < 100; i++)
1514                 {
1515                     ImGui::Text("%04d: scrollable region", i);
1516                     if (goto_line && line == i)
1517                         ImGui::SetScrollHereY();
1518                 }
1519                 if (goto_line && line >= 100)
1520                     ImGui::SetScrollHereY();
1521                 ImGui::EndChild();
1522             }
1523 
1524             ImGui::SameLine();
1525 
1526             // Child 2: rounded border
1527             {
1528                 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
1529                 ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar));
1530                 if (!disable_menu && ImGui::BeginMenuBar())
1531                 {
1532                     if (ImGui::BeginMenu("Menu"))
1533                     {
1534                         ShowExampleMenuFile();
1535                         ImGui::EndMenu();
1536                     }
1537                     ImGui::EndMenuBar();
1538                 }
1539                 ImGui::Columns(2);
1540                 for (int i = 0; i < 100; i++)
1541                 {
1542                     char buf[32];
1543                     sprintf(buf, "%03d", i);
1544                     ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
1545                     ImGui::NextColumn();
1546                 }
1547                 ImGui::EndChild();
1548                 ImGui::PopStyleVar();
1549             }
1550 
1551             ImGui::TreePop();
1552         }
1553 
1554         if (ImGui::TreeNode("Widgets Width"))
1555         {
1556             static float f = 0.0f;
1557             ImGui::Text("PushItemWidth(100)");
1558             ImGui::SameLine(); ShowHelpMarker("Fixed width.");
1559             ImGui::PushItemWidth(100);
1560             ImGui::DragFloat("float##1", &f);
1561             ImGui::PopItemWidth();
1562 
1563             ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
1564             ImGui::SameLine(); ShowHelpMarker("Half of window width.");
1565             ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
1566             ImGui::DragFloat("float##2", &f);
1567             ImGui::PopItemWidth();
1568 
1569             ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
1570             ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
1571             ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
1572             ImGui::DragFloat("float##3", &f);
1573             ImGui::PopItemWidth();
1574 
1575             ImGui::Text("PushItemWidth(-100)");
1576             ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
1577             ImGui::PushItemWidth(-100);
1578             ImGui::DragFloat("float##4", &f);
1579             ImGui::PopItemWidth();
1580 
1581             ImGui::Text("PushItemWidth(-1)");
1582             ImGui::SameLine(); ShowHelpMarker("Align to right edge");
1583             ImGui::PushItemWidth(-1);
1584             ImGui::DragFloat("float##5", &f);
1585             ImGui::PopItemWidth();
1586 
1587             ImGui::TreePop();
1588         }
1589 
1590         if (ImGui::TreeNode("Basic Horizontal Layout"))
1591         {
1592             ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1593 
1594             // Text
1595             ImGui::Text("Two items: Hello"); ImGui::SameLine();
1596             ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1597 
1598             // Adjust spacing
1599             ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
1600             ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1601 
1602             // Button
1603             ImGui::AlignTextToFramePadding();
1604             ImGui::Text("Normal buttons"); ImGui::SameLine();
1605             ImGui::Button("Banana"); ImGui::SameLine();
1606             ImGui::Button("Apple"); ImGui::SameLine();
1607             ImGui::Button("Corniflower");
1608 
1609             // Button
1610             ImGui::Text("Small buttons"); ImGui::SameLine();
1611             ImGui::SmallButton("Like this one"); ImGui::SameLine();
1612             ImGui::Text("can fit within a text block.");
1613 
1614             // Aligned to arbitrary position. Easy/cheap column.
1615             ImGui::Text("Aligned");
1616             ImGui::SameLine(150); ImGui::Text("x=150");
1617             ImGui::SameLine(300); ImGui::Text("x=300");
1618             ImGui::Text("Aligned");
1619             ImGui::SameLine(150); ImGui::SmallButton("x=150");
1620             ImGui::SameLine(300); ImGui::SmallButton("x=300");
1621 
1622             // Checkbox
1623             static bool c1=false,c2=false,c3=false,c4=false;
1624             ImGui::Checkbox("My", &c1); ImGui::SameLine();
1625             ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
1626             ImGui::Checkbox("Is", &c3); ImGui::SameLine();
1627             ImGui::Checkbox("Rich", &c4);
1628 
1629             // Various
1630             static float f0=1.0f, f1=2.0f, f2=3.0f;
1631             ImGui::PushItemWidth(80);
1632             const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
1633             static int item = -1;
1634             ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
1635             ImGui::SliderFloat("X", &f0, 0.0f,5.0f); ImGui::SameLine();
1636             ImGui::SliderFloat("Y", &f1, 0.0f,5.0f); ImGui::SameLine();
1637             ImGui::SliderFloat("Z", &f2, 0.0f,5.0f);
1638             ImGui::PopItemWidth();
1639 
1640             ImGui::PushItemWidth(80);
1641             ImGui::Text("Lists:");
1642             static int selection[4] = { 0, 1, 2, 3 };
1643             for (int i = 0; i < 4; i++)
1644             {
1645                 if (i > 0) ImGui::SameLine();
1646                 ImGui::PushID(i);
1647                 ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
1648                 ImGui::PopID();
1649                 //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
1650             }
1651             ImGui::PopItemWidth();
1652 
1653             // Dummy
1654             ImVec2 button_sz(40,40);
1655             ImGui::Button("A", button_sz); ImGui::SameLine();
1656             ImGui::Dummy(button_sz); ImGui::SameLine();
1657             ImGui::Button("B", button_sz);
1658 
1659             // Manually wrapping (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
1660             ImGui::Text("Manually wrapping:");
1661             ImGuiStyle& style = ImGui::GetStyle();
1662             int buttons_count = 20;
1663             float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
1664             for (int n = 0; n < buttons_count; n++)
1665             {
1666                 ImGui::PushID(n);
1667                 ImGui::Button("Box", button_sz);
1668                 float last_button_x2 = ImGui::GetItemRectMax().x;
1669                 float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
1670                 if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
1671                     ImGui::SameLine();
1672                 ImGui::PopID();
1673             }
1674 
1675             ImGui::TreePop();
1676         }
1677 
1678         if (ImGui::TreeNode("Groups"))
1679         {
1680             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.)");
1681             ImGui::BeginGroup();
1682             {
1683                 ImGui::BeginGroup();
1684                 ImGui::Button("AAA");
1685                 ImGui::SameLine();
1686                 ImGui::Button("BBB");
1687                 ImGui::SameLine();
1688                 ImGui::BeginGroup();
1689                 ImGui::Button("CCC");
1690                 ImGui::Button("DDD");
1691                 ImGui::EndGroup();
1692                 ImGui::SameLine();
1693                 ImGui::Button("EEE");
1694                 ImGui::EndGroup();
1695                 if (ImGui::IsItemHovered())
1696                     ImGui::SetTooltip("First group hovered");
1697             }
1698             // Capture the group size and create widgets using the same size
1699             ImVec2 size = ImGui::GetItemRectSize();
1700             const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
1701             ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
1702 
1703             ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
1704             ImGui::SameLine();
1705             ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f,size.y));
1706             ImGui::EndGroup();
1707             ImGui::SameLine();
1708 
1709             ImGui::Button("LEVERAGE\nBUZZWORD", size);
1710             ImGui::SameLine();
1711 
1712             if (ImGui::ListBoxHeader("List", size))
1713             {
1714                 ImGui::Selectable("Selected", true);
1715                 ImGui::Selectable("Not Selected", false);
1716                 ImGui::ListBoxFooter();
1717             }
1718 
1719             ImGui::TreePop();
1720         }
1721 
1722         if (ImGui::TreeNode("Text Baseline Alignment"))
1723         {
1724             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)");
1725 
1726             ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
1727             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1728             ImGui::Text("Banana");
1729 
1730             ImGui::Text("Banana"); ImGui::SameLine();
1731             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1732             ImGui::Text("One\nTwo\nThree");
1733 
1734             ImGui::Button("HOP##1"); ImGui::SameLine();
1735             ImGui::Text("Banana"); ImGui::SameLine();
1736             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1737             ImGui::Text("Banana");
1738 
1739             ImGui::Button("HOP##2"); ImGui::SameLine();
1740             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1741             ImGui::Text("Banana");
1742 
1743             ImGui::Button("TEST##1"); ImGui::SameLine();
1744             ImGui::Text("TEST"); ImGui::SameLine();
1745             ImGui::SmallButton("TEST##2");
1746 
1747             ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets.
1748             ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
1749             ImGui::Button("Widget##1"); ImGui::SameLine();
1750             ImGui::Text("Widget"); ImGui::SameLine();
1751             ImGui::SmallButton("Widget##2"); ImGui::SameLine();
1752             ImGui::Button("Widget##3");
1753 
1754             // Tree
1755             const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
1756             ImGui::Button("Button##1");
1757             ImGui::SameLine(0.0f, spacing);
1758             if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }    // Dummy tree data
1759 
1760             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).
1761             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.
1762             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
1763             if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }   // Dummy tree data
1764 
1765             // Bullet
1766             ImGui::Button("Button##3");
1767             ImGui::SameLine(0.0f, spacing);
1768             ImGui::BulletText("Bullet text");
1769 
1770             ImGui::AlignTextToFramePadding();
1771             ImGui::BulletText("Node");
1772             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
1773 
1774             ImGui::TreePop();
1775         }
1776 
1777         if (ImGui::TreeNode("Scrolling"))
1778         {
1779             ImGui::TextWrapped("(Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given position.)");
1780             static bool track = true;
1781             static int track_line = 50, scroll_to_px = 200;
1782             ImGui::Checkbox("Track", &track);
1783             ImGui::PushItemWidth(100);
1784             ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %d");
1785             bool scroll_to = ImGui::Button("Scroll To Pos");
1786             ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %d px");
1787             ImGui::PopItemWidth();
1788             if (scroll_to) track = false;
1789 
1790             for (int i = 0; i < 5; i++)
1791             {
1792                 if (i > 0) ImGui::SameLine();
1793                 ImGui::BeginGroup();
1794                 ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
1795                 ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
1796                 if (scroll_to)
1797                     ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
1798                 for (int line = 0; line < 100; line++)
1799                 {
1800                     if (track && line == track_line)
1801                     {
1802                         ImGui::TextColored(ImColor(255,255,0), "Line %d", line);
1803                         ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
1804                     }
1805                     else
1806                     {
1807                         ImGui::Text("Line %d", line);
1808                     }
1809                 }
1810                 float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
1811                 ImGui::EndChild();
1812                 ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
1813                 ImGui::EndGroup();
1814             }
1815             ImGui::TreePop();
1816         }
1817 
1818         if (ImGui::TreeNode("Horizontal Scrolling"))
1819         {
1820             ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
1821             ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
1822             static int lines = 7;
1823             ImGui::SliderInt("Lines", &lines, 1, 15);
1824             ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
1825             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
1826             ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
1827             for (int line = 0; line < lines; line++)
1828             {
1829                 // 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
1830                 // 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)
1831                 int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
1832                 for (int n = 0; n < num_buttons; n++)
1833                 {
1834                     if (n > 0) ImGui::SameLine();
1835                     ImGui::PushID(n + line * 1000);
1836                     char num_buf[16];
1837                     sprintf(num_buf, "%d", n);
1838                     const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf;
1839                     float hue = n*0.05f;
1840                     ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
1841                     ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
1842                     ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
1843                     ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
1844                     ImGui::PopStyleColor(3);
1845                     ImGui::PopID();
1846                 }
1847             }
1848             float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
1849             ImGui::EndChild();
1850             ImGui::PopStyleVar(2);
1851             float scroll_x_delta = 0.0f;
1852             ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
1853             ImGui::Text("Scroll from code"); ImGui::SameLine();
1854             ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
1855             ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
1856             if (scroll_x_delta != 0.0f)
1857             {
1858                 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)
1859                 ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
1860                 ImGui::End();
1861             }
1862             ImGui::TreePop();
1863         }
1864 
1865         if (ImGui::TreeNode("Clipping"))
1866         {
1867             static ImVec2 size(100, 100), offset(50, 20);
1868             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.");
1869             ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
1870             ImGui::TextWrapped("(Click and drag)");
1871             ImVec2 pos = ImGui::GetCursorScreenPos();
1872             ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y);
1873             ImGui::InvisibleButton("##dummy", size);
1874             if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
1875             ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), IM_COL32(90,90,120,255));
1876             ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), IM_COL32(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
1877             ImGui::TreePop();
1878         }
1879     }
1880 
1881     if (ImGui::CollapsingHeader("Popups & Modal windows"))
1882     {
1883         // Popups are windows with a few special properties:
1884         // - They block normal mouse hovering detection outside them. (*)
1885         // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
1886         // - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls.
1887         // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup.
1888         // Those three properties are intimately connected. The library needs to hold their visibility state because it can close popups at any time.
1889 
1890         // Typical use for regular windows:
1891         //   bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End();
1892         // Typical use for popups:
1893         //   if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
1894 
1895         // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
1896         // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
1897 
1898         if (ImGui::TreeNode("Popups"))
1899         {
1900             ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
1901 
1902             static int selected_fish = -1;
1903             const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
1904             static bool toggles[] = { true, false, false, false, false };
1905 
1906             // Simple selection popup
1907             // (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)
1908             if (ImGui::Button("Select.."))
1909                 ImGui::OpenPopup("my_select_popup");
1910             ImGui::SameLine();
1911             ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
1912             if (ImGui::BeginPopup("my_select_popup"))
1913             {
1914                 ImGui::Text("Aquarium");
1915                 ImGui::Separator();
1916                 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1917                     if (ImGui::Selectable(names[i]))
1918                         selected_fish = i;
1919                 ImGui::EndPopup();
1920             }
1921 
1922             // Showing a menu with toggles
1923             if (ImGui::Button("Toggle.."))
1924                 ImGui::OpenPopup("my_toggle_popup");
1925             if (ImGui::BeginPopup("my_toggle_popup"))
1926             {
1927                 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1928                     ImGui::MenuItem(names[i], "", &toggles[i]);
1929                 if (ImGui::BeginMenu("Sub-menu"))
1930                 {
1931                     ImGui::MenuItem("Click me");
1932                     ImGui::EndMenu();
1933                 }
1934 
1935                 ImGui::Separator();
1936                 ImGui::Text("Tooltip here");
1937                 if (ImGui::IsItemHovered())
1938                     ImGui::SetTooltip("I am a tooltip over a popup");
1939 
1940                 if (ImGui::Button("Stacked Popup"))
1941                     ImGui::OpenPopup("another popup");
1942                 if (ImGui::BeginPopup("another popup"))
1943                 {
1944                     for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1945                         ImGui::MenuItem(names[i], "", &toggles[i]);
1946                     if (ImGui::BeginMenu("Sub-menu"))
1947                     {
1948                         ImGui::MenuItem("Click me");
1949                         ImGui::EndMenu();
1950                     }
1951                     ImGui::EndPopup();
1952                 }
1953                 ImGui::EndPopup();
1954             }
1955 
1956             // Call the more complete ShowExampleMenuFile which we use in various places of this demo
1957             if (ImGui::Button("File Menu.."))
1958                 ImGui::OpenPopup("my_file_popup");
1959             if (ImGui::BeginPopup("my_file_popup"))
1960             {
1961                 ShowExampleMenuFile();
1962                 ImGui::EndPopup();
1963             }
1964 
1965             ImGui::TreePop();
1966         }
1967 
1968         if (ImGui::TreeNode("Context menus"))
1969         {
1970             // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
1971             //    if (IsItemHovered() && IsMouseReleased(0))
1972             //       OpenPopup(id);
1973             //    return BeginPopup(id);
1974             // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
1975             static float value = 0.5f;
1976             ImGui::Text("Value = %.3f (<-- right-click here)", value);
1977             if (ImGui::BeginPopupContextItem("item context menu"))
1978             {
1979                 if (ImGui::Selectable("Set to zero")) value = 0.0f;
1980                 if (ImGui::Selectable("Set to PI")) value = 3.1415f;
1981                 ImGui::PushItemWidth(-1);
1982                 ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
1983                 ImGui::PopItemWidth();
1984                 ImGui::EndPopup();
1985             }
1986 
1987             // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the Begin call.
1988             // So here we will make it that clicking on the text field with the right mouse button (1) will toggle the visibility of the popup above.
1989             ImGui::Text("(You can also right-click me to the same popup as above.)");
1990             ImGui::OpenPopupOnItemClick("item context menu", 1);
1991 
1992             // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
1993             // BeginPopupContextItem() will use the last item ID as the popup ID.
1994             // In addition here, we want to include your editable label inside the button label. We use the ### operator to override the ID (read FAQ about ID for details)
1995             static char name[32] = "Label1";
1996             char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
1997             ImGui::Button(buf);
1998             if (ImGui::BeginPopupContextItem())
1999             {
2000                 ImGui::Text("Edit name:");
2001                 ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
2002                 if (ImGui::Button("Close"))
2003                     ImGui::CloseCurrentPopup();
2004                 ImGui::EndPopup();
2005             }
2006             ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
2007 
2008             ImGui::TreePop();
2009         }
2010 
2011         if (ImGui::TreeNode("Modals"))
2012         {
2013             ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
2014 
2015             if (ImGui::Button("Delete.."))
2016                 ImGui::OpenPopup("Delete?");
2017             if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
2018             {
2019                 ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
2020                 ImGui::Separator();
2021 
2022                 //static int dummy_i = 0;
2023                 //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
2024 
2025                 static bool dont_ask_me_next_time = false;
2026                 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
2027                 ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
2028                 ImGui::PopStyleVar();
2029 
2030                 if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
2031                 ImGui::SetItemDefaultFocus();
2032                 ImGui::SameLine();
2033                 if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
2034                 ImGui::EndPopup();
2035             }
2036 
2037             if (ImGui::Button("Stacked modals.."))
2038                 ImGui::OpenPopup("Stacked 1");
2039             if (ImGui::BeginPopupModal("Stacked 1"))
2040             {
2041                 ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
2042                 static int item = 1;
2043                 ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
2044                 static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
2045                 ImGui::ColorEdit4("color", color);  // This is to test behavior of stacked regular popups over a modal
2046 
2047                 if (ImGui::Button("Add another modal.."))
2048                     ImGui::OpenPopup("Stacked 2");
2049                 if (ImGui::BeginPopupModal("Stacked 2"))
2050                 {
2051                     ImGui::Text("Hello from Stacked The Second!");
2052                     if (ImGui::Button("Close"))
2053                         ImGui::CloseCurrentPopup();
2054                     ImGui::EndPopup();
2055                 }
2056 
2057                 if (ImGui::Button("Close"))
2058                     ImGui::CloseCurrentPopup();
2059                 ImGui::EndPopup();
2060             }
2061 
2062             ImGui::TreePop();
2063         }
2064 
2065         if (ImGui::TreeNode("Menus inside a regular window"))
2066         {
2067             ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
2068             ImGui::Separator();
2069             // 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.
2070             // 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
2071             // 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.
2072             ImGui::PushID("foo");
2073             ImGui::MenuItem("Menu item", "CTRL+M");
2074             if (ImGui::BeginMenu("Menu inside a regular window"))
2075             {
2076                 ShowExampleMenuFile();
2077                 ImGui::EndMenu();
2078             }
2079             ImGui::PopID();
2080             ImGui::Separator();
2081             ImGui::TreePop();
2082         }
2083     }
2084 
2085     if (ImGui::CollapsingHeader("Columns"))
2086     {
2087         ImGui::PushID("Columns");
2088 
2089         // Basic columns
2090         if (ImGui::TreeNode("Basic"))
2091         {
2092             ImGui::Text("Without border:");
2093             ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
2094             ImGui::Separator();
2095             for (int n = 0; n < 14; n++)
2096             {
2097                 char label[32];
2098                 sprintf(label, "Item %d", n);
2099                 if (ImGui::Selectable(label)) {}
2100                 //if (ImGui::Button(label, ImVec2(-1,0))) {}
2101                 ImGui::NextColumn();
2102             }
2103             ImGui::Columns(1);
2104             ImGui::Separator();
2105 
2106             ImGui::Text("With border:");
2107             ImGui::Columns(4, "mycolumns"); // 4-ways, with border
2108             ImGui::Separator();
2109             ImGui::Text("ID"); ImGui::NextColumn();
2110             ImGui::Text("Name"); ImGui::NextColumn();
2111             ImGui::Text("Path"); ImGui::NextColumn();
2112             ImGui::Text("Hovered"); ImGui::NextColumn();
2113             ImGui::Separator();
2114             const char* names[3] = { "One", "Two", "Three" };
2115             const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
2116             static int selected = -1;
2117             for (int i = 0; i < 3; i++)
2118             {
2119                 char label[32];
2120                 sprintf(label, "%04d", i);
2121                 if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
2122                     selected = i;
2123                 bool hovered = ImGui::IsItemHovered();
2124                 ImGui::NextColumn();
2125                 ImGui::Text(names[i]); ImGui::NextColumn();
2126                 ImGui::Text(paths[i]); ImGui::NextColumn();
2127                 ImGui::Text("%d", hovered); ImGui::NextColumn();
2128             }
2129             ImGui::Columns(1);
2130             ImGui::Separator();
2131             ImGui::TreePop();
2132         }
2133 
2134         // Create multiple items in a same cell before switching to next column
2135         if (ImGui::TreeNode("Mixed items"))
2136         {
2137             ImGui::Columns(3, "mixed");
2138             ImGui::Separator();
2139 
2140             ImGui::Text("Hello");
2141             ImGui::Button("Banana");
2142             ImGui::NextColumn();
2143 
2144             ImGui::Text("ImGui");
2145             ImGui::Button("Apple");
2146             static float foo = 1.0f;
2147             ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
2148             ImGui::Text("An extra line here.");
2149             ImGui::NextColumn();
2150 
2151                 ImGui::Text("Sailor");
2152             ImGui::Button("Corniflower");
2153             static float bar = 1.0f;
2154             ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
2155             ImGui::NextColumn();
2156 
2157             if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2158             if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2159             if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2160             ImGui::Columns(1);
2161             ImGui::Separator();
2162             ImGui::TreePop();
2163         }
2164 
2165         // Word wrapping
2166         if (ImGui::TreeNode("Word-wrapping"))
2167         {
2168             ImGui::Columns(2, "word-wrapping");
2169             ImGui::Separator();
2170             ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2171             ImGui::TextWrapped("Hello Left");
2172             ImGui::NextColumn();
2173             ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2174             ImGui::TextWrapped("Hello Right");
2175             ImGui::Columns(1);
2176             ImGui::Separator();
2177             ImGui::TreePop();
2178         }
2179 
2180         if (ImGui::TreeNode("Borders"))
2181         {
2182             // NB: Future columns API should allow automatic horizontal borders.
2183             static bool h_borders = true;
2184             static bool v_borders = true;
2185             ImGui::Checkbox("horizontal", &h_borders);
2186             ImGui::SameLine();
2187             ImGui::Checkbox("vertical", &v_borders);
2188             ImGui::Columns(4, NULL, v_borders);
2189             for (int i = 0; i < 4*3; i++)
2190             {
2191                 if (h_borders && ImGui::GetColumnIndex() == 0)
2192                     ImGui::Separator();
2193                 ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
2194                 ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
2195                 ImGui::NextColumn();
2196             }
2197             ImGui::Columns(1);
2198             if (h_borders)
2199                 ImGui::Separator();
2200             ImGui::TreePop();
2201         }
2202 
2203         // Scrolling columns
2204         /*
2205         if (ImGui::TreeNode("Vertical Scrolling"))
2206         {
2207             ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
2208             ImGui::Columns(3);
2209             ImGui::Text("ID"); ImGui::NextColumn();
2210             ImGui::Text("Name"); ImGui::NextColumn();
2211             ImGui::Text("Path"); ImGui::NextColumn();
2212             ImGui::Columns(1);
2213             ImGui::Separator();
2214             ImGui::EndChild();
2215             ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
2216             ImGui::Columns(3);
2217             for (int i = 0; i < 10; i++)
2218             {
2219                 ImGui::Text("%04d", i); ImGui::NextColumn();
2220                 ImGui::Text("Foobar"); ImGui::NextColumn();
2221                 ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
2222             }
2223             ImGui::Columns(1);
2224             ImGui::EndChild();
2225             ImGui::TreePop();
2226         }
2227         */
2228 
2229         if (ImGui::TreeNode("Horizontal Scrolling"))
2230         {
2231             ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
2232             ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
2233             ImGui::Columns(10);
2234             int ITEMS_COUNT = 2000;
2235             ImGuiListClipper clipper(ITEMS_COUNT);  // Also demonstrate using the clipper for large list
2236             while (clipper.Step())
2237             {
2238                 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
2239                     for (int j = 0; j < 10; j++)
2240                     {
2241                         ImGui::Text("Line %d Column %d...", i, j);
2242                         ImGui::NextColumn();
2243                     }
2244             }
2245             ImGui::Columns(1);
2246             ImGui::EndChild();
2247             ImGui::TreePop();
2248         }
2249 
2250         bool node_open = ImGui::TreeNode("Tree within single cell");
2251         ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
2252         if (node_open)
2253         {
2254             ImGui::Columns(2, "tree items");
2255             ImGui::Separator();
2256             if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
2257             if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
2258             ImGui::Columns(1);
2259             ImGui::Separator();
2260             ImGui::TreePop();
2261         }
2262         ImGui::PopID();
2263     }
2264 
2265     if (ImGui::CollapsingHeader("Filtering"))
2266     {
2267         static ImGuiTextFilter filter;
2268         ImGui::Text("Filter usage:\n"
2269                     "  \"\"         display all lines\n"
2270                     "  \"xxx\"      display lines containing \"xxx\"\n"
2271                     "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
2272                     "  \"-xxx\"     hide lines containing \"xxx\"");
2273         filter.Draw();
2274         const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
2275         for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
2276             if (filter.PassFilter(lines[i]))
2277                 ImGui::BulletText("%s", lines[i]);
2278     }
2279 
2280     if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
2281     {
2282         ImGuiIO& io = ImGui::GetIO();
2283 
2284         ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
2285         ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
2286         ImGui::Text("WantTextInput: %d", io.WantTextInput);
2287         ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
2288         ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
2289 
2290         if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
2291         {
2292             if (ImGui::IsMousePosValid())
2293                 ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
2294             else
2295                 ImGui::Text("Mouse pos: <INVALID>");
2296             ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
2297             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]); }
2298             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); }
2299             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); }
2300             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); }
2301             ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
2302 
2303             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]); }
2304             ImGui::Text("Keys pressed:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i))             { ImGui::SameLine(); ImGui::Text("%d", i); }
2305             ImGui::Text("Keys release:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i))            { ImGui::SameLine(); ImGui::Text("%d", i); }
2306             ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
2307 
2308             ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f)                    { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); }
2309             ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f)    { ImGui::SameLine(); ImGui::Text("[%d]", i); }
2310             ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); }
2311 
2312             ImGui::Button("Hovering me sets the\nkeyboard capture flag");
2313             if (ImGui::IsItemHovered())
2314                 ImGui::CaptureKeyboardFromApp(true);
2315             ImGui::SameLine();
2316             ImGui::Button("Holding me clears the\nthe keyboard capture flag");
2317             if (ImGui::IsItemActive())
2318                 ImGui::CaptureKeyboardFromApp(false);
2319 
2320             ImGui::TreePop();
2321         }
2322 
2323         if (ImGui::TreeNode("Tabbing"))
2324         {
2325             ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
2326             static char buf[32] = "dummy";
2327             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
2328             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
2329             ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
2330             ImGui::PushAllowKeyboardFocus(false);
2331             ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
2332             //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
2333             ImGui::PopAllowKeyboardFocus();
2334             ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
2335             ImGui::TreePop();
2336         }
2337 
2338         if (ImGui::TreeNode("Focus from code"))
2339         {
2340             bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
2341             bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
2342             bool focus_3 = ImGui::Button("Focus on 3");
2343             int has_focus = 0;
2344             static char buf[128] = "click on a button to set focus";
2345 
2346             if (focus_1) ImGui::SetKeyboardFocusHere();
2347             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
2348             if (ImGui::IsItemActive()) has_focus = 1;
2349 
2350             if (focus_2) ImGui::SetKeyboardFocusHere();
2351             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
2352             if (ImGui::IsItemActive()) has_focus = 2;
2353 
2354             ImGui::PushAllowKeyboardFocus(false);
2355             if (focus_3) ImGui::SetKeyboardFocusHere();
2356             ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
2357             if (ImGui::IsItemActive()) has_focus = 3;
2358             ImGui::PopAllowKeyboardFocus();
2359 
2360             if (has_focus)
2361                 ImGui::Text("Item with focus: %d", has_focus);
2362             else
2363                 ImGui::Text("Item with focus: <none>");
2364 
2365             // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
2366             static float f3[3] = { 0.0f, 0.0f, 0.0f };
2367             int focus_ahead = -1;
2368             if (ImGui::Button("Focus on X")) focus_ahead = 0; ImGui::SameLine();
2369             if (ImGui::Button("Focus on Y")) focus_ahead = 1; ImGui::SameLine();
2370             if (ImGui::Button("Focus on Z")) focus_ahead = 2;
2371             if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
2372             ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
2373 
2374             ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
2375             ImGui::TreePop();
2376         }
2377 
2378         if (ImGui::TreeNode("Dragging"))
2379         {
2380             ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
2381             for (int button = 0; button < 3; button++)
2382                 ImGui::Text("IsMouseDragging(%d):\n  w/ default threshold: %d,\n  w/ zero threshold: %d\n  w/ large threshold: %d",
2383                     button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
2384             ImGui::Button("Drag Me");
2385             if (ImGui::IsItemActive())
2386             {
2387                 // Draw a line between the button and the mouse cursor
2388                 ImDrawList* draw_list = ImGui::GetWindowDrawList();
2389                 draw_list->PushClipRectFullScreen();
2390                 draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f);
2391                 draw_list->PopClipRect();
2392 
2393                 // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
2394                 // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
2395                 ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
2396                 ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
2397                 ImVec2 mouse_delta = io.MouseDelta;
2398                 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);
2399             }
2400             ImGui::TreePop();
2401         }
2402 
2403         if (ImGui::TreeNode("Mouse cursors"))
2404         {
2405             const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" };
2406             IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
2407 
2408             ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
2409             ImGui::Text("Hover to see mouse cursors:");
2410             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.");
2411             for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
2412             {
2413                 char label[32];
2414                 sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
2415                 ImGui::Bullet(); ImGui::Selectable(label, false);
2416                 if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
2417                     ImGui::SetMouseCursor(i);
2418             }
2419             ImGui::TreePop();
2420         }
2421     }
2422 
2423     // End of ShowDemoWindow()
2424     ImGui::End();
2425 }
2426 
2427 //-----------------------------------------------------------------------------
2428 // [SECTION] Style Editor / ShowStyleEditor()
2429 //-----------------------------------------------------------------------------
2430 
2431 // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
2432 // Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally.
ShowStyleSelector(const char * label)2433 bool ImGui::ShowStyleSelector(const char* label)
2434 {
2435     static int style_idx = -1;
2436     if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
2437     {
2438         switch (style_idx)
2439         {
2440         case 0: ImGui::StyleColorsClassic(); break;
2441         case 1: ImGui::StyleColorsDark(); break;
2442         case 2: ImGui::StyleColorsLight(); break;
2443         }
2444         return true;
2445     }
2446     return false;
2447 }
2448 
2449 // Demo helper function to select among loaded fonts.
2450 // Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
ShowFontSelector(const char * label)2451 void ImGui::ShowFontSelector(const char* label)
2452 {
2453     ImGuiIO& io = ImGui::GetIO();
2454     ImFont* font_current = ImGui::GetFont();
2455     if (ImGui::BeginCombo(label, font_current->GetDebugName()))
2456     {
2457         for (int n = 0; n < io.Fonts->Fonts.Size; n++)
2458             if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current))
2459                 io.FontDefault = io.Fonts->Fonts[n];
2460         ImGui::EndCombo();
2461     }
2462     ImGui::SameLine();
2463     ShowHelpMarker(
2464         "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
2465         "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
2466         "- Read FAQ and documentation in misc/fonts/ for more details.\n"
2467         "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
2468 }
2469 
ShowStyleEditor(ImGuiStyle * ref)2470 void ImGui::ShowStyleEditor(ImGuiStyle* ref)
2471 {
2472     // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
2473     ImGuiStyle& style = ImGui::GetStyle();
2474     static ImGuiStyle ref_saved_style;
2475 
2476     // Default to using internal storage as reference
2477     static bool init = true;
2478     if (init && ref == NULL)
2479         ref_saved_style = style;
2480     init = false;
2481     if (ref == NULL)
2482         ref = &ref_saved_style;
2483 
2484     ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
2485 
2486     if (ImGui::ShowStyleSelector("Colors##Selector"))
2487         ref_saved_style = style;
2488     ImGui::ShowFontSelector("Fonts##Selector");
2489 
2490     // Simplified Settings
2491     if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
2492         style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
2493     { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
2494     ImGui::SameLine();
2495     { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
2496     ImGui::SameLine();
2497     { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
2498 
2499     // Save/Revert button
2500     if (ImGui::Button("Save Ref"))
2501         *ref = ref_saved_style = style;
2502     ImGui::SameLine();
2503     if (ImGui::Button("Revert Ref"))
2504         style = *ref;
2505     ImGui::SameLine();
2506     ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
2507 
2508     if (ImGui::TreeNode("Rendering"))
2509     {
2510         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.");
2511         ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
2512         ImGui::PushItemWidth(100);
2513         ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f);
2514         if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
2515         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.
2516         ImGui::PopItemWidth();
2517         ImGui::TreePop();
2518     }
2519 
2520     if (ImGui::TreeNode("Settings"))
2521     {
2522         ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
2523         ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f");
2524         ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
2525         ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
2526         ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
2527         ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
2528         ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
2529         ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
2530         ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
2531         ImGui::Text("BorderSize");
2532         ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
2533         ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
2534         ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
2535         ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
2536         ImGui::Text("Rounding");
2537         ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
2538         ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
2539         ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
2540         ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
2541         ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
2542         ImGui::Text("Alignment");
2543         ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
2544         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.");
2545         ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
2546         ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
2547         ImGui::TreePop();
2548     }
2549 
2550     if (ImGui::TreeNode("Colors"))
2551     {
2552         static int output_dest = 0;
2553         static bool output_only_modified = true;
2554         if (ImGui::Button("Export Unsaved"))
2555         {
2556             if (output_dest == 0)
2557                 ImGui::LogToClipboard();
2558             else
2559                 ImGui::LogToTTY();
2560             ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
2561             for (int i = 0; i < ImGuiCol_COUNT; i++)
2562             {
2563                 const ImVec4& col = style.Colors[i];
2564                 const char* name = ImGui::GetStyleColorName(i);
2565                 if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
2566                     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);
2567             }
2568             ImGui::LogFinish();
2569         }
2570         ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
2571         ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
2572 
2573         ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");
2574 
2575         static ImGuiTextFilter filter;
2576         filter.Draw("Filter colors", 200);
2577 
2578         static ImGuiColorEditFlags alpha_flags = 0;
2579         ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
2580         ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
2581         ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf);
2582 
2583         ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
2584         ImGui::PushItemWidth(-160);
2585         for (int i = 0; i < ImGuiCol_COUNT; i++)
2586         {
2587             const char* name = ImGui::GetStyleColorName(i);
2588             if (!filter.PassFilter(name))
2589                 continue;
2590             ImGui::PushID(i);
2591             ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
2592             if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
2593             {
2594                 // 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.
2595                 // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
2596                 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
2597                 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
2598             }
2599             ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
2600             ImGui::TextUnformatted(name);
2601             ImGui::PopID();
2602         }
2603         ImGui::PopItemWidth();
2604         ImGui::EndChild();
2605 
2606         ImGui::TreePop();
2607     }
2608 
2609     bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size);
2610     if (fonts_opened)
2611     {
2612         ImFontAtlas* atlas = ImGui::GetIO().Fonts;
2613         if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
2614         {
2615             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));
2616             ImGui::TreePop();
2617         }
2618         ImGui::PushItemWidth(100);
2619         for (int i = 0; i < atlas->Fonts.Size; i++)
2620         {
2621             ImFont* font = atlas->Fonts[i];
2622             ImGui::PushID(font);
2623             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);
2624             ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
2625             if (font_details_opened)
2626             {
2627                 ImGui::PushFont(font);
2628                 ImGui::Text("The quick brown fox jumps over the lazy dog");
2629                 ImGui::PopFont();
2630                 ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");   // Scale only this font
2631                 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.)");
2632                 ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f");
2633                 ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
2634                 ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
2635                 ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
2636                 for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
2637                     if (ImFontConfig* cfg = &font->ConfigData[config_i])
2638                         ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
2639                 if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
2640                 {
2641                     // Display all glyphs of the fonts in separate pages of 256 characters
2642                     for (int base = 0; base < 0x10000; base += 256)
2643                     {
2644                         int count = 0;
2645                         for (int n = 0; n < 256; n++)
2646                             count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0;
2647                         if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph"))
2648                         {
2649                             float cell_size = font->FontSize * 1;
2650                             float cell_spacing = style.ItemSpacing.y;
2651                             ImVec2 base_pos = ImGui::GetCursorScreenPos();
2652                             ImDrawList* draw_list = ImGui::GetWindowDrawList();
2653                             for (int n = 0; n < 256; n++)
2654                             {
2655                                 ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
2656                                 ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
2657                                 const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base+n));
2658                                 draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50));
2659                                 if (glyph)
2660                                     font->RenderChar(draw_list, cell_size, 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.
2661                                 if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
2662                                 {
2663                                     ImGui::BeginTooltip();
2664                                     ImGui::Text("Codepoint: U+%04X", base+n);
2665                                     ImGui::Separator();
2666                                     ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
2667                                     ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
2668                                     ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
2669                                     ImGui::EndTooltip();
2670                                 }
2671                             }
2672                             ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
2673                             ImGui::TreePop();
2674                         }
2675                     }
2676                     ImGui::TreePop();
2677                 }
2678                 ImGui::TreePop();
2679             }
2680             ImGui::PopID();
2681         }
2682         static float window_scale = 1.0f;
2683         ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f");              // scale only this window
2684         ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything
2685         ImGui::PopItemWidth();
2686         ImGui::SetWindowFontScale(window_scale);
2687         ImGui::TreePop();
2688     }
2689 
2690     ImGui::PopItemWidth();
2691 }
2692 
2693 //-----------------------------------------------------------------------------
2694 // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
2695 //-----------------------------------------------------------------------------
2696 
2697 // Demonstrate creating a fullscreen menu bar and populating it.
ShowExampleAppMainMenuBar()2698 static void ShowExampleAppMainMenuBar()
2699 {
2700     if (ImGui::BeginMainMenuBar())
2701     {
2702         if (ImGui::BeginMenu("File"))
2703         {
2704             ShowExampleMenuFile();
2705             ImGui::EndMenu();
2706         }
2707         if (ImGui::BeginMenu("Edit"))
2708         {
2709             if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
2710             if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
2711             ImGui::Separator();
2712             if (ImGui::MenuItem("Cut", "CTRL+X")) {}
2713             if (ImGui::MenuItem("Copy", "CTRL+C")) {}
2714             if (ImGui::MenuItem("Paste", "CTRL+V")) {}
2715             ImGui::EndMenu();
2716         }
2717         ImGui::EndMainMenuBar();
2718     }
2719 }
2720 
ShowExampleMenuFile()2721 static void ShowExampleMenuFile()
2722 {
2723     ImGui::MenuItem("(dummy menu)", NULL, false, false);
2724     if (ImGui::MenuItem("New")) {}
2725     if (ImGui::MenuItem("Open", "Ctrl+O")) {}
2726     if (ImGui::BeginMenu("Open Recent"))
2727     {
2728         ImGui::MenuItem("fish_hat.c");
2729         ImGui::MenuItem("fish_hat.inl");
2730         ImGui::MenuItem("fish_hat.h");
2731         if (ImGui::BeginMenu("More.."))
2732         {
2733             ImGui::MenuItem("Hello");
2734             ImGui::MenuItem("Sailor");
2735             if (ImGui::BeginMenu("Recurse.."))
2736             {
2737                 ShowExampleMenuFile();
2738                 ImGui::EndMenu();
2739             }
2740             ImGui::EndMenu();
2741         }
2742         ImGui::EndMenu();
2743     }
2744     if (ImGui::MenuItem("Save", "Ctrl+S")) {}
2745     if (ImGui::MenuItem("Save As..")) {}
2746     ImGui::Separator();
2747     if (ImGui::BeginMenu("Options"))
2748     {
2749         static bool enabled = true;
2750         ImGui::MenuItem("Enabled", "", &enabled);
2751         ImGui::BeginChild("child", ImVec2(0, 60), true);
2752         for (int i = 0; i < 10; i++)
2753             ImGui::Text("Scrolling Text %d", i);
2754         ImGui::EndChild();
2755         static float f = 0.5f;
2756         static int n = 0;
2757         static bool b = true;
2758         ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
2759         ImGui::InputFloat("Input", &f, 0.1f);
2760         ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
2761         ImGui::Checkbox("Check", &b);
2762         ImGui::EndMenu();
2763     }
2764     if (ImGui::BeginMenu("Colors"))
2765     {
2766         float sz = ImGui::GetTextLineHeight();
2767         for (int i = 0; i < ImGuiCol_COUNT; i++)
2768         {
2769             const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
2770             ImVec2 p = ImGui::GetCursorScreenPos();
2771             ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i));
2772             ImGui::Dummy(ImVec2(sz, sz));
2773             ImGui::SameLine();
2774             ImGui::MenuItem(name);
2775         }
2776         ImGui::EndMenu();
2777     }
2778     if (ImGui::BeginMenu("Disabled", false)) // Disabled
2779     {
2780         IM_ASSERT(0);
2781     }
2782     if (ImGui::MenuItem("Checked", NULL, true)) {}
2783     if (ImGui::MenuItem("Quit", "Alt+F4")) {}
2784 }
2785 
2786 //-----------------------------------------------------------------------------
2787 // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
2788 //-----------------------------------------------------------------------------
2789 
2790 // Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
2791 // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
2792 struct ExampleAppConsole
2793 {
2794     char                  InputBuf[256];
2795     ImVector<char*>       Items;
2796     bool                  ScrollToBottom;
2797     ImVector<char*>       History;
2798     int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
2799     ImVector<const char*> Commands;
2800 
ExampleAppConsoleExampleAppConsole2801     ExampleAppConsole()
2802     {
2803         ClearLog();
2804         memset(InputBuf, 0, sizeof(InputBuf));
2805         HistoryPos = -1;
2806         Commands.push_back("HELP");
2807         Commands.push_back("HISTORY");
2808         Commands.push_back("CLEAR");
2809         Commands.push_back("CLASSIFY");  // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
2810         AddLog("Welcome to Dear ImGui!");
2811     }
~ExampleAppConsoleExampleAppConsole2812     ~ExampleAppConsole()
2813     {
2814         ClearLog();
2815         for (int i = 0; i < History.Size; i++)
2816             free(History[i]);
2817     }
2818 
2819     // Portable helpers
StricmpExampleAppConsole2820     static int   Stricmp(const char* str1, const char* str2)         { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
StrnicmpExampleAppConsole2821     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; }
StrdupExampleAppConsole2822     static char* Strdup(const char *str)                             { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }
StrtrimExampleAppConsole2823     static void  Strtrim(char* str)                                  { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; }
2824 
ClearLogExampleAppConsole2825     void    ClearLog()
2826     {
2827         for (int i = 0; i < Items.Size; i++)
2828             free(Items[i]);
2829         Items.clear();
2830         ScrollToBottom = true;
2831     }
2832 
AddLogExampleAppConsole2833     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
2834     {
2835         // FIXME-OPT
2836         char buf[1024];
2837         va_list args;
2838         va_start(args, fmt);
2839         vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
2840         buf[IM_ARRAYSIZE(buf)-1] = 0;
2841         va_end(args);
2842         Items.push_back(Strdup(buf));
2843         ScrollToBottom = true;
2844     }
2845 
DrawExampleAppConsole2846     void    Draw(const char* title, bool* p_open)
2847     {
2848         ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
2849         if (!ImGui::Begin(title, p_open))
2850         {
2851             ImGui::End();
2852             return;
2853         }
2854 
2855         // 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.
2856         // Here we create a context menu only available from the title bar.
2857         if (ImGui::BeginPopupContextItem())
2858         {
2859             if (ImGui::MenuItem("Close Console"))
2860                 *p_open = false;
2861             ImGui::EndPopup();
2862         }
2863 
2864         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.");
2865         ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
2866 
2867         // TODO: display items starting from the bottom
2868 
2869         if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
2870         if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
2871         if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
2872         bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine();
2873         if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
2874         //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
2875 
2876         ImGui::Separator();
2877 
2878         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0));
2879         static ImGuiTextFilter filter;
2880         filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
2881         ImGui::PopStyleVar();
2882         ImGui::Separator();
2883 
2884         const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
2885         ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText
2886         if (ImGui::BeginPopupContextWindow())
2887         {
2888             if (ImGui::Selectable("Clear")) ClearLog();
2889             ImGui::EndPopup();
2890         }
2891 
2892         // 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());
2893         // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
2894         // 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.
2895         // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
2896         //     ImGuiListClipper clipper(Items.Size);
2897         //     while (clipper.Step())
2898         //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
2899         // However, 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.
2900         // 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,
2901         // 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!
2902         // 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.
2903         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
2904         if (copy_to_clipboard)
2905             ImGui::LogToClipboard();
2906         ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text);
2907         for (int i = 0; i < Items.Size; i++)
2908         {
2909             const char* item = Items[i];
2910             if (!filter.PassFilter(item))
2911                 continue;
2912             ImVec4 col = col_default_text;
2913             if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f);
2914             else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f);
2915             ImGui::PushStyleColor(ImGuiCol_Text, col);
2916             ImGui::TextUnformatted(item);
2917             ImGui::PopStyleColor();
2918         }
2919         if (copy_to_clipboard)
2920             ImGui::LogFinish();
2921         if (ScrollToBottom)
2922             ImGui::SetScrollHereY(1.0f);
2923         ScrollToBottom = false;
2924         ImGui::PopStyleVar();
2925         ImGui::EndChild();
2926         ImGui::Separator();
2927 
2928         // Command-line
2929         bool reclaim_focus = false;
2930         if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
2931         {
2932             char* s = InputBuf;
2933             Strtrim(s);
2934             if (s[0])
2935                 ExecCommand(s);
2936             strcpy(s, "");
2937             reclaim_focus = true;
2938         }
2939 
2940         // Auto-focus on window apparition
2941         ImGui::SetItemDefaultFocus();
2942         if (reclaim_focus)
2943             ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
2944 
2945         ImGui::End();
2946     }
2947 
ExecCommandExampleAppConsole2948     void    ExecCommand(const char* command_line)
2949     {
2950         AddLog("# %s\n", command_line);
2951 
2952         // 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.
2953         HistoryPos = -1;
2954         for (int i = History.Size-1; i >= 0; i--)
2955             if (Stricmp(History[i], command_line) == 0)
2956             {
2957                 free(History[i]);
2958                 History.erase(History.begin() + i);
2959                 break;
2960             }
2961         History.push_back(Strdup(command_line));
2962 
2963         // Process command
2964         if (Stricmp(command_line, "CLEAR") == 0)
2965         {
2966             ClearLog();
2967         }
2968         else if (Stricmp(command_line, "HELP") == 0)
2969         {
2970             AddLog("Commands:");
2971             for (int i = 0; i < Commands.Size; i++)
2972                 AddLog("- %s", Commands[i]);
2973         }
2974         else if (Stricmp(command_line, "HISTORY") == 0)
2975         {
2976             int first = History.Size - 10;
2977             for (int i = first > 0 ? first : 0; i < History.Size; i++)
2978                 AddLog("%3d: %s\n", i, History[i]);
2979         }
2980         else
2981         {
2982             AddLog("Unknown command: '%s'\n", command_line);
2983         }
2984     }
2985 
TextEditCallbackStubExampleAppConsole2986     static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
2987     {
2988         ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
2989         return console->TextEditCallback(data);
2990     }
2991 
TextEditCallbackExampleAppConsole2992     int     TextEditCallback(ImGuiInputTextCallbackData* data)
2993     {
2994         //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
2995         switch (data->EventFlag)
2996         {
2997         case ImGuiInputTextFlags_CallbackCompletion:
2998             {
2999                 // Example of TEXT COMPLETION
3000 
3001                 // Locate beginning of current word
3002                 const char* word_end = data->Buf + data->CursorPos;
3003                 const char* word_start = word_end;
3004                 while (word_start > data->Buf)
3005                 {
3006                     const char c = word_start[-1];
3007                     if (c == ' ' || c == '\t' || c == ',' || c == ';')
3008                         break;
3009                     word_start--;
3010                 }
3011 
3012                 // Build a list of candidates
3013                 ImVector<const char*> candidates;
3014                 for (int i = 0; i < Commands.Size; i++)
3015                     if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
3016                         candidates.push_back(Commands[i]);
3017 
3018                 if (candidates.Size == 0)
3019                 {
3020                     // No match
3021                     AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
3022                 }
3023                 else if (candidates.Size == 1)
3024                 {
3025                     // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
3026                     data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
3027                     data->InsertChars(data->CursorPos, candidates[0]);
3028                     data->InsertChars(data->CursorPos, " ");
3029                 }
3030                 else
3031                 {
3032                     // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
3033                     int match_len = (int)(word_end - word_start);
3034                     for (;;)
3035                     {
3036                         int c = 0;
3037                         bool all_candidates_matches = true;
3038                         for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
3039                             if (i == 0)
3040                                 c = toupper(candidates[i][match_len]);
3041                             else if (c == 0 || c != toupper(candidates[i][match_len]))
3042                                 all_candidates_matches = false;
3043                         if (!all_candidates_matches)
3044                             break;
3045                         match_len++;
3046                     }
3047 
3048                     if (match_len > 0)
3049                     {
3050                         data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
3051                         data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
3052                     }
3053 
3054                     // List matches
3055                     AddLog("Possible matches:\n");
3056                     for (int i = 0; i < candidates.Size; i++)
3057                         AddLog("- %s\n", candidates[i]);
3058                 }
3059 
3060                 break;
3061             }
3062         case ImGuiInputTextFlags_CallbackHistory:
3063             {
3064                 // Example of HISTORY
3065                 const int prev_history_pos = HistoryPos;
3066                 if (data->EventKey == ImGuiKey_UpArrow)
3067                 {
3068                     if (HistoryPos == -1)
3069                         HistoryPos = History.Size - 1;
3070                     else if (HistoryPos > 0)
3071                         HistoryPos--;
3072                 }
3073                 else if (data->EventKey == ImGuiKey_DownArrow)
3074                 {
3075                     if (HistoryPos != -1)
3076                         if (++HistoryPos >= History.Size)
3077                             HistoryPos = -1;
3078                 }
3079 
3080                 // A better implementation would preserve the data on the current input line along with cursor position.
3081                 if (prev_history_pos != HistoryPos)
3082                 {
3083                     const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
3084                     data->DeleteChars(0, data->BufTextLen);
3085                     data->InsertChars(0, history_str);
3086                 }
3087             }
3088         }
3089         return 0;
3090     }
3091 };
3092 
ShowExampleAppConsole(bool * p_open)3093 static void ShowExampleAppConsole(bool* p_open)
3094 {
3095     static ExampleAppConsole console;
3096     console.Draw("Example: Console", p_open);
3097 }
3098 
3099 //-----------------------------------------------------------------------------
3100 // [SECTION] Example App: Debug Log / ShowExampleAppLog()
3101 //-----------------------------------------------------------------------------
3102 
3103 // Usage:
3104 //  static ExampleAppLog my_log;
3105 //  my_log.AddLog("Hello %d world\n", 123);
3106 //  my_log.Draw("title");
3107 struct ExampleAppLog
3108 {
3109     ImGuiTextBuffer     Buf;
3110     ImGuiTextFilter     Filter;
3111     ImVector<int>       LineOffsets;        // Index to lines offset
3112     bool                ScrollToBottom;
3113 
ClearExampleAppLog3114     void    Clear()     { Buf.clear(); LineOffsets.clear(); }
3115 
AddLogExampleAppLog3116     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
3117     {
3118         int old_size = Buf.size();
3119         va_list args;
3120         va_start(args, fmt);
3121         Buf.appendfv(fmt, args);
3122         va_end(args);
3123         for (int new_size = Buf.size(); old_size < new_size; old_size++)
3124             if (Buf[old_size] == '\n')
3125                 LineOffsets.push_back(old_size);
3126         ScrollToBottom = true;
3127     }
3128 
DrawExampleAppLog3129     void    Draw(const char* title, bool* p_open = NULL)
3130     {
3131         ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver);
3132         if (!ImGui::Begin(title, p_open))
3133         {
3134             ImGui::End();
3135             return;
3136         }
3137         if (ImGui::Button("Clear")) Clear();
3138         ImGui::SameLine();
3139         bool copy = ImGui::Button("Copy");
3140         ImGui::SameLine();
3141         Filter.Draw("Filter", -100.0f);
3142         ImGui::Separator();
3143         ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
3144         if (copy) ImGui::LogToClipboard();
3145 
3146         if (Filter.IsActive())
3147         {
3148             const char* buf_begin = Buf.begin();
3149             const char* line = buf_begin;
3150             for (int line_no = 0; line != NULL; line_no++)
3151             {
3152                 const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
3153                 if (Filter.PassFilter(line, line_end))
3154                     ImGui::TextUnformatted(line, line_end);
3155                 line = line_end && line_end[1] ? line_end + 1 : NULL;
3156             }
3157         }
3158         else
3159         {
3160             ImGui::TextUnformatted(Buf.begin());
3161         }
3162 
3163         if (ScrollToBottom)
3164             ImGui::SetScrollHereY(1.0f);
3165         ScrollToBottom = false;
3166         ImGui::EndChild();
3167         ImGui::End();
3168     }
3169 };
3170 
3171 // Demonstrate creating a simple log window with basic filtering.
ShowExampleAppLog(bool * p_open)3172 static void ShowExampleAppLog(bool* p_open)
3173 {
3174     static ExampleAppLog log;
3175 
3176     // Demo: add random items (unless Ctrl is held)
3177     static double last_time = -1.0;
3178     double time = ImGui::GetTime();
3179     if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl)
3180     {
3181         const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
3182         log.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, ImGui::GetFrameCount());
3183         last_time = time;
3184     }
3185 
3186     log.Draw("Example: Log", p_open);
3187 }
3188 
3189 //-----------------------------------------------------------------------------
3190 // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
3191 //-----------------------------------------------------------------------------
3192 
3193 // Demonstrate create a window with multiple child windows.
ShowExampleAppLayout(bool * p_open)3194 static void ShowExampleAppLayout(bool* p_open)
3195 {
3196     ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
3197     if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
3198     {
3199         if (ImGui::BeginMenuBar())
3200         {
3201             if (ImGui::BeginMenu("File"))
3202             {
3203                 if (ImGui::MenuItem("Close")) *p_open = false;
3204                 ImGui::EndMenu();
3205             }
3206             ImGui::EndMenuBar();
3207         }
3208 
3209         // left
3210         static int selected = 0;
3211         ImGui::BeginChild("left pane", ImVec2(150, 0), true);
3212         for (int i = 0; i < 100; i++)
3213         {
3214             char label[128];
3215             sprintf(label, "MyObject %d", i);
3216             if (ImGui::Selectable(label, selected == i))
3217                 selected = i;
3218         }
3219         ImGui::EndChild();
3220         ImGui::SameLine();
3221 
3222         // right
3223         ImGui::BeginGroup();
3224             ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
3225                 ImGui::Text("MyObject: %d", selected);
3226                 ImGui::Separator();
3227                 ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
3228             ImGui::EndChild();
3229             if (ImGui::Button("Revert")) {}
3230             ImGui::SameLine();
3231             if (ImGui::Button("Save")) {}
3232         ImGui::EndGroup();
3233     }
3234     ImGui::End();
3235 }
3236 
3237 //-----------------------------------------------------------------------------
3238 // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
3239 //-----------------------------------------------------------------------------
3240 
3241 // Demonstrate create a simple property editor.
ShowExampleAppPropertyEditor(bool * p_open)3242 static void ShowExampleAppPropertyEditor(bool* p_open)
3243 {
3244     ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
3245     if (!ImGui::Begin("Example: Property editor", p_open))
3246     {
3247         ImGui::End();
3248         return;
3249     }
3250 
3251     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.");
3252 
3253     ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
3254     ImGui::Columns(2);
3255     ImGui::Separator();
3256 
3257     struct funcs
3258     {
3259         static void ShowDummyObject(const char* prefix, int uid)
3260         {
3261             ImGui::PushID(uid);                      // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
3262             ImGui::AlignTextToFramePadding();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
3263             bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
3264             ImGui::NextColumn();
3265             ImGui::AlignTextToFramePadding();
3266             ImGui::Text("my sailor is rich");
3267             ImGui::NextColumn();
3268             if (node_open)
3269             {
3270                 static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
3271                 for (int i = 0; i < 8; i++)
3272                 {
3273                     ImGui::PushID(i); // Use field index as identifier.
3274                     if (i < 2)
3275                     {
3276                         ShowDummyObject("Child", 424242);
3277                     }
3278                     else
3279                     {
3280                         // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
3281                         ImGui::AlignTextToFramePadding();
3282                         ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i);
3283                         ImGui::NextColumn();
3284                         ImGui::PushItemWidth(-1);
3285                         if (i >= 5)
3286                             ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
3287                         else
3288                             ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
3289                         ImGui::PopItemWidth();
3290                         ImGui::NextColumn();
3291                     }
3292                     ImGui::PopID();
3293                 }
3294                 ImGui::TreePop();
3295             }
3296             ImGui::PopID();
3297         }
3298     };
3299 
3300     // Iterate dummy objects with dummy members (all the same data)
3301     for (int obj_i = 0; obj_i < 3; obj_i++)
3302         funcs::ShowDummyObject("Object", obj_i);
3303 
3304     ImGui::Columns(1);
3305     ImGui::Separator();
3306     ImGui::PopStyleVar();
3307     ImGui::End();
3308 }
3309 
3310 //-----------------------------------------------------------------------------
3311 // [SECTION] Example App: Long Text / ShowExampleAppLongText()
3312 //-----------------------------------------------------------------------------
3313 
3314 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
ShowExampleAppLongText(bool * p_open)3315 static void ShowExampleAppLongText(bool* p_open)
3316 {
3317     ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
3318     if (!ImGui::Begin("Example: Long text display", p_open))
3319     {
3320         ImGui::End();
3321         return;
3322     }
3323 
3324     static int test_type = 0;
3325     static ImGuiTextBuffer log;
3326     static int lines = 0;
3327     ImGui::Text("Printing unusually long amount of text.");
3328     ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
3329     ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
3330     if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
3331     ImGui::SameLine();
3332     if (ImGui::Button("Add 1000 lines"))
3333     {
3334         for (int i = 0; i < 1000; i++)
3335             log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
3336         lines += 1000;
3337     }
3338     ImGui::BeginChild("Log");
3339     switch (test_type)
3340     {
3341     case 0:
3342         // Single call to TextUnformatted() with a big buffer
3343         ImGui::TextUnformatted(log.begin(), log.end());
3344         break;
3345     case 1:
3346         {
3347             // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
3348             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
3349             ImGuiListClipper clipper(lines);
3350             while (clipper.Step())
3351                 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
3352                     ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
3353             ImGui::PopStyleVar();
3354             break;
3355         }
3356     case 2:
3357         // Multiple calls to Text(), not clipped (slow)
3358         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
3359         for (int i = 0; i < lines; i++)
3360             ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
3361         ImGui::PopStyleVar();
3362         break;
3363     }
3364     ImGui::EndChild();
3365     ImGui::End();
3366 }
3367 
3368 //-----------------------------------------------------------------------------
3369 // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
3370 //-----------------------------------------------------------------------------
3371 
3372 // Demonstrate creating a window which gets auto-resized according to its content.
ShowExampleAppAutoResize(bool * p_open)3373 static void ShowExampleAppAutoResize(bool* p_open)
3374 {
3375     if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
3376     {
3377         ImGui::End();
3378         return;
3379     }
3380 
3381     static int lines = 10;
3382     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.");
3383     ImGui::SliderInt("Number of lines", &lines, 1, 20);
3384     for (int i = 0; i < lines; i++)
3385         ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
3386     ImGui::End();
3387 }
3388 
3389 //-----------------------------------------------------------------------------
3390 // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
3391 //-----------------------------------------------------------------------------
3392 
3393 // Demonstrate creating a window with custom resize constraints.
ShowExampleAppConstrainedResize(bool * p_open)3394 static void ShowExampleAppConstrainedResize(bool* p_open)
3395 {
3396     struct CustomConstraints // Helper functions to demonstrate programmatic constraints
3397     {
3398         static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
3399         static void Step(ImGuiSizeCallbackData* 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); }
3400     };
3401 
3402     static bool auto_resize = false;
3403     static int type = 0;
3404     static int display_lines = 10;
3405     if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Vertical only
3406     if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Horizontal only
3407     if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
3408     if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width 400-500
3409     if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, 500));          // Height 400-500
3410     if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);          // Always Square
3411     if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step
3412 
3413     ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
3414     if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
3415     {
3416         const char* desc[] =
3417         {
3418             "Resize vertical only",
3419             "Resize horizontal only",
3420             "Width > 100, Height > 100",
3421             "Width 400-500",
3422             "Height 400-500",
3423             "Custom: Always Square",
3424             "Custom: Fixed Steps (100)",
3425         };
3426         if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
3427         if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
3428         if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
3429         ImGui::PushItemWidth(200);
3430         ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
3431         ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
3432         ImGui::PopItemWidth();
3433         ImGui::Checkbox("Auto-resize", &auto_resize);
3434         for (int i = 0; i < display_lines; i++)
3435             ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
3436     }
3437     ImGui::End();
3438 }
3439 
3440 //-----------------------------------------------------------------------------
3441 // [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
3442 //-----------------------------------------------------------------------------
3443 
3444 // Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
ShowExampleAppSimpleOverlay(bool * p_open)3445 static void ShowExampleAppSimpleOverlay(bool* p_open)
3446 {
3447     const float DISTANCE = 10.0f;
3448     static int corner = 0;
3449     ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
3450     ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
3451     if (corner != -1)
3452         ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
3453     ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background
3454     if (ImGui::Begin("Example: Simple Overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
3455     {
3456         ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
3457         ImGui::Separator();
3458         if (ImGui::IsMousePosValid())
3459             ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
3460         else
3461             ImGui::Text("Mouse Position: <invalid>");
3462         if (ImGui::BeginPopupContextWindow())
3463         {
3464             if (ImGui::MenuItem("Custom",       NULL, corner == -1)) corner = -1;
3465             if (ImGui::MenuItem("Top-left",     NULL, corner == 0)) corner = 0;
3466             if (ImGui::MenuItem("Top-right",    NULL, corner == 1)) corner = 1;
3467             if (ImGui::MenuItem("Bottom-left",  NULL, corner == 2)) corner = 2;
3468             if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
3469             if (p_open && ImGui::MenuItem("Close")) *p_open = false;
3470             ImGui::EndPopup();
3471         }
3472     }
3473     ImGui::End();
3474 }
3475 
3476 //-----------------------------------------------------------------------------
3477 // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
3478 //-----------------------------------------------------------------------------
3479 
3480 // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
3481 // This apply to all regular items as well. Read FAQ 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." for details.
ShowExampleAppWindowTitles(bool *)3482 static void ShowExampleAppWindowTitles(bool*)
3483 {
3484     // By default, Windows are uniquely identified by their title.
3485     // You can use the "##" and "###" markers to manipulate the display/ID.
3486 
3487     // Using "##" to display same title but have unique identifier.
3488     ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
3489     ImGui::Begin("Same title as another window##1");
3490     ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
3491     ImGui::End();
3492 
3493     ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
3494     ImGui::Begin("Same title as another window##2");
3495     ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
3496     ImGui::End();
3497 
3498     // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
3499     char buf[128];
3500     sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
3501     ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
3502     ImGui::Begin(buf);
3503     ImGui::Text("This window has a changing title.");
3504     ImGui::End();
3505 }
3506 
3507 //-----------------------------------------------------------------------------
3508 // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
3509 //-----------------------------------------------------------------------------
3510 
3511 // Demonstrate using the low-level ImDrawList to draw custom shapes.
ShowExampleAppCustomRendering(bool * p_open)3512 static void ShowExampleAppCustomRendering(bool* p_open)
3513 {
3514     ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver);
3515     if (!ImGui::Begin("Example: Custom rendering", p_open))
3516     {
3517         ImGui::End();
3518         return;
3519     }
3520 
3521     // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
3522     // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
3523     // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
3524     // In this example we are not using the maths operators!
3525     ImDrawList* draw_list = ImGui::GetWindowDrawList();
3526 
3527     // Primitives
3528     ImGui::Text("Primitives");
3529     static float sz = 36.0f;
3530     static float thickness = 4.0f;
3531     static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
3532     ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
3533     ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
3534     ImGui::ColorEdit3("Color", &col.x);
3535     {
3536         const ImVec2 p = ImGui::GetCursorScreenPos();
3537         const ImU32 col32 = ImColor(col);
3538         float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
3539         for (int n = 0; n < 2; n++)
3540         {
3541             float curr_thickness = (n == 0) ? 1.0f : thickness;
3542             draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, curr_thickness); x += sz+spacing;
3543             draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing;
3544             draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, curr_thickness); x += sz+spacing;
3545             draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, curr_thickness); x += sz+spacing;
3546             draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, curr_thickness); x += sz+spacing;
3547             draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y   ), col32, curr_thickness); x += sz+spacing;   // Horizontal line (note: drawing a filled rectangle will be faster!)
3548             draw_list->AddLine(ImVec2(x, y), ImVec2(x,    y+sz), col32, curr_thickness); x += spacing;      // Vertical line (note: drawing a filled rectangle will be faster!)
3549             draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, curr_thickness); x += sz+spacing;   // Diagonal line
3550             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, curr_thickness);
3551             x = p.x + 4;
3552             y += sz+spacing;
3553         }
3554         draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;
3555         draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
3556         draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
3557         draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;
3558         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;
3559         draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+thickness), col32); x += sz+spacing;          // Horizontal line (faster than AddLine, but only handle integer thickness)
3560         draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+thickness, y+sz), col32); x += spacing+spacing;     // Vertical line (faster than AddLine, but only handle integer thickness)
3561         draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+1, y+1), col32);          x += sz;                  // Pixel (faster than AddLine)
3562         draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), IM_COL32(0,0,0,255), IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255));
3563         ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
3564     }
3565     ImGui::Separator();
3566     {
3567         static ImVector<ImVec2> points;
3568         static bool adding_line = false;
3569         ImGui::Text("Canvas example");
3570         if (ImGui::Button("Clear")) points.clear();
3571         if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
3572         ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
3573 
3574         // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
3575         // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
3576         // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
3577         ImVec2 canvas_pos = ImGui::GetCursorScreenPos();            // ImDrawList API uses screen coordinates!
3578         ImVec2 canvas_size = ImGui::GetContentRegionAvail();        // Resize canvas to what's available
3579         if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
3580         if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
3581         draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50, 50, 50, 255), IM_COL32(50, 50, 60, 255), IM_COL32(60, 60, 70, 255), IM_COL32(50, 50, 60, 255));
3582         draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255));
3583 
3584         bool adding_preview = false;
3585         ImGui::InvisibleButton("canvas", canvas_size);
3586         ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
3587         if (adding_line)
3588         {
3589             adding_preview = true;
3590             points.push_back(mouse_pos_in_canvas);
3591             if (!ImGui::IsMouseDown(0))
3592                 adding_line = adding_preview = false;
3593         }
3594         if (ImGui::IsItemHovered())
3595         {
3596             if (!adding_line && ImGui::IsMouseClicked(0))
3597             {
3598                 points.push_back(mouse_pos_in_canvas);
3599                 adding_line = true;
3600             }
3601             if (ImGui::IsMouseClicked(1) && !points.empty())
3602             {
3603                 adding_line = adding_preview = false;
3604                 points.pop_back();
3605                 points.pop_back();
3606             }
3607         }
3608         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.)
3609         for (int i = 0; i < points.Size - 1; i += 2)
3610             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);
3611         draw_list->PopClipRect();
3612         if (adding_preview)
3613             points.pop_back();
3614     }
3615     ImGui::End();
3616 }
3617 
3618 // End of Demo code
3619 #else
3620 
ShowDemoWindow(bool *)3621 void ImGui::ShowDemoWindow(bool*) {}
ShowUserGuide()3622 void ImGui::ShowUserGuide() {}
ShowStyleEditor(ImGuiStyle *)3623 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
3624 
3625 #endif
3626