• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // dear imgui, v1.85
2 // (demo code)
3 
4 // Help:
5 // - Read FAQ at http://dearimgui.org/faq
6 // - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
7 // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
8 // Read imgui.cpp for more details, documentation and comments.
9 // Get the latest version at https://github.com/ocornut/imgui
10 
11 // Message to the person tempted to delete this file when integrating Dear ImGui into their codebase:
12 // Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other
13 // coders will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available
14 // debug menu of your game/app! Removing this file from your project is hindering access to documentation for everyone
15 // in your team, likely leading you to poorer usage of the library.
16 // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
17 // If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
18 // linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
19 // In another situation, whenever you have Dear ImGui available you probably want this to be available for reference.
20 // Thank you,
21 // -Your beloved friend, imgui_demo.cpp (which you won't delete)
22 
23 // Message to beginner C/C++ programmers about the meaning of the 'static' keyword:
24 // In this demo code, we frequently use 'static' variables inside functions. A static variable persists across calls,
25 // so it is essentially like a global variable but declared inside the scope of the function. We do this as a way to
26 // gather code and data in the same place, to make the demo source code faster to read, faster to write, and smaller
27 // in size. It also happens to be a convenient way of storing simple UI related information as long as your function
28 // doesn't need to be reentrant or used in multiple threads. This might be a pattern you will want to use in your code,
29 // but most of the real data you would be editing is likely going to be stored outside your functions.
30 
31 // The Demo code in this file is designed to be easy to copy-and-paste into your application!
32 // Because of this:
33 // - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
34 // - We try to declare static variables in the local scope, as close as possible to the code using them.
35 // - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
36 // - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
37 //   by imgui_internal.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
38 //   and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
39 //   Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
40 
41 // Navigating this file:
42 // - In Visual Studio IDE: CTRL+comma ("Edit.NavigateTo") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
43 // - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
44 
45 /*
46 
47 Index of this file:
48 
49 // [SECTION] Forward Declarations, Helpers
50 // [SECTION] Demo Window / ShowDemoWindow()
51 // - sub section: ShowDemoWindowWidgets()
52 // - sub section: ShowDemoWindowLayout()
53 // - sub section: ShowDemoWindowPopups()
54 // - sub section: ShowDemoWindowTables()
55 // - sub section: ShowDemoWindowMisc()
56 // [SECTION] About Window / ShowAboutWindow()
57 // [SECTION] Style Editor / ShowStyleEditor()
58 // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
59 // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
60 // [SECTION] Example App: Debug Log / ShowExampleAppLog()
61 // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
62 // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
63 // [SECTION] Example App: Long Text / ShowExampleAppLongText()
64 // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
65 // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
66 // [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
67 // [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
68 // [SECTION] Example App: Manipulating window titles / ShowExampleAppWindowTitles()
69 // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
70 // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
71 
72 */
73 
74 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
75 #define _CRT_SECURE_NO_WARNINGS
76 #endif
77 
78 #include "imgui.h"
79 #ifndef IMGUI_DISABLE
80 
81 // System includes
82 #include <ctype.h>          // toupper
83 #include <limits.h>         // INT_MIN, INT_MAX
84 #include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
85 #include <stdio.h>          // vsnprintf, sscanf, printf
86 #include <stdlib.h>         // NULL, malloc, free, atoi
87 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
88 #include <stddef.h>         // intptr_t
89 #else
90 #include <stdint.h>         // intptr_t
91 #endif
92 
93 // Visual Studio warnings
94 #ifdef _MSC_VER
95 #pragma warning (disable: 4996)     // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
96 #pragma warning (disable: 26451)    // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
97 #endif
98 
99 // Clang/GCC warnings with -Weverything
100 #if defined(__clang__)
101 #if __has_warning("-Wunknown-warning-option")
102 #pragma clang diagnostic ignored "-Wunknown-warning-option"         // warning: unknown warning group 'xxx'                     // not all warnings are known by all Clang versions and they tend to be rename-happy.. so ignoring warnings triggers new warnings on some configuration. Great!
103 #endif
104 #pragma clang diagnostic ignored "-Wunknown-pragmas"                // warning: unknown warning group 'xxx'
105 #pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast                           // yes, they are more terse.
106 #pragma clang diagnostic ignored "-Wdeprecated-declarations"        // warning: 'xx' is deprecated: The POSIX name for this..   // for strdup used in demo code (so user can copy & paste the code)
107 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"       // warning: cast to 'void *' from smaller integer type
108 #pragma clang diagnostic ignored "-Wformat-security"                // warning: format string is not a string literal
109 #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.
110 #pragma clang diagnostic ignored "-Wunused-macros"                  // warning: macro is not used                               // we define snprintf/vsnprintf on Windows so they are available, but not always used.
111 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant                   // some standard header variations use #define NULL 0
112 #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.
113 #pragma clang diagnostic ignored "-Wreserved-id-macro"              // warning: macro name is a reserved identifier
114 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
115 #elif defined(__GNUC__)
116 #pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
117 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
118 #pragma GCC diagnostic ignored "-Wformat-security"          // warning: format string is not a string literal (potentially insecure)
119 #pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
120 #pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
121 #pragma GCC diagnostic ignored "-Wmisleading-indentation"   // [__GNUC__ >= 6] warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
122 #endif
123 
124 // Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
125 #ifdef _WIN32
126 #define IM_NEWLINE  "\r\n"
127 #else
128 #define IM_NEWLINE  "\n"
129 #endif
130 
131 // Helpers
132 #if defined(_MSC_VER) && !defined(snprintf)
133 #define snprintf    _snprintf
134 #endif
135 #if defined(_MSC_VER) && !defined(vsnprintf)
136 #define vsnprintf   _vsnprintf
137 #endif
138 
139 // Format specifiers, printing 64-bit hasn't been decently standardized...
140 // In a real application you should be using PRId64 and PRIu64 from <inttypes.h> (non-windows) and on Windows define them yourself.
141 #ifdef _MSC_VER
142 #define IM_PRId64   "I64d"
143 #define IM_PRIu64   "I64u"
144 #else
145 #define IM_PRId64   "lld"
146 #define IM_PRIu64   "llu"
147 #endif
148 
149 // Helpers macros
150 // We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
151 // but making an exception here as those are largely simplifying code...
152 // In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo.
153 #define IM_MIN(A, B)            (((A) < (B)) ? (A) : (B))
154 #define IM_MAX(A, B)            (((A) >= (B)) ? (A) : (B))
155 #define IM_CLAMP(V, MN, MX)     ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
156 
157 // Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
158 #ifndef IMGUI_CDECL
159 #ifdef _MSC_VER
160 #define IMGUI_CDECL __cdecl
161 #else
162 #define IMGUI_CDECL
163 #endif
164 #endif
165 
166 //-----------------------------------------------------------------------------
167 // [SECTION] Forward Declarations, Helpers
168 //-----------------------------------------------------------------------------
169 
170 #if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
171 
172 // Forward Declarations
173 static void ShowExampleAppDocuments(bool* p_open);
174 static void ShowExampleAppMainMenuBar();
175 static void ShowExampleAppConsole(bool* p_open);
176 static void ShowExampleAppLog(bool* p_open);
177 static void ShowExampleAppLayout(bool* p_open);
178 static void ShowExampleAppPropertyEditor(bool* p_open);
179 static void ShowExampleAppLongText(bool* p_open);
180 static void ShowExampleAppAutoResize(bool* p_open);
181 static void ShowExampleAppConstrainedResize(bool* p_open);
182 static void ShowExampleAppSimpleOverlay(bool* p_open);
183 static void ShowExampleAppFullscreen(bool* p_open);
184 static void ShowExampleAppWindowTitles(bool* p_open);
185 static void ShowExampleAppCustomRendering(bool* p_open);
186 static void ShowExampleMenuFile();
187 
188 // Helper to display a little (?) mark which shows a tooltip when hovered.
189 // In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
HelpMarker(const char * desc)190 static void HelpMarker(const char* desc)
191 {
192     ImGui::TextDisabled("(?)");
193     if (ImGui::IsItemHovered())
194     {
195         ImGui::BeginTooltip();
196         ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
197         ImGui::TextUnformatted(desc);
198         ImGui::PopTextWrapPos();
199         ImGui::EndTooltip();
200     }
201 }
202 
203 // Helper to display basic user controls.
ShowUserGuide()204 void ImGui::ShowUserGuide()
205 {
206     ImGuiIO& io = ImGui::GetIO();
207     ImGui::BulletText("Double-click on title bar to collapse window.");
208     ImGui::BulletText(
209         "Click and drag on lower corner to resize window\n"
210         "(double-click to auto fit window to its contents).");
211     ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
212     ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
213     if (io.FontAllowUserScaling)
214         ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
215     ImGui::BulletText("While inputing text:\n");
216     ImGui::Indent();
217     ImGui::BulletText("CTRL+Left/Right to word jump.");
218     ImGui::BulletText("CTRL+A or double-click to select all.");
219     ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
220     ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
221     ImGui::BulletText("ESCAPE to revert.");
222     ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
223     ImGui::Unindent();
224     ImGui::BulletText("With keyboard navigation enabled:");
225     ImGui::Indent();
226     ImGui::BulletText("Arrow keys to navigate.");
227     ImGui::BulletText("Space to activate a widget.");
228     ImGui::BulletText("Return to input text into a widget.");
229     ImGui::BulletText("Escape to deactivate a widget, close popup, exit child window.");
230     ImGui::BulletText("Alt to jump to the menu layer of a window.");
231     ImGui::BulletText("CTRL+Tab to select a window.");
232     ImGui::Unindent();
233 }
234 
235 //-----------------------------------------------------------------------------
236 // [SECTION] Demo Window / ShowDemoWindow()
237 //-----------------------------------------------------------------------------
238 // - ShowDemoWindowWidgets()
239 // - ShowDemoWindowLayout()
240 // - ShowDemoWindowPopups()
241 // - ShowDemoWindowTables()
242 // - ShowDemoWindowColumns()
243 // - ShowDemoWindowMisc()
244 //-----------------------------------------------------------------------------
245 
246 // We split the contents of the big ShowDemoWindow() function into smaller functions
247 // (because the link time of very large functions grow non-linearly)
248 static void ShowDemoWindowWidgets();
249 static void ShowDemoWindowLayout();
250 static void ShowDemoWindowPopups();
251 static void ShowDemoWindowTables();
252 static void ShowDemoWindowColumns();
253 static void ShowDemoWindowMisc();
254 
255 // Demonstrate most Dear ImGui features (this is big function!)
256 // You may execute this function to experiment with the UI and understand what it does.
257 // You may then search for keywords in the code when you are interested by a specific feature.
ShowDemoWindow(bool * p_open)258 void ImGui::ShowDemoWindow(bool* p_open)
259 {
260     // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
261     // Most ImGui functions would normally just crash if the context is missing.
262     IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing dear imgui context. Refer to examples app!");
263 
264     // Examples Apps (accessible from the "Examples" menu)
265     static bool show_app_main_menu_bar = false;
266     static bool show_app_documents = false;
267 
268     static bool show_app_console = false;
269     static bool show_app_log = false;
270     static bool show_app_layout = false;
271     static bool show_app_property_editor = false;
272     static bool show_app_long_text = false;
273     static bool show_app_auto_resize = false;
274     static bool show_app_constrained_resize = false;
275     static bool show_app_simple_overlay = false;
276     static bool show_app_fullscreen = false;
277     static bool show_app_window_titles = false;
278     static bool show_app_custom_rendering = false;
279 
280     if (show_app_main_menu_bar)       ShowExampleAppMainMenuBar();
281     if (show_app_documents)           ShowExampleAppDocuments(&show_app_documents);
282 
283     if (show_app_console)             ShowExampleAppConsole(&show_app_console);
284     if (show_app_log)                 ShowExampleAppLog(&show_app_log);
285     if (show_app_layout)              ShowExampleAppLayout(&show_app_layout);
286     if (show_app_property_editor)     ShowExampleAppPropertyEditor(&show_app_property_editor);
287     if (show_app_long_text)           ShowExampleAppLongText(&show_app_long_text);
288     if (show_app_auto_resize)         ShowExampleAppAutoResize(&show_app_auto_resize);
289     if (show_app_constrained_resize)  ShowExampleAppConstrainedResize(&show_app_constrained_resize);
290     if (show_app_simple_overlay)      ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
291     if (show_app_fullscreen)          ShowExampleAppFullscreen(&show_app_fullscreen);
292     if (show_app_window_titles)       ShowExampleAppWindowTitles(&show_app_window_titles);
293     if (show_app_custom_rendering)    ShowExampleAppCustomRendering(&show_app_custom_rendering);
294 
295     // Dear ImGui Apps (accessible from the "Tools" menu)
296     static bool show_app_metrics = false;
297     static bool show_app_stack_tool = false;
298     static bool show_app_style_editor = false;
299     static bool show_app_about = false;
300 
301     if (show_app_metrics)       { ImGui::ShowMetricsWindow(&show_app_metrics); }
302     if (show_app_stack_tool)    { ImGui::ShowStackToolWindow(&show_app_stack_tool); }
303     if (show_app_about)         { ImGui::ShowAboutWindow(&show_app_about); }
304     if (show_app_style_editor)
305     {
306         ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor);
307         ImGui::ShowStyleEditor();
308         ImGui::End();
309     }
310 
311     // Demonstrate the various window flags. Typically you would just use the default!
312     static bool no_titlebar = false;
313     static bool no_scrollbar = false;
314     static bool no_menu = false;
315     static bool no_move = false;
316     static bool no_resize = false;
317     static bool no_collapse = false;
318     static bool no_close = false;
319     static bool no_nav = false;
320     static bool no_background = false;
321     static bool no_bring_to_front = false;
322     static bool unsaved_document = false;
323 
324     ImGuiWindowFlags window_flags = 0;
325     if (no_titlebar)        window_flags |= ImGuiWindowFlags_NoTitleBar;
326     if (no_scrollbar)       window_flags |= ImGuiWindowFlags_NoScrollbar;
327     if (!no_menu)           window_flags |= ImGuiWindowFlags_MenuBar;
328     if (no_move)            window_flags |= ImGuiWindowFlags_NoMove;
329     if (no_resize)          window_flags |= ImGuiWindowFlags_NoResize;
330     if (no_collapse)        window_flags |= ImGuiWindowFlags_NoCollapse;
331     if (no_nav)             window_flags |= ImGuiWindowFlags_NoNav;
332     if (no_background)      window_flags |= ImGuiWindowFlags_NoBackground;
333     if (no_bring_to_front)  window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
334     if (unsaved_document)   window_flags |= ImGuiWindowFlags_UnsavedDocument;
335     if (no_close)           p_open = NULL; // Don't pass our bool* to Begin
336 
337     // We specify a default position/size in case there's no data in the .ini file.
338     // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
339     const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
340     ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), ImGuiCond_FirstUseEver);
341     ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
342 
343     // Main body of the Demo window starts here.
344     if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags))
345     {
346         // Early out if the window is collapsed, as an optimization.
347         ImGui::End();
348         return;
349     }
350 
351     // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
352 
353     // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align)
354     //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f);
355 
356     // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
357     ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
358 
359     // Menu Bar
360     if (ImGui::BeginMenuBar())
361     {
362         if (ImGui::BeginMenu("Menu"))
363         {
364             ShowExampleMenuFile();
365             ImGui::EndMenu();
366         }
367         if (ImGui::BeginMenu("Examples"))
368         {
369             ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
370             ImGui::MenuItem("Console", NULL, &show_app_console);
371             ImGui::MenuItem("Log", NULL, &show_app_log);
372             ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
373             ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
374             ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
375             ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
376             ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
377             ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
378             ImGui::MenuItem("Fullscreen window", NULL, &show_app_fullscreen);
379             ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
380             ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
381             ImGui::MenuItem("Documents", NULL, &show_app_documents);
382             ImGui::EndMenu();
383         }
384         //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar!
385         if (ImGui::BeginMenu("Tools"))
386         {
387 #ifndef IMGUI_DISABLE_METRICS_WINDOW
388             ImGui::MenuItem("Metrics/Debugger", NULL, &show_app_metrics);
389             ImGui::MenuItem("Stack Tool", NULL, &show_app_stack_tool);
390 #endif
391             ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
392             ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
393             ImGui::EndMenu();
394         }
395         ImGui::EndMenuBar();
396     }
397 
398     ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
399     ImGui::Spacing();
400 
401     if (ImGui::CollapsingHeader("Help"))
402     {
403         ImGui::Text("ABOUT THIS DEMO:");
404         ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
405         ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
406         ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
407                           "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
408         ImGui::Separator();
409 
410         ImGui::Text("PROGRAMMER GUIDE:");
411         ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
412         ImGui::BulletText("See comments in imgui.cpp.");
413         ImGui::BulletText("See example applications in the examples/ folder.");
414         ImGui::BulletText("Read the FAQ at http://www.dearimgui.org/faq/");
415         ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
416         ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
417         ImGui::Separator();
418 
419         ImGui::Text("USER GUIDE:");
420         ImGui::ShowUserGuide();
421     }
422 
423     if (ImGui::CollapsingHeader("Configuration"))
424     {
425         ImGuiIO& io = ImGui::GetIO();
426 
427         if (ImGui::TreeNode("Configuration##2"))
428         {
429             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard",    &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
430             ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
431             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad",     &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
432             ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
433             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", &io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
434             ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
435             ImGui::CheckboxFlags("io.ConfigFlags: NoMouse",              &io.ConfigFlags, ImGuiConfigFlags_NoMouse);
436             if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
437             {
438                 // The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it:
439                 if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
440                 {
441                     ImGui::SameLine();
442                     ImGui::Text("<<PRESS SPACE TO DISABLE>>");
443                 }
444                 if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
445                     io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
446             }
447             ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
448             ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
449             ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
450             ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting)");
451             ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
452             ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
453             ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
454             ImGui::SameLine(); HelpMarker("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.");
455             ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
456             ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
457             ImGui::SameLine(); HelpMarker("Instruct Dear ImGui to render a mouse cursor itself. 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).");
458             ImGui::Text("Also see Style->Rendering for rendering options.");
459             ImGui::TreePop();
460             ImGui::Separator();
461         }
462 
463         if (ImGui::TreeNode("Backend Flags"))
464         {
465             HelpMarker(
466                 "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
467                 "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
468 
469             // Make a local copy to avoid modifying actual backend flags.
470             ImGuiBackendFlags backend_flags = io.BackendFlags;
471             ImGui::CheckboxFlags("io.BackendFlags: HasGamepad",           &backend_flags, ImGuiBackendFlags_HasGamepad);
472             ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors",      &backend_flags, ImGuiBackendFlags_HasMouseCursors);
473             ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos",       &backend_flags, ImGuiBackendFlags_HasSetMousePos);
474             ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &backend_flags, ImGuiBackendFlags_RendererHasVtxOffset);
475             ImGui::TreePop();
476             ImGui::Separator();
477         }
478 
479         if (ImGui::TreeNode("Style"))
480         {
481             HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
482             ImGui::ShowStyleEditor();
483             ImGui::TreePop();
484             ImGui::Separator();
485         }
486 
487         if (ImGui::TreeNode("Capture/Logging"))
488         {
489             HelpMarker(
490                 "The logging API redirects all text output so you can easily capture the content of "
491                 "a window or a block. Tree nodes can be automatically expanded.\n"
492                 "Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
493             ImGui::LogButtons();
494 
495             HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output.");
496             if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
497             {
498                 ImGui::LogToClipboard();
499                 ImGui::LogText("Hello, world!");
500                 ImGui::LogFinish();
501             }
502             ImGui::TreePop();
503         }
504     }
505 
506     if (ImGui::CollapsingHeader("Window options"))
507     {
508         if (ImGui::BeginTable("split", 3))
509         {
510             ImGui::TableNextColumn(); ImGui::Checkbox("No titlebar", &no_titlebar);
511             ImGui::TableNextColumn(); ImGui::Checkbox("No scrollbar", &no_scrollbar);
512             ImGui::TableNextColumn(); ImGui::Checkbox("No menu", &no_menu);
513             ImGui::TableNextColumn(); ImGui::Checkbox("No move", &no_move);
514             ImGui::TableNextColumn(); ImGui::Checkbox("No resize", &no_resize);
515             ImGui::TableNextColumn(); ImGui::Checkbox("No collapse", &no_collapse);
516             ImGui::TableNextColumn(); ImGui::Checkbox("No close", &no_close);
517             ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav);
518             ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background);
519             ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front);
520             ImGui::TableNextColumn(); ImGui::Checkbox("Unsaved document", &unsaved_document);
521             ImGui::EndTable();
522         }
523     }
524 
525     // All demo contents
526     ShowDemoWindowWidgets();
527     ShowDemoWindowLayout();
528     ShowDemoWindowPopups();
529     ShowDemoWindowTables();
530     ShowDemoWindowMisc();
531 
532     // End of ShowDemoWindow()
533     ImGui::PopItemWidth();
534     ImGui::End();
535 }
536 
ShowDemoWindowWidgets()537 static void ShowDemoWindowWidgets()
538 {
539     if (!ImGui::CollapsingHeader("Widgets"))
540         return;
541 
542     static bool disable_all = false; // The Checkbox for that is inside the "Disabled" section at the bottom
543     if (disable_all)
544         ImGui::BeginDisabled();
545 
546     if (ImGui::TreeNode("Basic"))
547     {
548         static int clicked = 0;
549         if (ImGui::Button("Button"))
550             clicked++;
551         if (clicked & 1)
552         {
553             ImGui::SameLine();
554             ImGui::Text("Thanks for clicking me!");
555         }
556 
557         static bool check = true;
558         ImGui::Checkbox("checkbox", &check);
559 
560         static int e = 0;
561         ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
562         ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
563         ImGui::RadioButton("radio c", &e, 2);
564 
565         // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
566         for (int i = 0; i < 7; i++)
567         {
568             if (i > 0)
569                 ImGui::SameLine();
570             ImGui::PushID(i);
571             ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
572             ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
573             ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
574             ImGui::Button("Click");
575             ImGui::PopStyleColor(3);
576             ImGui::PopID();
577         }
578 
579         // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
580         // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
581         // See 'Demo->Layout->Text Baseline Alignment' for details.
582         ImGui::AlignTextToFramePadding();
583         ImGui::Text("Hold to repeat:");
584         ImGui::SameLine();
585 
586         // Arrow buttons with Repeater
587         static int counter = 0;
588         float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
589         ImGui::PushButtonRepeat(true);
590         if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
591         ImGui::SameLine(0.0f, spacing);
592         if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
593         ImGui::PopButtonRepeat();
594         ImGui::SameLine();
595         ImGui::Text("%d", counter);
596 
597         ImGui::Text("Hover over me");
598         if (ImGui::IsItemHovered())
599             ImGui::SetTooltip("I am a tooltip");
600 
601         ImGui::SameLine();
602         ImGui::Text("- or me");
603         if (ImGui::IsItemHovered())
604         {
605             ImGui::BeginTooltip();
606             ImGui::Text("I am a fancy tooltip");
607             static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
608             ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
609             ImGui::EndTooltip();
610         }
611 
612         ImGui::Separator();
613 
614         ImGui::LabelText("label", "Value");
615 
616         {
617             // Using the _simplified_ one-liner Combo() api here
618             // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
619             const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
620             static int item_current = 0;
621             ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
622             ImGui::SameLine(); HelpMarker(
623                 "Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
624         }
625 
626         {
627             // To wire InputText() with std::string or any other custom string type,
628             // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
629             static char str0[128] = "Hello, world!";
630             ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
631             ImGui::SameLine(); HelpMarker(
632                 "USER:\n"
633                 "Hold SHIFT or use mouse to select text.\n"
634                 "CTRL+Left/Right to word jump.\n"
635                 "CTRL+A or double-click to select all.\n"
636                 "CTRL+X,CTRL+C,CTRL+V clipboard.\n"
637                 "CTRL+Z,CTRL+Y undo/redo.\n"
638                 "ESCAPE to revert.\n\n"
639                 "PROGRAMMER:\n"
640                 "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
641                 "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
642                 "in imgui_demo.cpp).");
643 
644             static char str1[128] = "";
645             ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
646 
647             static int i0 = 123;
648             ImGui::InputInt("input int", &i0);
649             ImGui::SameLine(); HelpMarker(
650                 "You can apply arithmetic operators +,*,/ on numerical values.\n"
651                 "  e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n"
652                 "Use +- to subtract.");
653 
654             static float f0 = 0.001f;
655             ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
656 
657             static double d0 = 999999.00000001;
658             ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
659 
660             static float f1 = 1.e10f;
661             ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
662             ImGui::SameLine(); HelpMarker(
663                 "You can input value using the scientific notation,\n"
664                 "  e.g. \"1e+8\" becomes \"100000000\".");
665 
666             static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
667             ImGui::InputFloat3("input float3", vec4a);
668         }
669 
670         {
671             static int i1 = 50, i2 = 42;
672             ImGui::DragInt("drag int", &i1, 1);
673             ImGui::SameLine(); HelpMarker(
674                 "Click and drag to edit value.\n"
675                 "Hold SHIFT/ALT for faster/slower edit.\n"
676                 "Double-click or CTRL+click to input value.");
677 
678             ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
679 
680             static float f1 = 1.00f, f2 = 0.0067f;
681             ImGui::DragFloat("drag float", &f1, 0.005f);
682             ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
683         }
684 
685         {
686             static int i1 = 0;
687             ImGui::SliderInt("slider int", &i1, -1, 3);
688             ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
689 
690             static float f1 = 0.123f, f2 = 0.0f;
691             ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
692             ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic);
693 
694             static float angle = 0.0f;
695             ImGui::SliderAngle("slider angle", &angle);
696 
697             // Using the format string to display a name instead of an integer.
698             // Here we completely omit '%d' from the format string, so it'll only display a name.
699             // This technique can also be used with DragInt().
700             enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
701             static int elem = Element_Fire;
702             const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
703             const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
704             ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name);
705             ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
706         }
707 
708         {
709             static float col1[3] = { 1.0f, 0.0f, 0.2f };
710             static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
711             ImGui::ColorEdit3("color 1", col1);
712             ImGui::SameLine(); HelpMarker(
713                 "Click on the color square to open a color picker.\n"
714                 "Click and hold to use drag and drop.\n"
715                 "Right-click on the color square to show options.\n"
716                 "CTRL+click on individual component to input value.\n");
717 
718             ImGui::ColorEdit4("color 2", col2);
719         }
720 
721         {
722             // Using the _simplified_ one-liner ListBox() api here
723             // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
724             const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
725             static int item_current = 1;
726             ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4);
727             ImGui::SameLine(); HelpMarker(
728                 "Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
729         }
730 
731         ImGui::TreePop();
732     }
733 
734     // Testing ImGuiOnceUponAFrame helper.
735     //static ImGuiOnceUponAFrame once;
736     //for (int i = 0; i < 5; i++)
737     //    if (once)
738     //        ImGui::Text("This will be displayed only once.");
739 
740     if (ImGui::TreeNode("Trees"))
741     {
742         if (ImGui::TreeNode("Basic trees"))
743         {
744             for (int i = 0; i < 5; i++)
745             {
746                 // Use SetNextItemOpen() so set the default state of a node to be open. We could
747                 // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
748                 if (i == 0)
749                     ImGui::SetNextItemOpen(true, ImGuiCond_Once);
750 
751                 if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
752                 {
753                     ImGui::Text("blah blah");
754                     ImGui::SameLine();
755                     if (ImGui::SmallButton("button")) {}
756                     ImGui::TreePop();
757                 }
758             }
759             ImGui::TreePop();
760         }
761 
762         if (ImGui::TreeNode("Advanced, with Selectable nodes"))
763         {
764             HelpMarker(
765                 "This is a more typical looking tree with selectable nodes.\n"
766                 "Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
767             static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
768             static bool align_label_with_current_x_position = false;
769             static bool test_drag_and_drop = false;
770             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow",       &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
771             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
772             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth",    &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
773             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth",     &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
774             ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
775             ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
776             ImGui::Text("Hello!");
777             if (align_label_with_current_x_position)
778                 ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
779 
780             // 'selection_mask' is dumb representation of what may be user-side selection state.
781             //  You may retain selection state inside or outside your objects in whatever format you see fit.
782             // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
783             /// of the loop. May be a pointer to your own node type, etc.
784             static int selection_mask = (1 << 2);
785             int node_clicked = -1;
786             for (int i = 0; i < 6; i++)
787             {
788                 // Disable the default "open on single-click behavior" + set Selected flag according to our selection.
789                 ImGuiTreeNodeFlags node_flags = base_flags;
790                 const bool is_selected = (selection_mask & (1 << i)) != 0;
791                 if (is_selected)
792                     node_flags |= ImGuiTreeNodeFlags_Selected;
793                 if (i < 3)
794                 {
795                     // Items 0..2 are Tree Node
796                     bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
797                     if (ImGui::IsItemClicked())
798                         node_clicked = i;
799                     if (test_drag_and_drop && ImGui::BeginDragDropSource())
800                     {
801                         ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
802                         ImGui::Text("This is a drag and drop source");
803                         ImGui::EndDragDropSource();
804                     }
805                     if (node_open)
806                     {
807                         ImGui::BulletText("Blah blah\nBlah Blah");
808                         ImGui::TreePop();
809                     }
810                 }
811                 else
812                 {
813                     // Items 3..5 are Tree Leaves
814                     // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
815                     // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
816                     node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
817                     ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
818                     if (ImGui::IsItemClicked())
819                         node_clicked = i;
820                     if (test_drag_and_drop && ImGui::BeginDragDropSource())
821                     {
822                         ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
823                         ImGui::Text("This is a drag and drop source");
824                         ImGui::EndDragDropSource();
825                     }
826                 }
827             }
828             if (node_clicked != -1)
829             {
830                 // Update selection state
831                 // (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
832                 if (ImGui::GetIO().KeyCtrl)
833                     selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
834                 else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
835                     selection_mask = (1 << node_clicked);           // Click to single-select
836             }
837             if (align_label_with_current_x_position)
838                 ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
839             ImGui::TreePop();
840         }
841         ImGui::TreePop();
842     }
843 
844     if (ImGui::TreeNode("Collapsing Headers"))
845     {
846         static bool closable_group = true;
847         ImGui::Checkbox("Show 2nd header", &closable_group);
848         if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None))
849         {
850             ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
851             for (int i = 0; i < 5; i++)
852                 ImGui::Text("Some content %d", i);
853         }
854         if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
855         {
856             ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
857             for (int i = 0; i < 5; i++)
858                 ImGui::Text("More content %d", i);
859         }
860         /*
861         if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet))
862             ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
863         */
864         ImGui::TreePop();
865     }
866 
867     if (ImGui::TreeNode("Bullets"))
868     {
869         ImGui::BulletText("Bullet point 1");
870         ImGui::BulletText("Bullet point 2\nOn multiple lines");
871         if (ImGui::TreeNode("Tree node"))
872         {
873             ImGui::BulletText("Another bullet point");
874             ImGui::TreePop();
875         }
876         ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
877         ImGui::Bullet(); ImGui::SmallButton("Button");
878         ImGui::TreePop();
879     }
880 
881     if (ImGui::TreeNode("Text"))
882     {
883         if (ImGui::TreeNode("Colorful Text"))
884         {
885             // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
886             ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
887             ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
888             ImGui::TextDisabled("Disabled");
889             ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
890             ImGui::TreePop();
891         }
892 
893         if (ImGui::TreeNode("Word Wrapping"))
894         {
895             // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
896             ImGui::TextWrapped(
897                 "This text should automatically wrap on the edge of the window. The current implementation "
898                 "for text wrapping follows simple rules suitable for English and possibly other languages.");
899             ImGui::Spacing();
900 
901             static float wrap_width = 200.0f;
902             ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
903 
904             ImDrawList* draw_list = ImGui::GetWindowDrawList();
905             for (int n = 0; n < 2; n++)
906             {
907                 ImGui::Text("Test paragraph %d:", n);
908                 ImVec2 pos = ImGui::GetCursorScreenPos();
909                 ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y);
910                 ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight());
911                 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
912                 if (n == 0)
913                     ImGui::Text("The lazy dog is a good dog. This paragraph should fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
914                 else
915                     ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
916 
917                 // Draw actual text bounding box, following by marker of our expected limit (should not overlap!)
918                 draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
919                 draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255));
920                 ImGui::PopTextWrapPos();
921             }
922 
923             ImGui::TreePop();
924         }
925 
926         if (ImGui::TreeNode("UTF-8 Text"))
927         {
928             // UTF-8 test with Japanese characters
929             // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
930             // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
931             // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
932             //   can save your source files as 'UTF-8 without signature').
933             // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8
934             //   CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants.
935             //   Don't do this in your application! Please use u8"text in any language" in your application!
936             // Note that characters values are preserved even by InputText() if the font cannot be displayed,
937             // so you can safely copy & paste garbled characters into another application.
938             ImGui::TextWrapped(
939                 "CJK text will only appears if the font was loaded with the appropriate CJK character ranges. "
940                 "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. "
941                 "Read docs/FONTS.md for details.");
942             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.
943             ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
944             static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
945             //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
946             ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
947             ImGui::TreePop();
948         }
949         ImGui::TreePop();
950     }
951 
952     if (ImGui::TreeNode("Images"))
953     {
954         ImGuiIO& io = ImGui::GetIO();
955         ImGui::TextWrapped(
956             "Below we are displaying the font texture (which is the only texture we have access to in this demo). "
957             "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. "
958             "Hover the texture for a zoomed view!");
959 
960         // Below we are displaying the font texture because it is the only texture we have access to inside the demo!
961         // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that
962         // will be passed to the rendering backend via the ImDrawCmd structure.
963         // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top
964         // of their respective source file to specify what they expect to be stored in ImTextureID, for example:
965         // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer
966         // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc.
967         // More:
968         // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers
969         //   to ImGui::Image(), and gather width/height through your own functions, etc.
970         // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer,
971         //   it will help you debug issues if you are confused about it.
972         // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
973         // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
974         // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
975         ImTextureID my_tex_id = io.Fonts->TexID;
976         float my_tex_w = (float)io.Fonts->TexWidth;
977         float my_tex_h = (float)io.Fonts->TexHeight;
978         {
979             ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
980             ImVec2 pos = ImGui::GetCursorScreenPos();
981             ImVec2 uv_min = ImVec2(0.0f, 0.0f);                 // Top-left
982             ImVec2 uv_max = ImVec2(1.0f, 1.0f);                 // Lower-right
983             ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);   // No tint
984             ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white
985             ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
986             if (ImGui::IsItemHovered())
987             {
988                 ImGui::BeginTooltip();
989                 float region_sz = 32.0f;
990                 float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
991                 float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
992                 float zoom = 4.0f;
993                 if (region_x < 0.0f) { region_x = 0.0f; }
994                 else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
995                 if (region_y < 0.0f) { region_y = 0.0f; }
996                 else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
997                 ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
998                 ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
999                 ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
1000                 ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
1001                 ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col);
1002                 ImGui::EndTooltip();
1003             }
1004         }
1005         ImGui::TextWrapped("And now some textured buttons..");
1006         static int pressed_count = 0;
1007         for (int i = 0; i < 8; i++)
1008         {
1009             ImGui::PushID(i);
1010             int frame_padding = -1 + i;                             // -1 == uses default padding (style.FramePadding)
1011             ImVec2 size = ImVec2(32.0f, 32.0f);                     // Size of the image we want to make visible
1012             ImVec2 uv0 = ImVec2(0.0f, 0.0f);                        // UV coordinates for lower-left
1013             ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h);// UV coordinates for (32,32) in our texture
1014             ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);         // Black background
1015             ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);       // No tint
1016             if (ImGui::ImageButton(my_tex_id, size, uv0, uv1, frame_padding, bg_col, tint_col))
1017                 pressed_count += 1;
1018             ImGui::PopID();
1019             ImGui::SameLine();
1020         }
1021         ImGui::NewLine();
1022         ImGui::Text("Pressed %d times.", pressed_count);
1023         ImGui::TreePop();
1024     }
1025 
1026     if (ImGui::TreeNode("Combo"))
1027     {
1028         // Expose flags as checkbox for the demo
1029         static ImGuiComboFlags flags = 0;
1030         ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft);
1031         ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
1032         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton))
1033             flags &= ~ImGuiComboFlags_NoPreview;     // Clear the other flag, as we cannot combine both
1034         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview))
1035             flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both
1036 
1037         // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
1038         // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
1039         // stored in the object itself, etc.)
1040         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
1041         static int item_current_idx = 0; // Here we store our selection data as an index.
1042         const char* combo_preview_value = items[item_current_idx];  // Pass in the preview value visible before opening the combo (it could be anything)
1043         if (ImGui::BeginCombo("combo 1", combo_preview_value, flags))
1044         {
1045             for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1046             {
1047                 const bool is_selected = (item_current_idx == n);
1048                 if (ImGui::Selectable(items[n], is_selected))
1049                     item_current_idx = n;
1050 
1051                 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1052                 if (is_selected)
1053                     ImGui::SetItemDefaultFocus();
1054             }
1055             ImGui::EndCombo();
1056         }
1057 
1058         // Simplified one-liner Combo() API, using values packed in a single constant string
1059         // This is a convenience for when the selection set is small and known at compile-time.
1060         static int item_current_2 = 0;
1061         ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
1062 
1063         // Simplified one-liner Combo() using an array of const char*
1064         // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control.
1065         static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
1066         ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
1067 
1068         // Simplified one-liner Combo() using an accessor function
1069         struct Funcs { static bool ItemGetter(void* data, int n, const char** out_str) { *out_str = ((const char**)data)[n]; return true; } };
1070         static int item_current_4 = 0;
1071         ImGui::Combo("combo 4 (function)", &item_current_4, &Funcs::ItemGetter, items, IM_ARRAYSIZE(items));
1072 
1073         ImGui::TreePop();
1074     }
1075 
1076     if (ImGui::TreeNode("List boxes"))
1077     {
1078         // Using the generic BeginListBox() API, you have full control over how to display the combo contents.
1079         // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
1080         // stored in the object itself, etc.)
1081         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
1082         static int item_current_idx = 0; // Here we store our selection data as an index.
1083         if (ImGui::BeginListBox("listbox 1"))
1084         {
1085             for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1086             {
1087                 const bool is_selected = (item_current_idx == n);
1088                 if (ImGui::Selectable(items[n], is_selected))
1089                     item_current_idx = n;
1090 
1091                 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1092                 if (is_selected)
1093                     ImGui::SetItemDefaultFocus();
1094             }
1095             ImGui::EndListBox();
1096         }
1097 
1098         // Custom size: use all width, 5 items tall
1099         ImGui::Text("Full-width:");
1100         if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing())))
1101         {
1102             for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1103             {
1104                 const bool is_selected = (item_current_idx == n);
1105                 if (ImGui::Selectable(items[n], is_selected))
1106                     item_current_idx = n;
1107 
1108                 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1109                 if (is_selected)
1110                     ImGui::SetItemDefaultFocus();
1111             }
1112             ImGui::EndListBox();
1113         }
1114 
1115         ImGui::TreePop();
1116     }
1117 
1118     if (ImGui::TreeNode("Selectables"))
1119     {
1120         // Selectable() has 2 overloads:
1121         // - The one taking "bool selected" as a read-only selection information.
1122         //   When Selectable() has been clicked it returns true and you can alter selection state accordingly.
1123         // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
1124         // The earlier is more flexible, as in real application your selection may be stored in many different ways
1125         // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc).
1126         if (ImGui::TreeNode("Basic"))
1127         {
1128             static bool selection[5] = { false, true, false, false, false };
1129             ImGui::Selectable("1. I am selectable", &selection[0]);
1130             ImGui::Selectable("2. I am selectable", &selection[1]);
1131             ImGui::Text("(I am not selectable)");
1132             ImGui::Selectable("4. I am selectable", &selection[3]);
1133             if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
1134                 if (ImGui::IsMouseDoubleClicked(0))
1135                     selection[4] = !selection[4];
1136             ImGui::TreePop();
1137         }
1138         if (ImGui::TreeNode("Selection State: Single Selection"))
1139         {
1140             static int selected = -1;
1141             for (int n = 0; n < 5; n++)
1142             {
1143                 char buf[32];
1144                 sprintf(buf, "Object %d", n);
1145                 if (ImGui::Selectable(buf, selected == n))
1146                     selected = n;
1147             }
1148             ImGui::TreePop();
1149         }
1150         if (ImGui::TreeNode("Selection State: Multiple Selection"))
1151         {
1152             HelpMarker("Hold CTRL and click to select multiple items.");
1153             static bool selection[5] = { false, false, false, false, false };
1154             for (int n = 0; n < 5; n++)
1155             {
1156                 char buf[32];
1157                 sprintf(buf, "Object %d", n);
1158                 if (ImGui::Selectable(buf, selection[n]))
1159                 {
1160                     if (!ImGui::GetIO().KeyCtrl)    // Clear selection when CTRL is not held
1161                         memset(selection, 0, sizeof(selection));
1162                     selection[n] ^= 1;
1163                 }
1164             }
1165             ImGui::TreePop();
1166         }
1167         if (ImGui::TreeNode("Rendering more text into the same line"))
1168         {
1169             // Using the Selectable() override that takes "bool* p_selected" parameter,
1170             // this function toggle your bool value automatically.
1171             static bool selected[3] = { false, false, false };
1172             ImGui::Selectable("main.c",    &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
1173             ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
1174             ImGui::Selectable("Hello.h",   &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
1175             ImGui::TreePop();
1176         }
1177         if (ImGui::TreeNode("In columns"))
1178         {
1179             static bool selected[10] = {};
1180 
1181             if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
1182             {
1183                 for (int i = 0; i < 10; i++)
1184                 {
1185                     char label[32];
1186                     sprintf(label, "Item %d", i);
1187                     ImGui::TableNextColumn();
1188                     ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap
1189                 }
1190                 ImGui::EndTable();
1191             }
1192             ImGui::Spacing();
1193             if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
1194             {
1195                 for (int i = 0; i < 10; i++)
1196                 {
1197                     char label[32];
1198                     sprintf(label, "Item %d", i);
1199                     ImGui::TableNextRow();
1200                     ImGui::TableNextColumn();
1201                     ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns);
1202                     ImGui::TableNextColumn();
1203                     ImGui::Text("Some other contents");
1204                     ImGui::TableNextColumn();
1205                     ImGui::Text("123456");
1206                 }
1207                 ImGui::EndTable();
1208             }
1209             ImGui::TreePop();
1210         }
1211         if (ImGui::TreeNode("Grid"))
1212         {
1213             static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
1214 
1215             // Add in a bit of silly fun...
1216             const float time = (float)ImGui::GetTime();
1217             const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected...
1218             if (winning_state)
1219                 ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f)));
1220 
1221             for (int y = 0; y < 4; y++)
1222                 for (int x = 0; x < 4; x++)
1223                 {
1224                     if (x > 0)
1225                         ImGui::SameLine();
1226                     ImGui::PushID(y * 4 + x);
1227                     if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50)))
1228                     {
1229                         // Toggle clicked cell + toggle neighbors
1230                         selected[y][x] ^= 1;
1231                         if (x > 0) { selected[y][x - 1] ^= 1; }
1232                         if (x < 3) { selected[y][x + 1] ^= 1; }
1233                         if (y > 0) { selected[y - 1][x] ^= 1; }
1234                         if (y < 3) { selected[y + 1][x] ^= 1; }
1235                     }
1236                     ImGui::PopID();
1237                 }
1238 
1239             if (winning_state)
1240                 ImGui::PopStyleVar();
1241             ImGui::TreePop();
1242         }
1243         if (ImGui::TreeNode("Alignment"))
1244         {
1245             HelpMarker(
1246                 "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item "
1247                 "basis using PushStyleVar(). You'll probably want to always keep your default situation to "
1248                 "left-align otherwise it becomes difficult to layout multiple items on a same line");
1249             static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true };
1250             for (int y = 0; y < 3; y++)
1251             {
1252                 for (int x = 0; x < 3; x++)
1253                 {
1254                     ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
1255                     char name[32];
1256                     sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
1257                     if (x > 0) ImGui::SameLine();
1258                     ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
1259                     ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80));
1260                     ImGui::PopStyleVar();
1261                 }
1262             }
1263             ImGui::TreePop();
1264         }
1265         ImGui::TreePop();
1266     }
1267 
1268     // To wire InputText() with std::string or any other custom string type,
1269     // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
1270     if (ImGui::TreeNode("Text Input"))
1271     {
1272         if (ImGui::TreeNode("Multi-line Text Input"))
1273         {
1274             // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
1275             // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
1276             static char text[1024 * 16] =
1277                 "/*\n"
1278                 " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
1279                 " the hexadecimal encoding of one offending instruction,\n"
1280                 " more formally, the invalid operand with locked CMPXCHG8B\n"
1281                 " instruction bug, is a design flaw in the majority of\n"
1282                 " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
1283                 " processors (all in the P5 microarchitecture).\n"
1284                 "*/\n\n"
1285                 "label:\n"
1286                 "\tlock cmpxchg8b eax\n";
1287 
1288             static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
1289             HelpMarker("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 because we don't want to include <string> in here)");
1290             ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
1291             ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
1292             ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
1293             ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
1294             ImGui::TreePop();
1295         }
1296 
1297         if (ImGui::TreeNode("Filtered Text Input"))
1298         {
1299             struct TextFilters
1300             {
1301                 // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i'
1302                 static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
1303                 {
1304                     if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
1305                         return 0;
1306                     return 1;
1307                 }
1308             };
1309 
1310             static char buf1[64] = ""; ImGui::InputText("default",     buf1, 64);
1311             static char buf2[64] = ""; ImGui::InputText("decimal",     buf2, 64, ImGuiInputTextFlags_CharsDecimal);
1312             static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
1313             static char buf4[64] = ""; ImGui::InputText("uppercase",   buf4, 64, ImGuiInputTextFlags_CharsUppercase);
1314             static char buf5[64] = ""; ImGui::InputText("no blank",    buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
1315             static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
1316             ImGui::TreePop();
1317         }
1318 
1319         if (ImGui::TreeNode("Password Input"))
1320         {
1321             static char password[64] = "password123";
1322             ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
1323             ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
1324             ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
1325             ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password));
1326             ImGui::TreePop();
1327         }
1328 
1329         if (ImGui::TreeNode("Completion, History, Edit Callbacks"))
1330         {
1331             struct Funcs
1332             {
1333                 static int MyCallback(ImGuiInputTextCallbackData* data)
1334                 {
1335                     if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
1336                     {
1337                         data->InsertChars(data->CursorPos, "..");
1338                     }
1339                     else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
1340                     {
1341                         if (data->EventKey == ImGuiKey_UpArrow)
1342                         {
1343                             data->DeleteChars(0, data->BufTextLen);
1344                             data->InsertChars(0, "Pressed Up!");
1345                             data->SelectAll();
1346                         }
1347                         else if (data->EventKey == ImGuiKey_DownArrow)
1348                         {
1349                             data->DeleteChars(0, data->BufTextLen);
1350                             data->InsertChars(0, "Pressed Down!");
1351                             data->SelectAll();
1352                         }
1353                     }
1354                     else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
1355                     {
1356                         // Toggle casing of first character
1357                         char c = data->Buf[0];
1358                         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32;
1359                         data->BufDirty = true;
1360 
1361                         // Increment a counter
1362                         int* p_int = (int*)data->UserData;
1363                         *p_int = *p_int + 1;
1364                     }
1365                     return 0;
1366                 }
1367             };
1368             static char buf1[64];
1369             ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
1370             ImGui::SameLine(); HelpMarker("Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
1371 
1372             static char buf2[64];
1373             ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
1374             ImGui::SameLine(); HelpMarker("Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
1375 
1376             static char buf3[64];
1377             static int edit_count = 0;
1378             ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
1379             ImGui::SameLine(); HelpMarker("Here we toggle the casing of the first character on every edits + count edits.");
1380             ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
1381 
1382             ImGui::TreePop();
1383         }
1384 
1385         if (ImGui::TreeNode("Resize Callback"))
1386         {
1387             // To wire InputText() with std::string or any other custom string type,
1388             // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper
1389             // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string.
1390             HelpMarker(
1391                 "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n"
1392                 "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string.");
1393             struct Funcs
1394             {
1395                 static int MyResizeCallback(ImGuiInputTextCallbackData* data)
1396                 {
1397                     if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
1398                     {
1399                         ImVector<char>* my_str = (ImVector<char>*)data->UserData;
1400                         IM_ASSERT(my_str->begin() == data->Buf);
1401                         my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1
1402                         data->Buf = my_str->begin();
1403                     }
1404                     return 0;
1405                 }
1406 
1407                 // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace.
1408                 // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)'
1409                 static bool MyInputTextMultiline(const char* label, ImVector<char>* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
1410                 {
1411                     IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
1412                     return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str);
1413                 }
1414             };
1415 
1416             // For this demo we are using ImVector as a string container.
1417             // Note that because we need to store a terminating zero character, our size/capacity are 1 more
1418             // than usually reported by a typical string class.
1419             static ImVector<char> my_str;
1420             if (my_str.empty())
1421                 my_str.push_back(0);
1422             Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16));
1423             ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity());
1424             ImGui::TreePop();
1425         }
1426 
1427         ImGui::TreePop();
1428     }
1429 
1430     // Tabs
1431     if (ImGui::TreeNode("Tabs"))
1432     {
1433         if (ImGui::TreeNode("Basic"))
1434         {
1435             ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
1436             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1437             {
1438                 if (ImGui::BeginTabItem("Avocado"))
1439                 {
1440                     ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
1441                     ImGui::EndTabItem();
1442                 }
1443                 if (ImGui::BeginTabItem("Broccoli"))
1444                 {
1445                     ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
1446                     ImGui::EndTabItem();
1447                 }
1448                 if (ImGui::BeginTabItem("Cucumber"))
1449                 {
1450                     ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
1451                     ImGui::EndTabItem();
1452                 }
1453                 ImGui::EndTabBar();
1454             }
1455             ImGui::Separator();
1456             ImGui::TreePop();
1457         }
1458 
1459         if (ImGui::TreeNode("Advanced & Close Button"))
1460         {
1461             // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
1462             static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
1463             ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable);
1464             ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
1465             ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
1466             ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
1467             if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
1468                 tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
1469             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
1470                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
1471             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
1472                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
1473 
1474             // Tab Bar
1475             const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
1476             static bool opened[4] = { true, true, true, true }; // Persistent user state
1477             for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1478             {
1479                 if (n > 0) { ImGui::SameLine(); }
1480                 ImGui::Checkbox(names[n], &opened[n]);
1481             }
1482 
1483             // Passing a bool* to BeginTabItem() is similar to passing one to Begin():
1484             // the underlying bool will be set to false when the tab is closed.
1485             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1486             {
1487                 for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1488                     if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
1489                     {
1490                         ImGui::Text("This is the %s tab!", names[n]);
1491                         if (n & 1)
1492                             ImGui::Text("I am an odd tab.");
1493                         ImGui::EndTabItem();
1494                     }
1495                 ImGui::EndTabBar();
1496             }
1497             ImGui::Separator();
1498             ImGui::TreePop();
1499         }
1500 
1501         if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags"))
1502         {
1503             static ImVector<int> active_tabs;
1504             static int next_tab_id = 0;
1505             if (next_tab_id == 0) // Initialize with some default tabs
1506                 for (int i = 0; i < 3; i++)
1507                     active_tabs.push_back(next_tab_id++);
1508 
1509             // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together.
1510             // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags...
1511             // but they tend to make more sense together)
1512             static bool show_leading_button = true;
1513             static bool show_trailing_button = true;
1514             ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
1515             ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
1516 
1517             // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
1518             static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown;
1519             ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
1520             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
1521                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
1522             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
1523                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
1524 
1525             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1526             {
1527                 // Demo a Leading TabItemButton(): click the "?" button to open a menu
1528                 if (show_leading_button)
1529                     if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip))
1530                         ImGui::OpenPopup("MyHelpMenu");
1531                 if (ImGui::BeginPopup("MyHelpMenu"))
1532                 {
1533                     ImGui::Selectable("Hello!");
1534                     ImGui::EndPopup();
1535                 }
1536 
1537                 // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+")
1538                 // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
1539                 if (show_trailing_button)
1540                     if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
1541                         active_tabs.push_back(next_tab_id++); // Add new tab
1542 
1543                 // Submit our regular tabs
1544                 for (int n = 0; n < active_tabs.Size; )
1545                 {
1546                     bool open = true;
1547                     char name[16];
1548                     snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);
1549                     if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
1550                     {
1551                         ImGui::Text("This is the %s tab!", name);
1552                         ImGui::EndTabItem();
1553                     }
1554 
1555                     if (!open)
1556                         active_tabs.erase(active_tabs.Data + n);
1557                     else
1558                         n++;
1559                 }
1560 
1561                 ImGui::EndTabBar();
1562             }
1563             ImGui::Separator();
1564             ImGui::TreePop();
1565         }
1566         ImGui::TreePop();
1567     }
1568 
1569     // Plot/Graph widgets are not very good.
1570     // Consider using a third-party library such as ImPlot: https://github.com/epezent/implot
1571     // (see others https://github.com/ocornut/imgui/wiki/Useful-Extensions)
1572     if (ImGui::TreeNode("Plots Widgets"))
1573     {
1574         static bool animate = true;
1575         ImGui::Checkbox("Animate", &animate);
1576 
1577         // Plot as lines and plot as histogram
1578         static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
1579         ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
1580         ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
1581 
1582         // Fill an array of contiguous float values to plot
1583         // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
1584         // and the sizeof() of your structure in the "stride" parameter.
1585         static float values[90] = {};
1586         static int values_offset = 0;
1587         static double refresh_time = 0.0;
1588         if (!animate || refresh_time == 0.0)
1589             refresh_time = ImGui::GetTime();
1590         while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
1591         {
1592             static float phase = 0.0f;
1593             values[values_offset] = cosf(phase);
1594             values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
1595             phase += 0.10f * values_offset;
1596             refresh_time += 1.0f / 60.0f;
1597         }
1598 
1599         // Plots can display overlay texts
1600         // (in this example, we will display an average value)
1601         {
1602             float average = 0.0f;
1603             for (int n = 0; n < IM_ARRAYSIZE(values); n++)
1604                 average += values[n];
1605             average /= (float)IM_ARRAYSIZE(values);
1606             char overlay[32];
1607             sprintf(overlay, "avg %f", average);
1608             ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
1609         }
1610 
1611         // Use functions to generate output
1612         // FIXME: This is rather awkward because current plot API only pass in indices.
1613         // We probably want an API passing floats and user provide sample rate/count.
1614         struct Funcs
1615         {
1616             static float Sin(void*, int i) { return sinf(i * 0.1f); }
1617             static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
1618         };
1619         static int func_type = 0, display_count = 70;
1620         ImGui::Separator();
1621         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1622         ImGui::Combo("func", &func_type, "Sin\0Saw\0");
1623         ImGui::SameLine();
1624         ImGui::SliderInt("Sample count", &display_count, 1, 400);
1625         float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
1626         ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
1627         ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
1628         ImGui::Separator();
1629 
1630         // Animate a simple progress bar
1631         static float progress = 0.0f, progress_dir = 1.0f;
1632         if (animate)
1633         {
1634             progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
1635             if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
1636             if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
1637         }
1638 
1639         // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
1640         // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
1641         ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
1642         ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1643         ImGui::Text("Progress Bar");
1644 
1645         float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
1646         char buf[32];
1647         sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
1648         ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
1649         ImGui::TreePop();
1650     }
1651 
1652     if (ImGui::TreeNode("Color/Picker Widgets"))
1653     {
1654         static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
1655 
1656         static bool alpha_preview = true;
1657         static bool alpha_half_preview = false;
1658         static bool drag_and_drop = true;
1659         static bool options_menu = true;
1660         static bool hdr = false;
1661         ImGui::Checkbox("With Alpha Preview", &alpha_preview);
1662         ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
1663         ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
1664         ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
1665         ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
1666         ImGuiColorEditFlags 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);
1667 
1668         ImGui::Text("Color widget:");
1669         ImGui::SameLine(); HelpMarker(
1670             "Click on the color square to open a color picker.\n"
1671             "CTRL+click on individual component to input value.\n");
1672         ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
1673 
1674         ImGui::Text("Color widget HSV with Alpha:");
1675         ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags);
1676 
1677         ImGui::Text("Color widget with Float Display:");
1678         ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
1679 
1680         ImGui::Text("Color button with Picker:");
1681         ImGui::SameLine(); HelpMarker(
1682             "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n"
1683             "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only "
1684             "be used for the tooltip and picker popup.");
1685         ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
1686 
1687         ImGui::Text("Color button with Custom Picker Popup:");
1688 
1689         // Generate a default palette. The palette will persist and can be edited.
1690         static bool saved_palette_init = true;
1691         static ImVec4 saved_palette[32] = {};
1692         if (saved_palette_init)
1693         {
1694             for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1695             {
1696                 ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f,
1697                     saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
1698                 saved_palette[n].w = 1.0f; // Alpha
1699             }
1700             saved_palette_init = false;
1701         }
1702 
1703         static ImVec4 backup_color;
1704         bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
1705         ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
1706         open_popup |= ImGui::Button("Palette");
1707         if (open_popup)
1708         {
1709             ImGui::OpenPopup("mypicker");
1710             backup_color = color;
1711         }
1712         if (ImGui::BeginPopup("mypicker"))
1713         {
1714             ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
1715             ImGui::Separator();
1716             ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
1717             ImGui::SameLine();
1718 
1719             ImGui::BeginGroup(); // Lock X position
1720             ImGui::Text("Current");
1721             ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
1722             ImGui::Text("Previous");
1723             if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
1724                 color = backup_color;
1725             ImGui::Separator();
1726             ImGui::Text("Palette");
1727             for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1728             {
1729                 ImGui::PushID(n);
1730                 if ((n % 8) != 0)
1731                     ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
1732 
1733                 ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
1734                 if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
1735                     color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
1736 
1737                 // Allow user to drop colors into each palette entry. Note that ColorButton() is already a
1738                 // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag.
1739                 if (ImGui::BeginDragDropTarget())
1740                 {
1741                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
1742                         memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
1743                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
1744                         memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
1745                     ImGui::EndDragDropTarget();
1746                 }
1747 
1748                 ImGui::PopID();
1749             }
1750             ImGui::EndGroup();
1751             ImGui::EndPopup();
1752         }
1753 
1754         ImGui::Text("Color button only:");
1755         static bool no_border = false;
1756         ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
1757         ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
1758 
1759         ImGui::Text("Color picker:");
1760         static bool alpha = true;
1761         static bool alpha_bar = true;
1762         static bool side_preview = true;
1763         static bool ref_color = false;
1764         static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
1765         static int display_mode = 0;
1766         static int picker_mode = 0;
1767         ImGui::Checkbox("With Alpha", &alpha);
1768         ImGui::Checkbox("With Alpha Bar", &alpha_bar);
1769         ImGui::Checkbox("With Side Preview", &side_preview);
1770         if (side_preview)
1771         {
1772             ImGui::SameLine();
1773             ImGui::Checkbox("With Ref Color", &ref_color);
1774             if (ref_color)
1775             {
1776                 ImGui::SameLine();
1777                 ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
1778             }
1779         }
1780         ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
1781         ImGui::SameLine(); HelpMarker(
1782             "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
1783             "but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
1784             "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
1785         ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
1786         ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode.");
1787         ImGuiColorEditFlags flags = misc_flags;
1788         if (!alpha)            flags |= ImGuiColorEditFlags_NoAlpha;        // This is by default if you call ColorPicker3() instead of ColorPicker4()
1789         if (alpha_bar)         flags |= ImGuiColorEditFlags_AlphaBar;
1790         if (!side_preview)     flags |= ImGuiColorEditFlags_NoSidePreview;
1791         if (picker_mode == 1)  flags |= ImGuiColorEditFlags_PickerHueBar;
1792         if (picker_mode == 2)  flags |= ImGuiColorEditFlags_PickerHueWheel;
1793         if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;       // Disable all RGB/HSV/Hex displays
1794         if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB;     // Override display mode
1795         if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
1796         if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
1797         ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
1798 
1799         ImGui::Text("Set defaults in code:");
1800         ImGui::SameLine(); HelpMarker(
1801             "SetColorEditOptions() is designed to allow you to set boot-time default.\n"
1802             "We don't have Push/Pop functions because you can force options on a per-widget basis if needed,"
1803             "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid"
1804             "encouraging you to persistently save values that aren't forward-compatible.");
1805         if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
1806             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
1807         if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
1808             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
1809 
1810         // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
1811         static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
1812         ImGui::Spacing();
1813         ImGui::Text("HSV encoded colors");
1814         ImGui::SameLine(); HelpMarker(
1815             "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV"
1816             "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the"
1817             "added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
1818         ImGui::Text("Color widget with InputHSV:");
1819         ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
1820         ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
1821         ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f);
1822 
1823         ImGui::TreePop();
1824     }
1825 
1826     if (ImGui::TreeNode("Drag/Slider Flags"))
1827     {
1828         // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
1829         static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
1830         ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp);
1831         ImGui::SameLine(); HelpMarker("Always clamp value to min/max bounds (if any) when input manually with CTRL+Click.");
1832         ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic);
1833         ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values).");
1834         ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat);
1835         ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
1836         ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
1837         ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
1838 
1839         // Drags
1840         static float drag_f = 0.5f;
1841         static int drag_i = 50;
1842         ImGui::Text("Underlying float value: %f", drag_f);
1843         ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags);
1844         ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags);
1845         ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags);
1846         ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags);
1847         ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
1848 
1849         // Sliders
1850         static float slider_f = 0.5f;
1851         static int slider_i = 50;
1852         ImGui::Text("Underlying float value: %f", slider_f);
1853         ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags);
1854         ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags);
1855 
1856         ImGui::TreePop();
1857     }
1858 
1859     if (ImGui::TreeNode("Range Widgets"))
1860     {
1861         static float begin = 10, end = 90;
1862         static int begin_i = 100, end_i = 1000;
1863         ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp);
1864         ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units");
1865         ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
1866         ImGui::TreePop();
1867     }
1868 
1869     if (ImGui::TreeNode("Data Types"))
1870     {
1871         // DragScalar/InputScalar/SliderScalar functions allow various data types
1872         // - signed/unsigned
1873         // - 8/16/32/64-bits
1874         // - integer/float/double
1875         // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum
1876         // to pass the type, and passing all arguments by pointer.
1877         // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
1878         // In practice, if you frequently use a given type that is not covered by the normal API entry points,
1879         // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*,
1880         // and then pass their address to the generic function. For example:
1881         //   bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
1882         //   {
1883         //      return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
1884         //   }
1885 
1886         // Setup limits (as helper variables so we can take their address, as explained above)
1887         // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
1888         #ifndef LLONG_MIN
1889         ImS64 LLONG_MIN = -9223372036854775807LL - 1;
1890         ImS64 LLONG_MAX = 9223372036854775807LL;
1891         ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
1892         #endif
1893         const char    s8_zero  = 0,   s8_one  = 1,   s8_fifty  = 50, s8_min  = -128,        s8_max = 127;
1894         const ImU8    u8_zero  = 0,   u8_one  = 1,   u8_fifty  = 50, u8_min  = 0,           u8_max = 255;
1895         const short   s16_zero = 0,   s16_one = 1,   s16_fifty = 50, s16_min = -32768,      s16_max = 32767;
1896         const ImU16   u16_zero = 0,   u16_one = 1,   u16_fifty = 50, u16_min = 0,           u16_max = 65535;
1897         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;
1898         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;
1899         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;
1900         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;
1901         const float   f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
1902         const double  f64_zero = 0.,  f64_one = 1.,  f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
1903 
1904         // State
1905         static char   s8_v  = 127;
1906         static ImU8   u8_v  = 255;
1907         static short  s16_v = 32767;
1908         static ImU16  u16_v = 65535;
1909         static ImS32  s32_v = -1;
1910         static ImU32  u32_v = (ImU32)-1;
1911         static ImS64  s64_v = -1;
1912         static ImU64  u64_v = (ImU64)-1;
1913         static float  f32_v = 0.123f;
1914         static double f64_v = 90000.01234567890123456789;
1915 
1916         const float drag_speed = 0.2f;
1917         static bool drag_clamp = false;
1918         ImGui::Text("Drags:");
1919         ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
1920         ImGui::SameLine(); HelpMarker(
1921             "As with every widgets in dear imgui, we never modify values unless there is a user interaction.\n"
1922             "You can override the clamping limits by using CTRL+Click to input a value.");
1923         ImGui::DragScalar("drag s8",        ImGuiDataType_S8,     &s8_v,  drag_speed, drag_clamp ? &s8_zero  : NULL, drag_clamp ? &s8_fifty  : NULL);
1924         ImGui::DragScalar("drag u8",        ImGuiDataType_U8,     &u8_v,  drag_speed, drag_clamp ? &u8_zero  : NULL, drag_clamp ? &u8_fifty  : NULL, "%u ms");
1925         ImGui::DragScalar("drag s16",       ImGuiDataType_S16,    &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
1926         ImGui::DragScalar("drag u16",       ImGuiDataType_U16,    &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
1927         ImGui::DragScalar("drag s32",       ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
1928         ImGui::DragScalar("drag u32",       ImGuiDataType_U32,    &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
1929         ImGui::DragScalar("drag s64",       ImGuiDataType_S64,    &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
1930         ImGui::DragScalar("drag u64",       ImGuiDataType_U64,    &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
1931         ImGui::DragScalar("drag float",     ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f");
1932         ImGui::DragScalar("drag float log", ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic);
1933         ImGui::DragScalar("drag double",    ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL,     "%.10f grams");
1934         ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic);
1935 
1936         ImGui::Text("Sliders");
1937         ImGui::SliderScalar("slider s8 full",       ImGuiDataType_S8,     &s8_v,  &s8_min,   &s8_max,   "%d");
1938         ImGui::SliderScalar("slider u8 full",       ImGuiDataType_U8,     &u8_v,  &u8_min,   &u8_max,   "%u");
1939         ImGui::SliderScalar("slider s16 full",      ImGuiDataType_S16,    &s16_v, &s16_min,  &s16_max,  "%d");
1940         ImGui::SliderScalar("slider u16 full",      ImGuiDataType_U16,    &u16_v, &u16_min,  &u16_max,  "%u");
1941         ImGui::SliderScalar("slider s32 low",       ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty,"%d");
1942         ImGui::SliderScalar("slider s32 high",      ImGuiDataType_S32,    &s32_v, &s32_hi_a, &s32_hi_b, "%d");
1943         ImGui::SliderScalar("slider s32 full",      ImGuiDataType_S32,    &s32_v, &s32_min,  &s32_max,  "%d");
1944         ImGui::SliderScalar("slider u32 low",       ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u");
1945         ImGui::SliderScalar("slider u32 high",      ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u");
1946         ImGui::SliderScalar("slider u32 full",      ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u");
1947         ImGui::SliderScalar("slider s64 low",       ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%" IM_PRId64);
1948         ImGui::SliderScalar("slider s64 high",      ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%" IM_PRId64);
1949         ImGui::SliderScalar("slider s64 full",      ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%" IM_PRId64);
1950         ImGui::SliderScalar("slider u64 low",       ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%" IM_PRIu64 " ms");
1951         ImGui::SliderScalar("slider u64 high",      ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%" IM_PRIu64 " ms");
1952         ImGui::SliderScalar("slider u64 full",      ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%" IM_PRIu64 " ms");
1953         ImGui::SliderScalar("slider float low",     ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one);
1954         ImGui::SliderScalar("slider float low log", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
1955         ImGui::SliderScalar("slider float high",    ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e");
1956         ImGui::SliderScalar("slider double low",    ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f grams");
1957         ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
1958         ImGui::SliderScalar("slider double high",   ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
1959 
1960         ImGui::Text("Sliders (reverse)");
1961         ImGui::SliderScalar("slider s8 reverse",    ImGuiDataType_S8,   &s8_v,  &s8_max,    &s8_min,   "%d");
1962         ImGui::SliderScalar("slider u8 reverse",    ImGuiDataType_U8,   &u8_v,  &u8_max,    &u8_min,   "%u");
1963         ImGui::SliderScalar("slider s32 reverse",   ImGuiDataType_S32,  &s32_v, &s32_fifty, &s32_zero, "%d");
1964         ImGui::SliderScalar("slider u32 reverse",   ImGuiDataType_U32,  &u32_v, &u32_fifty, &u32_zero, "%u");
1965         ImGui::SliderScalar("slider s64 reverse",   ImGuiDataType_S64,  &s64_v, &s64_fifty, &s64_zero, "%" IM_PRId64);
1966         ImGui::SliderScalar("slider u64 reverse",   ImGuiDataType_U64,  &u64_v, &u64_fifty, &u64_zero, "%" IM_PRIu64 " ms");
1967 
1968         static bool inputs_step = true;
1969         ImGui::Text("Inputs");
1970         ImGui::Checkbox("Show step buttons", &inputs_step);
1971         ImGui::InputScalar("input s8",      ImGuiDataType_S8,     &s8_v,  inputs_step ? &s8_one  : NULL, NULL, "%d");
1972         ImGui::InputScalar("input u8",      ImGuiDataType_U8,     &u8_v,  inputs_step ? &u8_one  : NULL, NULL, "%u");
1973         ImGui::InputScalar("input s16",     ImGuiDataType_S16,    &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d");
1974         ImGui::InputScalar("input u16",     ImGuiDataType_U16,    &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u");
1975         ImGui::InputScalar("input s32",     ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
1976         ImGui::InputScalar("input s32 hex", ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1977         ImGui::InputScalar("input u32",     ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
1978         ImGui::InputScalar("input u32 hex", ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1979         ImGui::InputScalar("input s64",     ImGuiDataType_S64,    &s64_v, inputs_step ? &s64_one : NULL);
1980         ImGui::InputScalar("input u64",     ImGuiDataType_U64,    &u64_v, inputs_step ? &u64_one : NULL);
1981         ImGui::InputScalar("input float",   ImGuiDataType_Float,  &f32_v, inputs_step ? &f32_one : NULL);
1982         ImGui::InputScalar("input double",  ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
1983 
1984         ImGui::TreePop();
1985     }
1986 
1987     if (ImGui::TreeNode("Multi-component Widgets"))
1988     {
1989         static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
1990         static int vec4i[4] = { 1, 5, 100, 255 };
1991 
1992         ImGui::InputFloat2("input float2", vec4f);
1993         ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
1994         ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
1995         ImGui::InputInt2("input int2", vec4i);
1996         ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
1997         ImGui::SliderInt2("slider int2", vec4i, 0, 255);
1998         ImGui::Spacing();
1999 
2000         ImGui::InputFloat3("input float3", vec4f);
2001         ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
2002         ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
2003         ImGui::InputInt3("input int3", vec4i);
2004         ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
2005         ImGui::SliderInt3("slider int3", vec4i, 0, 255);
2006         ImGui::Spacing();
2007 
2008         ImGui::InputFloat4("input float4", vec4f);
2009         ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
2010         ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
2011         ImGui::InputInt4("input int4", vec4i);
2012         ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
2013         ImGui::SliderInt4("slider int4", vec4i, 0, 255);
2014 
2015         ImGui::TreePop();
2016     }
2017 
2018     if (ImGui::TreeNode("Vertical Sliders"))
2019     {
2020         const float spacing = 4;
2021         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
2022 
2023         static int int_value = 0;
2024         ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
2025         ImGui::SameLine();
2026 
2027         static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
2028         ImGui::PushID("set1");
2029         for (int i = 0; i < 7; i++)
2030         {
2031             if (i > 0) ImGui::SameLine();
2032             ImGui::PushID(i);
2033             ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
2034             ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
2035             ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
2036             ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
2037             ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
2038             if (ImGui::IsItemActive() || ImGui::IsItemHovered())
2039                 ImGui::SetTooltip("%.3f", values[i]);
2040             ImGui::PopStyleColor(4);
2041             ImGui::PopID();
2042         }
2043         ImGui::PopID();
2044 
2045         ImGui::SameLine();
2046         ImGui::PushID("set2");
2047         static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
2048         const int rows = 3;
2049         const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
2050         for (int nx = 0; nx < 4; nx++)
2051         {
2052             if (nx > 0) ImGui::SameLine();
2053             ImGui::BeginGroup();
2054             for (int ny = 0; ny < rows; ny++)
2055             {
2056                 ImGui::PushID(nx * rows + ny);
2057                 ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
2058                 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
2059                     ImGui::SetTooltip("%.3f", values2[nx]);
2060                 ImGui::PopID();
2061             }
2062             ImGui::EndGroup();
2063         }
2064         ImGui::PopID();
2065 
2066         ImGui::SameLine();
2067         ImGui::PushID("set3");
2068         for (int i = 0; i < 4; i++)
2069         {
2070             if (i > 0) ImGui::SameLine();
2071             ImGui::PushID(i);
2072             ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
2073             ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
2074             ImGui::PopStyleVar();
2075             ImGui::PopID();
2076         }
2077         ImGui::PopID();
2078         ImGui::PopStyleVar();
2079         ImGui::TreePop();
2080     }
2081 
2082     if (ImGui::TreeNode("Drag and Drop"))
2083     {
2084         if (ImGui::TreeNode("Drag and drop in standard widgets"))
2085         {
2086             // ColorEdit widgets automatically act as drag source and drag target.
2087             // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F
2088             // to allow your own widgets to use colors in their drag and drop interaction.
2089             // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo.
2090             HelpMarker("You can drag from the color squares.");
2091             static float col1[3] = { 1.0f, 0.0f, 0.2f };
2092             static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
2093             ImGui::ColorEdit3("color 1", col1);
2094             ImGui::ColorEdit4("color 2", col2);
2095             ImGui::TreePop();
2096         }
2097 
2098         if (ImGui::TreeNode("Drag and drop to copy/swap items"))
2099         {
2100             enum Mode
2101             {
2102                 Mode_Copy,
2103                 Mode_Move,
2104                 Mode_Swap
2105             };
2106             static int mode = 0;
2107             if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
2108             if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
2109             if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
2110             static const char* names[9] =
2111             {
2112                 "Bobby", "Beatrice", "Betty",
2113                 "Brianna", "Barry", "Bernard",
2114                 "Bibi", "Blaine", "Bryn"
2115             };
2116             for (int n = 0; n < IM_ARRAYSIZE(names); n++)
2117             {
2118                 ImGui::PushID(n);
2119                 if ((n % 3) != 0)
2120                     ImGui::SameLine();
2121                 ImGui::Button(names[n], ImVec2(60, 60));
2122 
2123                 // Our buttons are both drag sources and drag targets here!
2124                 if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
2125                 {
2126                     // Set payload to carry the index of our item (could be anything)
2127                     ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));
2128 
2129                     // Display preview (could be anything, e.g. when dragging an image we could decide to display
2130                     // the filename and a small preview of the image, etc.)
2131                     if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }
2132                     if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
2133                     if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
2134                     ImGui::EndDragDropSource();
2135                 }
2136                 if (ImGui::BeginDragDropTarget())
2137                 {
2138                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
2139                     {
2140                         IM_ASSERT(payload->DataSize == sizeof(int));
2141                         int payload_n = *(const int*)payload->Data;
2142                         if (mode == Mode_Copy)
2143                         {
2144                             names[n] = names[payload_n];
2145                         }
2146                         if (mode == Mode_Move)
2147                         {
2148                             names[n] = names[payload_n];
2149                             names[payload_n] = "";
2150                         }
2151                         if (mode == Mode_Swap)
2152                         {
2153                             const char* tmp = names[n];
2154                             names[n] = names[payload_n];
2155                             names[payload_n] = tmp;
2156                         }
2157                     }
2158                     ImGui::EndDragDropTarget();
2159                 }
2160                 ImGui::PopID();
2161             }
2162             ImGui::TreePop();
2163         }
2164 
2165         if (ImGui::TreeNode("Drag to reorder items (simple)"))
2166         {
2167             // Simple reordering
2168             HelpMarker(
2169                 "We don't use the drag and drop api at all here! "
2170                 "Instead we query when the item is held but not hovered, and order items accordingly.");
2171             static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
2172             for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
2173             {
2174                 const char* item = item_names[n];
2175                 ImGui::Selectable(item);
2176 
2177                 if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
2178                 {
2179                     int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
2180                     if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
2181                     {
2182                         item_names[n] = item_names[n_next];
2183                         item_names[n_next] = item;
2184                         ImGui::ResetMouseDragDelta();
2185                     }
2186                 }
2187             }
2188             ImGui::TreePop();
2189         }
2190 
2191         ImGui::TreePop();
2192     }
2193 
2194     if (ImGui::TreeNode("Querying Item Status (Edited/Active/Hovered etc.)"))
2195     {
2196         // Select an item type
2197         const char* item_names[] =
2198         {
2199             "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat",
2200             "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"
2201         };
2202         static int item_type = 4;
2203         static bool item_disabled = false;
2204         ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
2205         ImGui::SameLine();
2206         HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
2207         ImGui::Checkbox("Item Disabled",  &item_disabled);
2208 
2209         // Submit selected item item so we can query their status in the code following it.
2210         bool ret = false;
2211         static bool b = false;
2212         static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
2213         static char str[16] = {};
2214         if (item_disabled)
2215             ImGui::BeginDisabled(true);
2216         if (item_type == 0) { ImGui::Text("ITEM: Text"); }                                              // Testing text items with no identifier/interaction
2217         if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); }                                    // Testing button
2218         if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater)
2219         if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); }                            // Testing checkbox
2220         if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
2221         if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); }  // Testing input text (which handles tabbing)
2222         if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); }               // Testing +/- buttons on scalar input
2223         if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); }                   // Testing multi-component items (IsItemXXX flags are reported merged)
2224         if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
2225         if (item_type == 9) { ret = ImGui::Selectable("ITEM: Selectable"); }                            // Testing selectable item
2226         if (item_type == 10){ ret = ImGui::MenuItem("ITEM: MenuItem"); }                                // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
2227         if (item_type == 11){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); }     // Testing tree node
2228         if (item_type == 12){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
2229         if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); }
2230         if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
2231 
2232         // Display the values of IsItemHovered() and other common item state functions.
2233         // Note that the ImGuiHoveredFlags_XXX flags can be combined.
2234         // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
2235         // we query every state in a single call to avoid storing them and to simplify the code.
2236         ImGui::BulletText(
2237             "Return value = %d\n"
2238             "IsItemFocused() = %d\n"
2239             "IsItemHovered() = %d\n"
2240             "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
2241             "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
2242             "IsItemHovered(_AllowWhenOverlapped) = %d\n"
2243             "IsItemHovered(_AllowWhenDisabled) = %d\n"
2244             "IsItemHovered(_RectOnly) = %d\n"
2245             "IsItemActive() = %d\n"
2246             "IsItemEdited() = %d\n"
2247             "IsItemActivated() = %d\n"
2248             "IsItemDeactivated() = %d\n"
2249             "IsItemDeactivatedAfterEdit() = %d\n"
2250             "IsItemVisible() = %d\n"
2251             "IsItemClicked() = %d\n"
2252             "IsItemToggledOpen() = %d\n"
2253             "GetItemRectMin() = (%.1f, %.1f)\n"
2254             "GetItemRectMax() = (%.1f, %.1f)\n"
2255             "GetItemRectSize() = (%.1f, %.1f)",
2256             ret,
2257             ImGui::IsItemFocused(),
2258             ImGui::IsItemHovered(),
2259             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2260             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
2261             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
2262             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled),
2263             ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
2264             ImGui::IsItemActive(),
2265             ImGui::IsItemEdited(),
2266             ImGui::IsItemActivated(),
2267             ImGui::IsItemDeactivated(),
2268             ImGui::IsItemDeactivatedAfterEdit(),
2269             ImGui::IsItemVisible(),
2270             ImGui::IsItemClicked(),
2271             ImGui::IsItemToggledOpen(),
2272             ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
2273             ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
2274             ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
2275         );
2276 
2277         if (item_disabled)
2278             ImGui::EndDisabled();
2279 
2280         char buf[1] = "";
2281         ImGui::InputText("unused", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_ReadOnly);
2282         ImGui::SameLine();
2283         HelpMarker("This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status.");
2284 
2285         ImGui::TreePop();
2286     }
2287 
2288     if (ImGui::TreeNode("Querying Window Status (Focused/Hovered etc.)"))
2289     {
2290         static bool embed_all_inside_a_child_window = false;
2291         ImGui::Checkbox("Embed everything inside a child window for testing _RootWindow flag.", &embed_all_inside_a_child_window);
2292         if (embed_all_inside_a_child_window)
2293             ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), true);
2294 
2295         // Testing IsWindowFocused() function with its various flags.
2296         ImGui::BulletText(
2297             "IsWindowFocused() = %d\n"
2298             "IsWindowFocused(_ChildWindows) = %d\n"
2299             "IsWindowFocused(_ChildWindows|_NoPopupHierarchy) = %d\n"
2300             "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
2301             "IsWindowFocused(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
2302             "IsWindowFocused(_RootWindow) = %d\n"
2303             "IsWindowFocused(_RootWindow|_NoPopupHierarchy) = %d\n"
2304             "IsWindowFocused(_AnyWindow) = %d\n",
2305             ImGui::IsWindowFocused(),
2306             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
2307             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy),
2308             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
2309             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
2310             ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
2311             ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
2312             ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
2313 
2314         // Testing IsWindowHovered() function with its various flags.
2315         ImGui::BulletText(
2316             "IsWindowHovered() = %d\n"
2317             "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
2318             "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
2319             "IsWindowHovered(_ChildWindows) = %d\n"
2320             "IsWindowHovered(_ChildWindows|_NoPopupHierarchy) = %d\n"
2321             "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
2322             "IsWindowHovered(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
2323             "IsWindowHovered(_RootWindow) = %d\n"
2324             "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n"
2325             "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
2326             "IsWindowHovered(_AnyWindow) = %d\n",
2327             ImGui::IsWindowHovered(),
2328             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2329             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
2330             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
2331             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy),
2332             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
2333             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
2334             ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
2335             ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
2336             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2337             ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
2338 
2339         ImGui::BeginChild("child", ImVec2(0, 50), true);
2340         ImGui::Text("This is another child window for testing the _ChildWindows flag.");
2341         ImGui::EndChild();
2342         if (embed_all_inside_a_child_window)
2343             ImGui::EndChild();
2344 
2345         // Calling IsItemHovered() after begin returns the hovered status of the title bar.
2346         // This is useful in particular if you want to create a context menu associated to the title bar of a window.
2347         static bool test_window = false;
2348         ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
2349         if (test_window)
2350         {
2351             ImGui::Begin("Title bar Hovered/Active tests", &test_window);
2352             if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
2353             {
2354                 if (ImGui::MenuItem("Close")) { test_window = false; }
2355                 ImGui::EndPopup();
2356             }
2357             ImGui::Text(
2358                 "IsItemHovered() after begin = %d (== is title bar hovered)\n"
2359                 "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
2360                 ImGui::IsItemHovered(), ImGui::IsItemActive());
2361             ImGui::End();
2362         }
2363 
2364         ImGui::TreePop();
2365     }
2366 
2367     // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd:
2368     // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space)
2369     if (disable_all)
2370         ImGui::EndDisabled();
2371 
2372     if (ImGui::TreeNode("Disable block"))
2373     {
2374         ImGui::Checkbox("Disable entire section above", &disable_all);
2375         ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across this section.");
2376         ImGui::TreePop();
2377     }
2378 }
2379 
ShowDemoWindowLayout()2380 static void ShowDemoWindowLayout()
2381 {
2382     if (!ImGui::CollapsingHeader("Layout & Scrolling"))
2383         return;
2384 
2385     if (ImGui::TreeNode("Child windows"))
2386     {
2387         HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
2388         static bool disable_mouse_wheel = false;
2389         static bool disable_menu = false;
2390         ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
2391         ImGui::Checkbox("Disable Menu", &disable_menu);
2392 
2393         // Child 1: no border, enable horizontal scrollbar
2394         {
2395             ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
2396             if (disable_mouse_wheel)
2397                 window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
2398             ImGui::BeginChild("ChildL", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 260), false, window_flags);
2399             for (int i = 0; i < 100; i++)
2400                 ImGui::Text("%04d: scrollable region", i);
2401             ImGui::EndChild();
2402         }
2403 
2404         ImGui::SameLine();
2405 
2406         // Child 2: rounded border
2407         {
2408             ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
2409             if (disable_mouse_wheel)
2410                 window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
2411             if (!disable_menu)
2412                 window_flags |= ImGuiWindowFlags_MenuBar;
2413             ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
2414             ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags);
2415             if (!disable_menu && ImGui::BeginMenuBar())
2416             {
2417                 if (ImGui::BeginMenu("Menu"))
2418                 {
2419                     ShowExampleMenuFile();
2420                     ImGui::EndMenu();
2421                 }
2422                 ImGui::EndMenuBar();
2423             }
2424             if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
2425             {
2426                 for (int i = 0; i < 100; i++)
2427                 {
2428                     char buf[32];
2429                     sprintf(buf, "%03d", i);
2430                     ImGui::TableNextColumn();
2431                     ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
2432                 }
2433                 ImGui::EndTable();
2434             }
2435             ImGui::EndChild();
2436             ImGui::PopStyleVar();
2437         }
2438 
2439         ImGui::Separator();
2440 
2441         // Demonstrate a few extra things
2442         // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
2443         // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window)
2444         //   You can also call SetNextWindowPos() to position the child window. The parent window will effectively
2445         //   layout from this position.
2446         // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from
2447         //   the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details.
2448         {
2449             static int offset_x = 0;
2450             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
2451             ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
2452 
2453             ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
2454             ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
2455             ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None);
2456             for (int n = 0; n < 50; n++)
2457                 ImGui::Text("Some test %d", n);
2458             ImGui::EndChild();
2459             bool child_is_hovered = ImGui::IsItemHovered();
2460             ImVec2 child_rect_min = ImGui::GetItemRectMin();
2461             ImVec2 child_rect_max = ImGui::GetItemRectMax();
2462             ImGui::PopStyleColor();
2463             ImGui::Text("Hovered: %d", child_is_hovered);
2464             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);
2465         }
2466 
2467         ImGui::TreePop();
2468     }
2469 
2470     if (ImGui::TreeNode("Widgets Width"))
2471     {
2472         static float f = 0.0f;
2473         static bool show_indented_items = true;
2474         ImGui::Checkbox("Show indented items", &show_indented_items);
2475 
2476         // Use SetNextItemWidth() to set the width of a single upcoming item.
2477         // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
2478         // In real code use you'll probably want to choose width values that are proportional to your font size
2479         // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
2480 
2481         ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
2482         ImGui::SameLine(); HelpMarker("Fixed width.");
2483         ImGui::PushItemWidth(100);
2484         ImGui::DragFloat("float##1b", &f);
2485         if (show_indented_items)
2486         {
2487             ImGui::Indent();
2488             ImGui::DragFloat("float (indented)##1b", &f);
2489             ImGui::Unindent();
2490         }
2491         ImGui::PopItemWidth();
2492 
2493         ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
2494         ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
2495         ImGui::PushItemWidth(-100);
2496         ImGui::DragFloat("float##2a", &f);
2497         if (show_indented_items)
2498         {
2499             ImGui::Indent();
2500             ImGui::DragFloat("float (indented)##2b", &f);
2501             ImGui::Unindent();
2502         }
2503         ImGui::PopItemWidth();
2504 
2505         ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
2506         ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
2507         ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
2508         ImGui::DragFloat("float##3a", &f);
2509         if (show_indented_items)
2510         {
2511             ImGui::Indent();
2512             ImGui::DragFloat("float (indented)##3b", &f);
2513             ImGui::Unindent();
2514         }
2515         ImGui::PopItemWidth();
2516 
2517         ImGui::Text("SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)");
2518         ImGui::SameLine(); HelpMarker("Align to right edge minus half");
2519         ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
2520         ImGui::DragFloat("float##4a", &f);
2521         if (show_indented_items)
2522         {
2523             ImGui::Indent();
2524             ImGui::DragFloat("float (indented)##4b", &f);
2525             ImGui::Unindent();
2526         }
2527         ImGui::PopItemWidth();
2528 
2529         // Demonstrate using PushItemWidth to surround three items.
2530         // Calling SetNextItemWidth() before each of them would have the same effect.
2531         ImGui::Text("SetNextItemWidth/PushItemWidth(-FLT_MIN)");
2532         ImGui::SameLine(); HelpMarker("Align to right edge");
2533         ImGui::PushItemWidth(-FLT_MIN);
2534         ImGui::DragFloat("##float5a", &f);
2535         if (show_indented_items)
2536         {
2537             ImGui::Indent();
2538             ImGui::DragFloat("float (indented)##5b", &f);
2539             ImGui::Unindent();
2540         }
2541         ImGui::PopItemWidth();
2542 
2543         ImGui::TreePop();
2544     }
2545 
2546     if (ImGui::TreeNode("Basic Horizontal Layout"))
2547     {
2548         ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
2549 
2550         // Text
2551         ImGui::Text("Two items: Hello"); ImGui::SameLine();
2552         ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
2553 
2554         // Adjust spacing
2555         ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
2556         ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
2557 
2558         // Button
2559         ImGui::AlignTextToFramePadding();
2560         ImGui::Text("Normal buttons"); ImGui::SameLine();
2561         ImGui::Button("Banana"); ImGui::SameLine();
2562         ImGui::Button("Apple"); ImGui::SameLine();
2563         ImGui::Button("Corniflower");
2564 
2565         // Button
2566         ImGui::Text("Small buttons"); ImGui::SameLine();
2567         ImGui::SmallButton("Like this one"); ImGui::SameLine();
2568         ImGui::Text("can fit within a text block.");
2569 
2570         // Aligned to arbitrary position. Easy/cheap column.
2571         ImGui::Text("Aligned");
2572         ImGui::SameLine(150); ImGui::Text("x=150");
2573         ImGui::SameLine(300); ImGui::Text("x=300");
2574         ImGui::Text("Aligned");
2575         ImGui::SameLine(150); ImGui::SmallButton("x=150");
2576         ImGui::SameLine(300); ImGui::SmallButton("x=300");
2577 
2578         // Checkbox
2579         static bool c1 = false, c2 = false, c3 = false, c4 = false;
2580         ImGui::Checkbox("My", &c1); ImGui::SameLine();
2581         ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
2582         ImGui::Checkbox("Is", &c3); ImGui::SameLine();
2583         ImGui::Checkbox("Rich", &c4);
2584 
2585         // Various
2586         static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
2587         ImGui::PushItemWidth(80);
2588         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
2589         static int item = -1;
2590         ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
2591         ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
2592         ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
2593         ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
2594         ImGui::PopItemWidth();
2595 
2596         ImGui::PushItemWidth(80);
2597         ImGui::Text("Lists:");
2598         static int selection[4] = { 0, 1, 2, 3 };
2599         for (int i = 0; i < 4; i++)
2600         {
2601             if (i > 0) ImGui::SameLine();
2602             ImGui::PushID(i);
2603             ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
2604             ImGui::PopID();
2605             //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
2606         }
2607         ImGui::PopItemWidth();
2608 
2609         // Dummy
2610         ImVec2 button_sz(40, 40);
2611         ImGui::Button("A", button_sz); ImGui::SameLine();
2612         ImGui::Dummy(button_sz); ImGui::SameLine();
2613         ImGui::Button("B", button_sz);
2614 
2615         // Manually wrapping
2616         // (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
2617         ImGui::Text("Manually wrapping:");
2618         ImGuiStyle& style = ImGui::GetStyle();
2619         int buttons_count = 20;
2620         float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
2621         for (int n = 0; n < buttons_count; n++)
2622         {
2623             ImGui::PushID(n);
2624             ImGui::Button("Box", button_sz);
2625             float last_button_x2 = ImGui::GetItemRectMax().x;
2626             float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
2627             if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
2628                 ImGui::SameLine();
2629             ImGui::PopID();
2630         }
2631 
2632         ImGui::TreePop();
2633     }
2634 
2635     if (ImGui::TreeNode("Groups"))
2636     {
2637         HelpMarker(
2638             "BeginGroup() basically locks the horizontal position for new line. "
2639             "EndGroup() bundles the whole group so that you can use \"item\" functions such as "
2640             "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group.");
2641         ImGui::BeginGroup();
2642         {
2643             ImGui::BeginGroup();
2644             ImGui::Button("AAA");
2645             ImGui::SameLine();
2646             ImGui::Button("BBB");
2647             ImGui::SameLine();
2648             ImGui::BeginGroup();
2649             ImGui::Button("CCC");
2650             ImGui::Button("DDD");
2651             ImGui::EndGroup();
2652             ImGui::SameLine();
2653             ImGui::Button("EEE");
2654             ImGui::EndGroup();
2655             if (ImGui::IsItemHovered())
2656                 ImGui::SetTooltip("First group hovered");
2657         }
2658         // Capture the group size and create widgets using the same size
2659         ImVec2 size = ImGui::GetItemRectSize();
2660         const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
2661         ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
2662 
2663         ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
2664         ImGui::SameLine();
2665         ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
2666         ImGui::EndGroup();
2667         ImGui::SameLine();
2668 
2669         ImGui::Button("LEVERAGE\nBUZZWORD", size);
2670         ImGui::SameLine();
2671 
2672         if (ImGui::BeginListBox("List", size))
2673         {
2674             ImGui::Selectable("Selected", true);
2675             ImGui::Selectable("Not Selected", false);
2676             ImGui::EndListBox();
2677         }
2678 
2679         ImGui::TreePop();
2680     }
2681 
2682     if (ImGui::TreeNode("Text Baseline Alignment"))
2683     {
2684         {
2685             ImGui::BulletText("Text baseline:");
2686             ImGui::SameLine(); HelpMarker(
2687                 "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. "
2688                 "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets.");
2689             ImGui::Indent();
2690 
2691             ImGui::Text("KO Blahblah"); ImGui::SameLine();
2692             ImGui::Button("Some framed item"); ImGui::SameLine();
2693             HelpMarker("Baseline of button will look misaligned with text..");
2694 
2695             // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
2696             // (because we don't know what's coming after the Text() statement, we need to move the text baseline
2697             // down by FramePadding.y ahead of time)
2698             ImGui::AlignTextToFramePadding();
2699             ImGui::Text("OK Blahblah"); ImGui::SameLine();
2700             ImGui::Button("Some framed item"); ImGui::SameLine();
2701             HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
2702 
2703             // SmallButton() uses the same vertical padding as Text
2704             ImGui::Button("TEST##1"); ImGui::SameLine();
2705             ImGui::Text("TEST"); ImGui::SameLine();
2706             ImGui::SmallButton("TEST##2");
2707 
2708             // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
2709             ImGui::AlignTextToFramePadding();
2710             ImGui::Text("Text aligned to framed item"); ImGui::SameLine();
2711             ImGui::Button("Item##1"); ImGui::SameLine();
2712             ImGui::Text("Item"); ImGui::SameLine();
2713             ImGui::SmallButton("Item##2"); ImGui::SameLine();
2714             ImGui::Button("Item##3");
2715 
2716             ImGui::Unindent();
2717         }
2718 
2719         ImGui::Spacing();
2720 
2721         {
2722             ImGui::BulletText("Multi-line text:");
2723             ImGui::Indent();
2724             ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
2725             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2726             ImGui::Text("Banana");
2727 
2728             ImGui::Text("Banana"); ImGui::SameLine();
2729             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2730             ImGui::Text("One\nTwo\nThree");
2731 
2732             ImGui::Button("HOP##1"); ImGui::SameLine();
2733             ImGui::Text("Banana"); ImGui::SameLine();
2734             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2735             ImGui::Text("Banana");
2736 
2737             ImGui::Button("HOP##2"); ImGui::SameLine();
2738             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2739             ImGui::Text("Banana");
2740             ImGui::Unindent();
2741         }
2742 
2743         ImGui::Spacing();
2744 
2745         {
2746             ImGui::BulletText("Misc items:");
2747             ImGui::Indent();
2748 
2749             // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button.
2750             ImGui::Button("80x80", ImVec2(80, 80));
2751             ImGui::SameLine();
2752             ImGui::Button("50x50", ImVec2(50, 50));
2753             ImGui::SameLine();
2754             ImGui::Button("Button()");
2755             ImGui::SameLine();
2756             ImGui::SmallButton("SmallButton()");
2757 
2758             // Tree
2759             const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
2760             ImGui::Button("Button##1");
2761             ImGui::SameLine(0.0f, spacing);
2762             if (ImGui::TreeNode("Node##1"))
2763             {
2764                 // Placeholder tree data
2765                 for (int i = 0; i < 6; i++)
2766                     ImGui::BulletText("Item %d..", i);
2767                 ImGui::TreePop();
2768             }
2769 
2770             // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget.
2771             // Otherwise you can use SmallButton() (smaller fit).
2772             ImGui::AlignTextToFramePadding();
2773 
2774             // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add
2775             // other contents below the node.
2776             bool node_open = ImGui::TreeNode("Node##2");
2777             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
2778             if (node_open)
2779             {
2780                 // Placeholder tree data
2781                 for (int i = 0; i < 6; i++)
2782                     ImGui::BulletText("Item %d..", i);
2783                 ImGui::TreePop();
2784             }
2785 
2786             // Bullet
2787             ImGui::Button("Button##3");
2788             ImGui::SameLine(0.0f, spacing);
2789             ImGui::BulletText("Bullet text");
2790 
2791             ImGui::AlignTextToFramePadding();
2792             ImGui::BulletText("Node");
2793             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
2794             ImGui::Unindent();
2795         }
2796 
2797         ImGui::TreePop();
2798     }
2799 
2800     if (ImGui::TreeNode("Scrolling"))
2801     {
2802         // Vertical scroll functions
2803         HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
2804 
2805         static int track_item = 50;
2806         static bool enable_track = true;
2807         static bool enable_extra_decorations = false;
2808         static float scroll_to_off_px = 0.0f;
2809         static float scroll_to_pos_px = 200.0f;
2810 
2811         ImGui::Checkbox("Decoration", &enable_extra_decorations);
2812 
2813         ImGui::Checkbox("Track", &enable_track);
2814         ImGui::PushItemWidth(100);
2815         ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
2816 
2817         bool scroll_to_off = ImGui::Button("Scroll Offset");
2818         ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
2819 
2820         bool scroll_to_pos = ImGui::Button("Scroll To Pos");
2821         ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
2822         ImGui::PopItemWidth();
2823 
2824         if (scroll_to_off || scroll_to_pos)
2825             enable_track = false;
2826 
2827         ImGuiStyle& style = ImGui::GetStyle();
2828         float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
2829         if (child_w < 1.0f)
2830             child_w = 1.0f;
2831         ImGui::PushID("##VerticalScrolling");
2832         for (int i = 0; i < 5; i++)
2833         {
2834             if (i > 0) ImGui::SameLine();
2835             ImGui::BeginGroup();
2836             const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
2837             ImGui::TextUnformatted(names[i]);
2838 
2839             const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
2840             const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
2841             const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), true, child_flags);
2842             if (ImGui::BeginMenuBar())
2843             {
2844                 ImGui::TextUnformatted("abc");
2845                 ImGui::EndMenuBar();
2846             }
2847             if (scroll_to_off)
2848                 ImGui::SetScrollY(scroll_to_off_px);
2849             if (scroll_to_pos)
2850                 ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
2851             if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
2852             {
2853                 for (int item = 0; item < 100; item++)
2854                 {
2855                     if (enable_track && item == track_item)
2856                     {
2857                         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
2858                         ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
2859                     }
2860                     else
2861                     {
2862                         ImGui::Text("Item %d", item);
2863                     }
2864                 }
2865             }
2866             float scroll_y = ImGui::GetScrollY();
2867             float scroll_max_y = ImGui::GetScrollMaxY();
2868             ImGui::EndChild();
2869             ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
2870             ImGui::EndGroup();
2871         }
2872         ImGui::PopID();
2873 
2874         // Horizontal scroll functions
2875         ImGui::Spacing();
2876         HelpMarker(
2877             "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n"
2878             "Because the clipping rectangle of most window hides half worth of WindowPadding on the "
2879             "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the "
2880             "equivalent SetScrollFromPosY(+1) wouldn't.");
2881         ImGui::PushID("##HorizontalScrolling");
2882         for (int i = 0; i < 5; i++)
2883         {
2884             float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
2885             ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
2886             ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
2887             bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), true, child_flags);
2888             if (scroll_to_off)
2889                 ImGui::SetScrollX(scroll_to_off_px);
2890             if (scroll_to_pos)
2891                 ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
2892             if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
2893             {
2894                 for (int item = 0; item < 100; item++)
2895                 {
2896                     if (item > 0)
2897                         ImGui::SameLine();
2898                     if (enable_track && item == track_item)
2899                     {
2900                         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
2901                         ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
2902                     }
2903                     else
2904                     {
2905                         ImGui::Text("Item %d", item);
2906                     }
2907                 }
2908             }
2909             float scroll_x = ImGui::GetScrollX();
2910             float scroll_max_x = ImGui::GetScrollMaxX();
2911             ImGui::EndChild();
2912             ImGui::SameLine();
2913             const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
2914             ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
2915             ImGui::Spacing();
2916         }
2917         ImGui::PopID();
2918 
2919         // Miscellaneous Horizontal Scrolling Demo
2920         HelpMarker(
2921             "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n"
2922             "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin().");
2923         static int lines = 7;
2924         ImGui::SliderInt("Lines", &lines, 1, 15);
2925         ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
2926         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
2927         ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
2928         ImGui::BeginChild("scrolling", scrolling_child_size, true, ImGuiWindowFlags_HorizontalScrollbar);
2929         for (int line = 0; line < lines; line++)
2930         {
2931             // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
2932             // If you want to create your own time line for a real application you may be better off manipulating
2933             // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
2934             // yourself. You may also want to use the lower-level ImDrawList API.
2935             int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
2936             for (int n = 0; n < num_buttons; n++)
2937             {
2938                 if (n > 0) ImGui::SameLine();
2939                 ImGui::PushID(n + line * 1000);
2940                 char num_buf[16];
2941                 sprintf(num_buf, "%d", n);
2942                 const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
2943                 float hue = n * 0.05f;
2944                 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
2945                 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
2946                 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
2947                 ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
2948                 ImGui::PopStyleColor(3);
2949                 ImGui::PopID();
2950             }
2951         }
2952         float scroll_x = ImGui::GetScrollX();
2953         float scroll_max_x = ImGui::GetScrollMaxX();
2954         ImGui::EndChild();
2955         ImGui::PopStyleVar(2);
2956         float scroll_x_delta = 0.0f;
2957         ImGui::SmallButton("<<");
2958         if (ImGui::IsItemActive())
2959             scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
2960         ImGui::SameLine();
2961         ImGui::Text("Scroll from code"); ImGui::SameLine();
2962         ImGui::SmallButton(">>");
2963         if (ImGui::IsItemActive())
2964             scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
2965         ImGui::SameLine();
2966         ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
2967         if (scroll_x_delta != 0.0f)
2968         {
2969             // Demonstrate a trick: you can use Begin to set yourself in the context of another window
2970             // (here we are already out of your child window)
2971             ImGui::BeginChild("scrolling");
2972             ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
2973             ImGui::EndChild();
2974         }
2975         ImGui::Spacing();
2976 
2977         static bool show_horizontal_contents_size_demo_window = false;
2978         ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
2979 
2980         if (show_horizontal_contents_size_demo_window)
2981         {
2982             static bool show_h_scrollbar = true;
2983             static bool show_button = true;
2984             static bool show_tree_nodes = true;
2985             static bool show_text_wrapped = false;
2986             static bool show_columns = true;
2987             static bool show_tab_bar = true;
2988             static bool show_child = false;
2989             static bool explicit_content_size = false;
2990             static float contents_size_x = 300.0f;
2991             if (explicit_content_size)
2992                 ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
2993             ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
2994             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
2995             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
2996             HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
2997             ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
2998             ImGui::Checkbox("Button", &show_button);            // Will grow contents size (unless explicitly overwritten)
2999             ImGui::Checkbox("Tree nodes", &show_tree_nodes);    // Will grow contents size and display highlight over full width
3000             ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
3001             ImGui::Checkbox("Columns", &show_columns);          // Will use contents size
3002             ImGui::Checkbox("Tab bar", &show_tab_bar);          // Will use contents size
3003             ImGui::Checkbox("Child", &show_child);              // Will grow and use contents size
3004             ImGui::Checkbox("Explicit content size", &explicit_content_size);
3005             ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
3006             if (explicit_content_size)
3007             {
3008                 ImGui::SameLine();
3009                 ImGui::SetNextItemWidth(100);
3010                 ImGui::DragFloat("##csx", &contents_size_x);
3011                 ImVec2 p = ImGui::GetCursorScreenPos();
3012                 ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
3013                 ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
3014                 ImGui::Dummy(ImVec2(0, 10));
3015             }
3016             ImGui::PopStyleVar(2);
3017             ImGui::Separator();
3018             if (show_button)
3019             {
3020                 ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
3021             }
3022             if (show_tree_nodes)
3023             {
3024                 bool open = true;
3025                 if (ImGui::TreeNode("this is a tree node"))
3026                 {
3027                     if (ImGui::TreeNode("another one of those tree node..."))
3028                     {
3029                         ImGui::Text("Some tree contents");
3030                         ImGui::TreePop();
3031                     }
3032                     ImGui::TreePop();
3033                 }
3034                 ImGui::CollapsingHeader("CollapsingHeader", &open);
3035             }
3036             if (show_text_wrapped)
3037             {
3038                 ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
3039             }
3040             if (show_columns)
3041             {
3042                 ImGui::Text("Tables:");
3043                 if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders))
3044                 {
3045                     for (int n = 0; n < 4; n++)
3046                     {
3047                         ImGui::TableNextColumn();
3048                         ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x);
3049                     }
3050                     ImGui::EndTable();
3051                 }
3052                 ImGui::Text("Columns:");
3053                 ImGui::Columns(4);
3054                 for (int n = 0; n < 4; n++)
3055                 {
3056                     ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
3057                     ImGui::NextColumn();
3058                 }
3059                 ImGui::Columns(1);
3060             }
3061             if (show_tab_bar && ImGui::BeginTabBar("Hello"))
3062             {
3063                 if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
3064                 if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
3065                 if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
3066                 if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
3067                 ImGui::EndTabBar();
3068             }
3069             if (show_child)
3070             {
3071                 ImGui::BeginChild("child", ImVec2(0, 0), true);
3072                 ImGui::EndChild();
3073             }
3074             ImGui::End();
3075         }
3076 
3077         ImGui::TreePop();
3078     }
3079 
3080     if (ImGui::TreeNode("Clipping"))
3081     {
3082         static ImVec2 size(100.0f, 100.0f);
3083         static ImVec2 offset(30.0f, 30.0f);
3084         ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
3085         ImGui::TextWrapped("(Click and drag to scroll)");
3086 
3087         for (int n = 0; n < 3; n++)
3088         {
3089             if (n > 0)
3090                 ImGui::SameLine();
3091             ImGui::PushID(n);
3092             ImGui::BeginGroup(); // Lock X position
3093 
3094             ImGui::InvisibleButton("##empty", size);
3095             if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
3096             {
3097                 offset.x += ImGui::GetIO().MouseDelta.x;
3098                 offset.y += ImGui::GetIO().MouseDelta.y;
3099             }
3100             const ImVec2 p0 = ImGui::GetItemRectMin();
3101             const ImVec2 p1 = ImGui::GetItemRectMax();
3102             const char* text_str = "Line 1 hello\nLine 2 clip me!";
3103             const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y);
3104             ImDrawList* draw_list = ImGui::GetWindowDrawList();
3105 
3106             switch (n)
3107             {
3108             case 0:
3109                 HelpMarker(
3110                     "Using ImGui::PushClipRect():\n"
3111                     "Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
3112                     "(use this if you want your clipping rectangle to affect interactions)");
3113                 ImGui::PushClipRect(p0, p1, true);
3114                 draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
3115                 draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
3116                 ImGui::PopClipRect();
3117                 break;
3118             case 1:
3119                 HelpMarker(
3120                     "Using ImDrawList::PushClipRect():\n"
3121                     "Will alter ImDrawList rendering only.\n"
3122                     "(use this as a shortcut if you are only using ImDrawList calls)");
3123                 draw_list->PushClipRect(p0, p1, true);
3124                 draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
3125                 draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
3126                 draw_list->PopClipRect();
3127                 break;
3128             case 2:
3129                 HelpMarker(
3130                     "Using ImDrawList::AddText() with a fine ClipRect:\n"
3131                     "Will alter only this specific ImDrawList::AddText() rendering.\n"
3132                     "(this is often used internally to avoid altering the clipping rectangle and minimize draw calls)");
3133                 ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert.
3134                 draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
3135                 draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect);
3136                 break;
3137             }
3138             ImGui::EndGroup();
3139             ImGui::PopID();
3140         }
3141 
3142         ImGui::TreePop();
3143     }
3144 }
3145 
ShowDemoWindowPopups()3146 static void ShowDemoWindowPopups()
3147 {
3148     if (!ImGui::CollapsingHeader("Popups & Modal windows"))
3149         return;
3150 
3151     // The properties of popups windows are:
3152     // - They block normal mouse hovering detection outside them. (*)
3153     // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
3154     // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as
3155     //   we are used to with regular Begin() calls. User can manipulate the visibility state by calling OpenPopup().
3156     // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even
3157     //     when normally blocked by a popup.
3158     // Those three properties are connected. The library needs to hold their visibility state BECAUSE it can close
3159     // popups at any time.
3160 
3161     // Typical use for regular windows:
3162     //   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();
3163     // Typical use for popups:
3164     //   if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
3165 
3166     // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
3167     // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
3168 
3169     if (ImGui::TreeNode("Popups"))
3170     {
3171         ImGui::TextWrapped(
3172             "When a popup is active, it inhibits interacting with windows that are behind the popup. "
3173             "Clicking outside the popup closes it.");
3174 
3175         static int selected_fish = -1;
3176         const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
3177         static bool toggles[] = { true, false, false, false, false };
3178 
3179         // Simple selection popup (if you want to show the current selection inside the Button itself,
3180         // you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
3181         if (ImGui::Button("Select.."))
3182             ImGui::OpenPopup("my_select_popup");
3183         ImGui::SameLine();
3184         ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
3185         if (ImGui::BeginPopup("my_select_popup"))
3186         {
3187             ImGui::Text("Aquarium");
3188             ImGui::Separator();
3189             for (int i = 0; i < IM_ARRAYSIZE(names); i++)
3190                 if (ImGui::Selectable(names[i]))
3191                     selected_fish = i;
3192             ImGui::EndPopup();
3193         }
3194 
3195         // Showing a menu with toggles
3196         if (ImGui::Button("Toggle.."))
3197             ImGui::OpenPopup("my_toggle_popup");
3198         if (ImGui::BeginPopup("my_toggle_popup"))
3199         {
3200             for (int i = 0; i < IM_ARRAYSIZE(names); i++)
3201                 ImGui::MenuItem(names[i], "", &toggles[i]);
3202             if (ImGui::BeginMenu("Sub-menu"))
3203             {
3204                 ImGui::MenuItem("Click me");
3205                 ImGui::EndMenu();
3206             }
3207 
3208             ImGui::Separator();
3209             ImGui::Text("Tooltip here");
3210             if (ImGui::IsItemHovered())
3211                 ImGui::SetTooltip("I am a tooltip over a popup");
3212 
3213             if (ImGui::Button("Stacked Popup"))
3214                 ImGui::OpenPopup("another popup");
3215             if (ImGui::BeginPopup("another popup"))
3216             {
3217                 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
3218                     ImGui::MenuItem(names[i], "", &toggles[i]);
3219                 if (ImGui::BeginMenu("Sub-menu"))
3220                 {
3221                     ImGui::MenuItem("Click me");
3222                     if (ImGui::Button("Stacked Popup"))
3223                         ImGui::OpenPopup("another popup");
3224                     if (ImGui::BeginPopup("another popup"))
3225                     {
3226                         ImGui::Text("I am the last one here.");
3227                         ImGui::EndPopup();
3228                     }
3229                     ImGui::EndMenu();
3230                 }
3231                 ImGui::EndPopup();
3232             }
3233             ImGui::EndPopup();
3234         }
3235 
3236         // Call the more complete ShowExampleMenuFile which we use in various places of this demo
3237         if (ImGui::Button("File Menu.."))
3238             ImGui::OpenPopup("my_file_popup");
3239         if (ImGui::BeginPopup("my_file_popup"))
3240         {
3241             ShowExampleMenuFile();
3242             ImGui::EndPopup();
3243         }
3244 
3245         ImGui::TreePop();
3246     }
3247 
3248     if (ImGui::TreeNode("Context menus"))
3249     {
3250         HelpMarker("\"Context\" functions are simple helpers to associate a Popup to a given Item or Window identifier.");
3251 
3252         // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
3253         //     if (id == 0)
3254         //         id = GetItemID(); // Use last item id
3255         //     if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
3256         //         OpenPopup(id);
3257         //     return BeginPopup(id);
3258         // For advanced advanced uses you may want to replicate and customize this code.
3259         // See more details in BeginPopupContextItem().
3260 
3261         // Example 1
3262         // When used after an item that has an ID (e.g. Button), we can skip providing an ID to BeginPopupContextItem(),
3263         // and BeginPopupContextItem() will use the last item ID as the popup ID.
3264         {
3265             const char* names[5] = { "Label1", "Label2", "Label3", "Label4", "Label5" };
3266             for (int n = 0; n < 5; n++)
3267             {
3268                 ImGui::Selectable(names[n]);
3269                 if (ImGui::BeginPopupContextItem()) // <-- use last item id as popup id
3270                 {
3271                     ImGui::Text("This a popup for \"%s\"!", names[n]);
3272                     if (ImGui::Button("Close"))
3273                         ImGui::CloseCurrentPopup();
3274                     ImGui::EndPopup();
3275                 }
3276                 if (ImGui::IsItemHovered())
3277                     ImGui::SetTooltip("Right-click to open popup");
3278             }
3279         }
3280 
3281         // Example 2
3282         // Popup on a Text() element which doesn't have an identifier: we need to provide an identifier to BeginPopupContextItem().
3283         // Using an explicit identifier is also convenient if you want to activate the popups from different locations.
3284         {
3285             HelpMarker("Text() elements don't have stable identifiers so we need to provide one.");
3286             static float value = 0.5f;
3287             ImGui::Text("Value = %.3f <-- (1) right-click this value", value);
3288             if (ImGui::BeginPopupContextItem("my popup"))
3289             {
3290                 if (ImGui::Selectable("Set to zero")) value = 0.0f;
3291                 if (ImGui::Selectable("Set to PI")) value = 3.1415f;
3292                 ImGui::SetNextItemWidth(-FLT_MIN);
3293                 ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
3294                 ImGui::EndPopup();
3295             }
3296 
3297             // We can also use OpenPopupOnItemClick() to toggle the visibility of a given popup.
3298             // Here we make it that right-clicking this other text element opens the same popup as above.
3299             // The popup itself will be submitted by the code above.
3300             ImGui::Text("(2) Or right-click this text");
3301             ImGui::OpenPopupOnItemClick("my popup", ImGuiPopupFlags_MouseButtonRight);
3302 
3303             // Back to square one: manually open the same popup.
3304             if (ImGui::Button("(3) Or click this button"))
3305                 ImGui::OpenPopup("my popup");
3306         }
3307 
3308         // Example 3
3309         // When using BeginPopupContextItem() with an implicit identifier (NULL == use last item ID),
3310         // we need to make sure your item identifier is stable.
3311         // In this example we showcase altering the item label while preserving its identifier, using the ### operator (see FAQ).
3312         {
3313             HelpMarker("Showcase using a popup ID linked to item ID, with the item having a changing label + stable ID using the ### operator.");
3314             static char name[32] = "Label1";
3315             char buf[64];
3316             sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
3317             ImGui::Button(buf);
3318             if (ImGui::BeginPopupContextItem())
3319             {
3320                 ImGui::Text("Edit name:");
3321                 ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
3322                 if (ImGui::Button("Close"))
3323                     ImGui::CloseCurrentPopup();
3324                 ImGui::EndPopup();
3325             }
3326             ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
3327         }
3328 
3329         ImGui::TreePop();
3330     }
3331 
3332     if (ImGui::TreeNode("Modals"))
3333     {
3334         ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside.");
3335 
3336         if (ImGui::Button("Delete.."))
3337             ImGui::OpenPopup("Delete?");
3338 
3339         // Always center this window when appearing
3340         ImVec2 center = ImGui::GetMainViewport()->GetCenter();
3341         ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
3342 
3343         if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
3344         {
3345             ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
3346             ImGui::Separator();
3347 
3348             //static int unused_i = 0;
3349             //ImGui::Combo("Combo", &unused_i, "Delete\0Delete harder\0");
3350 
3351             static bool dont_ask_me_next_time = false;
3352             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
3353             ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
3354             ImGui::PopStyleVar();
3355 
3356             if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
3357             ImGui::SetItemDefaultFocus();
3358             ImGui::SameLine();
3359             if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
3360             ImGui::EndPopup();
3361         }
3362 
3363         if (ImGui::Button("Stacked modals.."))
3364             ImGui::OpenPopup("Stacked 1");
3365         if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
3366         {
3367             if (ImGui::BeginMenuBar())
3368             {
3369                 if (ImGui::BeginMenu("File"))
3370                 {
3371                     if (ImGui::MenuItem("Some menu item")) {}
3372                     ImGui::EndMenu();
3373                 }
3374                 ImGui::EndMenuBar();
3375             }
3376             ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
3377 
3378             // Testing behavior of widgets stacking their own regular popups over the modal.
3379             static int item = 1;
3380             static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
3381             ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
3382             ImGui::ColorEdit4("color", color);
3383 
3384             if (ImGui::Button("Add another modal.."))
3385                 ImGui::OpenPopup("Stacked 2");
3386 
3387             // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which
3388             // will close the popup. Note that the visibility state of popups is owned by imgui, so the input value
3389             // of the bool actually doesn't matter here.
3390             bool unused_open = true;
3391             if (ImGui::BeginPopupModal("Stacked 2", &unused_open))
3392             {
3393                 ImGui::Text("Hello from Stacked The Second!");
3394                 if (ImGui::Button("Close"))
3395                     ImGui::CloseCurrentPopup();
3396                 ImGui::EndPopup();
3397             }
3398 
3399             if (ImGui::Button("Close"))
3400                 ImGui::CloseCurrentPopup();
3401             ImGui::EndPopup();
3402         }
3403 
3404         ImGui::TreePop();
3405     }
3406 
3407     if (ImGui::TreeNode("Menus inside a regular window"))
3408     {
3409         ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
3410         ImGui::Separator();
3411 
3412         // Note: As a quirk in this very specific example, we want to differentiate the parent of this menu from the
3413         // parent of the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block
3414         // to make them two different menusets. If we don't, opening any popup above and hovering our menu here would
3415         // open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it,
3416         // which is the desired behavior for regular menus.
3417         ImGui::PushID("foo");
3418         ImGui::MenuItem("Menu item", "CTRL+M");
3419         if (ImGui::BeginMenu("Menu inside a regular window"))
3420         {
3421             ShowExampleMenuFile();
3422             ImGui::EndMenu();
3423         }
3424         ImGui::PopID();
3425         ImGui::Separator();
3426         ImGui::TreePop();
3427     }
3428 }
3429 
3430 // Dummy data structure that we use for the Table demo.
3431 // (pre-C++11 doesn't allow us to instantiate ImVector<MyItem> template if this structure if defined inside the demo function)
3432 namespace
3433 {
3434 // We are passing our own identifier to TableSetupColumn() to facilitate identifying columns in the sorting code.
3435 // This identifier will be passed down into ImGuiTableSortSpec::ColumnUserID.
3436 // But it is possible to omit the user id parameter of TableSetupColumn() and just use the column index instead! (ImGuiTableSortSpec::ColumnIndex)
3437 // If you don't use sorting, you will generally never care about giving column an ID!
3438 enum MyItemColumnID
3439 {
3440     MyItemColumnID_ID,
3441     MyItemColumnID_Name,
3442     MyItemColumnID_Action,
3443     MyItemColumnID_Quantity,
3444     MyItemColumnID_Description
3445 };
3446 
3447 struct MyItem
3448 {
3449     int         ID;
3450     const char* Name;
3451     int         Quantity;
3452 
3453     // We have a problem which is affecting _only this demo_ and should not affect your code:
3454     // As we don't rely on std:: or other third-party library to compile dear imgui, we only have reliable access to qsort(),
3455     // however qsort doesn't allow passing user data to comparing function.
3456     // As a workaround, we are storing the sort specs in a static/global for the comparing function to access.
3457     // In your own use case you would probably pass the sort specs to your sorting/comparing functions directly and not use a global.
3458     // We could technically call ImGui::TableGetSortSpecs() in CompareWithSortSpecs(), but considering that this function is called
3459     // very often by the sorting algorithm it would be a little wasteful.
3460     static const ImGuiTableSortSpecs* s_current_sort_specs;
3461 
3462     // Compare function to be used by qsort()
CompareWithSortSpecs__anon34f31b530111::MyItem3463     static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs)
3464     {
3465         const MyItem* a = (const MyItem*)lhs;
3466         const MyItem* b = (const MyItem*)rhs;
3467         for (int n = 0; n < s_current_sort_specs->SpecsCount; n++)
3468         {
3469             // Here we identify columns using the ColumnUserID value that we ourselves passed to TableSetupColumn()
3470             // We could also choose to identify columns based on their index (sort_spec->ColumnIndex), which is simpler!
3471             const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n];
3472             int delta = 0;
3473             switch (sort_spec->ColumnUserID)
3474             {
3475             case MyItemColumnID_ID:             delta = (a->ID - b->ID);                break;
3476             case MyItemColumnID_Name:           delta = (strcmp(a->Name, b->Name));     break;
3477             case MyItemColumnID_Quantity:       delta = (a->Quantity - b->Quantity);    break;
3478             case MyItemColumnID_Description:    delta = (strcmp(a->Name, b->Name));     break;
3479             default: IM_ASSERT(0); break;
3480             }
3481             if (delta > 0)
3482                 return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1;
3483             if (delta < 0)
3484                 return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1;
3485         }
3486 
3487         // qsort() is instable so always return a way to differenciate items.
3488         // Your own compare function may want to avoid fallback on implicit sort specs e.g. a Name compare if it wasn't already part of the sort specs.
3489         return (a->ID - b->ID);
3490     }
3491 };
3492 const ImGuiTableSortSpecs* MyItem::s_current_sort_specs = NULL;
3493 }
3494 
3495 // Make the UI compact because there are so many fields
PushStyleCompact()3496 static void PushStyleCompact()
3497 {
3498     ImGuiStyle& style = ImGui::GetStyle();
3499     ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f)));
3500     ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f)));
3501 }
3502 
PopStyleCompact()3503 static void PopStyleCompact()
3504 {
3505     ImGui::PopStyleVar(2);
3506 }
3507 
3508 // Show a combo box with a choice of sizing policies
EditTableSizingFlags(ImGuiTableFlags * p_flags)3509 static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
3510 {
3511     struct EnumDesc { ImGuiTableFlags Value; const char* Name; const char* Tooltip; };
3512     static const EnumDesc policies[] =
3513     {
3514         { ImGuiTableFlags_None,               "Default",                            "Use default sizing policy:\n- ImGuiTableFlags_SizingFixedFit if ScrollX is on or if host window has ImGuiWindowFlags_AlwaysAutoResize.\n- ImGuiTableFlags_SizingStretchSame otherwise." },
3515         { ImGuiTableFlags_SizingFixedFit,     "ImGuiTableFlags_SizingFixedFit",     "Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width." },
3516         { ImGuiTableFlags_SizingFixedSame,    "ImGuiTableFlags_SizingFixedSame",    "Columns are all the same width, matching the maximum contents width.\nImplicitly disable ImGuiTableFlags_Resizable and enable ImGuiTableFlags_NoKeepColumnsVisible." },
3517         { ImGuiTableFlags_SizingStretchProp,  "ImGuiTableFlags_SizingStretchProp",  "Columns default to _WidthStretch with weights proportional to their widths." },
3518         { ImGuiTableFlags_SizingStretchSame,  "ImGuiTableFlags_SizingStretchSame",  "Columns default to _WidthStretch with same weights." }
3519     };
3520     int idx;
3521     for (idx = 0; idx < IM_ARRAYSIZE(policies); idx++)
3522         if (policies[idx].Value == (*p_flags & ImGuiTableFlags_SizingMask_))
3523             break;
3524     const char* preview_text = (idx < IM_ARRAYSIZE(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : "";
3525     if (ImGui::BeginCombo("Sizing Policy", preview_text))
3526     {
3527         for (int n = 0; n < IM_ARRAYSIZE(policies); n++)
3528             if (ImGui::Selectable(policies[n].Name, idx == n))
3529                 *p_flags = (*p_flags & ~ImGuiTableFlags_SizingMask_) | policies[n].Value;
3530         ImGui::EndCombo();
3531     }
3532     ImGui::SameLine();
3533     ImGui::TextDisabled("(?)");
3534     if (ImGui::IsItemHovered())
3535     {
3536         ImGui::BeginTooltip();
3537         ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
3538         for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
3539         {
3540             ImGui::Separator();
3541             ImGui::Text("%s:", policies[m].Name);
3542             ImGui::Separator();
3543             ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().IndentSpacing * 0.5f);
3544             ImGui::TextUnformatted(policies[m].Tooltip);
3545         }
3546         ImGui::PopTextWrapPos();
3547         ImGui::EndTooltip();
3548     }
3549 }
3550 
EditTableColumnsFlags(ImGuiTableColumnFlags * p_flags)3551 static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
3552 {
3553     ImGui::CheckboxFlags("_Disabled", p_flags, ImGuiTableColumnFlags_Disabled); ImGui::SameLine(); HelpMarker("Master disable flag (also hide from context menu)");
3554     ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide);
3555     ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort);
3556     if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch))
3557         *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch);
3558     if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed))
3559         *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed);
3560     ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize);
3561     ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder);
3562     ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide);
3563     ImGui::CheckboxFlags("_NoClip", p_flags, ImGuiTableColumnFlags_NoClip);
3564     ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort);
3565     ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending);
3566     ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending);
3567     ImGui::CheckboxFlags("_NoHeaderLabel", p_flags, ImGuiTableColumnFlags_NoHeaderLabel);
3568     ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth);
3569     ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending);
3570     ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending);
3571     ImGui::CheckboxFlags("_IndentEnable", p_flags, ImGuiTableColumnFlags_IndentEnable); ImGui::SameLine(); HelpMarker("Default for column 0");
3572     ImGui::CheckboxFlags("_IndentDisable", p_flags, ImGuiTableColumnFlags_IndentDisable); ImGui::SameLine(); HelpMarker("Default for column >0");
3573 }
3574 
ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags)3575 static void ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags)
3576 {
3577     ImGui::CheckboxFlags("_IsEnabled", &flags, ImGuiTableColumnFlags_IsEnabled);
3578     ImGui::CheckboxFlags("_IsVisible", &flags, ImGuiTableColumnFlags_IsVisible);
3579     ImGui::CheckboxFlags("_IsSorted", &flags, ImGuiTableColumnFlags_IsSorted);
3580     ImGui::CheckboxFlags("_IsHovered", &flags, ImGuiTableColumnFlags_IsHovered);
3581 }
3582 
ShowDemoWindowTables()3583 static void ShowDemoWindowTables()
3584 {
3585     //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
3586     if (!ImGui::CollapsingHeader("Tables & Columns"))
3587         return;
3588 
3589     // Using those as a base value to create width/height that are factor of the size of our font
3590     const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
3591     const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
3592 
3593     ImGui::PushID("Tables");
3594 
3595     int open_action = -1;
3596     if (ImGui::Button("Open all"))
3597         open_action = 1;
3598     ImGui::SameLine();
3599     if (ImGui::Button("Close all"))
3600         open_action = 0;
3601     ImGui::SameLine();
3602 
3603     // Options
3604     static bool disable_indent = false;
3605     ImGui::Checkbox("Disable tree indentation", &disable_indent);
3606     ImGui::SameLine();
3607     HelpMarker("Disable the indenting of tree nodes so demo tables can use the full window width.");
3608     ImGui::Separator();
3609     if (disable_indent)
3610         ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
3611 
3612     // About Styling of tables
3613     // Most settings are configured on a per-table basis via the flags passed to BeginTable() and TableSetupColumns APIs.
3614     // There are however a few settings that a shared and part of the ImGuiStyle structure:
3615     //   style.CellPadding                          // Padding within each cell
3616     //   style.Colors[ImGuiCol_TableHeaderBg]       // Table header background
3617     //   style.Colors[ImGuiCol_TableBorderStrong]   // Table outer and header borders
3618     //   style.Colors[ImGuiCol_TableBorderLight]    // Table inner borders
3619     //   style.Colors[ImGuiCol_TableRowBg]          // Table row background when ImGuiTableFlags_RowBg is enabled (even rows)
3620     //   style.Colors[ImGuiCol_TableRowBgAlt]       // Table row background when ImGuiTableFlags_RowBg is enabled (odds rows)
3621 
3622     // Demos
3623     if (open_action != -1)
3624         ImGui::SetNextItemOpen(open_action != 0);
3625     if (ImGui::TreeNode("Basic"))
3626     {
3627         // Here we will showcase three different ways to output a table.
3628         // They are very simple variations of a same thing!
3629 
3630         // [Method 1] Using TableNextRow() to create a new row, and TableSetColumnIndex() to select the column.
3631         // In many situations, this is the most flexible and easy to use pattern.
3632         HelpMarker("Using TableNextRow() + calling TableSetColumnIndex() _before_ each cell, in a loop.");
3633         if (ImGui::BeginTable("table1", 3))
3634         {
3635             for (int row = 0; row < 4; row++)
3636             {
3637                 ImGui::TableNextRow();
3638                 for (int column = 0; column < 3; column++)
3639                 {
3640                     ImGui::TableSetColumnIndex(column);
3641                     ImGui::Text("Row %d Column %d", row, column);
3642                 }
3643             }
3644             ImGui::EndTable();
3645         }
3646 
3647         // [Method 2] Using TableNextColumn() called multiple times, instead of using a for loop + TableSetColumnIndex().
3648         // This is generally more convenient when you have code manually submitting the contents of each columns.
3649         HelpMarker("Using TableNextRow() + calling TableNextColumn() _before_ each cell, manually.");
3650         if (ImGui::BeginTable("table2", 3))
3651         {
3652             for (int row = 0; row < 4; row++)
3653             {
3654                 ImGui::TableNextRow();
3655                 ImGui::TableNextColumn();
3656                 ImGui::Text("Row %d", row);
3657                 ImGui::TableNextColumn();
3658                 ImGui::Text("Some contents");
3659                 ImGui::TableNextColumn();
3660                 ImGui::Text("123.456");
3661             }
3662             ImGui::EndTable();
3663         }
3664 
3665         // [Method 3] We call TableNextColumn() _before_ each cell. We never call TableNextRow(),
3666         // as TableNextColumn() will automatically wrap around and create new roes as needed.
3667         // This is generally more convenient when your cells all contains the same type of data.
3668         HelpMarker(
3669             "Only using TableNextColumn(), which tends to be convenient for tables where every cells contains the same type of contents.\n"
3670             "This is also more similar to the old NextColumn() function of the Columns API, and provided to facilitate the Columns->Tables API transition.");
3671         if (ImGui::BeginTable("table3", 3))
3672         {
3673             for (int item = 0; item < 14; item++)
3674             {
3675                 ImGui::TableNextColumn();
3676                 ImGui::Text("Item %d", item);
3677             }
3678             ImGui::EndTable();
3679         }
3680 
3681         ImGui::TreePop();
3682     }
3683 
3684     if (open_action != -1)
3685         ImGui::SetNextItemOpen(open_action != 0);
3686     if (ImGui::TreeNode("Borders, background"))
3687     {
3688         // Expose a few Borders related flags interactively
3689         enum ContentsType { CT_Text, CT_FillButton };
3690         static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
3691         static bool display_headers = false;
3692         static int contents_type = CT_Text;
3693 
3694         PushStyleCompact();
3695         ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
3696         ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
3697         ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterH");
3698         ImGui::Indent();
3699 
3700         ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
3701         ImGui::Indent();
3702         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
3703         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
3704         ImGui::Unindent();
3705 
3706         ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
3707         ImGui::Indent();
3708         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
3709         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
3710         ImGui::Unindent();
3711 
3712         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags, ImGuiTableFlags_BordersOuter);
3713         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags, ImGuiTableFlags_BordersInner);
3714         ImGui::Unindent();
3715 
3716         ImGui::AlignTextToFramePadding(); ImGui::Text("Cell contents:");
3717         ImGui::SameLine(); ImGui::RadioButton("Text", &contents_type, CT_Text);
3718         ImGui::SameLine(); ImGui::RadioButton("FillButton", &contents_type, CT_FillButton);
3719         ImGui::Checkbox("Display headers", &display_headers);
3720         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appears in Headers");
3721         PopStyleCompact();
3722 
3723         if (ImGui::BeginTable("table1", 3, flags))
3724         {
3725             // Display headers so we can inspect their interaction with borders.
3726             // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them too much. See other sections for details)
3727             if (display_headers)
3728             {
3729                 ImGui::TableSetupColumn("One");
3730                 ImGui::TableSetupColumn("Two");
3731                 ImGui::TableSetupColumn("Three");
3732                 ImGui::TableHeadersRow();
3733             }
3734 
3735             for (int row = 0; row < 5; row++)
3736             {
3737                 ImGui::TableNextRow();
3738                 for (int column = 0; column < 3; column++)
3739                 {
3740                     ImGui::TableSetColumnIndex(column);
3741                     char buf[32];
3742                     sprintf(buf, "Hello %d,%d", column, row);
3743                     if (contents_type == CT_Text)
3744                         ImGui::TextUnformatted(buf);
3745                     else if (contents_type)
3746                         ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
3747                 }
3748             }
3749             ImGui::EndTable();
3750         }
3751         ImGui::TreePop();
3752     }
3753 
3754     if (open_action != -1)
3755         ImGui::SetNextItemOpen(open_action != 0);
3756     if (ImGui::TreeNode("Resizable, stretch"))
3757     {
3758         // By default, if we don't enable ScrollX the sizing policy for each columns is "Stretch"
3759         // Each columns maintain a sizing weight, and they will occupy all available width.
3760         static ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
3761         PushStyleCompact();
3762         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
3763         ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
3764         ImGui::SameLine(); HelpMarker("Using the _Resizable flag automatically enables the _BordersInnerV flag as well, this is why the resize borders are still showing when unchecking this.");
3765         PopStyleCompact();
3766 
3767         if (ImGui::BeginTable("table1", 3, flags))
3768         {
3769             for (int row = 0; row < 5; row++)
3770             {
3771                 ImGui::TableNextRow();
3772                 for (int column = 0; column < 3; column++)
3773                 {
3774                     ImGui::TableSetColumnIndex(column);
3775                     ImGui::Text("Hello %d,%d", column, row);
3776                 }
3777             }
3778             ImGui::EndTable();
3779         }
3780         ImGui::TreePop();
3781     }
3782 
3783     if (open_action != -1)
3784         ImGui::SetNextItemOpen(open_action != 0);
3785     if (ImGui::TreeNode("Resizable, fixed"))
3786     {
3787         // Here we use ImGuiTableFlags_SizingFixedFit (even though _ScrollX is not set)
3788         // So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small)
3789         // If there is not enough available width to fit all columns, they will however be resized down.
3790         // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings
3791         HelpMarker(
3792             "Using _Resizable + _SizingFixedFit flags.\n"
3793             "Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n"
3794             "Double-click a column border to auto-fit the column to its contents.");
3795         PushStyleCompact();
3796         static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
3797         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
3798         PopStyleCompact();
3799 
3800         if (ImGui::BeginTable("table1", 3, flags))
3801         {
3802             for (int row = 0; row < 5; row++)
3803             {
3804                 ImGui::TableNextRow();
3805                 for (int column = 0; column < 3; column++)
3806                 {
3807                     ImGui::TableSetColumnIndex(column);
3808                     ImGui::Text("Hello %d,%d", column, row);
3809                 }
3810             }
3811             ImGui::EndTable();
3812         }
3813         ImGui::TreePop();
3814     }
3815 
3816     if (open_action != -1)
3817         ImGui::SetNextItemOpen(open_action != 0);
3818     if (ImGui::TreeNode("Resizable, mixed"))
3819     {
3820         HelpMarker(
3821             "Using TableSetupColumn() to alter resizing policy on a per-column basis.\n\n"
3822             "When combining Fixed and Stretch columns, generally you only want one, maybe two trailing columns to use _WidthStretch.");
3823         static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
3824 
3825         if (ImGui::BeginTable("table1", 3, flags))
3826         {
3827             ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
3828             ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
3829             ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthStretch);
3830             ImGui::TableHeadersRow();
3831             for (int row = 0; row < 5; row++)
3832             {
3833                 ImGui::TableNextRow();
3834                 for (int column = 0; column < 3; column++)
3835                 {
3836                     ImGui::TableSetColumnIndex(column);
3837                     ImGui::Text("%s %d,%d", (column == 2) ? "Stretch" : "Fixed", column, row);
3838                 }
3839             }
3840             ImGui::EndTable();
3841         }
3842         if (ImGui::BeginTable("table2", 6, flags))
3843         {
3844             ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
3845             ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
3846             ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_DefaultHide);
3847             ImGui::TableSetupColumn("DDD", ImGuiTableColumnFlags_WidthStretch);
3848             ImGui::TableSetupColumn("EEE", ImGuiTableColumnFlags_WidthStretch);
3849             ImGui::TableSetupColumn("FFF", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_DefaultHide);
3850             ImGui::TableHeadersRow();
3851             for (int row = 0; row < 5; row++)
3852             {
3853                 ImGui::TableNextRow();
3854                 for (int column = 0; column < 6; column++)
3855                 {
3856                     ImGui::TableSetColumnIndex(column);
3857                     ImGui::Text("%s %d,%d", (column >= 3) ? "Stretch" : "Fixed", column, row);
3858                 }
3859             }
3860             ImGui::EndTable();
3861         }
3862         ImGui::TreePop();
3863     }
3864 
3865     if (open_action != -1)
3866         ImGui::SetNextItemOpen(open_action != 0);
3867     if (ImGui::TreeNode("Reorderable, hideable, with headers"))
3868     {
3869         HelpMarker(
3870             "Click and drag column headers to reorder columns.\n\n"
3871             "Right-click on a header to open a context menu.");
3872         static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV;
3873         PushStyleCompact();
3874         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
3875         ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
3876         ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
3877         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody);
3878         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers)");
3879         PopStyleCompact();
3880 
3881         if (ImGui::BeginTable("table1", 3, flags))
3882         {
3883             // Submit columns name with TableSetupColumn() and call TableHeadersRow() to create a row with a header in each column.
3884             // (Later we will show how TableSetupColumn() has other uses, optional flags, sizing weight etc.)
3885             ImGui::TableSetupColumn("One");
3886             ImGui::TableSetupColumn("Two");
3887             ImGui::TableSetupColumn("Three");
3888             ImGui::TableHeadersRow();
3889             for (int row = 0; row < 6; row++)
3890             {
3891                 ImGui::TableNextRow();
3892                 for (int column = 0; column < 3; column++)
3893                 {
3894                     ImGui::TableSetColumnIndex(column);
3895                     ImGui::Text("Hello %d,%d", column, row);
3896                 }
3897             }
3898             ImGui::EndTable();
3899         }
3900 
3901         // Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column)
3902         if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f)))
3903         {
3904             ImGui::TableSetupColumn("One");
3905             ImGui::TableSetupColumn("Two");
3906             ImGui::TableSetupColumn("Three");
3907             ImGui::TableHeadersRow();
3908             for (int row = 0; row < 6; row++)
3909             {
3910                 ImGui::TableNextRow();
3911                 for (int column = 0; column < 3; column++)
3912                 {
3913                     ImGui::TableSetColumnIndex(column);
3914                     ImGui::Text("Fixed %d,%d", column, row);
3915                 }
3916             }
3917             ImGui::EndTable();
3918         }
3919         ImGui::TreePop();
3920     }
3921 
3922     if (open_action != -1)
3923         ImGui::SetNextItemOpen(open_action != 0);
3924     if (ImGui::TreeNode("Padding"))
3925     {
3926         // First example: showcase use of padding flags and effect of BorderOuterV/BorderInnerV on X padding.
3927         // We don't expose BorderOuterH/BorderInnerH here because they have no effect on X padding.
3928         HelpMarker(
3929             "We often want outer padding activated when any using features which makes the edges of a column visible:\n"
3930             "e.g.:\n"
3931             "- BorderOuterV\n"
3932             "- any form of row selection\n"
3933             "Because of this, activating BorderOuterV sets the default to PadOuterX. Using PadOuterX or NoPadOuterX you can override the default.\n\n"
3934             "Actual padding values are using style.CellPadding.\n\n"
3935             "In this demo we don't show horizontal borders to emphasis how they don't affect default horizontal padding.");
3936 
3937         static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV;
3938         PushStyleCompact();
3939         ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags1, ImGuiTableFlags_PadOuterX);
3940         ImGui::SameLine(); HelpMarker("Enable outer-most padding (default if ImGuiTableFlags_BordersOuterV is set)");
3941         ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags1, ImGuiTableFlags_NoPadOuterX);
3942         ImGui::SameLine(); HelpMarker("Disable outer-most padding (default if ImGuiTableFlags_BordersOuterV is not set)");
3943         ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags1, ImGuiTableFlags_NoPadInnerX);
3944         ImGui::SameLine(); HelpMarker("Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off)");
3945         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags1, ImGuiTableFlags_BordersOuterV);
3946         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags1, ImGuiTableFlags_BordersInnerV);
3947         static bool show_headers = false;
3948         ImGui::Checkbox("show_headers", &show_headers);
3949         PopStyleCompact();
3950 
3951         if (ImGui::BeginTable("table_padding", 3, flags1))
3952         {
3953             if (show_headers)
3954             {
3955                 ImGui::TableSetupColumn("One");
3956                 ImGui::TableSetupColumn("Two");
3957                 ImGui::TableSetupColumn("Three");
3958                 ImGui::TableHeadersRow();
3959             }
3960 
3961             for (int row = 0; row < 5; row++)
3962             {
3963                 ImGui::TableNextRow();
3964                 for (int column = 0; column < 3; column++)
3965                 {
3966                     ImGui::TableSetColumnIndex(column);
3967                     if (row == 0)
3968                     {
3969                         ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
3970                     }
3971                     else
3972                     {
3973                         char buf[32];
3974                         sprintf(buf, "Hello %d,%d", column, row);
3975                         ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
3976                     }
3977                     //if (ImGui::TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered)
3978                     //    ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, IM_COL32(0, 100, 0, 255));
3979                 }
3980             }
3981             ImGui::EndTable();
3982         }
3983 
3984         // Second example: set style.CellPadding to (0.0) or a custom value.
3985         // FIXME-TABLE: Vertical border effectively not displayed the same way as horizontal one...
3986         HelpMarker("Setting style.CellPadding to (0,0) or a custom value.");
3987         static ImGuiTableFlags flags2 = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
3988         static ImVec2 cell_padding(0.0f, 0.0f);
3989         static bool show_widget_frame_bg = true;
3990 
3991         PushStyleCompact();
3992         ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags2, ImGuiTableFlags_Borders);
3993         ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags2, ImGuiTableFlags_BordersH);
3994         ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags2, ImGuiTableFlags_BordersV);
3995         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags2, ImGuiTableFlags_BordersInner);
3996         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags2, ImGuiTableFlags_BordersOuter);
3997         ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags2, ImGuiTableFlags_RowBg);
3998         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags2, ImGuiTableFlags_Resizable);
3999         ImGui::Checkbox("show_widget_frame_bg", &show_widget_frame_bg);
4000         ImGui::SliderFloat2("CellPadding", &cell_padding.x, 0.0f, 10.0f, "%.0f");
4001         PopStyleCompact();
4002 
4003         ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cell_padding);
4004         if (ImGui::BeginTable("table_padding_2", 3, flags2))
4005         {
4006             static char text_bufs[3 * 5][16]; // Mini text storage for 3x5 cells
4007             static bool init = true;
4008             if (!show_widget_frame_bg)
4009                 ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);
4010             for (int cell = 0; cell < 3 * 5; cell++)
4011             {
4012                 ImGui::TableNextColumn();
4013                 if (init)
4014                     strcpy(text_bufs[cell], "edit me");
4015                 ImGui::SetNextItemWidth(-FLT_MIN);
4016                 ImGui::PushID(cell);
4017                 ImGui::InputText("##cell", text_bufs[cell], IM_ARRAYSIZE(text_bufs[cell]));
4018                 ImGui::PopID();
4019             }
4020             if (!show_widget_frame_bg)
4021                 ImGui::PopStyleColor();
4022             init = false;
4023             ImGui::EndTable();
4024         }
4025         ImGui::PopStyleVar();
4026 
4027         ImGui::TreePop();
4028     }
4029 
4030     if (open_action != -1)
4031         ImGui::SetNextItemOpen(open_action != 0);
4032     if (ImGui::TreeNode("Sizing policies"))
4033     {
4034         static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
4035         PushStyleCompact();
4036         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
4037         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags1, ImGuiTableFlags_NoHostExtendX);
4038         PopStyleCompact();
4039 
4040         static ImGuiTableFlags sizing_policy_flags[4] = { ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp, ImGuiTableFlags_SizingStretchSame };
4041         for (int table_n = 0; table_n < 4; table_n++)
4042         {
4043             ImGui::PushID(table_n);
4044             ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 30);
4045             EditTableSizingFlags(&sizing_policy_flags[table_n]);
4046 
4047             // To make it easier to understand the different sizing policy,
4048             // For each policy: we display one table where the columns have equal contents width, and one where the columns have different contents width.
4049             if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1))
4050             {
4051                 for (int row = 0; row < 3; row++)
4052                 {
4053                     ImGui::TableNextRow();
4054                     ImGui::TableNextColumn(); ImGui::Text("Oh dear");
4055                     ImGui::TableNextColumn(); ImGui::Text("Oh dear");
4056                     ImGui::TableNextColumn(); ImGui::Text("Oh dear");
4057                 }
4058                 ImGui::EndTable();
4059             }
4060             if (ImGui::BeginTable("table2", 3, sizing_policy_flags[table_n] | flags1))
4061             {
4062                 for (int row = 0; row < 3; row++)
4063                 {
4064                     ImGui::TableNextRow();
4065                     ImGui::TableNextColumn(); ImGui::Text("AAAA");
4066                     ImGui::TableNextColumn(); ImGui::Text("BBBBBBBB");
4067                     ImGui::TableNextColumn(); ImGui::Text("CCCCCCCCCCCC");
4068                 }
4069                 ImGui::EndTable();
4070             }
4071             ImGui::PopID();
4072         }
4073 
4074         ImGui::Spacing();
4075         ImGui::TextUnformatted("Advanced");
4076         ImGui::SameLine();
4077         HelpMarker("This section allows you to interact and see the effect of various sizing policies depending on whether Scroll is enabled and the contents of your columns.");
4078 
4079         enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText };
4080         static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable;
4081         static int contents_type = CT_ShowWidth;
4082         static int column_count = 3;
4083 
4084         PushStyleCompact();
4085         ImGui::PushID("Advanced");
4086         ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
4087         EditTableSizingFlags(&flags);
4088         ImGui::Combo("Contents", &contents_type, "Show width\0Short Text\0Long Text\0Button\0Fill Button\0InputText\0");
4089         if (contents_type == CT_FillButton)
4090         {
4091             ImGui::SameLine();
4092             HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width.");
4093         }
4094         ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
4095         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
4096         ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
4097         ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.");
4098         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
4099         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
4100         ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
4101         ImGui::PopItemWidth();
4102         ImGui::PopID();
4103         PopStyleCompact();
4104 
4105         if (ImGui::BeginTable("table2", column_count, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 7)))
4106         {
4107             for (int cell = 0; cell < 10 * column_count; cell++)
4108             {
4109                 ImGui::TableNextColumn();
4110                 int column = ImGui::TableGetColumnIndex();
4111                 int row = ImGui::TableGetRowIndex();
4112 
4113                 ImGui::PushID(cell);
4114                 char label[32];
4115                 static char text_buf[32] = "";
4116                 sprintf(label, "Hello %d,%d", column, row);
4117                 switch (contents_type)
4118                 {
4119                 case CT_ShortText:  ImGui::TextUnformatted(label); break;
4120                 case CT_LongText:   ImGui::Text("Some %s text %d,%d\nOver two lines..", column == 0 ? "long" : "longeeer", column, row); break;
4121                 case CT_ShowWidth:  ImGui::Text("W: %.1f", ImGui::GetContentRegionAvail().x); break;
4122                 case CT_Button:     ImGui::Button(label); break;
4123                 case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
4124                 case CT_InputText:  ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
4125                 }
4126                 ImGui::PopID();
4127             }
4128             ImGui::EndTable();
4129         }
4130         ImGui::TreePop();
4131     }
4132 
4133     if (open_action != -1)
4134         ImGui::SetNextItemOpen(open_action != 0);
4135     if (ImGui::TreeNode("Vertical scrolling, with clipping"))
4136     {
4137         HelpMarker("Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\nWe also demonstrate using ImGuiListClipper to virtualize the submission of many items.");
4138         static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
4139 
4140         PushStyleCompact();
4141         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
4142         PopStyleCompact();
4143 
4144         // When using ScrollX or ScrollY we need to specify a size for our table container!
4145         // Otherwise by default the table will fit all available space, like a BeginChild() call.
4146         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
4147         if (ImGui::BeginTable("table_scrolly", 3, flags, outer_size))
4148         {
4149             ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
4150             ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None);
4151             ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None);
4152             ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None);
4153             ImGui::TableHeadersRow();
4154 
4155             // Demonstrate using clipper for large vertical lists
4156             ImGuiListClipper clipper;
4157             clipper.Begin(1000);
4158             while (clipper.Step())
4159             {
4160                 for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++)
4161                 {
4162                     ImGui::TableNextRow();
4163                     for (int column = 0; column < 3; column++)
4164                     {
4165                         ImGui::TableSetColumnIndex(column);
4166                         ImGui::Text("Hello %d,%d", column, row);
4167                     }
4168                 }
4169             }
4170             ImGui::EndTable();
4171         }
4172         ImGui::TreePop();
4173     }
4174 
4175     if (open_action != -1)
4176         ImGui::SetNextItemOpen(open_action != 0);
4177     if (ImGui::TreeNode("Horizontal scrolling"))
4178     {
4179         HelpMarker(
4180             "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, "
4181             "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n"
4182             "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX,"
4183             "because the container window won't automatically extend vertically to fix contents (this may be improved in future versions).");
4184         static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
4185         static int freeze_cols = 1;
4186         static int freeze_rows = 1;
4187 
4188         PushStyleCompact();
4189         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
4190         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
4191         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
4192         ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
4193         ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
4194         ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
4195         ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
4196         PopStyleCompact();
4197 
4198         // When using ScrollX or ScrollY we need to specify a size for our table container!
4199         // Otherwise by default the table will fit all available space, like a BeginChild() call.
4200         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
4201         if (ImGui::BeginTable("table_scrollx", 7, flags, outer_size))
4202         {
4203             ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
4204             ImGui::TableSetupColumn("Line #", ImGuiTableColumnFlags_NoHide); // Make the first column not hideable to match our use of TableSetupScrollFreeze()
4205             ImGui::TableSetupColumn("One");
4206             ImGui::TableSetupColumn("Two");
4207             ImGui::TableSetupColumn("Three");
4208             ImGui::TableSetupColumn("Four");
4209             ImGui::TableSetupColumn("Five");
4210             ImGui::TableSetupColumn("Six");
4211             ImGui::TableHeadersRow();
4212             for (int row = 0; row < 20; row++)
4213             {
4214                 ImGui::TableNextRow();
4215                 for (int column = 0; column < 7; column++)
4216                 {
4217                     // Both TableNextColumn() and TableSetColumnIndex() return true when a column is visible or performing width measurement.
4218                     // Because here we know that:
4219                     // - A) all our columns are contributing the same to row height
4220                     // - B) column 0 is always visible,
4221                     // We only always submit this one column and can skip others.
4222                     // More advanced per-column clipping behaviors may benefit from polling the status flags via TableGetColumnFlags().
4223                     if (!ImGui::TableSetColumnIndex(column) && column > 0)
4224                         continue;
4225                     if (column == 0)
4226                         ImGui::Text("Line %d", row);
4227                     else
4228                         ImGui::Text("Hello world %d,%d", column, row);
4229                 }
4230             }
4231             ImGui::EndTable();
4232         }
4233 
4234         ImGui::Spacing();
4235         ImGui::TextUnformatted("Stretch + ScrollX");
4236         ImGui::SameLine();
4237         HelpMarker(
4238             "Showcase using Stretch columns + ScrollX together: "
4239             "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
4240             "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense.");
4241         static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
4242         static float inner_width = 1000.0f;
4243         PushStyleCompact();
4244         ImGui::PushID("flags3");
4245         ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
4246         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX);
4247         ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
4248         ImGui::PopItemWidth();
4249         ImGui::PopID();
4250         PopStyleCompact();
4251         if (ImGui::BeginTable("table2", 7, flags2, outer_size, inner_width))
4252         {
4253             for (int cell = 0; cell < 20 * 7; cell++)
4254             {
4255                 ImGui::TableNextColumn();
4256                 ImGui::Text("Hello world %d,%d", ImGui::TableGetColumnIndex(), ImGui::TableGetRowIndex());
4257             }
4258             ImGui::EndTable();
4259         }
4260         ImGui::TreePop();
4261     }
4262 
4263     if (open_action != -1)
4264         ImGui::SetNextItemOpen(open_action != 0);
4265     if (ImGui::TreeNode("Columns flags"))
4266     {
4267         // Create a first table just to show all the options/flags we want to make visible in our example!
4268         const int column_count = 3;
4269         const char* column_names[column_count] = { "One", "Two", "Three" };
4270         static ImGuiTableColumnFlags column_flags[column_count] = { ImGuiTableColumnFlags_DefaultSort, ImGuiTableColumnFlags_None, ImGuiTableColumnFlags_DefaultHide };
4271         static ImGuiTableColumnFlags column_flags_out[column_count] = { 0, 0, 0 }; // Output from TableGetColumnFlags()
4272 
4273         if (ImGui::BeginTable("table_columns_flags_checkboxes", column_count, ImGuiTableFlags_None))
4274         {
4275             PushStyleCompact();
4276             for (int column = 0; column < column_count; column++)
4277             {
4278                 ImGui::TableNextColumn();
4279                 ImGui::PushID(column);
4280                 ImGui::AlignTextToFramePadding(); // FIXME-TABLE: Workaround for wrong text baseline propagation
4281                 ImGui::Text("'%s'", column_names[column]);
4282                 ImGui::Spacing();
4283                 ImGui::Text("Input flags:");
4284                 EditTableColumnsFlags(&column_flags[column]);
4285                 ImGui::Spacing();
4286                 ImGui::Text("Output flags:");
4287                 ShowTableColumnsStatusFlags(column_flags_out[column]);
4288                 ImGui::PopID();
4289             }
4290             PopStyleCompact();
4291             ImGui::EndTable();
4292         }
4293 
4294         // Create the real table we care about for the example!
4295         // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in
4296         // a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down)
4297         const ImGuiTableFlags flags
4298             = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
4299             | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV
4300             | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable;
4301         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 9);
4302         if (ImGui::BeginTable("table_columns_flags", column_count, flags, outer_size))
4303         {
4304             for (int column = 0; column < column_count; column++)
4305                 ImGui::TableSetupColumn(column_names[column], column_flags[column]);
4306             ImGui::TableHeadersRow();
4307             for (int column = 0; column < column_count; column++)
4308                 column_flags_out[column] = ImGui::TableGetColumnFlags(column);
4309             float indent_step = (float)((int)TEXT_BASE_WIDTH / 2);
4310             for (int row = 0; row < 8; row++)
4311             {
4312                 ImGui::Indent(indent_step); // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags.
4313                 ImGui::TableNextRow();
4314                 for (int column = 0; column < column_count; column++)
4315                 {
4316                     ImGui::TableSetColumnIndex(column);
4317                     ImGui::Text("%s %s", (column == 0) ? "Indented" : "Hello", ImGui::TableGetColumnName(column));
4318                 }
4319             }
4320             ImGui::Unindent(indent_step * 8.0f);
4321 
4322             ImGui::EndTable();
4323         }
4324         ImGui::TreePop();
4325     }
4326 
4327     if (open_action != -1)
4328         ImGui::SetNextItemOpen(open_action != 0);
4329     if (ImGui::TreeNode("Columns widths"))
4330     {
4331         HelpMarker("Using TableSetupColumn() to setup default width.");
4332 
4333         static ImGuiTableFlags flags1 = ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBodyUntilResize;
4334         PushStyleCompact();
4335         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
4336         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags1, ImGuiTableFlags_NoBordersInBodyUntilResize);
4337         PopStyleCompact();
4338         if (ImGui::BeginTable("table1", 3, flags1))
4339         {
4340             // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed.
4341             ImGui::TableSetupColumn("one", ImGuiTableColumnFlags_WidthFixed, 100.0f); // Default to 100.0f
4342             ImGui::TableSetupColumn("two", ImGuiTableColumnFlags_WidthFixed, 200.0f); // Default to 200.0f
4343             ImGui::TableSetupColumn("three", ImGuiTableColumnFlags_WidthFixed);       // Default to auto
4344             ImGui::TableHeadersRow();
4345             for (int row = 0; row < 4; row++)
4346             {
4347                 ImGui::TableNextRow();
4348                 for (int column = 0; column < 3; column++)
4349                 {
4350                     ImGui::TableSetColumnIndex(column);
4351                     if (row == 0)
4352                         ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
4353                     else
4354                         ImGui::Text("Hello %d,%d", column, row);
4355                 }
4356             }
4357             ImGui::EndTable();
4358         }
4359 
4360         HelpMarker("Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, fixed columns with set width may still be shrunk down if there's not enough space in the host.");
4361 
4362         static ImGuiTableFlags flags2 = ImGuiTableFlags_None;
4363         PushStyleCompact();
4364         ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags2, ImGuiTableFlags_NoKeepColumnsVisible);
4365         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags2, ImGuiTableFlags_BordersInnerV);
4366         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags2, ImGuiTableFlags_BordersOuterV);
4367         PopStyleCompact();
4368         if (ImGui::BeginTable("table2", 4, flags2))
4369         {
4370             // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed.
4371             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f);
4372             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
4373             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f);
4374             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
4375             for (int row = 0; row < 5; row++)
4376             {
4377                 ImGui::TableNextRow();
4378                 for (int column = 0; column < 4; column++)
4379                 {
4380                     ImGui::TableSetColumnIndex(column);
4381                     if (row == 0)
4382                         ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
4383                     else
4384                         ImGui::Text("Hello %d,%d", column, row);
4385                 }
4386             }
4387             ImGui::EndTable();
4388         }
4389         ImGui::TreePop();
4390     }
4391 
4392     if (open_action != -1)
4393         ImGui::SetNextItemOpen(open_action != 0);
4394     if (ImGui::TreeNode("Nested tables"))
4395     {
4396         HelpMarker("This demonstrate embedding a table into another table cell.");
4397 
4398         if (ImGui::BeginTable("table_nested1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
4399         {
4400             ImGui::TableSetupColumn("A0");
4401             ImGui::TableSetupColumn("A1");
4402             ImGui::TableHeadersRow();
4403 
4404             ImGui::TableNextColumn();
4405             ImGui::Text("A0 Row 0");
4406             {
4407                 float rows_height = TEXT_BASE_HEIGHT * 2;
4408                 if (ImGui::BeginTable("table_nested2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
4409                 {
4410                     ImGui::TableSetupColumn("B0");
4411                     ImGui::TableSetupColumn("B1");
4412                     ImGui::TableHeadersRow();
4413 
4414                     ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
4415                     ImGui::TableNextColumn();
4416                     ImGui::Text("B0 Row 0");
4417                     ImGui::TableNextColumn();
4418                     ImGui::Text("B1 Row 0");
4419                     ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
4420                     ImGui::TableNextColumn();
4421                     ImGui::Text("B0 Row 1");
4422                     ImGui::TableNextColumn();
4423                     ImGui::Text("B1 Row 1");
4424 
4425                     ImGui::EndTable();
4426                 }
4427             }
4428             ImGui::TableNextColumn(); ImGui::Text("A1 Row 0");
4429             ImGui::TableNextColumn(); ImGui::Text("A0 Row 1");
4430             ImGui::TableNextColumn(); ImGui::Text("A1 Row 1");
4431             ImGui::EndTable();
4432         }
4433         ImGui::TreePop();
4434     }
4435 
4436     if (open_action != -1)
4437         ImGui::SetNextItemOpen(open_action != 0);
4438     if (ImGui::TreeNode("Row height"))
4439     {
4440         HelpMarker("You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\nWe cannot honor a _maximum_ row height as that would requires a unique clipping rectangle per row.");
4441         if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerV))
4442         {
4443             for (int row = 0; row < 10; row++)
4444             {
4445                 float min_row_height = (float)(int)(TEXT_BASE_HEIGHT * 0.30f * row);
4446                 ImGui::TableNextRow(ImGuiTableRowFlags_None, min_row_height);
4447                 ImGui::TableNextColumn();
4448                 ImGui::Text("min_row_height = %.2f", min_row_height);
4449             }
4450             ImGui::EndTable();
4451         }
4452         ImGui::TreePop();
4453     }
4454 
4455     if (open_action != -1)
4456         ImGui::SetNextItemOpen(open_action != 0);
4457     if (ImGui::TreeNode("Outer size"))
4458     {
4459         // Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY
4460         // Important to that note how the two flags have slightly different behaviors!
4461         ImGui::Text("Using NoHostExtendX and NoHostExtendY:");
4462         PushStyleCompact();
4463         static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX;
4464         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
4465         ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used.");
4466         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
4467         ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.");
4468         PopStyleCompact();
4469 
4470         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f);
4471         if (ImGui::BeginTable("table1", 3, flags, outer_size))
4472         {
4473             for (int row = 0; row < 10; row++)
4474             {
4475                 ImGui::TableNextRow();
4476                 for (int column = 0; column < 3; column++)
4477                 {
4478                     ImGui::TableNextColumn();
4479                     ImGui::Text("Cell %d,%d", column, row);
4480                 }
4481             }
4482             ImGui::EndTable();
4483         }
4484         ImGui::SameLine();
4485         ImGui::Text("Hello!");
4486 
4487         ImGui::Spacing();
4488 
4489         ImGui::Text("Using explicit size:");
4490         if (ImGui::BeginTable("table2", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
4491         {
4492             for (int row = 0; row < 5; row++)
4493             {
4494                 ImGui::TableNextRow();
4495                 for (int column = 0; column < 3; column++)
4496                 {
4497                     ImGui::TableNextColumn();
4498                     ImGui::Text("Cell %d,%d", column, row);
4499                 }
4500             }
4501             ImGui::EndTable();
4502         }
4503         ImGui::SameLine();
4504         if (ImGui::BeginTable("table3", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
4505         {
4506             for (int row = 0; row < 3; row++)
4507             {
4508                 ImGui::TableNextRow(0, TEXT_BASE_HEIGHT * 1.5f);
4509                 for (int column = 0; column < 3; column++)
4510                 {
4511                     ImGui::TableNextColumn();
4512                     ImGui::Text("Cell %d,%d", column, row);
4513                 }
4514             }
4515             ImGui::EndTable();
4516         }
4517 
4518         ImGui::TreePop();
4519     }
4520 
4521     if (open_action != -1)
4522         ImGui::SetNextItemOpen(open_action != 0);
4523     if (ImGui::TreeNode("Background color"))
4524     {
4525         static ImGuiTableFlags flags = ImGuiTableFlags_RowBg;
4526         static int row_bg_type = 1;
4527         static int row_bg_target = 1;
4528         static int cell_bg_type = 1;
4529 
4530         PushStyleCompact();
4531         ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
4532         ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
4533         ImGui::SameLine(); HelpMarker("ImGuiTableFlags_RowBg automatically sets RowBg0 to alternative colors pulled from the Style.");
4534         ImGui::Combo("row bg type", (int*)&row_bg_type, "None\0Red\0Gradient\0");
4535         ImGui::Combo("row bg target", (int*)&row_bg_target, "RowBg0\0RowBg1\0"); ImGui::SameLine(); HelpMarker("Target RowBg0 to override the alternating odd/even colors,\nTarget RowBg1 to blend with them.");
4536         ImGui::Combo("cell bg type", (int*)&cell_bg_type, "None\0Blue\0"); ImGui::SameLine(); HelpMarker("We are colorizing cells to B1->C2 here.");
4537         IM_ASSERT(row_bg_type >= 0 && row_bg_type <= 2);
4538         IM_ASSERT(row_bg_target >= 0 && row_bg_target <= 1);
4539         IM_ASSERT(cell_bg_type >= 0 && cell_bg_type <= 1);
4540         PopStyleCompact();
4541 
4542         if (ImGui::BeginTable("table1", 5, flags))
4543         {
4544             for (int row = 0; row < 6; row++)
4545             {
4546                 ImGui::TableNextRow();
4547 
4548                 // Demonstrate setting a row background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBgX, ...)'
4549                 // We use a transparent color so we can see the one behind in case our target is RowBg1 and RowBg0 was already targeted by the ImGuiTableFlags_RowBg flag.
4550                 if (row_bg_type != 0)
4551                 {
4552                     ImU32 row_bg_color = ImGui::GetColorU32(row_bg_type == 1 ? ImVec4(0.7f, 0.3f, 0.3f, 0.65f) : ImVec4(0.2f + row * 0.1f, 0.2f, 0.2f, 0.65f)); // Flat or Gradient?
4553                     ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0 + row_bg_target, row_bg_color);
4554                 }
4555 
4556                 // Fill cells
4557                 for (int column = 0; column < 5; column++)
4558                 {
4559                     ImGui::TableSetColumnIndex(column);
4560                     ImGui::Text("%c%c", 'A' + row, '0' + column);
4561 
4562                     // Change background of Cells B1->C2
4563                     // Demonstrate setting a cell background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ...)'
4564                     // (the CellBg color will be blended over the RowBg and ColumnBg colors)
4565                     // We can also pass a column number as a third parameter to TableSetBgColor() and do this outside the column loop.
4566                     if (row >= 1 && row <= 2 && column >= 1 && column <= 2 && cell_bg_type == 1)
4567                     {
4568                         ImU32 cell_bg_color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 0.7f, 0.65f));
4569                         ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, cell_bg_color);
4570                     }
4571                 }
4572             }
4573             ImGui::EndTable();
4574         }
4575         ImGui::TreePop();
4576     }
4577 
4578     if (open_action != -1)
4579         ImGui::SetNextItemOpen(open_action != 0);
4580     if (ImGui::TreeNode("Tree view"))
4581     {
4582         static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
4583 
4584         if (ImGui::BeginTable("3ways", 3, flags))
4585         {
4586             // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On
4587             ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
4588             ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f);
4589             ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 18.0f);
4590             ImGui::TableHeadersRow();
4591 
4592             // Simple storage to output a dummy file-system.
4593             struct MyTreeNode
4594             {
4595                 const char*     Name;
4596                 const char*     Type;
4597                 int             Size;
4598                 int             ChildIdx;
4599                 int             ChildCount;
4600                 static void DisplayNode(const MyTreeNode* node, const MyTreeNode* all_nodes)
4601                 {
4602                     ImGui::TableNextRow();
4603                     ImGui::TableNextColumn();
4604                     const bool is_folder = (node->ChildCount > 0);
4605                     if (is_folder)
4606                     {
4607                         bool open = ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_SpanFullWidth);
4608                         ImGui::TableNextColumn();
4609                         ImGui::TextDisabled("--");
4610                         ImGui::TableNextColumn();
4611                         ImGui::TextUnformatted(node->Type);
4612                         if (open)
4613                         {
4614                             for (int child_n = 0; child_n < node->ChildCount; child_n++)
4615                                 DisplayNode(&all_nodes[node->ChildIdx + child_n], all_nodes);
4616                             ImGui::TreePop();
4617                         }
4618                     }
4619                     else
4620                     {
4621                         ImGui::TreeNodeEx(node->Name, ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_SpanFullWidth);
4622                         ImGui::TableNextColumn();
4623                         ImGui::Text("%d", node->Size);
4624                         ImGui::TableNextColumn();
4625                         ImGui::TextUnformatted(node->Type);
4626                     }
4627                 }
4628             };
4629             static const MyTreeNode nodes[] =
4630             {
4631                 { "Root",                         "Folder",       -1,       1, 3    }, // 0
4632                 { "Music",                        "Folder",       -1,       4, 2    }, // 1
4633                 { "Textures",                     "Folder",       -1,       6, 3    }, // 2
4634                 { "desktop.ini",                  "System file",  1024,    -1,-1    }, // 3
4635                 { "File1_a.wav",                  "Audio file",   123000,  -1,-1    }, // 4
4636                 { "File1_b.wav",                  "Audio file",   456000,  -1,-1    }, // 5
4637                 { "Image001.png",                 "Image file",   203128,  -1,-1    }, // 6
4638                 { "Copy of Image001.png",         "Image file",   203256,  -1,-1    }, // 7
4639                 { "Copy of Image001 (Final2).png","Image file",   203512,  -1,-1    }, // 8
4640             };
4641 
4642             MyTreeNode::DisplayNode(&nodes[0], nodes);
4643 
4644             ImGui::EndTable();
4645         }
4646         ImGui::TreePop();
4647     }
4648 
4649     if (open_action != -1)
4650         ImGui::SetNextItemOpen(open_action != 0);
4651     if (ImGui::TreeNode("Item width"))
4652     {
4653         HelpMarker(
4654             "Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n"
4655             "Note that on auto-resizing non-resizable fixed columns, querying the content width for e.g. right-alignment doesn't make sense.");
4656         if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders))
4657         {
4658             ImGui::TableSetupColumn("small");
4659             ImGui::TableSetupColumn("half");
4660             ImGui::TableSetupColumn("right-align");
4661             ImGui::TableHeadersRow();
4662 
4663             for (int row = 0; row < 3; row++)
4664             {
4665                 ImGui::TableNextRow();
4666                 if (row == 0)
4667                 {
4668                     // Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient)
4669                     ImGui::TableSetColumnIndex(0);
4670                     ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small
4671                     ImGui::TableSetColumnIndex(1);
4672                     ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
4673                     ImGui::TableSetColumnIndex(2);
4674                     ImGui::PushItemWidth(-FLT_MIN); // Right-aligned
4675                 }
4676 
4677                 // Draw our contents
4678                 static float dummy_f = 0.0f;
4679                 ImGui::PushID(row);
4680                 ImGui::TableSetColumnIndex(0);
4681                 ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f);
4682                 ImGui::TableSetColumnIndex(1);
4683                 ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
4684                 ImGui::TableSetColumnIndex(2);
4685                 ImGui::SliderFloat("float2", &dummy_f, 0.0f, 1.0f);
4686                 ImGui::PopID();
4687             }
4688             ImGui::EndTable();
4689         }
4690         ImGui::TreePop();
4691     }
4692 
4693     // Demonstrate using TableHeader() calls instead of TableHeadersRow()
4694     if (open_action != -1)
4695         ImGui::SetNextItemOpen(open_action != 0);
4696     if (ImGui::TreeNode("Custom headers"))
4697     {
4698         const int COLUMNS_COUNT = 3;
4699         if (ImGui::BeginTable("table_custom_headers", COLUMNS_COUNT, ImGuiTableFlags_Borders | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
4700         {
4701             ImGui::TableSetupColumn("Apricot");
4702             ImGui::TableSetupColumn("Banana");
4703             ImGui::TableSetupColumn("Cherry");
4704 
4705             // Dummy entire-column selection storage
4706             // FIXME: It would be nice to actually demonstrate full-featured selection using those checkbox.
4707             static bool column_selected[3] = {};
4708 
4709             // Instead of calling TableHeadersRow() we'll submit custom headers ourselves
4710             ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
4711             for (int column = 0; column < COLUMNS_COUNT; column++)
4712             {
4713                 ImGui::TableSetColumnIndex(column);
4714                 const char* column_name = ImGui::TableGetColumnName(column); // Retrieve name passed to TableSetupColumn()
4715                 ImGui::PushID(column);
4716                 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
4717                 ImGui::Checkbox("##checkall", &column_selected[column]);
4718                 ImGui::PopStyleVar();
4719                 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
4720                 ImGui::TableHeader(column_name);
4721                 ImGui::PopID();
4722             }
4723 
4724             for (int row = 0; row < 5; row++)
4725             {
4726                 ImGui::TableNextRow();
4727                 for (int column = 0; column < 3; column++)
4728                 {
4729                     char buf[32];
4730                     sprintf(buf, "Cell %d,%d", column, row);
4731                     ImGui::TableSetColumnIndex(column);
4732                     ImGui::Selectable(buf, column_selected[column]);
4733                 }
4734             }
4735             ImGui::EndTable();
4736         }
4737         ImGui::TreePop();
4738     }
4739 
4740     // Demonstrate creating custom context menus inside columns, while playing it nice with context menus provided by TableHeadersRow()/TableHeader()
4741     if (open_action != -1)
4742         ImGui::SetNextItemOpen(open_action != 0);
4743     if (ImGui::TreeNode("Context menus"))
4744     {
4745         HelpMarker("By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\nUsing ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body.");
4746         static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody;
4747 
4748         PushStyleCompact();
4749         ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags1, ImGuiTableFlags_ContextMenuInBody);
4750         PopStyleCompact();
4751 
4752         // Context Menus: first example
4753         // [1.1] Right-click on the TableHeadersRow() line to open the default table context menu.
4754         // [1.2] Right-click in columns also open the default table context menu (if ImGuiTableFlags_ContextMenuInBody is set)
4755         const int COLUMNS_COUNT = 3;
4756         if (ImGui::BeginTable("table_context_menu", COLUMNS_COUNT, flags1))
4757         {
4758             ImGui::TableSetupColumn("One");
4759             ImGui::TableSetupColumn("Two");
4760             ImGui::TableSetupColumn("Three");
4761 
4762             // [1.1]] Right-click on the TableHeadersRow() line to open the default table context menu.
4763             ImGui::TableHeadersRow();
4764 
4765             // Submit dummy contents
4766             for (int row = 0; row < 4; row++)
4767             {
4768                 ImGui::TableNextRow();
4769                 for (int column = 0; column < COLUMNS_COUNT; column++)
4770                 {
4771                     ImGui::TableSetColumnIndex(column);
4772                     ImGui::Text("Cell %d,%d", column, row);
4773                 }
4774             }
4775             ImGui::EndTable();
4776         }
4777 
4778         // Context Menus: second example
4779         // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
4780         // [2.2] Right-click on the ".." to open a custom popup
4781         // [2.3] Right-click in columns to open another custom popup
4782         HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body).");
4783         ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders;
4784         if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2))
4785         {
4786             ImGui::TableSetupColumn("One");
4787             ImGui::TableSetupColumn("Two");
4788             ImGui::TableSetupColumn("Three");
4789 
4790             // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
4791             ImGui::TableHeadersRow();
4792             for (int row = 0; row < 4; row++)
4793             {
4794                 ImGui::TableNextRow();
4795                 for (int column = 0; column < COLUMNS_COUNT; column++)
4796                 {
4797                     // Submit dummy contents
4798                     ImGui::TableSetColumnIndex(column);
4799                     ImGui::Text("Cell %d,%d", column, row);
4800                     ImGui::SameLine();
4801 
4802                     // [2.2] Right-click on the ".." to open a custom popup
4803                     ImGui::PushID(row * COLUMNS_COUNT + column);
4804                     ImGui::SmallButton("..");
4805                     if (ImGui::BeginPopupContextItem())
4806                     {
4807                         ImGui::Text("This is the popup for Button(\"..\") in Cell %d,%d", column, row);
4808                         if (ImGui::Button("Close"))
4809                             ImGui::CloseCurrentPopup();
4810                         ImGui::EndPopup();
4811                     }
4812                     ImGui::PopID();
4813                 }
4814             }
4815 
4816             // [2.3] Right-click anywhere in columns to open another custom popup
4817             // (instead of testing for !IsAnyItemHovered() we could also call OpenPopup() with ImGuiPopupFlags_NoOpenOverExistingPopup
4818             // to manage popup priority as the popups triggers, here "are we hovering a column" are overlapping)
4819             int hovered_column = -1;
4820             for (int column = 0; column < COLUMNS_COUNT + 1; column++)
4821             {
4822                 ImGui::PushID(column);
4823                 if (ImGui::TableGetColumnFlags(column) & ImGuiTableColumnFlags_IsHovered)
4824                     hovered_column = column;
4825                 if (hovered_column == column && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(1))
4826                     ImGui::OpenPopup("MyPopup");
4827                 if (ImGui::BeginPopup("MyPopup"))
4828                 {
4829                     if (column == COLUMNS_COUNT)
4830                         ImGui::Text("This is a custom popup for unused space after the last column.");
4831                     else
4832                         ImGui::Text("This is a custom popup for Column %d", column);
4833                     if (ImGui::Button("Close"))
4834                         ImGui::CloseCurrentPopup();
4835                     ImGui::EndPopup();
4836                 }
4837                 ImGui::PopID();
4838             }
4839 
4840             ImGui::EndTable();
4841             ImGui::Text("Hovered column: %d", hovered_column);
4842         }
4843         ImGui::TreePop();
4844     }
4845 
4846     // Demonstrate creating multiple tables with the same ID
4847     if (open_action != -1)
4848         ImGui::SetNextItemOpen(open_action != 0);
4849     if (ImGui::TreeNode("Synced instances"))
4850     {
4851         HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc.");
4852         for (int n = 0; n < 3; n++)
4853         {
4854             char buf[32];
4855             sprintf(buf, "Synced Table %d", n);
4856             bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen);
4857             if (open && ImGui::BeginTable("Table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings))
4858             {
4859                 ImGui::TableSetupColumn("One");
4860                 ImGui::TableSetupColumn("Two");
4861                 ImGui::TableSetupColumn("Three");
4862                 ImGui::TableHeadersRow();
4863                 for (int cell = 0; cell < 9; cell++)
4864                 {
4865                     ImGui::TableNextColumn();
4866                     ImGui::Text("this cell %d", cell);
4867                 }
4868                 ImGui::EndTable();
4869             }
4870         }
4871         ImGui::TreePop();
4872     }
4873 
4874     // Demonstrate using Sorting facilities
4875     // This is a simplified version of the "Advanced" example, where we mostly focus on the code necessary to handle sorting.
4876     // Note that the "Advanced" example also showcase manually triggering a sort (e.g. if item quantities have been modified)
4877     static const char* template_items_names[] =
4878     {
4879         "Banana", "Apple", "Cherry", "Watermelon", "Grapefruit", "Strawberry", "Mango",
4880         "Kiwi", "Orange", "Pineapple", "Blueberry", "Plum", "Coconut", "Pear", "Apricot"
4881     };
4882     if (open_action != -1)
4883         ImGui::SetNextItemOpen(open_action != 0);
4884     if (ImGui::TreeNode("Sorting"))
4885     {
4886         // Create item list
4887         static ImVector<MyItem> items;
4888         if (items.Size == 0)
4889         {
4890             items.resize(50, MyItem());
4891             for (int n = 0; n < items.Size; n++)
4892             {
4893                 const int template_n = n % IM_ARRAYSIZE(template_items_names);
4894                 MyItem& item = items[n];
4895                 item.ID = n;
4896                 item.Name = template_items_names[template_n];
4897                 item.Quantity = (n * n - n) % 20; // Assign default quantities
4898             }
4899         }
4900 
4901         // Options
4902         static ImGuiTableFlags flags =
4903             ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
4904             | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody
4905             | ImGuiTableFlags_ScrollY;
4906         PushStyleCompact();
4907         ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
4908         ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
4909         ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
4910         ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
4911         PopStyleCompact();
4912 
4913         if (ImGui::BeginTable("table_sorting", 4, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 15), 0.0f))
4914         {
4915             // Declare columns
4916             // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
4917             // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
4918             // Demonstrate using a mixture of flags among available sort-related flags:
4919             // - ImGuiTableColumnFlags_DefaultSort
4920             // - ImGuiTableColumnFlags_NoSort / ImGuiTableColumnFlags_NoSortAscending / ImGuiTableColumnFlags_NoSortDescending
4921             // - ImGuiTableColumnFlags_PreferSortAscending / ImGuiTableColumnFlags_PreferSortDescending
4922             ImGui::TableSetupColumn("ID",       ImGuiTableColumnFlags_DefaultSort          | ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_ID);
4923             ImGui::TableSetupColumn("Name",                                                  ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_Name);
4924             ImGui::TableSetupColumn("Action",   ImGuiTableColumnFlags_NoSort               | ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_Action);
4925             ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Quantity);
4926             ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible
4927             ImGui::TableHeadersRow();
4928 
4929             // Sort our data if sort specs have been changed!
4930             if (ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs())
4931                 if (sorts_specs->SpecsDirty)
4932                 {
4933                     MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function.
4934                     if (items.Size > 1)
4935                         qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs);
4936                     MyItem::s_current_sort_specs = NULL;
4937                     sorts_specs->SpecsDirty = false;
4938                 }
4939 
4940             // Demonstrate using clipper for large vertical lists
4941             ImGuiListClipper clipper;
4942             clipper.Begin(items.Size);
4943             while (clipper.Step())
4944                 for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
4945                 {
4946                     // Display a data item
4947                     MyItem* item = &items[row_n];
4948                     ImGui::PushID(item->ID);
4949                     ImGui::TableNextRow();
4950                     ImGui::TableNextColumn();
4951                     ImGui::Text("%04d", item->ID);
4952                     ImGui::TableNextColumn();
4953                     ImGui::TextUnformatted(item->Name);
4954                     ImGui::TableNextColumn();
4955                     ImGui::SmallButton("None");
4956                     ImGui::TableNextColumn();
4957                     ImGui::Text("%d", item->Quantity);
4958                     ImGui::PopID();
4959                 }
4960             ImGui::EndTable();
4961         }
4962         ImGui::TreePop();
4963     }
4964 
4965     // In this example we'll expose most table flags and settings.
4966     // For specific flags and settings refer to the corresponding section for more detailed explanation.
4967     // This section is mostly useful to experiment with combining certain flags or settings with each others.
4968     //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // [DEBUG]
4969     if (open_action != -1)
4970         ImGui::SetNextItemOpen(open_action != 0);
4971     if (ImGui::TreeNode("Advanced"))
4972     {
4973         static ImGuiTableFlags flags =
4974             ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable
4975             | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
4976             | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody
4977             | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
4978             | ImGuiTableFlags_SizingFixedFit;
4979 
4980         enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow };
4981         static int contents_type = CT_SelectableSpanRow;
4982         const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable", "Selectable (span row)" };
4983         static int freeze_cols = 1;
4984         static int freeze_rows = 1;
4985         static int items_count = IM_ARRAYSIZE(template_items_names) * 2;
4986         static ImVec2 outer_size_value = ImVec2(0.0f, TEXT_BASE_HEIGHT * 12);
4987         static float row_min_height = 0.0f; // Auto
4988         static float inner_width_with_scroll = 0.0f; // Auto-extend
4989         static bool outer_size_enabled = true;
4990         static bool show_headers = true;
4991         static bool show_wrapped_text = false;
4992         //static ImGuiTextFilter filter;
4993         //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // FIXME-TABLE: Enabling this results in initial clipped first pass on table which tend to affects column sizing
4994         if (ImGui::TreeNode("Options"))
4995         {
4996             // Make the UI compact because there are so many fields
4997             PushStyleCompact();
4998             ImGui::PushItemWidth(TEXT_BASE_WIDTH * 28.0f);
4999 
5000             if (ImGui::TreeNodeEx("Features:", ImGuiTreeNodeFlags_DefaultOpen))
5001             {
5002                 ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
5003                 ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
5004                 ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
5005                 ImGui::CheckboxFlags("ImGuiTableFlags_Sortable", &flags, ImGuiTableFlags_Sortable);
5006                 ImGui::CheckboxFlags("ImGuiTableFlags_NoSavedSettings", &flags, ImGuiTableFlags_NoSavedSettings);
5007                 ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags, ImGuiTableFlags_ContextMenuInBody);
5008                 ImGui::TreePop();
5009             }
5010 
5011             if (ImGui::TreeNodeEx("Decorations:", ImGuiTreeNodeFlags_DefaultOpen))
5012             {
5013                 ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
5014                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
5015                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
5016                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
5017                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
5018                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
5019                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
5020                 ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appears in Headers");
5021                 ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers)");
5022                 ImGui::TreePop();
5023             }
5024 
5025             if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen))
5026             {
5027                 EditTableSizingFlags(&flags);
5028                 ImGui::SameLine(); HelpMarker("In the Advanced demo we override the policy of each column so those table-wide settings have less effect that typical.");
5029                 ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
5030                 ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used.");
5031                 ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
5032                 ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.");
5033                 ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible);
5034                 ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled.");
5035                 ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
5036                 ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.");
5037                 ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
5038                 ImGui::SameLine(); HelpMarker("Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with ScrollFreeze options.");
5039                 ImGui::TreePop();
5040             }
5041 
5042             if (ImGui::TreeNodeEx("Padding:", ImGuiTreeNodeFlags_DefaultOpen))
5043             {
5044                 ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags, ImGuiTableFlags_PadOuterX);
5045                 ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags, ImGuiTableFlags_NoPadOuterX);
5046                 ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags, ImGuiTableFlags_NoPadInnerX);
5047                 ImGui::TreePop();
5048             }
5049 
5050             if (ImGui::TreeNodeEx("Scrolling:", ImGuiTreeNodeFlags_DefaultOpen))
5051             {
5052                 ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
5053                 ImGui::SameLine();
5054                 ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
5055                 ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
5056                 ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
5057                 ImGui::SameLine();
5058                 ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
5059                 ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
5060                 ImGui::TreePop();
5061             }
5062 
5063             if (ImGui::TreeNodeEx("Sorting:", ImGuiTreeNodeFlags_DefaultOpen))
5064             {
5065                 ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
5066                 ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
5067                 ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
5068                 ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
5069                 ImGui::TreePop();
5070             }
5071 
5072             if (ImGui::TreeNodeEx("Other:", ImGuiTreeNodeFlags_DefaultOpen))
5073             {
5074                 ImGui::Checkbox("show_headers", &show_headers);
5075                 ImGui::Checkbox("show_wrapped_text", &show_wrapped_text);
5076 
5077                 ImGui::DragFloat2("##OuterSize", &outer_size_value.x);
5078                 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
5079                 ImGui::Checkbox("outer_size", &outer_size_enabled);
5080                 ImGui::SameLine();
5081                 HelpMarker("If scrolling is disabled (ScrollX and ScrollY not set):\n"
5082                     "- The table is output directly in the parent window.\n"
5083                     "- OuterSize.x < 0.0f will right-align the table.\n"
5084                     "- OuterSize.x = 0.0f will narrow fit the table unless there are any Stretch column.\n"
5085                     "- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set).");
5086 
5087                 // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling.
5088                 // To facilitate toying with this demo we will actually pass 0.0f to the BeginTable() when ScrollX is disabled.
5089                 ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX);
5090 
5091                 ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX);
5092                 ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
5093 
5094                 ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999);
5095                 ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names));
5096                 //filter.Draw("filter");
5097                 ImGui::TreePop();
5098             }
5099 
5100             ImGui::PopItemWidth();
5101             PopStyleCompact();
5102             ImGui::Spacing();
5103             ImGui::TreePop();
5104         }
5105 
5106         // Update item list if we changed the number of items
5107         static ImVector<MyItem> items;
5108         static ImVector<int> selection;
5109         static bool items_need_sort = false;
5110         if (items.Size != items_count)
5111         {
5112             items.resize(items_count, MyItem());
5113             for (int n = 0; n < items_count; n++)
5114             {
5115                 const int template_n = n % IM_ARRAYSIZE(template_items_names);
5116                 MyItem& item = items[n];
5117                 item.ID = n;
5118                 item.Name = template_items_names[template_n];
5119                 item.Quantity = (template_n == 3) ? 10 : (template_n == 4) ? 20 : 0; // Assign default quantities
5120             }
5121         }
5122 
5123         const ImDrawList* parent_draw_list = ImGui::GetWindowDrawList();
5124         const int parent_draw_list_draw_cmd_count = parent_draw_list->CmdBuffer.Size;
5125         ImVec2 table_scroll_cur, table_scroll_max; // For debug display
5126         const ImDrawList* table_draw_list = NULL;  // "
5127 
5128         // Submit table
5129         const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : 0.0f;
5130         if (ImGui::BeginTable("table_advanced", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use))
5131         {
5132             // Declare columns
5133             // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
5134             // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
5135             ImGui::TableSetupColumn("ID",           ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, 0.0f, MyItemColumnID_ID);
5136             ImGui::TableSetupColumn("Name",         ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name);
5137             ImGui::TableSetupColumn("Action",       ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action);
5138             ImGui::TableSetupColumn("Quantity",     ImGuiTableColumnFlags_PreferSortDescending, 0.0f, MyItemColumnID_Quantity);
5139             ImGui::TableSetupColumn("Description",  (flags & ImGuiTableFlags_NoHostExtendX) ? 0 : ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Description);
5140             ImGui::TableSetupColumn("Hidden",       ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort);
5141             ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
5142 
5143             // Sort our data if sort specs have been changed!
5144             ImGuiTableSortSpecs* sorts_specs = ImGui::TableGetSortSpecs();
5145             if (sorts_specs && sorts_specs->SpecsDirty)
5146                 items_need_sort = true;
5147             if (sorts_specs && items_need_sort && items.Size > 1)
5148             {
5149                 MyItem::s_current_sort_specs = sorts_specs; // Store in variable accessible by the sort function.
5150                 qsort(&items[0], (size_t)items.Size, sizeof(items[0]), MyItem::CompareWithSortSpecs);
5151                 MyItem::s_current_sort_specs = NULL;
5152                 sorts_specs->SpecsDirty = false;
5153             }
5154             items_need_sort = false;
5155 
5156             // Take note of whether we are currently sorting based on the Quantity field,
5157             // we will use this to trigger sorting when we know the data of this column has been modified.
5158             const bool sorts_specs_using_quantity = (ImGui::TableGetColumnFlags(3) & ImGuiTableColumnFlags_IsSorted) != 0;
5159 
5160             // Show headers
5161             if (show_headers)
5162                 ImGui::TableHeadersRow();
5163 
5164             // Show data
5165             // FIXME-TABLE FIXME-NAV: How we can get decent up/down even though we have the buttons here?
5166             ImGui::PushButtonRepeat(true);
5167 #if 1
5168             // Demonstrate using clipper for large vertical lists
5169             ImGuiListClipper clipper;
5170             clipper.Begin(items.Size);
5171             while (clipper.Step())
5172             {
5173                 for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
5174 #else
5175             // Without clipper
5176             {
5177                 for (int row_n = 0; row_n < items.Size; row_n++)
5178 #endif
5179                 {
5180                     MyItem* item = &items[row_n];
5181                     //if (!filter.PassFilter(item->Name))
5182                     //    continue;
5183 
5184                     const bool item_is_selected = selection.contains(item->ID);
5185                     ImGui::PushID(item->ID);
5186                     ImGui::TableNextRow(ImGuiTableRowFlags_None, row_min_height);
5187 
5188                     // For the demo purpose we can select among different type of items submitted in the first column
5189                     ImGui::TableSetColumnIndex(0);
5190                     char label[32];
5191                     sprintf(label, "%04d", item->ID);
5192                     if (contents_type == CT_Text)
5193                         ImGui::TextUnformatted(label);
5194                     else if (contents_type == CT_Button)
5195                         ImGui::Button(label);
5196                     else if (contents_type == CT_SmallButton)
5197                         ImGui::SmallButton(label);
5198                     else if (contents_type == CT_FillButton)
5199                         ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f));
5200                     else if (contents_type == CT_Selectable || contents_type == CT_SelectableSpanRow)
5201                     {
5202                         ImGuiSelectableFlags selectable_flags = (contents_type == CT_SelectableSpanRow) ? ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowItemOverlap : ImGuiSelectableFlags_None;
5203                         if (ImGui::Selectable(label, item_is_selected, selectable_flags, ImVec2(0, row_min_height)))
5204                         {
5205                             if (ImGui::GetIO().KeyCtrl)
5206                             {
5207                                 if (item_is_selected)
5208                                     selection.find_erase_unsorted(item->ID);
5209                                 else
5210                                     selection.push_back(item->ID);
5211                             }
5212                             else
5213                             {
5214                                 selection.clear();
5215                                 selection.push_back(item->ID);
5216                             }
5217                         }
5218                     }
5219 
5220                     if (ImGui::TableSetColumnIndex(1))
5221                         ImGui::TextUnformatted(item->Name);
5222 
5223                     // Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity,
5224                     // and we are currently sorting on the column showing the Quantity.
5225                     // To avoid triggering a sort while holding the button, we only trigger it when the button has been released.
5226                     // You will probably need a more advanced system in your code if you want to automatically sort when a specific entry changes.
5227                     if (ImGui::TableSetColumnIndex(2))
5228                     {
5229                         if (ImGui::SmallButton("Chop")) { item->Quantity += 1; }
5230                         if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
5231                         ImGui::SameLine();
5232                         if (ImGui::SmallButton("Eat")) { item->Quantity -= 1; }
5233                         if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
5234                     }
5235 
5236                     if (ImGui::TableSetColumnIndex(3))
5237                         ImGui::Text("%d", item->Quantity);
5238 
5239                     ImGui::TableSetColumnIndex(4);
5240                     if (show_wrapped_text)
5241                         ImGui::TextWrapped("Lorem ipsum dolor sit amet");
5242                     else
5243                         ImGui::Text("Lorem ipsum dolor sit amet");
5244 
5245                     if (ImGui::TableSetColumnIndex(5))
5246                         ImGui::Text("1234");
5247 
5248                     ImGui::PopID();
5249                 }
5250             }
5251             ImGui::PopButtonRepeat();
5252 
5253             // Store some info to display debug details below
5254             table_scroll_cur = ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY());
5255             table_scroll_max = ImVec2(ImGui::GetScrollMaxX(), ImGui::GetScrollMaxY());
5256             table_draw_list = ImGui::GetWindowDrawList();
5257             ImGui::EndTable();
5258         }
5259         static bool show_debug_details = false;
5260         ImGui::Checkbox("Debug details", &show_debug_details);
5261         if (show_debug_details && table_draw_list)
5262         {
5263             ImGui::SameLine(0.0f, 0.0f);
5264             const int table_draw_list_draw_cmd_count = table_draw_list->CmdBuffer.Size;
5265             if (table_draw_list == parent_draw_list)
5266                 ImGui::Text(": DrawCmd: +%d (in same window)",
5267                     table_draw_list_draw_cmd_count - parent_draw_list_draw_cmd_count);
5268             else
5269                 ImGui::Text(": DrawCmd: +%d (in child window), Scroll: (%.f/%.f) (%.f/%.f)",
5270                     table_draw_list_draw_cmd_count - 1, table_scroll_cur.x, table_scroll_max.x, table_scroll_cur.y, table_scroll_max.y);
5271         }
5272         ImGui::TreePop();
5273     }
5274 
5275     ImGui::PopID();
5276 
5277     ShowDemoWindowColumns();
5278 
5279     if (disable_indent)
5280         ImGui::PopStyleVar();
5281 }
5282 
5283 // Demonstrate old/legacy Columns API!
5284 // [2020: Columns are under-featured and not maintained. Prefer using the more flexible and powerful BeginTable() API!]
5285 static void ShowDemoWindowColumns()
5286 {
5287     bool open = ImGui::TreeNode("Legacy Columns API");
5288     ImGui::SameLine();
5289     HelpMarker("Columns() is an old API! Prefer using the more flexible and powerful BeginTable() API!");
5290     if (!open)
5291         return;
5292 
5293     // Basic columns
5294     if (ImGui::TreeNode("Basic"))
5295     {
5296         ImGui::Text("Without border:");
5297         ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
5298         ImGui::Separator();
5299         for (int n = 0; n < 14; n++)
5300         {
5301             char label[32];
5302             sprintf(label, "Item %d", n);
5303             if (ImGui::Selectable(label)) {}
5304             //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {}
5305             ImGui::NextColumn();
5306         }
5307         ImGui::Columns(1);
5308         ImGui::Separator();
5309 
5310         ImGui::Text("With border:");
5311         ImGui::Columns(4, "mycolumns"); // 4-ways, with border
5312         ImGui::Separator();
5313         ImGui::Text("ID"); ImGui::NextColumn();
5314         ImGui::Text("Name"); ImGui::NextColumn();
5315         ImGui::Text("Path"); ImGui::NextColumn();
5316         ImGui::Text("Hovered"); ImGui::NextColumn();
5317         ImGui::Separator();
5318         const char* names[3] = { "One", "Two", "Three" };
5319         const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
5320         static int selected = -1;
5321         for (int i = 0; i < 3; i++)
5322         {
5323             char label[32];
5324             sprintf(label, "%04d", i);
5325             if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
5326                 selected = i;
5327             bool hovered = ImGui::IsItemHovered();
5328             ImGui::NextColumn();
5329             ImGui::Text(names[i]); ImGui::NextColumn();
5330             ImGui::Text(paths[i]); ImGui::NextColumn();
5331             ImGui::Text("%d", hovered); ImGui::NextColumn();
5332         }
5333         ImGui::Columns(1);
5334         ImGui::Separator();
5335         ImGui::TreePop();
5336     }
5337 
5338     if (ImGui::TreeNode("Borders"))
5339     {
5340         // NB: Future columns API should allow automatic horizontal borders.
5341         static bool h_borders = true;
5342         static bool v_borders = true;
5343         static int columns_count = 4;
5344         const int lines_count = 3;
5345         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
5346         ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns");
5347         if (columns_count < 2)
5348             columns_count = 2;
5349         ImGui::SameLine();
5350         ImGui::Checkbox("horizontal", &h_borders);
5351         ImGui::SameLine();
5352         ImGui::Checkbox("vertical", &v_borders);
5353         ImGui::Columns(columns_count, NULL, v_borders);
5354         for (int i = 0; i < columns_count * lines_count; i++)
5355         {
5356             if (h_borders && ImGui::GetColumnIndex() == 0)
5357                 ImGui::Separator();
5358             ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
5359             ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
5360             ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
5361             ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
5362             ImGui::Text("Long text that is likely to clip");
5363             ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f));
5364             ImGui::NextColumn();
5365         }
5366         ImGui::Columns(1);
5367         if (h_borders)
5368             ImGui::Separator();
5369         ImGui::TreePop();
5370     }
5371 
5372     // Create multiple items in a same cell before switching to next column
5373     if (ImGui::TreeNode("Mixed items"))
5374     {
5375         ImGui::Columns(3, "mixed");
5376         ImGui::Separator();
5377 
5378         ImGui::Text("Hello");
5379         ImGui::Button("Banana");
5380         ImGui::NextColumn();
5381 
5382         ImGui::Text("ImGui");
5383         ImGui::Button("Apple");
5384         static float foo = 1.0f;
5385         ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
5386         ImGui::Text("An extra line here.");
5387         ImGui::NextColumn();
5388 
5389         ImGui::Text("Sailor");
5390         ImGui::Button("Corniflower");
5391         static float bar = 1.0f;
5392         ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
5393         ImGui::NextColumn();
5394 
5395         if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
5396         if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
5397         if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
5398         ImGui::Columns(1);
5399         ImGui::Separator();
5400         ImGui::TreePop();
5401     }
5402 
5403     // Word wrapping
5404     if (ImGui::TreeNode("Word-wrapping"))
5405     {
5406         ImGui::Columns(2, "word-wrapping");
5407         ImGui::Separator();
5408         ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
5409         ImGui::TextWrapped("Hello Left");
5410         ImGui::NextColumn();
5411         ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
5412         ImGui::TextWrapped("Hello Right");
5413         ImGui::Columns(1);
5414         ImGui::Separator();
5415         ImGui::TreePop();
5416     }
5417 
5418     if (ImGui::TreeNode("Horizontal Scrolling"))
5419     {
5420         ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
5421         ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f);
5422         ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar);
5423         ImGui::Columns(10);
5424 
5425         // Also demonstrate using clipper for large vertical lists
5426         int ITEMS_COUNT = 2000;
5427         ImGuiListClipper clipper;
5428         clipper.Begin(ITEMS_COUNT);
5429         while (clipper.Step())
5430         {
5431             for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
5432                 for (int j = 0; j < 10; j++)
5433                 {
5434                     ImGui::Text("Line %d Column %d...", i, j);
5435                     ImGui::NextColumn();
5436                 }
5437         }
5438         ImGui::Columns(1);
5439         ImGui::EndChild();
5440         ImGui::TreePop();
5441     }
5442 
5443     if (ImGui::TreeNode("Tree"))
5444     {
5445         ImGui::Columns(2, "tree", true);
5446         for (int x = 0; x < 3; x++)
5447         {
5448             bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x);
5449             ImGui::NextColumn();
5450             ImGui::Text("Node contents");
5451             ImGui::NextColumn();
5452             if (open1)
5453             {
5454                 for (int y = 0; y < 3; y++)
5455                 {
5456                     bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y);
5457                     ImGui::NextColumn();
5458                     ImGui::Text("Node contents");
5459                     if (open2)
5460                     {
5461                         ImGui::Text("Even more contents");
5462                         if (ImGui::TreeNode("Tree in column"))
5463                         {
5464                             ImGui::Text("The quick brown fox jumps over the lazy dog");
5465                             ImGui::TreePop();
5466                         }
5467                     }
5468                     ImGui::NextColumn();
5469                     if (open2)
5470                         ImGui::TreePop();
5471                 }
5472                 ImGui::TreePop();
5473             }
5474         }
5475         ImGui::Columns(1);
5476         ImGui::TreePop();
5477     }
5478 
5479     ImGui::TreePop();
5480 }
5481 
5482 static void ShowDemoWindowMisc()
5483 {
5484     if (ImGui::CollapsingHeader("Filtering"))
5485     {
5486         // Helper class to easy setup a text filter.
5487         // You may want to implement a more feature-full filtering scheme in your own application.
5488         static ImGuiTextFilter filter;
5489         ImGui::Text("Filter usage:\n"
5490                     "  \"\"         display all lines\n"
5491                     "  \"xxx\"      display lines containing \"xxx\"\n"
5492                     "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
5493                     "  \"-xxx\"     hide lines containing \"xxx\"");
5494         filter.Draw();
5495         const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
5496         for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
5497             if (filter.PassFilter(lines[i]))
5498                 ImGui::BulletText("%s", lines[i]);
5499     }
5500 
5501     if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
5502     {
5503         ImGuiIO& io = ImGui::GetIO();
5504 
5505         // Display ImGuiIO output flags
5506         ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
5507         ImGui::Text("WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
5508         ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
5509         ImGui::Text("WantTextInput: %d", io.WantTextInput);
5510         ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
5511         ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
5512 
5513         // Display Mouse state
5514         if (ImGui::TreeNode("Mouse State"))
5515         {
5516             if (ImGui::IsMousePosValid())
5517                 ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
5518             else
5519                 ImGui::Text("Mouse pos: <INVALID>");
5520             ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
5521             ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i))         { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
5522             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); }
5523             ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)){ ImGui::SameLine(); ImGui::Text("b%d", i); }
5524             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); }
5525             ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
5526             ImGui::Text("Pen Pressure: %.1f", io.PenPressure); // Note: currently unused
5527             ImGui::TreePop();
5528         }
5529 
5530         // Display Keyboard/Mouse state
5531         if (ImGui::TreeNode("Keyboard & Navigation State"))
5532         {
5533             ImGui::Text("Keys down:");          for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyDown(i))        { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); }
5534             ImGui::Text("Keys pressed:");       for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i))     { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
5535             ImGui::Text("Keys release:");       for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i))    { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
5536             ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
5537             ImGui::Text("Chars queue:");        for (int i = 0; i < io.InputQueueCharacters.Size; i++) { ImWchar c = io.InputQueueCharacters[i]; ImGui::SameLine();  ImGui::Text("\'%c\' (0x%04X)", (c > ' ' && c <= 255) ? (char)c : '?', c); } // FIXME: We should convert 'c' to UTF-8 here but the functions are not public.
5538 
5539             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 (%.02f secs)", i, io.NavInputs[i], io.NavInputsDownDuration[i]); }
5540             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); }
5541 
5542             ImGui::Button("Hovering me sets the\nkeyboard capture flag");
5543             if (ImGui::IsItemHovered())
5544                 ImGui::CaptureKeyboardFromApp(true);
5545             ImGui::SameLine();
5546             ImGui::Button("Holding me clears the\nthe keyboard capture flag");
5547             if (ImGui::IsItemActive())
5548                 ImGui::CaptureKeyboardFromApp(false);
5549             ImGui::TreePop();
5550         }
5551 
5552         if (ImGui::TreeNode("Tabbing"))
5553         {
5554             ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
5555             static char buf[32] = "hello";
5556             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
5557             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
5558             ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
5559             ImGui::PushAllowKeyboardFocus(false);
5560             ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
5561             ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
5562             ImGui::PopAllowKeyboardFocus();
5563             ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
5564             ImGui::TreePop();
5565         }
5566 
5567         if (ImGui::TreeNode("Focus from code"))
5568         {
5569             bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
5570             bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
5571             bool focus_3 = ImGui::Button("Focus on 3");
5572             int has_focus = 0;
5573             static char buf[128] = "click on a button to set focus";
5574 
5575             if (focus_1) ImGui::SetKeyboardFocusHere();
5576             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
5577             if (ImGui::IsItemActive()) has_focus = 1;
5578 
5579             if (focus_2) ImGui::SetKeyboardFocusHere();
5580             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
5581             if (ImGui::IsItemActive()) has_focus = 2;
5582 
5583             ImGui::PushAllowKeyboardFocus(false);
5584             if (focus_3) ImGui::SetKeyboardFocusHere();
5585             ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
5586             if (ImGui::IsItemActive()) has_focus = 3;
5587             ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
5588             ImGui::PopAllowKeyboardFocus();
5589 
5590             if (has_focus)
5591                 ImGui::Text("Item with focus: %d", has_focus);
5592             else
5593                 ImGui::Text("Item with focus: <none>");
5594 
5595             // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
5596             static float f3[3] = { 0.0f, 0.0f, 0.0f };
5597             int focus_ahead = -1;
5598             if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
5599             if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
5600             if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
5601             if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
5602             ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
5603 
5604             ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
5605             ImGui::TreePop();
5606         }
5607 
5608         if (ImGui::TreeNode("Dragging"))
5609         {
5610             ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
5611             for (int button = 0; button < 3; button++)
5612             {
5613                 ImGui::Text("IsMouseDragging(%d):", button);
5614                 ImGui::Text("  w/ default threshold: %d,", ImGui::IsMouseDragging(button));
5615                 ImGui::Text("  w/ zero threshold: %d,", ImGui::IsMouseDragging(button, 0.0f));
5616                 ImGui::Text("  w/ large threshold: %d,", ImGui::IsMouseDragging(button, 20.0f));
5617             }
5618 
5619             ImGui::Button("Drag Me");
5620             if (ImGui::IsItemActive())
5621                 ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor
5622 
5623             // Drag operations gets "unlocked" when the mouse has moved past a certain threshold
5624             // (the default threshold is stored in io.MouseDragThreshold). You can request a lower or higher
5625             // threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta().
5626             ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
5627             ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
5628             ImVec2 mouse_delta = io.MouseDelta;
5629             ImGui::Text("GetMouseDragDelta(0):");
5630             ImGui::Text("  w/ default threshold: (%.1f, %.1f)", value_with_lock_threshold.x, value_with_lock_threshold.y);
5631             ImGui::Text("  w/ zero threshold: (%.1f, %.1f)", value_raw.x, value_raw.y);
5632             ImGui::Text("io.MouseDelta: (%.1f, %.1f)", mouse_delta.x, mouse_delta.y);
5633             ImGui::TreePop();
5634         }
5635 
5636         if (ImGui::TreeNode("Mouse cursors"))
5637         {
5638             const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" };
5639             IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
5640 
5641             ImGuiMouseCursor current = ImGui::GetMouseCursor();
5642             ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]);
5643             ImGui::Text("Hover to see mouse cursors:");
5644             ImGui::SameLine(); HelpMarker(
5645                 "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. "
5646                 "If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, "
5647                 "otherwise your backend needs to handle it.");
5648             for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
5649             {
5650                 char label[32];
5651                 sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
5652                 ImGui::Bullet(); ImGui::Selectable(label, false);
5653                 if (ImGui::IsItemHovered())
5654                     ImGui::SetMouseCursor(i);
5655             }
5656             ImGui::TreePop();
5657         }
5658     }
5659 }
5660 
5661 //-----------------------------------------------------------------------------
5662 // [SECTION] About Window / ShowAboutWindow()
5663 // Access from Dear ImGui Demo -> Tools -> About
5664 //-----------------------------------------------------------------------------
5665 
5666 void ImGui::ShowAboutWindow(bool* p_open)
5667 {
5668     if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
5669     {
5670         ImGui::End();
5671         return;
5672     }
5673     ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
5674     ImGui::Separator();
5675     ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
5676     ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
5677 
5678     static bool show_config_info = false;
5679     ImGui::Checkbox("Config/Build Information", &show_config_info);
5680     if (show_config_info)
5681     {
5682         ImGuiIO& io = ImGui::GetIO();
5683         ImGuiStyle& style = ImGui::GetStyle();
5684 
5685         bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
5686         ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18);
5687         ImGui::BeginChildFrame(ImGui::GetID("cfg_infos"), child_size, ImGuiWindowFlags_NoMove);
5688         if (copy_to_clipboard)
5689         {
5690             ImGui::LogToClipboard();
5691             ImGui::LogText("```\n"); // Back quotes will make text appears without formatting when pasting on GitHub
5692         }
5693 
5694         ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
5695         ImGui::Separator();
5696         ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
5697         ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
5698 #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
5699         ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
5700 #endif
5701 #ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
5702         ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
5703 #endif
5704 #ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
5705         ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
5706 #endif
5707 #ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
5708         ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
5709 #endif
5710 #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
5711         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS");
5712 #endif
5713 #ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
5714         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS");
5715 #endif
5716 #ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
5717         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS");
5718 #endif
5719 #ifdef IMGUI_DISABLE_FILE_FUNCTIONS
5720         ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS");
5721 #endif
5722 #ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
5723         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
5724 #endif
5725 #ifdef IMGUI_USE_BGRA_PACKED_COLOR
5726         ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
5727 #endif
5728 #ifdef _WIN32
5729         ImGui::Text("define: _WIN32");
5730 #endif
5731 #ifdef _WIN64
5732         ImGui::Text("define: _WIN64");
5733 #endif
5734 #ifdef __linux__
5735         ImGui::Text("define: __linux__");
5736 #endif
5737 #ifdef __APPLE__
5738         ImGui::Text("define: __APPLE__");
5739 #endif
5740 #ifdef _MSC_VER
5741         ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
5742 #endif
5743 #ifdef _MSVC_LANG
5744         ImGui::Text("define: _MSVC_LANG=%d", (int)_MSVC_LANG);
5745 #endif
5746 #ifdef __MINGW32__
5747         ImGui::Text("define: __MINGW32__");
5748 #endif
5749 #ifdef __MINGW64__
5750         ImGui::Text("define: __MINGW64__");
5751 #endif
5752 #ifdef __GNUC__
5753         ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
5754 #endif
5755 #ifdef __clang_version__
5756         ImGui::Text("define: __clang_version__=%s", __clang_version__);
5757 #endif
5758         ImGui::Separator();
5759         ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
5760         ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
5761         ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
5762         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)        ImGui::Text(" NavEnableKeyboard");
5763         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
5764         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)     ImGui::Text(" NavEnableSetMousePos");
5765         if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)     ImGui::Text(" NavNoCaptureKeyboard");
5766         if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
5767         if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
5768         if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
5769         if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
5770         if (io.ConfigInputTextCursorBlink)                              ImGui::Text("io.ConfigInputTextCursorBlink");
5771         if (io.ConfigWindowsResizeFromEdges)                            ImGui::Text("io.ConfigWindowsResizeFromEdges");
5772         if (io.ConfigWindowsMoveFromTitleBarOnly)                       ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
5773         if (io.ConfigMemoryCompactTimer >= 0.0f)                        ImGui::Text("io.ConfigMemoryCompactTimer = %.1f", io.ConfigMemoryCompactTimer);
5774         ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
5775         if (io.BackendFlags & ImGuiBackendFlags_HasGamepad)             ImGui::Text(" HasGamepad");
5776         if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)        ImGui::Text(" HasMouseCursors");
5777         if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)         ImGui::Text(" HasSetMousePos");
5778         if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)   ImGui::Text(" RendererHasVtxOffset");
5779         ImGui::Separator();
5780         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);
5781         ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
5782         ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
5783         ImGui::Separator();
5784         ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
5785         ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
5786         ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
5787         ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
5788         ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
5789         ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
5790         ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
5791 
5792         if (copy_to_clipboard)
5793         {
5794             ImGui::LogText("\n```\n");
5795             ImGui::LogFinish();
5796         }
5797         ImGui::EndChildFrame();
5798     }
5799     ImGui::End();
5800 }
5801 
5802 //-----------------------------------------------------------------------------
5803 // [SECTION] Style Editor / ShowStyleEditor()
5804 //-----------------------------------------------------------------------------
5805 // - ShowFontSelector()
5806 // - ShowStyleSelector()
5807 // - ShowStyleEditor()
5808 //-----------------------------------------------------------------------------
5809 
5810 // Forward declare ShowFontAtlas() which isn't worth putting in public API yet
5811 namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); }
5812 
5813 // Demo helper function to select among loaded fonts.
5814 // Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
5815 void ImGui::ShowFontSelector(const char* label)
5816 {
5817     ImGuiIO& io = ImGui::GetIO();
5818     ImFont* font_current = ImGui::GetFont();
5819     if (ImGui::BeginCombo(label, font_current->GetDebugName()))
5820     {
5821         for (int n = 0; n < io.Fonts->Fonts.Size; n++)
5822         {
5823             ImFont* font = io.Fonts->Fonts[n];
5824             ImGui::PushID((void*)font);
5825             if (ImGui::Selectable(font->GetDebugName(), font == font_current))
5826                 io.FontDefault = font;
5827             ImGui::PopID();
5828         }
5829         ImGui::EndCombo();
5830     }
5831     ImGui::SameLine();
5832     HelpMarker(
5833         "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
5834         "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
5835         "- Read FAQ and docs/FONTS.md for more details.\n"
5836         "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
5837 }
5838 
5839 // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
5840 // Here we use the simplified Combo() api that packs items into a single literal string.
5841 // Useful for quick combo boxes where the choices are known locally.
5842 bool ImGui::ShowStyleSelector(const char* label)
5843 {
5844     static int style_idx = -1;
5845     if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0"))
5846     {
5847         switch (style_idx)
5848         {
5849         case 0: ImGui::StyleColorsDark(); break;
5850         case 1: ImGui::StyleColorsLight(); break;
5851         case 2: ImGui::StyleColorsClassic(); break;
5852         }
5853         return true;
5854     }
5855     return false;
5856 }
5857 
5858 void ImGui::ShowStyleEditor(ImGuiStyle* ref)
5859 {
5860     // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
5861     // (without a reference style pointer, we will use one compared locally as a reference)
5862     ImGuiStyle& style = ImGui::GetStyle();
5863     static ImGuiStyle ref_saved_style;
5864 
5865     // Default to using internal storage as reference
5866     static bool init = true;
5867     if (init && ref == NULL)
5868         ref_saved_style = style;
5869     init = false;
5870     if (ref == NULL)
5871         ref = &ref_saved_style;
5872 
5873     ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
5874 
5875     if (ImGui::ShowStyleSelector("Colors##Selector"))
5876         ref_saved_style = style;
5877     ImGui::ShowFontSelector("Fonts##Selector");
5878 
5879     // Simplified Settings (expose floating-pointer border sizes as boolean representing 0.0f or 1.0f)
5880     if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
5881         style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
5882     { bool border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &border)) { style.WindowBorderSize = border ? 1.0f : 0.0f; } }
5883     ImGui::SameLine();
5884     { bool border = (style.FrameBorderSize > 0.0f);  if (ImGui::Checkbox("FrameBorder",  &border)) { style.FrameBorderSize  = border ? 1.0f : 0.0f; } }
5885     ImGui::SameLine();
5886     { bool border = (style.PopupBorderSize > 0.0f);  if (ImGui::Checkbox("PopupBorder",  &border)) { style.PopupBorderSize  = border ? 1.0f : 0.0f; } }
5887 
5888     // Save/Revert button
5889     if (ImGui::Button("Save Ref"))
5890         *ref = ref_saved_style = style;
5891     ImGui::SameLine();
5892     if (ImGui::Button("Revert Ref"))
5893         style = *ref;
5894     ImGui::SameLine();
5895     HelpMarker(
5896         "Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
5897         "Use \"Export\" below to save them somewhere.");
5898 
5899     ImGui::Separator();
5900 
5901     if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
5902     {
5903         if (ImGui::BeginTabItem("Sizes"))
5904         {
5905             ImGui::Text("Main");
5906             ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
5907             ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
5908             ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f");
5909             ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
5910             ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
5911             ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
5912             ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
5913             ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
5914             ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
5915             ImGui::Text("Borders");
5916             ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
5917             ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
5918             ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
5919             ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
5920             ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
5921             ImGui::Text("Rounding");
5922             ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
5923             ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
5924             ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
5925             ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
5926             ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
5927             ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
5928             ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
5929             ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
5930             ImGui::Text("Alignment");
5931             ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
5932             int window_menu_button_position = style.WindowMenuButtonPosition + 1;
5933             if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
5934                 style.WindowMenuButtonPosition = window_menu_button_position - 1;
5935             ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
5936             ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
5937             ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
5938             ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
5939             ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
5940             ImGui::Text("Safe Area Padding");
5941             ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
5942             ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
5943             ImGui::EndTabItem();
5944         }
5945 
5946         if (ImGui::BeginTabItem("Colors"))
5947         {
5948             static int output_dest = 0;
5949             static bool output_only_modified = true;
5950             if (ImGui::Button("Export"))
5951             {
5952                 if (output_dest == 0)
5953                     ImGui::LogToClipboard();
5954                 else
5955                     ImGui::LogToTTY();
5956                 ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
5957                 for (int i = 0; i < ImGuiCol_COUNT; i++)
5958                 {
5959                     const ImVec4& col = style.Colors[i];
5960                     const char* name = ImGui::GetStyleColorName(i);
5961                     if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
5962                         ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE,
5963                             name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
5964                 }
5965                 ImGui::LogFinish();
5966             }
5967             ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
5968             ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
5969 
5970             static ImGuiTextFilter filter;
5971             filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
5972 
5973             static ImGuiColorEditFlags alpha_flags = 0;
5974             if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None))             { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();
5975             if (ImGui::RadioButton("Alpha",  alpha_flags == ImGuiColorEditFlags_AlphaPreview))     { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
5976             if (ImGui::RadioButton("Both",   alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
5977             HelpMarker(
5978                 "In the color list:\n"
5979                 "Left-click on color square to open color picker,\n"
5980                 "Right-click to open edit options menu.");
5981 
5982             ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
5983             ImGui::PushItemWidth(-160);
5984             for (int i = 0; i < ImGuiCol_COUNT; i++)
5985             {
5986                 const char* name = ImGui::GetStyleColorName(i);
5987                 if (!filter.PassFilter(name))
5988                     continue;
5989                 ImGui::PushID(i);
5990                 ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
5991                 if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
5992                 {
5993                     // Tips: in a real user application, you may want to merge and use an icon font into the main font,
5994                     // so instead of "Save"/"Revert" you'd use icons!
5995                     // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
5996                     ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
5997                     ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
5998                 }
5999                 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
6000                 ImGui::TextUnformatted(name);
6001                 ImGui::PopID();
6002             }
6003             ImGui::PopItemWidth();
6004             ImGui::EndChild();
6005 
6006             ImGui::EndTabItem();
6007         }
6008 
6009         if (ImGui::BeginTabItem("Fonts"))
6010         {
6011             ImGuiIO& io = ImGui::GetIO();
6012             ImFontAtlas* atlas = io.Fonts;
6013             HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
6014             ImGui::ShowFontAtlas(atlas);
6015 
6016             // Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
6017             // (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
6018             const float MIN_SCALE = 0.3f;
6019             const float MAX_SCALE = 2.0f;
6020             HelpMarker(
6021                 "Those are old settings provided for convenience.\n"
6022                 "However, the _correct_ way of scaling your UI is currently to reload your font at the designed size, "
6023                 "rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n"
6024                 "Using those settings here will give you poor quality results.");
6025             static float window_scale = 1.0f;
6026             ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
6027             if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
6028                 ImGui::SetWindowFontScale(window_scale);
6029             ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything
6030             ImGui::PopItemWidth();
6031 
6032             ImGui::EndTabItem();
6033         }
6034 
6035         if (ImGui::BeginTabItem("Rendering"))
6036         {
6037             ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
6038             ImGui::SameLine();
6039             HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
6040 
6041             ImGui::Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex);
6042             ImGui::SameLine();
6043             HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
6044 
6045             ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
6046             ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
6047             ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
6048             if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
6049 
6050             // When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
6051             ImGui::DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
6052             if (ImGui::IsItemActive())
6053             {
6054                 ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
6055                 ImGui::BeginTooltip();
6056                 ImGui::TextUnformatted("(R = radius, N = number of segments)");
6057                 ImGui::Spacing();
6058                 ImDrawList* draw_list = ImGui::GetWindowDrawList();
6059                 const float min_widget_width = ImGui::CalcTextSize("N: MMM\nR: MMM").x;
6060                 for (int n = 0; n < 8; n++)
6061                 {
6062                     const float RAD_MIN = 5.0f;
6063                     const float RAD_MAX = 70.0f;
6064                     const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
6065 
6066                     ImGui::BeginGroup();
6067 
6068                     ImGui::Text("R: %.f\nN: %d", rad, draw_list->_CalcCircleAutoSegmentCount(rad));
6069 
6070                     const float canvas_width = IM_MAX(min_widget_width, rad * 2.0f);
6071                     const float offset_x     = floorf(canvas_width * 0.5f);
6072                     const float offset_y     = floorf(RAD_MAX);
6073 
6074                     const ImVec2 p1 = ImGui::GetCursorScreenPos();
6075                     draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
6076                     ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
6077 
6078                     /*
6079                     const ImVec2 p2 = ImGui::GetCursorScreenPos();
6080                     draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
6081                     ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
6082                     */
6083 
6084                     ImGui::EndGroup();
6085                     ImGui::SameLine();
6086                 }
6087                 ImGui::EndTooltip();
6088             }
6089             ImGui::SameLine();
6090             HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically.");
6091 
6092             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.
6093             ImGui::DragFloat("Disabled Alpha", &style.DisabledAlpha, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Additional alpha multiplier for disabled items (multiply over current value of Alpha).");
6094             ImGui::PopItemWidth();
6095 
6096             ImGui::EndTabItem();
6097         }
6098 
6099         ImGui::EndTabBar();
6100     }
6101 
6102     ImGui::PopItemWidth();
6103 }
6104 
6105 //-----------------------------------------------------------------------------
6106 // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
6107 //-----------------------------------------------------------------------------
6108 // - ShowExampleAppMainMenuBar()
6109 // - ShowExampleMenuFile()
6110 //-----------------------------------------------------------------------------
6111 
6112 // Demonstrate creating a "main" fullscreen menu bar and populating it.
6113 // Note the difference between BeginMainMenuBar() and BeginMenuBar():
6114 // - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!)
6115 // - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it.
6116 static void ShowExampleAppMainMenuBar()
6117 {
6118     if (ImGui::BeginMainMenuBar())
6119     {
6120         if (ImGui::BeginMenu("File"))
6121         {
6122             ShowExampleMenuFile();
6123             ImGui::EndMenu();
6124         }
6125         if (ImGui::BeginMenu("Edit"))
6126         {
6127             if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
6128             if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
6129             ImGui::Separator();
6130             if (ImGui::MenuItem("Cut", "CTRL+X")) {}
6131             if (ImGui::MenuItem("Copy", "CTRL+C")) {}
6132             if (ImGui::MenuItem("Paste", "CTRL+V")) {}
6133             ImGui::EndMenu();
6134         }
6135         ImGui::EndMainMenuBar();
6136     }
6137 }
6138 
6139 // Note that shortcuts are currently provided for display only
6140 // (future version will add explicit flags to BeginMenu() to request processing shortcuts)
6141 static void ShowExampleMenuFile()
6142 {
6143     ImGui::MenuItem("(demo menu)", NULL, false, false);
6144     if (ImGui::MenuItem("New")) {}
6145     if (ImGui::MenuItem("Open", "Ctrl+O")) {}
6146     if (ImGui::BeginMenu("Open Recent"))
6147     {
6148         ImGui::MenuItem("fish_hat.c");
6149         ImGui::MenuItem("fish_hat.inl");
6150         ImGui::MenuItem("fish_hat.h");
6151         if (ImGui::BeginMenu("More.."))
6152         {
6153             ImGui::MenuItem("Hello");
6154             ImGui::MenuItem("Sailor");
6155             if (ImGui::BeginMenu("Recurse.."))
6156             {
6157                 ShowExampleMenuFile();
6158                 ImGui::EndMenu();
6159             }
6160             ImGui::EndMenu();
6161         }
6162         ImGui::EndMenu();
6163     }
6164     if (ImGui::MenuItem("Save", "Ctrl+S")) {}
6165     if (ImGui::MenuItem("Save As..")) {}
6166 
6167     ImGui::Separator();
6168     if (ImGui::BeginMenu("Options"))
6169     {
6170         static bool enabled = true;
6171         ImGui::MenuItem("Enabled", "", &enabled);
6172         ImGui::BeginChild("child", ImVec2(0, 60), true);
6173         for (int i = 0; i < 10; i++)
6174             ImGui::Text("Scrolling Text %d", i);
6175         ImGui::EndChild();
6176         static float f = 0.5f;
6177         static int n = 0;
6178         ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
6179         ImGui::InputFloat("Input", &f, 0.1f);
6180         ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
6181         ImGui::EndMenu();
6182     }
6183 
6184     if (ImGui::BeginMenu("Colors"))
6185     {
6186         float sz = ImGui::GetTextLineHeight();
6187         for (int i = 0; i < ImGuiCol_COUNT; i++)
6188         {
6189             const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
6190             ImVec2 p = ImGui::GetCursorScreenPos();
6191             ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
6192             ImGui::Dummy(ImVec2(sz, sz));
6193             ImGui::SameLine();
6194             ImGui::MenuItem(name);
6195         }
6196         ImGui::EndMenu();
6197     }
6198 
6199     // Here we demonstrate appending again to the "Options" menu (which we already created above)
6200     // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice.
6201     // In a real code-base using it would make senses to use this feature from very different code locations.
6202     if (ImGui::BeginMenu("Options")) // <-- Append!
6203     {
6204         static bool b = true;
6205         ImGui::Checkbox("SomeOption", &b);
6206         ImGui::EndMenu();
6207     }
6208 
6209     if (ImGui::BeginMenu("Disabled", false)) // Disabled
6210     {
6211         IM_ASSERT(0);
6212     }
6213     if (ImGui::MenuItem("Checked", NULL, true)) {}
6214     if (ImGui::MenuItem("Quit", "Alt+F4")) {}
6215 }
6216 
6217 //-----------------------------------------------------------------------------
6218 // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
6219 //-----------------------------------------------------------------------------
6220 
6221 // Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
6222 // For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
6223 struct ExampleAppConsole
6224 {
6225     char                  InputBuf[256];
6226     ImVector<char*>       Items;
6227     ImVector<const char*> Commands;
6228     ImVector<char*>       History;
6229     int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
6230     ImGuiTextFilter       Filter;
6231     bool                  AutoScroll;
6232     bool                  ScrollToBottom;
6233 
6234     ExampleAppConsole()
6235     {
6236         ClearLog();
6237         memset(InputBuf, 0, sizeof(InputBuf));
6238         HistoryPos = -1;
6239 
6240         // "CLASSIFY" is here to provide the test case where "C"+[tab] completes to "CL" and display multiple matches.
6241         Commands.push_back("HELP");
6242         Commands.push_back("HISTORY");
6243         Commands.push_back("CLEAR");
6244         Commands.push_back("CLASSIFY");
6245         AutoScroll = true;
6246         ScrollToBottom = false;
6247         AddLog("Welcome to Dear ImGui!");
6248     }
6249     ~ExampleAppConsole()
6250     {
6251         ClearLog();
6252         for (int i = 0; i < History.Size; i++)
6253             free(History[i]);
6254     }
6255 
6256     // Portable helpers
6257     static int   Stricmp(const char* s1, const char* s2)         { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
6258     static int   Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; }
6259     static char* Strdup(const char* s)                           { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
6260     static void  Strtrim(char* s)                                { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
6261 
6262     void    ClearLog()
6263     {
6264         for (int i = 0; i < Items.Size; i++)
6265             free(Items[i]);
6266         Items.clear();
6267     }
6268 
6269     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
6270     {
6271         // FIXME-OPT
6272         char buf[1024];
6273         va_list args;
6274         va_start(args, fmt);
6275         vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
6276         buf[IM_ARRAYSIZE(buf)-1] = 0;
6277         va_end(args);
6278         Items.push_back(Strdup(buf));
6279     }
6280 
6281     void    Draw(const char* title, bool* p_open)
6282     {
6283         ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
6284         if (!ImGui::Begin(title, p_open))
6285         {
6286             ImGui::End();
6287             return;
6288         }
6289 
6290         // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar.
6291         // So e.g. IsItemHovered() will return true when hovering the title bar.
6292         // Here we create a context menu only available from the title bar.
6293         if (ImGui::BeginPopupContextItem())
6294         {
6295             if (ImGui::MenuItem("Close Console"))
6296                 *p_open = false;
6297             ImGui::EndPopup();
6298         }
6299 
6300         ImGui::TextWrapped(
6301             "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate "
6302             "implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
6303         ImGui::TextWrapped("Enter 'HELP' for help.");
6304 
6305         // TODO: display items starting from the bottom
6306 
6307         if (ImGui::SmallButton("Add Debug Text"))  { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); }
6308         ImGui::SameLine();
6309         if (ImGui::SmallButton("Add Debug Error")) { AddLog("[error] something went wrong"); }
6310         ImGui::SameLine();
6311         if (ImGui::SmallButton("Clear"))           { ClearLog(); }
6312         ImGui::SameLine();
6313         bool copy_to_clipboard = ImGui::SmallButton("Copy");
6314         //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
6315 
6316         ImGui::Separator();
6317 
6318         // Options menu
6319         if (ImGui::BeginPopup("Options"))
6320         {
6321             ImGui::Checkbox("Auto-scroll", &AutoScroll);
6322             ImGui::EndPopup();
6323         }
6324 
6325         // Options, Filter
6326         if (ImGui::Button("Options"))
6327             ImGui::OpenPopup("Options");
6328         ImGui::SameLine();
6329         Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
6330         ImGui::Separator();
6331 
6332         // Reserve enough left-over height for 1 separator + 1 input text
6333         const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
6334         ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar);
6335         if (ImGui::BeginPopupContextWindow())
6336         {
6337             if (ImGui::Selectable("Clear")) ClearLog();
6338             ImGui::EndPopup();
6339         }
6340 
6341         // Display every line as a separate entry so we can change their color or add custom widgets.
6342         // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
6343         // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
6344         // to only process visible items. The clipper will automatically measure the height of your first item and then
6345         // "seek" to display only items in the visible area.
6346         // To use the clipper we can replace your standard loop:
6347         //      for (int i = 0; i < Items.Size; i++)
6348         //   With:
6349         //      ImGuiListClipper clipper;
6350         //      clipper.Begin(Items.Size);
6351         //      while (clipper.Step())
6352         //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
6353         // - That your items are evenly spaced (same height)
6354         // - That you have cheap random access to your elements (you can access them given their index,
6355         //   without processing all the ones before)
6356         // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
6357         // We would need random-access on the post-filtered list.
6358         // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
6359         // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
6360         // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
6361         // to improve this example code!
6362         // If your items are of variable height:
6363         // - Split them into same height items would be simpler and facilitate random-seeking into your list.
6364         // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
6365         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
6366         if (copy_to_clipboard)
6367             ImGui::LogToClipboard();
6368         for (int i = 0; i < Items.Size; i++)
6369         {
6370             const char* item = Items[i];
6371             if (!Filter.PassFilter(item))
6372                 continue;
6373 
6374             // Normally you would store more information in your item than just a string.
6375             // (e.g. make Items[] an array of structure, store color/type etc.)
6376             ImVec4 color;
6377             bool has_color = false;
6378             if (strstr(item, "[error]"))          { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
6379             else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
6380             if (has_color)
6381                 ImGui::PushStyleColor(ImGuiCol_Text, color);
6382             ImGui::TextUnformatted(item);
6383             if (has_color)
6384                 ImGui::PopStyleColor();
6385         }
6386         if (copy_to_clipboard)
6387             ImGui::LogFinish();
6388 
6389         if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
6390             ImGui::SetScrollHereY(1.0f);
6391         ScrollToBottom = false;
6392 
6393         ImGui::PopStyleVar();
6394         ImGui::EndChild();
6395         ImGui::Separator();
6396 
6397         // Command-line
6398         bool reclaim_focus = false;
6399         ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
6400         if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
6401         {
6402             char* s = InputBuf;
6403             Strtrim(s);
6404             if (s[0])
6405                 ExecCommand(s);
6406             strcpy(s, "");
6407             reclaim_focus = true;
6408         }
6409 
6410         // Auto-focus on window apparition
6411         ImGui::SetItemDefaultFocus();
6412         if (reclaim_focus)
6413             ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
6414 
6415         ImGui::End();
6416     }
6417 
6418     void    ExecCommand(const char* command_line)
6419     {
6420         AddLog("# %s\n", command_line);
6421 
6422         // Insert into history. First find match and delete it so it can be pushed to the back.
6423         // This isn't trying to be smart or optimal.
6424         HistoryPos = -1;
6425         for (int i = History.Size - 1; i >= 0; i--)
6426             if (Stricmp(History[i], command_line) == 0)
6427             {
6428                 free(History[i]);
6429                 History.erase(History.begin() + i);
6430                 break;
6431             }
6432         History.push_back(Strdup(command_line));
6433 
6434         // Process command
6435         if (Stricmp(command_line, "CLEAR") == 0)
6436         {
6437             ClearLog();
6438         }
6439         else if (Stricmp(command_line, "HELP") == 0)
6440         {
6441             AddLog("Commands:");
6442             for (int i = 0; i < Commands.Size; i++)
6443                 AddLog("- %s", Commands[i]);
6444         }
6445         else if (Stricmp(command_line, "HISTORY") == 0)
6446         {
6447             int first = History.Size - 10;
6448             for (int i = first > 0 ? first : 0; i < History.Size; i++)
6449                 AddLog("%3d: %s\n", i, History[i]);
6450         }
6451         else
6452         {
6453             AddLog("Unknown command: '%s'\n", command_line);
6454         }
6455 
6456         // On command input, we scroll to bottom even if AutoScroll==false
6457         ScrollToBottom = true;
6458     }
6459 
6460     // In C++11 you'd be better off using lambdas for this sort of forwarding callbacks
6461     static int TextEditCallbackStub(ImGuiInputTextCallbackData* data)
6462     {
6463         ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
6464         return console->TextEditCallback(data);
6465     }
6466 
6467     int     TextEditCallback(ImGuiInputTextCallbackData* data)
6468     {
6469         //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
6470         switch (data->EventFlag)
6471         {
6472         case ImGuiInputTextFlags_CallbackCompletion:
6473             {
6474                 // Example of TEXT COMPLETION
6475 
6476                 // Locate beginning of current word
6477                 const char* word_end = data->Buf + data->CursorPos;
6478                 const char* word_start = word_end;
6479                 while (word_start > data->Buf)
6480                 {
6481                     const char c = word_start[-1];
6482                     if (c == ' ' || c == '\t' || c == ',' || c == ';')
6483                         break;
6484                     word_start--;
6485                 }
6486 
6487                 // Build a list of candidates
6488                 ImVector<const char*> candidates;
6489                 for (int i = 0; i < Commands.Size; i++)
6490                     if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
6491                         candidates.push_back(Commands[i]);
6492 
6493                 if (candidates.Size == 0)
6494                 {
6495                     // No match
6496                     AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
6497                 }
6498                 else if (candidates.Size == 1)
6499                 {
6500                     // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing.
6501                     data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
6502                     data->InsertChars(data->CursorPos, candidates[0]);
6503                     data->InsertChars(data->CursorPos, " ");
6504                 }
6505                 else
6506                 {
6507                     // Multiple matches. Complete as much as we can..
6508                     // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches.
6509                     int match_len = (int)(word_end - word_start);
6510                     for (;;)
6511                     {
6512                         int c = 0;
6513                         bool all_candidates_matches = true;
6514                         for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
6515                             if (i == 0)
6516                                 c = toupper(candidates[i][match_len]);
6517                             else if (c == 0 || c != toupper(candidates[i][match_len]))
6518                                 all_candidates_matches = false;
6519                         if (!all_candidates_matches)
6520                             break;
6521                         match_len++;
6522                     }
6523 
6524                     if (match_len > 0)
6525                     {
6526                         data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
6527                         data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
6528                     }
6529 
6530                     // List matches
6531                     AddLog("Possible matches:\n");
6532                     for (int i = 0; i < candidates.Size; i++)
6533                         AddLog("- %s\n", candidates[i]);
6534                 }
6535 
6536                 break;
6537             }
6538         case ImGuiInputTextFlags_CallbackHistory:
6539             {
6540                 // Example of HISTORY
6541                 const int prev_history_pos = HistoryPos;
6542                 if (data->EventKey == ImGuiKey_UpArrow)
6543                 {
6544                     if (HistoryPos == -1)
6545                         HistoryPos = History.Size - 1;
6546                     else if (HistoryPos > 0)
6547                         HistoryPos--;
6548                 }
6549                 else if (data->EventKey == ImGuiKey_DownArrow)
6550                 {
6551                     if (HistoryPos != -1)
6552                         if (++HistoryPos >= History.Size)
6553                             HistoryPos = -1;
6554                 }
6555 
6556                 // A better implementation would preserve the data on the current input line along with cursor position.
6557                 if (prev_history_pos != HistoryPos)
6558                 {
6559                     const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
6560                     data->DeleteChars(0, data->BufTextLen);
6561                     data->InsertChars(0, history_str);
6562                 }
6563             }
6564         }
6565         return 0;
6566     }
6567 };
6568 
6569 static void ShowExampleAppConsole(bool* p_open)
6570 {
6571     static ExampleAppConsole console;
6572     console.Draw("Example: Console", p_open);
6573 }
6574 
6575 //-----------------------------------------------------------------------------
6576 // [SECTION] Example App: Debug Log / ShowExampleAppLog()
6577 //-----------------------------------------------------------------------------
6578 
6579 // Usage:
6580 //  static ExampleAppLog my_log;
6581 //  my_log.AddLog("Hello %d world\n", 123);
6582 //  my_log.Draw("title");
6583 struct ExampleAppLog
6584 {
6585     ImGuiTextBuffer     Buf;
6586     ImGuiTextFilter     Filter;
6587     ImVector<int>       LineOffsets; // Index to lines offset. We maintain this with AddLog() calls.
6588     bool                AutoScroll;  // Keep scrolling if already at the bottom.
6589 
6590     ExampleAppLog()
6591     {
6592         AutoScroll = true;
6593         Clear();
6594     }
6595 
6596     void    Clear()
6597     {
6598         Buf.clear();
6599         LineOffsets.clear();
6600         LineOffsets.push_back(0);
6601     }
6602 
6603     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
6604     {
6605         int old_size = Buf.size();
6606         va_list args;
6607         va_start(args, fmt);
6608         Buf.appendfv(fmt, args);
6609         va_end(args);
6610         for (int new_size = Buf.size(); old_size < new_size; old_size++)
6611             if (Buf[old_size] == '\n')
6612                 LineOffsets.push_back(old_size + 1);
6613     }
6614 
6615     void    Draw(const char* title, bool* p_open = NULL)
6616     {
6617         if (!ImGui::Begin(title, p_open))
6618         {
6619             ImGui::End();
6620             return;
6621         }
6622 
6623         // Options menu
6624         if (ImGui::BeginPopup("Options"))
6625         {
6626             ImGui::Checkbox("Auto-scroll", &AutoScroll);
6627             ImGui::EndPopup();
6628         }
6629 
6630         // Main window
6631         if (ImGui::Button("Options"))
6632             ImGui::OpenPopup("Options");
6633         ImGui::SameLine();
6634         bool clear = ImGui::Button("Clear");
6635         ImGui::SameLine();
6636         bool copy = ImGui::Button("Copy");
6637         ImGui::SameLine();
6638         Filter.Draw("Filter", -100.0f);
6639 
6640         ImGui::Separator();
6641         ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
6642 
6643         if (clear)
6644             Clear();
6645         if (copy)
6646             ImGui::LogToClipboard();
6647 
6648         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
6649         const char* buf = Buf.begin();
6650         const char* buf_end = Buf.end();
6651         if (Filter.IsActive())
6652         {
6653             // In this example we don't use the clipper when Filter is enabled.
6654             // This is because we don't have a random access on the result on our filter.
6655             // A real application processing logs with ten of thousands of entries may want to store the result of
6656             // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
6657             for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
6658             {
6659                 const char* line_start = buf + LineOffsets[line_no];
6660                 const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
6661                 if (Filter.PassFilter(line_start, line_end))
6662                     ImGui::TextUnformatted(line_start, line_end);
6663             }
6664         }
6665         else
6666         {
6667             // The simplest and easy way to display the entire buffer:
6668             //   ImGui::TextUnformatted(buf_begin, buf_end);
6669             // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
6670             // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
6671             // within the visible area.
6672             // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
6673             // on your side is recommended. Using ImGuiListClipper requires
6674             // - A) random access into your data
6675             // - B) items all being the  same height,
6676             // both of which we can handle since we an array pointing to the beginning of each line of text.
6677             // When using the filter (in the block of code above) we don't have random access into the data to display
6678             // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
6679             // it possible (and would be recommended if you want to search through tens of thousands of entries).
6680             ImGuiListClipper clipper;
6681             clipper.Begin(LineOffsets.Size);
6682             while (clipper.Step())
6683             {
6684                 for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
6685                 {
6686                     const char* line_start = buf + LineOffsets[line_no];
6687                     const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
6688                     ImGui::TextUnformatted(line_start, line_end);
6689                 }
6690             }
6691             clipper.End();
6692         }
6693         ImGui::PopStyleVar();
6694 
6695         if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
6696             ImGui::SetScrollHereY(1.0f);
6697 
6698         ImGui::EndChild();
6699         ImGui::End();
6700     }
6701 };
6702 
6703 // Demonstrate creating a simple log window with basic filtering.
6704 static void ShowExampleAppLog(bool* p_open)
6705 {
6706     static ExampleAppLog log;
6707 
6708     // For the demo: add a debug button _BEFORE_ the normal log window contents
6709     // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
6710     // Most of the contents of the window will be added by the log.Draw() call.
6711     ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
6712     ImGui::Begin("Example: Log", p_open);
6713     if (ImGui::SmallButton("[Debug] Add 5 entries"))
6714     {
6715         static int counter = 0;
6716         const char* categories[3] = { "info", "warn", "error" };
6717         const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
6718         for (int n = 0; n < 5; n++)
6719         {
6720             const char* category = categories[counter % IM_ARRAYSIZE(categories)];
6721             const char* word = words[counter % IM_ARRAYSIZE(words)];
6722             log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
6723                 ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
6724             counter++;
6725         }
6726     }
6727     ImGui::End();
6728 
6729     // Actually call in the regular Log helper (which will Begin() into the same window as we just did)
6730     log.Draw("Example: Log", p_open);
6731 }
6732 
6733 //-----------------------------------------------------------------------------
6734 // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
6735 //-----------------------------------------------------------------------------
6736 
6737 // Demonstrate create a window with multiple child windows.
6738 static void ShowExampleAppLayout(bool* p_open)
6739 {
6740     ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
6741     if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
6742     {
6743         if (ImGui::BeginMenuBar())
6744         {
6745             if (ImGui::BeginMenu("File"))
6746             {
6747                 if (ImGui::MenuItem("Close")) *p_open = false;
6748                 ImGui::EndMenu();
6749             }
6750             ImGui::EndMenuBar();
6751         }
6752 
6753         // Left
6754         static int selected = 0;
6755         {
6756             ImGui::BeginChild("left pane", ImVec2(150, 0), true);
6757             for (int i = 0; i < 100; i++)
6758             {
6759                 // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav
6760                 char label[128];
6761                 sprintf(label, "MyObject %d", i);
6762                 if (ImGui::Selectable(label, selected == i))
6763                     selected = i;
6764             }
6765             ImGui::EndChild();
6766         }
6767         ImGui::SameLine();
6768 
6769         // Right
6770         {
6771             ImGui::BeginGroup();
6772             ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
6773             ImGui::Text("MyObject: %d", selected);
6774             ImGui::Separator();
6775             if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
6776             {
6777                 if (ImGui::BeginTabItem("Description"))
6778                 {
6779                     ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
6780                     ImGui::EndTabItem();
6781                 }
6782                 if (ImGui::BeginTabItem("Details"))
6783                 {
6784                     ImGui::Text("ID: 0123456789");
6785                     ImGui::EndTabItem();
6786                 }
6787                 ImGui::EndTabBar();
6788             }
6789             ImGui::EndChild();
6790             if (ImGui::Button("Revert")) {}
6791             ImGui::SameLine();
6792             if (ImGui::Button("Save")) {}
6793             ImGui::EndGroup();
6794         }
6795     }
6796     ImGui::End();
6797 }
6798 
6799 //-----------------------------------------------------------------------------
6800 // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
6801 //-----------------------------------------------------------------------------
6802 
6803 static void ShowPlaceholderObject(const char* prefix, int uid)
6804 {
6805     // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
6806     ImGui::PushID(uid);
6807 
6808     // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high.
6809     ImGui::TableNextRow();
6810     ImGui::TableSetColumnIndex(0);
6811     ImGui::AlignTextToFramePadding();
6812     bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
6813     ImGui::TableSetColumnIndex(1);
6814     ImGui::Text("my sailor is rich");
6815 
6816     if (node_open)
6817     {
6818         static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f };
6819         for (int i = 0; i < 8; i++)
6820         {
6821             ImGui::PushID(i); // Use field index as identifier.
6822             if (i < 2)
6823             {
6824                 ShowPlaceholderObject("Child", 424242);
6825             }
6826             else
6827             {
6828                 // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
6829                 ImGui::TableNextRow();
6830                 ImGui::TableSetColumnIndex(0);
6831                 ImGui::AlignTextToFramePadding();
6832                 ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet;
6833                 ImGui::TreeNodeEx("Field", flags, "Field_%d", i);
6834 
6835                 ImGui::TableSetColumnIndex(1);
6836                 ImGui::SetNextItemWidth(-FLT_MIN);
6837                 if (i >= 5)
6838                     ImGui::InputFloat("##value", &placeholder_members[i], 1.0f);
6839                 else
6840                     ImGui::DragFloat("##value", &placeholder_members[i], 0.01f);
6841                 ImGui::NextColumn();
6842             }
6843             ImGui::PopID();
6844         }
6845         ImGui::TreePop();
6846     }
6847     ImGui::PopID();
6848 }
6849 
6850 // Demonstrate create a simple property editor.
6851 static void ShowExampleAppPropertyEditor(bool* p_open)
6852 {
6853     ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
6854     if (!ImGui::Begin("Example: Property editor", p_open))
6855     {
6856         ImGui::End();
6857         return;
6858     }
6859 
6860     HelpMarker(
6861         "This example shows how you may implement a property editor using two columns.\n"
6862         "All objects/fields data are dummies here.\n"
6863         "Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position\n"
6864         "your cursor horizontally instead of using the Columns() API.");
6865 
6866     ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
6867     if (ImGui::BeginTable("split", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable))
6868     {
6869         // Iterate placeholder objects (all the same data)
6870         for (int obj_i = 0; obj_i < 4; obj_i++)
6871         {
6872             ShowPlaceholderObject("Object", obj_i);
6873             //ImGui::Separator();
6874         }
6875         ImGui::EndTable();
6876     }
6877     ImGui::PopStyleVar();
6878     ImGui::End();
6879 }
6880 
6881 //-----------------------------------------------------------------------------
6882 // [SECTION] Example App: Long Text / ShowExampleAppLongText()
6883 //-----------------------------------------------------------------------------
6884 
6885 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
6886 static void ShowExampleAppLongText(bool* p_open)
6887 {
6888     ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
6889     if (!ImGui::Begin("Example: Long text display", p_open))
6890     {
6891         ImGui::End();
6892         return;
6893     }
6894 
6895     static int test_type = 0;
6896     static ImGuiTextBuffer log;
6897     static int lines = 0;
6898     ImGui::Text("Printing unusually long amount of text.");
6899     ImGui::Combo("Test type", &test_type,
6900         "Single call to TextUnformatted()\0"
6901         "Multiple calls to Text(), clipped\0"
6902         "Multiple calls to Text(), not clipped (slow)\0");
6903     ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
6904     if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
6905     ImGui::SameLine();
6906     if (ImGui::Button("Add 1000 lines"))
6907     {
6908         for (int i = 0; i < 1000; i++)
6909             log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
6910         lines += 1000;
6911     }
6912     ImGui::BeginChild("Log");
6913     switch (test_type)
6914     {
6915     case 0:
6916         // Single call to TextUnformatted() with a big buffer
6917         ImGui::TextUnformatted(log.begin(), log.end());
6918         break;
6919     case 1:
6920         {
6921             // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
6922             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
6923             ImGuiListClipper clipper;
6924             clipper.Begin(lines);
6925             while (clipper.Step())
6926                 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
6927                     ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
6928             ImGui::PopStyleVar();
6929             break;
6930         }
6931     case 2:
6932         // Multiple calls to Text(), not clipped (slow)
6933         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
6934         for (int i = 0; i < lines; i++)
6935             ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
6936         ImGui::PopStyleVar();
6937         break;
6938     }
6939     ImGui::EndChild();
6940     ImGui::End();
6941 }
6942 
6943 //-----------------------------------------------------------------------------
6944 // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
6945 //-----------------------------------------------------------------------------
6946 
6947 // Demonstrate creating a window which gets auto-resized according to its content.
6948 static void ShowExampleAppAutoResize(bool* p_open)
6949 {
6950     if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
6951     {
6952         ImGui::End();
6953         return;
6954     }
6955 
6956     static int lines = 10;
6957     ImGui::TextUnformatted(
6958         "Window will resize every-frame to the size of its content.\n"
6959         "Note that you probably don't want to query the window size to\n"
6960         "output your content because that would create a feedback loop.");
6961     ImGui::SliderInt("Number of lines", &lines, 1, 20);
6962     for (int i = 0; i < lines; i++)
6963         ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
6964     ImGui::End();
6965 }
6966 
6967 //-----------------------------------------------------------------------------
6968 // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
6969 //-----------------------------------------------------------------------------
6970 
6971 // Demonstrate creating a window with custom resize constraints.
6972 static void ShowExampleAppConstrainedResize(bool* p_open)
6973 {
6974     struct CustomConstraints
6975     {
6976         // Helper functions to demonstrate programmatic constraints
6977         static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y); }
6978         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); }
6979     };
6980 
6981     const char* test_desc[] =
6982     {
6983         "Resize vertical only",
6984         "Resize horizontal only",
6985         "Width > 100, Height > 100",
6986         "Width 400-500",
6987         "Height 400-500",
6988         "Custom: Always Square",
6989         "Custom: Fixed Steps (100)",
6990     };
6991 
6992     static bool auto_resize = false;
6993     static int type = 0;
6994     static int display_lines = 10;
6995     if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Vertical only
6996     if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Horizontal only
6997     if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
6998     if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width 400-500
6999     if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, 500));          // Height 400-500
7000     if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);                     // Always Square
7001     if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
7002 
7003     ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
7004     if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
7005     {
7006         if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
7007         if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
7008         if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
7009         ImGui::SetNextItemWidth(200);
7010         ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
7011         ImGui::SetNextItemWidth(200);
7012         ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
7013         ImGui::Checkbox("Auto-resize", &auto_resize);
7014         for (int i = 0; i < display_lines; i++)
7015             ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
7016     }
7017     ImGui::End();
7018 }
7019 
7020 //-----------------------------------------------------------------------------
7021 // [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
7022 //-----------------------------------------------------------------------------
7023 
7024 // Demonstrate creating a simple static window with no decoration
7025 // + a context-menu to choose which corner of the screen to use.
7026 static void ShowExampleAppSimpleOverlay(bool* p_open)
7027 {
7028     static int corner = 0;
7029     ImGuiIO& io = ImGui::GetIO();
7030     ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
7031     if (corner != -1)
7032     {
7033         const float PAD = 10.0f;
7034         const ImGuiViewport* viewport = ImGui::GetMainViewport();
7035         ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
7036         ImVec2 work_size = viewport->WorkSize;
7037         ImVec2 window_pos, window_pos_pivot;
7038         window_pos.x = (corner & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
7039         window_pos.y = (corner & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
7040         window_pos_pivot.x = (corner & 1) ? 1.0f : 0.0f;
7041         window_pos_pivot.y = (corner & 2) ? 1.0f : 0.0f;
7042         ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
7043         window_flags |= ImGuiWindowFlags_NoMove;
7044     }
7045     ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
7046     if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
7047     {
7048         ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
7049         ImGui::Separator();
7050         if (ImGui::IsMousePosValid())
7051             ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
7052         else
7053             ImGui::Text("Mouse Position: <invalid>");
7054         if (ImGui::BeginPopupContextWindow())
7055         {
7056             if (ImGui::MenuItem("Custom",       NULL, corner == -1)) corner = -1;
7057             if (ImGui::MenuItem("Top-left",     NULL, corner == 0)) corner = 0;
7058             if (ImGui::MenuItem("Top-right",    NULL, corner == 1)) corner = 1;
7059             if (ImGui::MenuItem("Bottom-left",  NULL, corner == 2)) corner = 2;
7060             if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
7061             if (p_open && ImGui::MenuItem("Close")) *p_open = false;
7062             ImGui::EndPopup();
7063         }
7064     }
7065     ImGui::End();
7066 }
7067 
7068 //-----------------------------------------------------------------------------
7069 // [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
7070 //-----------------------------------------------------------------------------
7071 
7072 // Demonstrate creating a window covering the entire screen/viewport
7073 static void ShowExampleAppFullscreen(bool* p_open)
7074 {
7075     static bool use_work_area = true;
7076     static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
7077 
7078     // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
7079     // Based on your use case you may want one of the other.
7080     const ImGuiViewport* viewport = ImGui::GetMainViewport();
7081     ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
7082     ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
7083 
7084     if (ImGui::Begin("Example: Fullscreen window", p_open, flags))
7085     {
7086         ImGui::Checkbox("Use work area instead of main area", &use_work_area);
7087         ImGui::SameLine();
7088         HelpMarker("Main Area = entire viewport,\nWork Area = entire viewport minus sections used by the main menu bars, task bars etc.\n\nEnable the main-menu bar in Examples menu to see the difference.");
7089 
7090         ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground);
7091         ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration);
7092         ImGui::Indent();
7093         ImGui::CheckboxFlags("ImGuiWindowFlags_NoTitleBar", &flags, ImGuiWindowFlags_NoTitleBar);
7094         ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse);
7095         ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar);
7096         ImGui::Unindent();
7097 
7098         if (p_open && ImGui::Button("Close this window"))
7099             *p_open = false;
7100     }
7101     ImGui::End();
7102 }
7103 
7104 //-----------------------------------------------------------------------------
7105 // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
7106 //-----------------------------------------------------------------------------
7107 
7108 // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
7109 // This apply to all regular items as well.
7110 // Read FAQ section "How can I have multiple widgets with the same label?" for details.
7111 static void ShowExampleAppWindowTitles(bool*)
7112 {
7113     const ImGuiViewport* viewport = ImGui::GetMainViewport();
7114     const ImVec2 base_pos = viewport->Pos;
7115 
7116     // By default, Windows are uniquely identified by their title.
7117     // You can use the "##" and "###" markers to manipulate the display/ID.
7118 
7119     // Using "##" to display same title but have unique identifier.
7120     ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 100), ImGuiCond_FirstUseEver);
7121     ImGui::Begin("Same title as another window##1");
7122     ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
7123     ImGui::End();
7124 
7125     ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 200), ImGuiCond_FirstUseEver);
7126     ImGui::Begin("Same title as another window##2");
7127     ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
7128     ImGui::End();
7129 
7130     // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
7131     char buf[128];
7132     sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
7133     ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 300), ImGuiCond_FirstUseEver);
7134     ImGui::Begin(buf);
7135     ImGui::Text("This window has a changing title.");
7136     ImGui::End();
7137 }
7138 
7139 //-----------------------------------------------------------------------------
7140 // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
7141 //-----------------------------------------------------------------------------
7142 
7143 // Demonstrate using the low-level ImDrawList to draw custom shapes.
7144 static void ShowExampleAppCustomRendering(bool* p_open)
7145 {
7146     if (!ImGui::Begin("Example: Custom rendering", p_open))
7147     {
7148         ImGui::End();
7149         return;
7150     }
7151 
7152     // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of
7153     // overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your
7154     // types and ImVec2/ImVec4. Dear ImGui defines overloaded operators but they are internal to imgui.cpp and not
7155     // exposed outside (to avoid messing with your types) In this example we are not using the maths operators!
7156 
7157     if (ImGui::BeginTabBar("##TabBar"))
7158     {
7159         if (ImGui::BeginTabItem("Primitives"))
7160         {
7161             ImGui::PushItemWidth(-ImGui::GetFontSize() * 15);
7162             ImDrawList* draw_list = ImGui::GetWindowDrawList();
7163 
7164             // Draw gradients
7165             // (note that those are currently exacerbating our sRGB/Linear issues)
7166             // Calling ImGui::GetColorU32() multiplies the given colors by the current Style Alpha, but you may pass the IM_COL32() directly as well..
7167             ImGui::Text("Gradients");
7168             ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight());
7169             {
7170                 ImVec2 p0 = ImGui::GetCursorScreenPos();
7171                 ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
7172                 ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255));
7173                 ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255));
7174                 draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
7175                 ImGui::InvisibleButton("##gradient1", gradient_size);
7176             }
7177             {
7178                 ImVec2 p0 = ImGui::GetCursorScreenPos();
7179                 ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
7180                 ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255));
7181                 ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255));
7182                 draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
7183                 ImGui::InvisibleButton("##gradient2", gradient_size);
7184             }
7185 
7186             // Draw a bunch of primitives
7187             ImGui::Text("All primitives");
7188             static float sz = 36.0f;
7189             static float thickness = 3.0f;
7190             static int ngon_sides = 6;
7191             static bool circle_segments_override = false;
7192             static int circle_segments_override_v = 12;
7193             static bool curve_segments_override = false;
7194             static int curve_segments_override_v = 8;
7195             static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
7196             ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 100.0f, "%.0f");
7197             ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
7198             ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
7199             ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
7200             ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
7201             circle_segments_override |= ImGui::SliderInt("Circle segments override", &circle_segments_override_v, 3, 40);
7202             ImGui::Checkbox("##curvessegmentoverride", &curve_segments_override);
7203             ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
7204             curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 40);
7205             ImGui::ColorEdit4("Color", &colf.x);
7206 
7207             const ImVec2 p = ImGui::GetCursorScreenPos();
7208             const ImU32 col = ImColor(colf);
7209             const float spacing = 10.0f;
7210             const ImDrawFlags corners_tl_br = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomRight;
7211             const float rounding = sz / 5.0f;
7212             const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
7213             const int curve_segments = curve_segments_override ? curve_segments_override_v : 0;
7214             float x = p.x + 4.0f;
7215             float y = p.y + 4.0f;
7216             for (int n = 0; n < 2; n++)
7217             {
7218                 // First line uses a thickness of 1.0f, second line uses the configurable thickness
7219                 float th = (n == 0) ? 1.0f : thickness;
7220                 draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th);                 x += sz + spacing;  // N-gon
7221                 draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th);          x += sz + spacing;  // Circle
7222                 draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th);          x += sz + spacing;  // Square
7223                 draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th);      x += sz + spacing;  // Square with all rounded corners
7224                 draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th);         x += sz + spacing;  // Square with two rounded corners
7225                 draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing;  // Triangle
7226                 //draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
7227                 draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th);                                       x += sz + spacing;  // Horizontal line (note: drawing a filled rectangle will be faster!)
7228                 draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th);                                       x += spacing;       // Vertical line (note: drawing a filled rectangle will be faster!)
7229                 draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th);                                  x += sz + spacing;  // Diagonal line
7230 
7231                 // Quadratic Bezier Curve (3 control points)
7232                 ImVec2 cp3[3] = { ImVec2(x, y + sz * 0.6f), ImVec2(x + sz * 0.5f, y - sz * 0.4f), ImVec2(x + sz, y + sz) };
7233                 draw_list->AddBezierQuadratic(cp3[0], cp3[1], cp3[2], col, th, curve_segments); x += sz + spacing;
7234 
7235                 // Cubic Bezier Curve (4 control points)
7236                 ImVec2 cp4[4] = { 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) };
7237                 draw_list->AddBezierCubic(cp4[0], cp4[1], cp4[2], cp4[3], col, th, curve_segments);
7238 
7239                 x = p.x + 4;
7240                 y += sz + spacing;
7241             }
7242             draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides);               x += sz + spacing;  // N-gon
7243             draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments);            x += sz + spacing;  // Circle
7244             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col);                                    x += sz + spacing;  // Square
7245             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f);                             x += sz + spacing;  // Square with all rounded corners
7246             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br);              x += sz + spacing;  // Square with two rounded corners
7247             draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col);  x += sz + spacing;  // Triangle
7248             //draw_list->AddTriangleFilled(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col); x += sz*0.4f + spacing; // Thin triangle
7249             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + thickness), col);                             x += sz + spacing;  // Horizontal line (faster than AddLine, but only handle integer thickness)
7250             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + thickness, y + sz), col);                             x += spacing * 2.0f;// Vertical line (faster than AddLine, but only handle integer thickness)
7251             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col);                                      x += sz;            // Pixel (faster than AddLine)
7252             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));
7253 
7254             ImGui::Dummy(ImVec2((sz + spacing) * 10.2f, (sz + spacing) * 3.0f));
7255             ImGui::PopItemWidth();
7256             ImGui::EndTabItem();
7257         }
7258 
7259         if (ImGui::BeginTabItem("Canvas"))
7260         {
7261             static ImVector<ImVec2> points;
7262             static ImVec2 scrolling(0.0f, 0.0f);
7263             static bool opt_enable_grid = true;
7264             static bool opt_enable_context_menu = true;
7265             static bool adding_line = false;
7266 
7267             ImGui::Checkbox("Enable grid", &opt_enable_grid);
7268             ImGui::Checkbox("Enable context menu", &opt_enable_context_menu);
7269             ImGui::Text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.");
7270 
7271             // Typically you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling.
7272             // Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls.
7273             // To use a child window instead we could use, e.g:
7274             //      ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));      // Disable padding
7275             //      ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255));  // Set a background color
7276             //      ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_NoMove);
7277             //      ImGui::PopStyleColor();
7278             //      ImGui::PopStyleVar();
7279             //      [...]
7280             //      ImGui::EndChild();
7281 
7282             // Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive()
7283             ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();      // ImDrawList API uses screen coordinates!
7284             ImVec2 canvas_sz = ImGui::GetContentRegionAvail();   // Resize canvas to what's available
7285             if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
7286             if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f;
7287             ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
7288 
7289             // Draw border and background color
7290             ImGuiIO& io = ImGui::GetIO();
7291             ImDrawList* draw_list = ImGui::GetWindowDrawList();
7292             draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
7293             draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
7294 
7295             // This will catch our interactions
7296             ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
7297             const bool is_hovered = ImGui::IsItemHovered(); // Hovered
7298             const bool is_active = ImGui::IsItemActive();   // Held
7299             const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y); // Lock scrolled origin
7300             const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
7301 
7302             // Add first and second point
7303             if (is_hovered && !adding_line && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
7304             {
7305                 points.push_back(mouse_pos_in_canvas);
7306                 points.push_back(mouse_pos_in_canvas);
7307                 adding_line = true;
7308             }
7309             if (adding_line)
7310             {
7311                 points.back() = mouse_pos_in_canvas;
7312                 if (!ImGui::IsMouseDown(ImGuiMouseButton_Left))
7313                     adding_line = false;
7314             }
7315 
7316             // Pan (we use a zero mouse threshold when there's no context menu)
7317             // You may decide to make that threshold dynamic based on whether the mouse is hovering something etc.
7318             const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
7319             if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan))
7320             {
7321                 scrolling.x += io.MouseDelta.x;
7322                 scrolling.y += io.MouseDelta.y;
7323             }
7324 
7325             // Context menu (under default mouse threshold)
7326             ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
7327             if (opt_enable_context_menu && ImGui::IsMouseReleased(ImGuiMouseButton_Right) && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
7328                 ImGui::OpenPopupOnItemClick("context");
7329             if (ImGui::BeginPopup("context"))
7330             {
7331                 if (adding_line)
7332                     points.resize(points.size() - 2);
7333                 adding_line = false;
7334                 if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) { points.resize(points.size() - 2); }
7335                 if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) { points.clear(); }
7336                 ImGui::EndPopup();
7337             }
7338 
7339             // Draw grid + all lines in the canvas
7340             draw_list->PushClipRect(canvas_p0, canvas_p1, true);
7341             if (opt_enable_grid)
7342             {
7343                 const float GRID_STEP = 64.0f;
7344                 for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
7345                     draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), ImVec2(canvas_p0.x + x, canvas_p1.y), IM_COL32(200, 200, 200, 40));
7346                 for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
7347                     draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), ImVec2(canvas_p1.x, canvas_p0.y + y), IM_COL32(200, 200, 200, 40));
7348             }
7349             for (int n = 0; n < points.Size; n += 2)
7350                 draw_list->AddLine(ImVec2(origin.x + points[n].x, origin.y + points[n].y), ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
7351             draw_list->PopClipRect();
7352 
7353             ImGui::EndTabItem();
7354         }
7355 
7356         if (ImGui::BeginTabItem("BG/FG draw lists"))
7357         {
7358             static bool draw_bg = true;
7359             static bool draw_fg = true;
7360             ImGui::Checkbox("Draw in Background draw list", &draw_bg);
7361             ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows.");
7362             ImGui::Checkbox("Draw in Foreground draw list", &draw_fg);
7363             ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows.");
7364             ImVec2 window_pos = ImGui::GetWindowPos();
7365             ImVec2 window_size = ImGui::GetWindowSize();
7366             ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
7367             if (draw_bg)
7368                 ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4);
7369             if (draw_fg)
7370                 ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10);
7371             ImGui::EndTabItem();
7372         }
7373 
7374         ImGui::EndTabBar();
7375     }
7376 
7377     ImGui::End();
7378 }
7379 
7380 //-----------------------------------------------------------------------------
7381 // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
7382 //-----------------------------------------------------------------------------
7383 
7384 // Simplified structure to mimic a Document model
7385 struct MyDocument
7386 {
7387     const char* Name;       // Document title
7388     bool        Open;       // Set when open (we keep an array of all available documents to simplify demo code!)
7389     bool        OpenPrev;   // Copy of Open from last update.
7390     bool        Dirty;      // Set when the document has been modified
7391     bool        WantClose;  // Set when the document
7392     ImVec4      Color;      // An arbitrary variable associated to the document
7393 
7394     MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
7395     {
7396         Name = name;
7397         Open = OpenPrev = open;
7398         Dirty = false;
7399         WantClose = false;
7400         Color = color;
7401     }
7402     void DoOpen()       { Open = true; }
7403     void DoQueueClose() { WantClose = true; }
7404     void DoForceClose() { Open = false; Dirty = false; }
7405     void DoSave()       { Dirty = false; }
7406 
7407     // Display placeholder contents for the Document
7408     static void DisplayContents(MyDocument* doc)
7409     {
7410         ImGui::PushID(doc);
7411         ImGui::Text("Document \"%s\"", doc->Name);
7412         ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
7413         ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
7414         ImGui::PopStyleColor();
7415         if (ImGui::Button("Modify", ImVec2(100, 0)))
7416             doc->Dirty = true;
7417         ImGui::SameLine();
7418         if (ImGui::Button("Save", ImVec2(100, 0)))
7419             doc->DoSave();
7420         ImGui::ColorEdit3("color", &doc->Color.x);  // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
7421         ImGui::PopID();
7422     }
7423 
7424     // Display context menu for the Document
7425     static void DisplayContextMenu(MyDocument* doc)
7426     {
7427         if (!ImGui::BeginPopupContextItem())
7428             return;
7429 
7430         char buf[256];
7431         sprintf(buf, "Save %s", doc->Name);
7432         if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
7433             doc->DoSave();
7434         if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
7435             doc->DoQueueClose();
7436         ImGui::EndPopup();
7437     }
7438 };
7439 
7440 struct ExampleAppDocuments
7441 {
7442     ImVector<MyDocument> Documents;
7443 
7444     ExampleAppDocuments()
7445     {
7446         Documents.push_back(MyDocument("Lettuce",             true,  ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
7447         Documents.push_back(MyDocument("Eggplant",            true,  ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
7448         Documents.push_back(MyDocument("Carrot",              true,  ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
7449         Documents.push_back(MyDocument("Tomato",              false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
7450         Documents.push_back(MyDocument("A Rather Long Title", false));
7451         Documents.push_back(MyDocument("Some Document",       false));
7452     }
7453 };
7454 
7455 // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
7456 // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
7457 // as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
7458 // the tab bar to notice its absence. During this frame there will be a gap in the tab bar, and if the tab that has
7459 // disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
7460 // give the impression of a flicker for one frame.
7461 // We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
7462 // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
7463 static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
7464 {
7465     for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
7466     {
7467         MyDocument* doc = &app.Documents[doc_n];
7468         if (!doc->Open && doc->OpenPrev)
7469             ImGui::SetTabItemClosed(doc->Name);
7470         doc->OpenPrev = doc->Open;
7471     }
7472 }
7473 
7474 void ShowExampleAppDocuments(bool* p_open)
7475 {
7476     static ExampleAppDocuments app;
7477 
7478     // Options
7479     static bool opt_reorderable = true;
7480     static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
7481 
7482     bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
7483     if (!window_contents_visible)
7484     {
7485         ImGui::End();
7486         return;
7487     }
7488 
7489     // Menu
7490     if (ImGui::BeginMenuBar())
7491     {
7492         if (ImGui::BeginMenu("File"))
7493         {
7494             int open_count = 0;
7495             for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
7496                 open_count += app.Documents[doc_n].Open ? 1 : 0;
7497 
7498             if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
7499             {
7500                 for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
7501                 {
7502                     MyDocument* doc = &app.Documents[doc_n];
7503                     if (!doc->Open)
7504                         if (ImGui::MenuItem(doc->Name))
7505                             doc->DoOpen();
7506                 }
7507                 ImGui::EndMenu();
7508             }
7509             if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
7510                 for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
7511                     app.Documents[doc_n].DoQueueClose();
7512             if (ImGui::MenuItem("Exit", "Alt+F4")) {}
7513             ImGui::EndMenu();
7514         }
7515         ImGui::EndMenuBar();
7516     }
7517 
7518     // [Debug] List documents with one checkbox for each
7519     for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
7520     {
7521         MyDocument* doc = &app.Documents[doc_n];
7522         if (doc_n > 0)
7523             ImGui::SameLine();
7524         ImGui::PushID(doc);
7525         if (ImGui::Checkbox(doc->Name, &doc->Open))
7526             if (!doc->Open)
7527                 doc->DoForceClose();
7528         ImGui::PopID();
7529     }
7530 
7531     ImGui::Separator();
7532 
7533     // About the ImGuiWindowFlags_UnsavedDocument / ImGuiTabItemFlags_UnsavedDocument flags.
7534     // They have multiple effects:
7535     // - Display a dot next to the title.
7536     // - Tab is selected when clicking the X close button.
7537     // - Closure is not assumed (will wait for user to stop submitting the tab).
7538     //   Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
7539     //   We need to assume closure by default otherwise waiting for "lack of submission" on the next frame would leave an empty
7540     //   hole for one-frame, both in the tab-bar and in tab-contents when closing a tab/window.
7541     //   The rarely used SetTabItemClosed() function is a way to notify of programmatic closure to avoid the one-frame hole.
7542 
7543     // Submit Tab Bar and Tabs
7544     {
7545         ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
7546         if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
7547         {
7548             if (opt_reorderable)
7549                 NotifyOfDocumentsClosedElsewhere(app);
7550 
7551             // [DEBUG] Stress tests
7552             //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1;            // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
7553             //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name);  // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
7554 
7555             // Submit Tabs
7556             for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
7557             {
7558                 MyDocument* doc = &app.Documents[doc_n];
7559                 if (!doc->Open)
7560                     continue;
7561 
7562                 ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
7563                 bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
7564 
7565                 // Cancel attempt to close when unsaved add to save queue so we can display a popup.
7566                 if (!doc->Open && doc->Dirty)
7567                 {
7568                     doc->Open = true;
7569                     doc->DoQueueClose();
7570                 }
7571 
7572                 MyDocument::DisplayContextMenu(doc);
7573                 if (visible)
7574                 {
7575                     MyDocument::DisplayContents(doc);
7576                     ImGui::EndTabItem();
7577                 }
7578             }
7579 
7580             ImGui::EndTabBar();
7581         }
7582     }
7583 
7584     // Update closing queue
7585     static ImVector<MyDocument*> close_queue;
7586     if (close_queue.empty())
7587     {
7588         // Close queue is locked once we started a popup
7589         for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
7590         {
7591             MyDocument* doc = &app.Documents[doc_n];
7592             if (doc->WantClose)
7593             {
7594                 doc->WantClose = false;
7595                 close_queue.push_back(doc);
7596             }
7597         }
7598     }
7599 
7600     // Display closing confirmation UI
7601     if (!close_queue.empty())
7602     {
7603         int close_queue_unsaved_documents = 0;
7604         for (int n = 0; n < close_queue.Size; n++)
7605             if (close_queue[n]->Dirty)
7606                 close_queue_unsaved_documents++;
7607 
7608         if (close_queue_unsaved_documents == 0)
7609         {
7610             // Close documents when all are unsaved
7611             for (int n = 0; n < close_queue.Size; n++)
7612                 close_queue[n]->DoForceClose();
7613             close_queue.clear();
7614         }
7615         else
7616         {
7617             if (!ImGui::IsPopupOpen("Save?"))
7618                 ImGui::OpenPopup("Save?");
7619             if (ImGui::BeginPopupModal("Save?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
7620             {
7621                 ImGui::Text("Save change to the following items?");
7622                 float item_height = ImGui::GetTextLineHeightWithSpacing();
7623                 if (ImGui::BeginChildFrame(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height)))
7624                 {
7625                     for (int n = 0; n < close_queue.Size; n++)
7626                         if (close_queue[n]->Dirty)
7627                             ImGui::Text("%s", close_queue[n]->Name);
7628                     ImGui::EndChildFrame();
7629                 }
7630 
7631                 ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
7632                 if (ImGui::Button("Yes", button_size))
7633                 {
7634                     for (int n = 0; n < close_queue.Size; n++)
7635                     {
7636                         if (close_queue[n]->Dirty)
7637                             close_queue[n]->DoSave();
7638                         close_queue[n]->DoForceClose();
7639                     }
7640                     close_queue.clear();
7641                     ImGui::CloseCurrentPopup();
7642                 }
7643                 ImGui::SameLine();
7644                 if (ImGui::Button("No", button_size))
7645                 {
7646                     for (int n = 0; n < close_queue.Size; n++)
7647                         close_queue[n]->DoForceClose();
7648                     close_queue.clear();
7649                     ImGui::CloseCurrentPopup();
7650                 }
7651                 ImGui::SameLine();
7652                 if (ImGui::Button("Cancel", button_size))
7653                 {
7654                     close_queue.clear();
7655                     ImGui::CloseCurrentPopup();
7656                 }
7657                 ImGui::EndPopup();
7658             }
7659         }
7660     }
7661 
7662     ImGui::End();
7663 }
7664 
7665 // End of Demo code
7666 #else
7667 
7668 void ImGui::ShowAboutWindow(bool*) {}
7669 void ImGui::ShowDemoWindow(bool*) {}
7670 void ImGui::ShowUserGuide() {}
7671 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
7672 
7673 #endif
7674 
7675 #endif // #ifndef IMGUI_DISABLE
7676