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