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