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