1 // dear imgui, v1.75
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);
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("Alignment applies when a selectable is larger than its text content.\nBy default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar().");
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 bufpass[64] = "password123";
1044             ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
1045             ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
1046             ImGui::InputTextWithHint("password (w/ hint)", "<password>", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
1047             ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
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         ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80));
1268 
1269         ImGui::Text("Color picker:");
1270         static bool alpha = true;
1271         static bool alpha_bar = true;
1272         static bool side_preview = true;
1273         static bool ref_color = false;
1274         static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);
1275         static int display_mode = 0;
1276         static int picker_mode = 0;
1277         ImGui::Checkbox("With Alpha", &alpha);
1278         ImGui::Checkbox("With Alpha Bar", &alpha_bar);
1279         ImGui::Checkbox("With Side Preview", &side_preview);
1280         if (side_preview)
1281         {
1282             ImGui::SameLine();
1283             ImGui::Checkbox("With Ref Color", &ref_color);
1284             if (ref_color)
1285             {
1286                 ImGui::SameLine();
1287                 ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
1288             }
1289         }
1290         ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
1291         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().");
1292         ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
1293         ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode.");
1294         ImGuiColorEditFlags flags = misc_flags;
1295         if (!alpha)            flags |= ImGuiColorEditFlags_NoAlpha;        // This is by default if you call ColorPicker3() instead of ColorPicker4()
1296         if (alpha_bar)         flags |= ImGuiColorEditFlags_AlphaBar;
1297         if (!side_preview)     flags |= ImGuiColorEditFlags_NoSidePreview;
1298         if (picker_mode == 1)  flags |= ImGuiColorEditFlags_PickerHueBar;
1299         if (picker_mode == 2)  flags |= ImGuiColorEditFlags_PickerHueWheel;
1300         if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;       // Disable all RGB/HSV/Hex displays
1301         if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB;     // Override display mode
1302         if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
1303         if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
1304         ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
1305 
1306         ImGui::Text("Programmatically set defaults:");
1307         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.");
1308         if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
1309             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
1310         if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
1311             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
1312 
1313         // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
1314         static ImVec4 color_stored_as_hsv(0.23f, 1.0f, 1.0f, 1.0f);
1315         ImGui::Spacing();
1316         ImGui::Text("HSV encoded colors");
1317         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.");
1318         ImGui::Text("Color widget with InputHSV:");
1319         ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_stored_as_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
1320         ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_stored_as_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
1321         ImGui::DragFloat4("Raw HSV values", (float*)&color_stored_as_hsv, 0.01f, 0.0f, 1.0f);
1322 
1323         ImGui::TreePop();
1324     }
1325 
1326     if (ImGui::TreeNode("Range Widgets"))
1327     {
1328         static float begin = 10, end = 90;
1329         static int begin_i = 100, end_i = 1000;
1330         ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
1331         ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
1332         ImGui::TreePop();
1333     }
1334 
1335     if (ImGui::TreeNode("Data Types"))
1336     {
1337         // The DragScalar/InputScalar/SliderScalar functions allow various data types: signed/unsigned int/long long and float/double
1338         // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type,
1339         // and passing all arguments by address.
1340         // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
1341         // In practice, if you frequently use a given type that is not covered by the normal API entry points, you can wrap it
1342         // yourself inside a 1 line function which can take typed argument as value instead of void*, and then pass their address
1343         // to the generic function. For example:
1344         //   bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
1345         //   {
1346         //      return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
1347         //   }
1348 
1349         // Limits (as helper variables that we can take the address of)
1350         // Note that the SliderScalar function has a maximum usable range of half the natural type maximum, hence the /2 below.
1351         #ifndef LLONG_MIN
1352         ImS64 LLONG_MIN = -9223372036854775807LL - 1;
1353         ImS64 LLONG_MAX = 9223372036854775807LL;
1354         ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
1355         #endif
1356         const char    s8_zero  = 0,   s8_one  = 1,   s8_fifty  = 50, s8_min  = -128,        s8_max = 127;
1357         const ImU8    u8_zero  = 0,   u8_one  = 1,   u8_fifty  = 50, u8_min  = 0,           u8_max = 255;
1358         const short   s16_zero = 0,   s16_one = 1,   s16_fifty = 50, s16_min = -32768,      s16_max = 32767;
1359         const ImU16   u16_zero = 0,   u16_one = 1,   u16_fifty = 50, u16_min = 0,           u16_max = 65535;
1360         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;
1361         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;
1362         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;
1363         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;
1364         const float   f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
1365         const double  f64_zero = 0.,  f64_one = 1.,  f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
1366 
1367         // State
1368         static char   s8_v  = 127;
1369         static ImU8   u8_v  = 255;
1370         static short  s16_v = 32767;
1371         static ImU16  u16_v = 65535;
1372         static ImS32  s32_v = -1;
1373         static ImU32  u32_v = (ImU32)-1;
1374         static ImS64  s64_v = -1;
1375         static ImU64  u64_v = (ImU64)-1;
1376         static float  f32_v = 0.123f;
1377         static double f64_v = 90000.01234567890123456789;
1378 
1379         const float drag_speed = 0.2f;
1380         static bool drag_clamp = false;
1381         ImGui::Text("Drags:");
1382         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.");
1383         ImGui::DragScalar("drag s8",        ImGuiDataType_S8,     &s8_v,  drag_speed, drag_clamp ? &s8_zero  : NULL, drag_clamp ? &s8_fifty  : NULL);
1384         ImGui::DragScalar("drag u8",        ImGuiDataType_U8,     &u8_v,  drag_speed, drag_clamp ? &u8_zero  : NULL, drag_clamp ? &u8_fifty  : NULL, "%u ms");
1385         ImGui::DragScalar("drag s16",       ImGuiDataType_S16,    &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
1386         ImGui::DragScalar("drag u16",       ImGuiDataType_U16,    &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
1387         ImGui::DragScalar("drag s32",       ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
1388         ImGui::DragScalar("drag u32",       ImGuiDataType_U32,    &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
1389         ImGui::DragScalar("drag s64",       ImGuiDataType_S64,    &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
1390         ImGui::DragScalar("drag u64",       ImGuiDataType_U64,    &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
1391         ImGui::DragScalar("drag float",     ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", 1.0f);
1392         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.");
1393         ImGui::DragScalar("drag double",    ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL,     "%.10f grams", 1.0f);
1394         ImGui::DragScalar("drag double ^2", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", 2.0f);
1395 
1396         ImGui::Text("Sliders");
1397         ImGui::SliderScalar("slider s8 full",     ImGuiDataType_S8,     &s8_v,  &s8_min,   &s8_max,   "%d");
1398         ImGui::SliderScalar("slider u8 full",     ImGuiDataType_U8,     &u8_v,  &u8_min,   &u8_max,   "%u");
1399         ImGui::SliderScalar("slider s16 full",    ImGuiDataType_S16,    &s16_v, &s16_min,  &s16_max,  "%d");
1400         ImGui::SliderScalar("slider u16 full",    ImGuiDataType_U16,    &u16_v, &u16_min,  &u16_max,  "%u");
1401         ImGui::SliderScalar("slider s32 low",     ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty,"%d");
1402         ImGui::SliderScalar("slider s32 high",    ImGuiDataType_S32,    &s32_v, &s32_hi_a, &s32_hi_b, "%d");
1403         ImGui::SliderScalar("slider s32 full",    ImGuiDataType_S32,    &s32_v, &s32_min,  &s32_max,  "%d");
1404         ImGui::SliderScalar("slider u32 low",     ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u");
1405         ImGui::SliderScalar("slider u32 high",    ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u");
1406         ImGui::SliderScalar("slider u32 full",    ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u");
1407         ImGui::SliderScalar("slider s64 low",     ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%I64d");
1408         ImGui::SliderScalar("slider s64 high",    ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%I64d");
1409         ImGui::SliderScalar("slider s64 full",    ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%I64d");
1410         ImGui::SliderScalar("slider u64 low",     ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%I64u ms");
1411         ImGui::SliderScalar("slider u64 high",    ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms");
1412         ImGui::SliderScalar("slider u64 full",    ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%I64u ms");
1413         ImGui::SliderScalar("slider float low",   ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one);
1414         ImGui::SliderScalar("slider float low^2", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", 2.0f);
1415         ImGui::SliderScalar("slider float high",  ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e");
1416         ImGui::SliderScalar("slider double low",  ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f grams", 1.0f);
1417         ImGui::SliderScalar("slider double low^2",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", 2.0f);
1418         ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams", 1.0f);
1419 
1420         static bool inputs_step = true;
1421         ImGui::Text("Inputs");
1422         ImGui::Checkbox("Show step buttons", &inputs_step);
1423         ImGui::InputScalar("input s8",      ImGuiDataType_S8,     &s8_v,  inputs_step ? &s8_one  : NULL, NULL, "%d");
1424         ImGui::InputScalar("input u8",      ImGuiDataType_U8,     &u8_v,  inputs_step ? &u8_one  : NULL, NULL, "%u");
1425         ImGui::InputScalar("input s16",     ImGuiDataType_S16,    &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d");
1426         ImGui::InputScalar("input u16",     ImGuiDataType_U16,    &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u");
1427         ImGui::InputScalar("input s32",     ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
1428         ImGui::InputScalar("input s32 hex", ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1429         ImGui::InputScalar("input u32",     ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
1430         ImGui::InputScalar("input u32 hex", ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1431         ImGui::InputScalar("input s64",     ImGuiDataType_S64,    &s64_v, inputs_step ? &s64_one : NULL);
1432         ImGui::InputScalar("input u64",     ImGuiDataType_U64,    &u64_v, inputs_step ? &u64_one : NULL);
1433         ImGui::InputScalar("input float",   ImGuiDataType_Float,  &f32_v, inputs_step ? &f32_one : NULL);
1434         ImGui::InputScalar("input double",  ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
1435 
1436         ImGui::TreePop();
1437     }
1438 
1439     if (ImGui::TreeNode("Multi-component Widgets"))
1440     {
1441         static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
1442         static int vec4i[4] = { 1, 5, 100, 255 };
1443 
1444         ImGui::InputFloat2("input float2", vec4f);
1445         ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
1446         ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
1447         ImGui::InputInt2("input int2", vec4i);
1448         ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
1449         ImGui::SliderInt2("slider int2", vec4i, 0, 255);
1450         ImGui::Spacing();
1451 
1452         ImGui::InputFloat3("input float3", vec4f);
1453         ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
1454         ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
1455         ImGui::InputInt3("input int3", vec4i);
1456         ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
1457         ImGui::SliderInt3("slider int3", vec4i, 0, 255);
1458         ImGui::Spacing();
1459 
1460         ImGui::InputFloat4("input float4", vec4f);
1461         ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
1462         ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
1463         ImGui::InputInt4("input int4", vec4i);
1464         ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
1465         ImGui::SliderInt4("slider int4", vec4i, 0, 255);
1466 
1467         ImGui::TreePop();
1468     }
1469 
1470     if (ImGui::TreeNode("Vertical Sliders"))
1471     {
1472         const float spacing = 4;
1473         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1474 
1475         static int int_value = 0;
1476         ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
1477         ImGui::SameLine();
1478 
1479         static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
1480         ImGui::PushID("set1");
1481         for (int i = 0; i < 7; i++)
1482         {
1483             if (i > 0) ImGui::SameLine();
1484             ImGui::PushID(i);
1485             ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));
1486             ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));
1487             ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));
1488             ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));
1489             ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
1490             if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1491                 ImGui::SetTooltip("%.3f", values[i]);
1492             ImGui::PopStyleColor(4);
1493             ImGui::PopID();
1494         }
1495         ImGui::PopID();
1496 
1497         ImGui::SameLine();
1498         ImGui::PushID("set2");
1499         static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
1500         const int rows = 3;
1501         const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
1502         for (int nx = 0; nx < 4; nx++)
1503         {
1504             if (nx > 0) ImGui::SameLine();
1505             ImGui::BeginGroup();
1506             for (int ny = 0; ny < rows; ny++)
1507             {
1508                 ImGui::PushID(nx*rows+ny);
1509                 ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
1510                 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1511                     ImGui::SetTooltip("%.3f", values2[nx]);
1512                 ImGui::PopID();
1513             }
1514             ImGui::EndGroup();
1515         }
1516         ImGui::PopID();
1517 
1518         ImGui::SameLine();
1519         ImGui::PushID("set3");
1520         for (int i = 0; i < 4; i++)
1521         {
1522             if (i > 0) ImGui::SameLine();
1523             ImGui::PushID(i);
1524             ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
1525             ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
1526             ImGui::PopStyleVar();
1527             ImGui::PopID();
1528         }
1529         ImGui::PopID();
1530         ImGui::PopStyleVar();
1531         ImGui::TreePop();
1532     }
1533 
1534     if (ImGui::TreeNode("Drag and Drop"))
1535     {
1536         if (ImGui::TreeNode("Drag and drop in standard widgets"))
1537         {
1538             // ColorEdit widgets automatically act as drag source and drag target.
1539             // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets
1540             // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo.
1541             HelpMarker("You can drag from the colored squares.");
1542             static float col1[3] = { 1.0f, 0.0f, 0.2f };
1543             static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
1544             ImGui::ColorEdit3("color 1", col1);
1545             ImGui::ColorEdit4("color 2", col2);
1546             ImGui::TreePop();
1547         }
1548 
1549         if (ImGui::TreeNode("Drag and drop to copy/swap items"))
1550         {
1551             enum Mode
1552             {
1553                 Mode_Copy,
1554                 Mode_Move,
1555                 Mode_Swap
1556             };
1557             static int mode = 0;
1558             if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
1559             if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
1560             if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
1561             static const char* names[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", "Bibi", "Blaine", "Bryn" };
1562             for (int n = 0; n < IM_ARRAYSIZE(names); n++)
1563             {
1564                 ImGui::PushID(n);
1565                 if ((n % 3) != 0)
1566                     ImGui::SameLine();
1567                 ImGui::Button(names[n], ImVec2(60,60));
1568 
1569                 // Our buttons are both drag sources and drag targets here!
1570                 if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
1571                 {
1572                     ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));    // Set payload to carry the index of our item (could be anything)
1573                     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.)
1574                     if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
1575                     if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
1576                     ImGui::EndDragDropSource();
1577                 }
1578                 if (ImGui::BeginDragDropTarget())
1579                 {
1580                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
1581                     {
1582                         IM_ASSERT(payload->DataSize == sizeof(int));
1583                         int payload_n = *(const int*)payload->Data;
1584                         if (mode == Mode_Copy)
1585                         {
1586                             names[n] = names[payload_n];
1587                         }
1588                         if (mode == Mode_Move)
1589                         {
1590                             names[n] = names[payload_n];
1591                             names[payload_n] = "";
1592                         }
1593                         if (mode == Mode_Swap)
1594                         {
1595                             const char* tmp = names[n];
1596                             names[n] = names[payload_n];
1597                             names[payload_n] = tmp;
1598                         }
1599                     }
1600                     ImGui::EndDragDropTarget();
1601                 }
1602                 ImGui::PopID();
1603             }
1604             ImGui::TreePop();
1605         }
1606 
1607         if (ImGui::TreeNode("Drag to reorder items (simple)"))
1608         {
1609             // Simple reordering
1610             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.");
1611             static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
1612             for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
1613             {
1614                 const char* item = item_names[n];
1615                 ImGui::Selectable(item);
1616 
1617                 if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
1618                 {
1619                     int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
1620                     if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
1621                     {
1622                         item_names[n] = item_names[n_next];
1623                         item_names[n_next] = item;
1624                         ImGui::ResetMouseDragDelta();
1625                     }
1626                 }
1627             }
1628             ImGui::TreePop();
1629         }
1630 
1631         ImGui::TreePop();
1632     }
1633 
1634     if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)"))
1635     {
1636         // Submit an item (various types available) so we can query their status in the following block.
1637         static int item_type = 1;
1638         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);
1639         ImGui::SameLine();
1640         HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions.");
1641         bool ret = false;
1642         static bool b = false;
1643         static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
1644         static char str[16] = {};
1645         if (item_type == 0) { ImGui::Text("ITEM: Text"); }                                              // Testing text items with no identifier/interaction
1646         if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); }                                    // Testing button
1647         if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater)
1648         if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); }                            // Testing checkbox
1649         if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
1650         if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); }  // Testing input text (which handles tabbing)
1651         if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); }               // Testing +/- buttons on scalar input
1652         if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); }                   // Testing multi-component items (IsItemXXX flags are reported merged)
1653         if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
1654         if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); }                                // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
1655         if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); }     // Testing tree node
1656         if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
1657         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)); }
1658 
1659         // Display the value of IsItemHovered() and other common item state functions.
1660         // Note that the ImGuiHoveredFlags_XXX flags can be combined.
1661         // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
1662         // we query every state in a single call to avoid storing them and to simplify the code
1663         ImGui::BulletText(
1664             "Return value = %d\n"
1665             "IsItemFocused() = %d\n"
1666             "IsItemHovered() = %d\n"
1667             "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
1668             "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1669             "IsItemHovered(_AllowWhenOverlapped) = %d\n"
1670             "IsItemHovered(_RectOnly) = %d\n"
1671             "IsItemActive() = %d\n"
1672             "IsItemEdited() = %d\n"
1673             "IsItemActivated() = %d\n"
1674             "IsItemDeactivated() = %d\n"
1675             "IsItemDeactivatedAfterEdit() = %d\n"
1676             "IsItemVisible() = %d\n"
1677             "IsItemClicked() = %d\n"
1678             "IsItemToggledOpen() = %d\n"
1679             "GetItemRectMin() = (%.1f, %.1f)\n"
1680             "GetItemRectMax() = (%.1f, %.1f)\n"
1681             "GetItemRectSize() = (%.1f, %.1f)",
1682             ret,
1683             ImGui::IsItemFocused(),
1684             ImGui::IsItemHovered(),
1685             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1686             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1687             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
1688             ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
1689             ImGui::IsItemActive(),
1690             ImGui::IsItemEdited(),
1691             ImGui::IsItemActivated(),
1692             ImGui::IsItemDeactivated(),
1693             ImGui::IsItemDeactivatedAfterEdit(),
1694             ImGui::IsItemVisible(),
1695             ImGui::IsItemClicked(),
1696             ImGui::IsItemToggledOpen(),
1697             ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
1698             ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
1699             ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
1700         );
1701 
1702         static bool embed_all_inside_a_child_window = false;
1703         ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
1704         if (embed_all_inside_a_child_window)
1705             ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true);
1706 
1707         // Testing IsWindowFocused() function with its various flags.
1708         // Note that the ImGuiFocusedFlags_XXX flags can be combined.
1709         ImGui::BulletText(
1710             "IsWindowFocused() = %d\n"
1711             "IsWindowFocused(_ChildWindows) = %d\n"
1712             "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
1713             "IsWindowFocused(_RootWindow) = %d\n"
1714             "IsWindowFocused(_AnyWindow) = %d\n",
1715             ImGui::IsWindowFocused(),
1716             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
1717             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
1718             ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
1719             ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
1720 
1721         // Testing IsWindowHovered() function with its various flags.
1722         // Note that the ImGuiHoveredFlags_XXX flags can be combined.
1723         ImGui::BulletText(
1724             "IsWindowHovered() = %d\n"
1725             "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
1726             "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1727             "IsWindowHovered(_ChildWindows) = %d\n"
1728             "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
1729             "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
1730             "IsWindowHovered(_RootWindow) = %d\n"
1731             "IsWindowHovered(_AnyWindow) = %d\n",
1732             ImGui::IsWindowHovered(),
1733             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1734             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1735             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
1736             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
1737             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1738             ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
1739             ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
1740 
1741         ImGui::BeginChild("child", ImVec2(0, 50), true);
1742         ImGui::Text("This is another child window for testing the _ChildWindows flag.");
1743         ImGui::EndChild();
1744         if (embed_all_inside_a_child_window)
1745             ImGui::EndChild();
1746 
1747         static char dummy_str[] = "This is a dummy field to be able to tab-out of the widgets above.";
1748         ImGui::InputText("dummy", dummy_str, IM_ARRAYSIZE(dummy_str), ImGuiInputTextFlags_ReadOnly);
1749 
1750         // Calling IsItemHovered() after begin returns the hovered status of the title bar.
1751         // This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window.
1752         static bool test_window = false;
1753         ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
1754         if (test_window)
1755         {
1756             ImGui::Begin("Title bar Hovered/Active tests", &test_window);
1757             if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
1758             {
1759                 if (ImGui::MenuItem("Close")) { test_window = false; }
1760                 ImGui::EndPopup();
1761             }
1762             ImGui::Text(
1763                 "IsItemHovered() after begin = %d (== is title bar hovered)\n"
1764                 "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
1765                 ImGui::IsItemHovered(), ImGui::IsItemActive());
1766             ImGui::End();
1767         }
1768 
1769         ImGui::TreePop();
1770     }
1771 }
1772 
ShowDemoWindowLayout()1773 static void ShowDemoWindowLayout()
1774 {
1775     if (!ImGui::CollapsingHeader("Layout"))
1776         return;
1777 
1778     if (ImGui::TreeNode("Child windows"))
1779     {
1780         HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
1781         static bool disable_mouse_wheel = false;
1782         static bool disable_menu = false;
1783         ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
1784         ImGui::Checkbox("Disable Menu", &disable_menu);
1785 
1786         static int line = 50;
1787         bool goto_line = ImGui::Button("Goto");
1788         ImGui::SameLine();
1789         ImGui::SetNextItemWidth(100);
1790         goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
1791 
1792         // Child 1: no border, enable horizontal scrollbar
1793         {
1794             ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0);
1795             ImGui::BeginChild("ChildL", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags);
1796             for (int i = 0; i < 100; i++)
1797             {
1798                 ImGui::Text("%04d: scrollable region", i);
1799                 if (goto_line && line == i)
1800                     ImGui::SetScrollHereY();
1801             }
1802             if (goto_line && line >= 100)
1803                 ImGui::SetScrollHereY();
1804             ImGui::EndChild();
1805         }
1806 
1807         ImGui::SameLine();
1808 
1809         // Child 2: rounded border
1810         {
1811             ImGuiWindowFlags window_flags = (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar);
1812             ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
1813             ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags);
1814             if (!disable_menu && ImGui::BeginMenuBar())
1815             {
1816                 if (ImGui::BeginMenu("Menu"))
1817                 {
1818                     ShowExampleMenuFile();
1819                     ImGui::EndMenu();
1820                 }
1821                 ImGui::EndMenuBar();
1822             }
1823             ImGui::Columns(2);
1824             for (int i = 0; i < 100; i++)
1825             {
1826                 char buf[32];
1827                 sprintf(buf, "%03d", i);
1828                 ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
1829                 ImGui::NextColumn();
1830             }
1831             ImGui::EndChild();
1832             ImGui::PopStyleVar();
1833         }
1834 
1835         ImGui::Separator();
1836 
1837         // Demonstrate a few extra things
1838         // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
1839         // - Using SetCursorPos() to position the child window (because the child window is an item from the POV of the parent window)
1840         //   You can also call SetNextWindowPos() to position the child window. The parent window will effectively layout from this position.
1841         // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from the POV of the parent window)
1842         //   See "Widgets" -> "Querying Status (Active/Focused/Hovered etc.)" section for more details about this.
1843         {
1844             ImGui::SetCursorPosX(ImGui::GetCursorPosX() + 10);
1845             ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
1846             ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None);
1847             for (int n = 0; n < 50; n++)
1848                 ImGui::Text("Some test %d", n);
1849             ImGui::EndChild();
1850             ImVec2 child_rect_min = ImGui::GetItemRectMin();
1851             ImVec2 child_rect_max = ImGui::GetItemRectMax();
1852             ImGui::PopStyleColor();
1853             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);
1854         }
1855 
1856         ImGui::TreePop();
1857     }
1858 
1859     if (ImGui::TreeNode("Widgets Width"))
1860     {
1861         // Use SetNextItemWidth() to set the width of a single upcoming item.
1862         // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
1863         static float f = 0.0f;
1864         ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
1865         ImGui::SameLine(); HelpMarker("Fixed width.");
1866         ImGui::SetNextItemWidth(100);
1867         ImGui::DragFloat("float##1", &f);
1868 
1869         ImGui::Text("SetNextItemWidth/PushItemWidth(GetWindowWidth() * 0.5f)");
1870         ImGui::SameLine(); HelpMarker("Half of window width.");
1871         ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.5f);
1872         ImGui::DragFloat("float##2", &f);
1873 
1874         ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
1875         ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
1876         ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
1877         ImGui::DragFloat("float##3", &f);
1878 
1879         ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
1880         ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
1881         ImGui::SetNextItemWidth(-100);
1882         ImGui::DragFloat("float##4", &f);
1883 
1884         // Demonstrate using PushItemWidth to surround three items. Calling SetNextItemWidth() before each of them would have the same effect.
1885         ImGui::Text("SetNextItemWidth/PushItemWidth(-1)");
1886         ImGui::SameLine(); HelpMarker("Align to right edge");
1887         ImGui::PushItemWidth(-1);
1888         ImGui::DragFloat("##float5a", &f);
1889         ImGui::DragFloat("##float5b", &f);
1890         ImGui::DragFloat("##float5c", &f);
1891         ImGui::PopItemWidth();
1892 
1893         ImGui::TreePop();
1894     }
1895 
1896     if (ImGui::TreeNode("Basic Horizontal Layout"))
1897     {
1898         ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1899 
1900         // Text
1901         ImGui::Text("Two items: Hello"); ImGui::SameLine();
1902         ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1903 
1904         // Adjust spacing
1905         ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
1906         ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1907 
1908         // Button
1909         ImGui::AlignTextToFramePadding();
1910         ImGui::Text("Normal buttons"); ImGui::SameLine();
1911         ImGui::Button("Banana"); ImGui::SameLine();
1912         ImGui::Button("Apple"); ImGui::SameLine();
1913         ImGui::Button("Corniflower");
1914 
1915         // Button
1916         ImGui::Text("Small buttons"); ImGui::SameLine();
1917         ImGui::SmallButton("Like this one"); ImGui::SameLine();
1918         ImGui::Text("can fit within a text block.");
1919 
1920         // Aligned to arbitrary position. Easy/cheap column.
1921         ImGui::Text("Aligned");
1922         ImGui::SameLine(150); ImGui::Text("x=150");
1923         ImGui::SameLine(300); ImGui::Text("x=300");
1924         ImGui::Text("Aligned");
1925         ImGui::SameLine(150); ImGui::SmallButton("x=150");
1926         ImGui::SameLine(300); ImGui::SmallButton("x=300");
1927 
1928         // Checkbox
1929         static bool c1 = false, c2 = false, c3 = false, c4 = false;
1930         ImGui::Checkbox("My", &c1); ImGui::SameLine();
1931         ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
1932         ImGui::Checkbox("Is", &c3); ImGui::SameLine();
1933         ImGui::Checkbox("Rich", &c4);
1934 
1935         // Various
1936         static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
1937         ImGui::PushItemWidth(80);
1938         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
1939         static int item = -1;
1940         ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
1941         ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
1942         ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
1943         ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
1944         ImGui::PopItemWidth();
1945 
1946         ImGui::PushItemWidth(80);
1947         ImGui::Text("Lists:");
1948         static int selection[4] = { 0, 1, 2, 3 };
1949         for (int i = 0; i < 4; i++)
1950         {
1951             if (i > 0) ImGui::SameLine();
1952             ImGui::PushID(i);
1953             ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
1954             ImGui::PopID();
1955             //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
1956         }
1957         ImGui::PopItemWidth();
1958 
1959         // Dummy
1960         ImVec2 button_sz(40, 40);
1961         ImGui::Button("A", button_sz); ImGui::SameLine();
1962         ImGui::Dummy(button_sz); ImGui::SameLine();
1963         ImGui::Button("B", button_sz);
1964 
1965         // Manually wrapping (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
1966         ImGui::Text("Manually wrapping:");
1967         ImGuiStyle& style = ImGui::GetStyle();
1968         int buttons_count = 20;
1969         float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
1970         for (int n = 0; n < buttons_count; n++)
1971         {
1972             ImGui::PushID(n);
1973             ImGui::Button("Box", button_sz);
1974             float last_button_x2 = ImGui::GetItemRectMax().x;
1975             float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
1976             if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
1977                 ImGui::SameLine();
1978             ImGui::PopID();
1979         }
1980 
1981         ImGui::TreePop();
1982     }
1983 
1984     if (ImGui::TreeNode("Tabs"))
1985     {
1986         if (ImGui::TreeNode("Basic"))
1987         {
1988             ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
1989             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1990             {
1991                 if (ImGui::BeginTabItem("Avocado"))
1992                 {
1993                     ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
1994                     ImGui::EndTabItem();
1995                 }
1996                 if (ImGui::BeginTabItem("Broccoli"))
1997                 {
1998                     ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
1999                     ImGui::EndTabItem();
2000                 }
2001                 if (ImGui::BeginTabItem("Cucumber"))
2002                 {
2003                     ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
2004                     ImGui::EndTabItem();
2005                 }
2006                 ImGui::EndTabBar();
2007             }
2008             ImGui::Separator();
2009             ImGui::TreePop();
2010         }
2011 
2012         if (ImGui::TreeNode("Advanced & Close Button"))
2013         {
2014             // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
2015             static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
2016             ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_Reorderable);
2017             ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
2018             ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
2019             ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
2020             if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
2021                 tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
2022             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
2023                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
2024             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
2025                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
2026 
2027             // Tab Bar
2028             const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
2029             static bool opened[4] = { true, true, true, true }; // Persistent user state
2030             for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
2031             {
2032                 if (n > 0) { ImGui::SameLine(); }
2033                 ImGui::Checkbox(names[n], &opened[n]);
2034             }
2035 
2036             // 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.
2037             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
2038             {
2039                 for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
2040                     if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
2041                     {
2042                         ImGui::Text("This is the %s tab!", names[n]);
2043                         if (n & 1)
2044                             ImGui::Text("I am an odd tab.");
2045                         ImGui::EndTabItem();
2046                     }
2047                 ImGui::EndTabBar();
2048             }
2049             ImGui::Separator();
2050             ImGui::TreePop();
2051         }
2052         ImGui::TreePop();
2053     }
2054 
2055     if (ImGui::TreeNode("Groups"))
2056     {
2057         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.");
2058         ImGui::BeginGroup();
2059         {
2060             ImGui::BeginGroup();
2061             ImGui::Button("AAA");
2062             ImGui::SameLine();
2063             ImGui::Button("BBB");
2064             ImGui::SameLine();
2065             ImGui::BeginGroup();
2066             ImGui::Button("CCC");
2067             ImGui::Button("DDD");
2068             ImGui::EndGroup();
2069             ImGui::SameLine();
2070             ImGui::Button("EEE");
2071             ImGui::EndGroup();
2072             if (ImGui::IsItemHovered())
2073                 ImGui::SetTooltip("First group hovered");
2074         }
2075         // Capture the group size and create widgets using the same size
2076         ImVec2 size = ImGui::GetItemRectSize();
2077         const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
2078         ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
2079 
2080         ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
2081         ImGui::SameLine();
2082         ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
2083         ImGui::EndGroup();
2084         ImGui::SameLine();
2085 
2086         ImGui::Button("LEVERAGE\nBUZZWORD", size);
2087         ImGui::SameLine();
2088 
2089         if (ImGui::ListBoxHeader("List", size))
2090         {
2091             ImGui::Selectable("Selected", true);
2092             ImGui::Selectable("Not Selected", false);
2093             ImGui::ListBoxFooter();
2094         }
2095 
2096         ImGui::TreePop();
2097     }
2098 
2099     if (ImGui::TreeNode("Text Baseline Alignment"))
2100     {
2101         {
2102             ImGui::BulletText("Text baseline:");
2103             ImGui::SameLine();
2104             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.");
2105             ImGui::Indent();
2106 
2107             ImGui::Text("KO Blahblah"); ImGui::SameLine();
2108             ImGui::Button("Some framed item"); ImGui::SameLine();
2109             HelpMarker("Baseline of button will look misaligned with text..");
2110 
2111             // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
2112             // Because we don't know what's coming after the Text() statement, we need to move the text baseline down by FramePadding.y
2113             ImGui::AlignTextToFramePadding();
2114             ImGui::Text("OK Blahblah"); ImGui::SameLine();
2115             ImGui::Button("Some framed item"); ImGui::SameLine();
2116             HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
2117 
2118             // SmallButton() uses the same vertical padding as Text
2119             ImGui::Button("TEST##1"); ImGui::SameLine();
2120             ImGui::Text("TEST"); ImGui::SameLine();
2121             ImGui::SmallButton("TEST##2");
2122 
2123             // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
2124             ImGui::AlignTextToFramePadding();
2125             ImGui::Text("Text aligned to framed item"); ImGui::SameLine();
2126             ImGui::Button("Item##1"); ImGui::SameLine();
2127             ImGui::Text("Item"); ImGui::SameLine();
2128             ImGui::SmallButton("Item##2"); ImGui::SameLine();
2129             ImGui::Button("Item##3");
2130 
2131             ImGui::Unindent();
2132         }
2133 
2134         ImGui::Spacing();
2135 
2136         {
2137             ImGui::BulletText("Multi-line text:");
2138             ImGui::Indent();
2139             ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
2140             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2141             ImGui::Text("Banana");
2142 
2143             ImGui::Text("Banana"); ImGui::SameLine();
2144             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2145             ImGui::Text("One\nTwo\nThree");
2146 
2147             ImGui::Button("HOP##1"); ImGui::SameLine();
2148             ImGui::Text("Banana"); ImGui::SameLine();
2149             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2150             ImGui::Text("Banana");
2151 
2152             ImGui::Button("HOP##2"); ImGui::SameLine();
2153             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
2154             ImGui::Text("Banana");
2155             ImGui::Unindent();
2156         }
2157 
2158         ImGui::Spacing();
2159 
2160         {
2161             ImGui::BulletText("Misc items:");
2162             ImGui::Indent();
2163 
2164             // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button
2165             ImGui::Button("80x80", ImVec2(80, 80));
2166             ImGui::SameLine();
2167             ImGui::Button("50x50", ImVec2(50, 50));
2168             ImGui::SameLine();
2169             ImGui::Button("Button()");
2170             ImGui::SameLine();
2171             ImGui::SmallButton("SmallButton()");
2172 
2173             // Tree
2174             const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
2175             ImGui::Button("Button##1");
2176             ImGui::SameLine(0.0f, spacing);
2177             if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }    // Dummy tree data
2178 
2179             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).
2180             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.
2181             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
2182             if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }   // Dummy tree data
2183 
2184             // Bullet
2185             ImGui::Button("Button##3");
2186             ImGui::SameLine(0.0f, spacing);
2187             ImGui::BulletText("Bullet text");
2188 
2189             ImGui::AlignTextToFramePadding();
2190             ImGui::BulletText("Node");
2191             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
2192             ImGui::Unindent();
2193         }
2194 
2195         ImGui::TreePop();
2196     }
2197 
2198     if (ImGui::TreeNode("Scrolling"))
2199     {
2200         // Vertical scroll functions
2201         HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
2202 
2203         static int track_item = 50;
2204         static bool enable_track = true;
2205         static bool enable_extra_decorations = false;
2206         static float scroll_to_off_px = 0.0f;
2207         static float scroll_to_pos_px = 200.0f;
2208 
2209         ImGui::Checkbox("Decoration", &enable_extra_decorations);
2210         ImGui::SameLine();
2211         HelpMarker("We expose this for testing because scrolling sometimes had issues with window decoration such as menu-bars.");
2212 
2213         ImGui::Checkbox("Track", &enable_track);
2214         ImGui::PushItemWidth(100);
2215         ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
2216 
2217         bool scroll_to_off = ImGui::Button("Scroll Offset");
2218         ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
2219 
2220         bool scroll_to_pos = ImGui::Button("Scroll To Pos");
2221         ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
2222         ImGui::PopItemWidth();
2223 
2224         if (scroll_to_off || scroll_to_pos)
2225             enable_track = false;
2226 
2227         ImGuiStyle& style = ImGui::GetStyle();
2228         float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
2229         if (child_w < 1.0f)
2230             child_w = 1.0f;
2231         ImGui::PushID("##VerticalScrolling");
2232         for (int i = 0; i < 5; i++)
2233         {
2234             if (i > 0) ImGui::SameLine();
2235             ImGui::BeginGroup();
2236             const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
2237             ImGui::TextUnformatted(names[i]);
2238 
2239             ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
2240             bool window_visible = ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(child_w, 200.0f), true, child_flags);
2241             if (ImGui::BeginMenuBar())
2242             {
2243                 ImGui::TextUnformatted("abc");
2244                 ImGui::EndMenuBar();
2245             }
2246             if (scroll_to_off)
2247                 ImGui::SetScrollY(scroll_to_off_px);
2248             if (scroll_to_pos)
2249                 ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
2250             if (window_visible) // Avoid calling SetScrollHereY when running with culled items
2251             {
2252                 for (int item = 0; item < 100; item++)
2253                 {
2254                     if (enable_track && item == track_item)
2255                     {
2256                         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
2257                         ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
2258                     }
2259                     else
2260                     {
2261                         ImGui::Text("Item %d", item);
2262                     }
2263                 }
2264             }
2265             float scroll_y = ImGui::GetScrollY();
2266             float scroll_max_y = ImGui::GetScrollMaxY();
2267             ImGui::EndChild();
2268             ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
2269             ImGui::EndGroup();
2270         }
2271         ImGui::PopID();
2272 
2273         // Horizontal scroll functions
2274         ImGui::Spacing();
2275         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.");
2276         ImGui::PushID("##HorizontalScrolling");
2277         for (int i = 0; i < 5; i++)
2278         {
2279             float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
2280             ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
2281             bool window_visible = ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(-100, child_height), true, child_flags);
2282             if (scroll_to_off)
2283                 ImGui::SetScrollX(scroll_to_off_px);
2284             if (scroll_to_pos)
2285                 ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
2286             if (window_visible) // Avoid calling SetScrollHereY when running with culled items
2287             {
2288                 for (int item = 0; item < 100; item++)
2289                 {
2290                     if (enable_track && item == track_item)
2291                     {
2292                         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
2293                         ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
2294                     }
2295                     else
2296                     {
2297                         ImGui::Text("Item %d", item);
2298                     }
2299                     ImGui::SameLine();
2300                 }
2301             }
2302             float scroll_x = ImGui::GetScrollX();
2303             float scroll_max_x = ImGui::GetScrollMaxX();
2304             ImGui::EndChild();
2305             ImGui::SameLine();
2306             const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
2307             ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
2308             ImGui::Spacing();
2309         }
2310         ImGui::PopID();
2311 
2312         // Miscellaneous Horizontal Scrolling Demo
2313         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().");
2314         static int lines = 7;
2315         ImGui::SliderInt("Lines", &lines, 1, 15);
2316         ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
2317         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
2318         ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
2319         for (int line = 0; line < lines; line++)
2320         {
2321             // 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
2322             // 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)
2323             int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
2324             for (int n = 0; n < num_buttons; n++)
2325             {
2326                 if (n > 0) ImGui::SameLine();
2327                 ImGui::PushID(n + line * 1000);
2328                 char num_buf[16];
2329                 sprintf(num_buf, "%d", n);
2330                 const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf;
2331                 float hue = n*0.05f;
2332                 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
2333                 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
2334                 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
2335                 ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
2336                 ImGui::PopStyleColor(3);
2337                 ImGui::PopID();
2338             }
2339         }
2340         float scroll_x = ImGui::GetScrollX();
2341         float scroll_max_x = ImGui::GetScrollMaxX();
2342         ImGui::EndChild();
2343         ImGui::PopStyleVar(2);
2344         float scroll_x_delta = 0.0f;
2345         ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) { scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; } ImGui::SameLine();
2346         ImGui::Text("Scroll from code"); ImGui::SameLine();
2347         ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) { scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; } ImGui::SameLine();
2348         ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
2349         if (scroll_x_delta != 0.0f)
2350         {
2351             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)
2352             ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
2353             ImGui::EndChild();
2354         }
2355         ImGui::Spacing();
2356 
2357         static bool show_horizontal_contents_size_demo_window = false;
2358         ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
2359 
2360         if (show_horizontal_contents_size_demo_window)
2361         {
2362             static bool show_h_scrollbar = true;
2363             static bool show_button = true;
2364             static bool show_tree_nodes = true;
2365             static bool show_text_wrapped = false;
2366             static bool show_columns = true;
2367             static bool show_tab_bar = true;
2368             static bool show_child = false;
2369             static bool explicit_content_size = false;
2370             static float contents_size_x = 300.0f;
2371             if (explicit_content_size)
2372                 ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
2373             ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
2374             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
2375             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
2376             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.");
2377             ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
2378             ImGui::Checkbox("Button", &show_button);            // Will grow contents size (unless explicitly overwritten)
2379             ImGui::Checkbox("Tree nodes", &show_tree_nodes);    // Will grow contents size and display highlight over full width
2380             ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
2381             ImGui::Checkbox("Columns", &show_columns);          // Will use contents size
2382             ImGui::Checkbox("Tab bar", &show_tab_bar);          // Will use contents size
2383             ImGui::Checkbox("Child", &show_child);              // Will grow and use contents size
2384             ImGui::Checkbox("Explicit content size", &explicit_content_size);
2385             ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
2386             if (explicit_content_size)
2387             {
2388                 ImGui::SameLine();
2389                 ImGui::SetNextItemWidth(100);
2390                 ImGui::DragFloat("##csx", &contents_size_x);
2391                 ImVec2 p = ImGui::GetCursorScreenPos();
2392                 ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
2393                 ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
2394                 ImGui::Dummy(ImVec2(0, 10));
2395             }
2396             ImGui::PopStyleVar(2);
2397             ImGui::Separator();
2398             if (show_button)
2399             {
2400                 ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
2401             }
2402             if (show_tree_nodes)
2403             {
2404                 bool open = true;
2405                 if (ImGui::TreeNode("this is a tree node"))
2406                 {
2407                     if (ImGui::TreeNode("another one of those tree node..."))
2408                     {
2409                         ImGui::Text("Some tree contents");
2410                         ImGui::TreePop();
2411                     }
2412                     ImGui::TreePop();
2413                 }
2414                 ImGui::CollapsingHeader("CollapsingHeader", &open);
2415             }
2416             if (show_text_wrapped)
2417             {
2418                 ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
2419             }
2420             if (show_columns)
2421             {
2422                 ImGui::Columns(4);
2423                 for (int n = 0; n < 4; n++)
2424                 {
2425                     ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
2426                     ImGui::NextColumn();
2427                 }
2428                 ImGui::Columns(1);
2429             }
2430             if (show_tab_bar && ImGui::BeginTabBar("Hello"))
2431             {
2432                 if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
2433                 if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
2434                 if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
2435                 if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
2436                 ImGui::EndTabBar();
2437             }
2438             if (show_child)
2439             {
2440                 ImGui::BeginChild("child", ImVec2(0,0), true);
2441                 ImGui::EndChild();
2442             }
2443             ImGui::End();
2444         }
2445 
2446         ImGui::TreePop();
2447     }
2448 
2449     if (ImGui::TreeNode("Clipping"))
2450     {
2451         static ImVec2 size(100, 100), offset(50, 20);
2452         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.");
2453         ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
2454         ImGui::TextWrapped("(Click and drag)");
2455         ImVec2 pos = ImGui::GetCursorScreenPos();
2456         ImVec4 clip_rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y);
2457         ImGui::InvisibleButton("##dummy", size);
2458         if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0)) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
2459         ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(90, 90, 120, 255));
2460         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);
2461         ImGui::TreePop();
2462     }
2463 }
2464 
ShowDemoWindowPopups()2465 static void ShowDemoWindowPopups()
2466 {
2467     if (!ImGui::CollapsingHeader("Popups & Modal windows"))
2468         return;
2469 
2470     // The properties of popups windows are:
2471     // - They block normal mouse hovering detection outside them. (*)
2472     // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
2473     // - 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.
2474     //   User can manipulate the visibility state by calling OpenPopup().
2475     // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup.
2476     // Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time.
2477 
2478     // Typical use for regular windows:
2479     //   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();
2480     // Typical use for popups:
2481     //   if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
2482 
2483     // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
2484     // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
2485 
2486     if (ImGui::TreeNode("Popups"))
2487     {
2488         ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
2489 
2490         static int selected_fish = -1;
2491         const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
2492         static bool toggles[] = { true, false, false, false, false };
2493 
2494         // Simple selection popup
2495         // (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)
2496         if (ImGui::Button("Select.."))
2497             ImGui::OpenPopup("my_select_popup");
2498         ImGui::SameLine();
2499         ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
2500         if (ImGui::BeginPopup("my_select_popup"))
2501         {
2502             ImGui::Text("Aquarium");
2503             ImGui::Separator();
2504             for (int i = 0; i < IM_ARRAYSIZE(names); i++)
2505                 if (ImGui::Selectable(names[i]))
2506                     selected_fish = i;
2507             ImGui::EndPopup();
2508         }
2509 
2510         // Showing a menu with toggles
2511         if (ImGui::Button("Toggle.."))
2512             ImGui::OpenPopup("my_toggle_popup");
2513         if (ImGui::BeginPopup("my_toggle_popup"))
2514         {
2515             for (int i = 0; i < IM_ARRAYSIZE(names); i++)
2516                 ImGui::MenuItem(names[i], "", &toggles[i]);
2517             if (ImGui::BeginMenu("Sub-menu"))
2518             {
2519                 ImGui::MenuItem("Click me");
2520                 ImGui::EndMenu();
2521             }
2522 
2523             ImGui::Separator();
2524             ImGui::Text("Tooltip here");
2525             if (ImGui::IsItemHovered())
2526                 ImGui::SetTooltip("I am a tooltip over a popup");
2527 
2528             if (ImGui::Button("Stacked Popup"))
2529                 ImGui::OpenPopup("another popup");
2530             if (ImGui::BeginPopup("another popup"))
2531             {
2532                 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
2533                     ImGui::MenuItem(names[i], "", &toggles[i]);
2534                 if (ImGui::BeginMenu("Sub-menu"))
2535                 {
2536                     ImGui::MenuItem("Click me");
2537                     if (ImGui::Button("Stacked Popup"))
2538                         ImGui::OpenPopup("another popup");
2539                     if (ImGui::BeginPopup("another popup"))
2540                     {
2541                         ImGui::Text("I am the last one here.");
2542                         ImGui::EndPopup();
2543                     }
2544                     ImGui::EndMenu();
2545                 }
2546                 ImGui::EndPopup();
2547             }
2548             ImGui::EndPopup();
2549         }
2550 
2551         // Call the more complete ShowExampleMenuFile which we use in various places of this demo
2552         if (ImGui::Button("File Menu.."))
2553             ImGui::OpenPopup("my_file_popup");
2554         if (ImGui::BeginPopup("my_file_popup"))
2555         {
2556             ShowExampleMenuFile();
2557             ImGui::EndPopup();
2558         }
2559 
2560         ImGui::TreePop();
2561     }
2562 
2563     if (ImGui::TreeNode("Context menus"))
2564     {
2565         // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
2566         //    if (IsItemHovered() && IsMouseReleased(0))
2567         //       OpenPopup(id);
2568         //    return BeginPopup(id);
2569         // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
2570         static float value = 0.5f;
2571         ImGui::Text("Value = %.3f (<-- right-click here)", value);
2572         if (ImGui::BeginPopupContextItem("item context menu"))
2573         {
2574             if (ImGui::Selectable("Set to zero")) value = 0.0f;
2575             if (ImGui::Selectable("Set to PI")) value = 3.1415f;
2576             ImGui::SetNextItemWidth(-1);
2577             ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
2578             ImGui::EndPopup();
2579         }
2580 
2581         // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the Begin call.
2582         // 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.
2583         ImGui::Text("(You can also right-click me to open the same popup as above.)");
2584         ImGui::OpenPopupOnItemClick("item context menu", 1);
2585 
2586         // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
2587         // BeginPopupContextItem() will use the last item ID as the popup ID.
2588         // 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)
2589         static char name[32] = "Label1";
2590         char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
2591         ImGui::Button(buf);
2592         if (ImGui::BeginPopupContextItem())
2593         {
2594             ImGui::Text("Edit name:");
2595             ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
2596             if (ImGui::Button("Close"))
2597                 ImGui::CloseCurrentPopup();
2598             ImGui::EndPopup();
2599         }
2600         ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
2601 
2602         ImGui::TreePop();
2603     }
2604 
2605     if (ImGui::TreeNode("Modals"))
2606     {
2607         ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
2608 
2609         if (ImGui::Button("Delete.."))
2610             ImGui::OpenPopup("Delete?");
2611 
2612         if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
2613         {
2614             ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
2615             ImGui::Separator();
2616 
2617             //static int dummy_i = 0;
2618             //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
2619 
2620             static bool dont_ask_me_next_time = false;
2621             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
2622             ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
2623             ImGui::PopStyleVar();
2624 
2625             if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
2626             ImGui::SetItemDefaultFocus();
2627             ImGui::SameLine();
2628             if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
2629             ImGui::EndPopup();
2630         }
2631 
2632         if (ImGui::Button("Stacked modals.."))
2633             ImGui::OpenPopup("Stacked 1");
2634         if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
2635         {
2636             if (ImGui::BeginMenuBar())
2637             {
2638                 if (ImGui::BeginMenu("File"))
2639                 {
2640                     if (ImGui::MenuItem("Dummy menu item")) {}
2641                     ImGui::EndMenu();
2642                 }
2643                 ImGui::EndMenuBar();
2644             }
2645             ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
2646 
2647             // Testing behavior of widgets stacking their own regular popups over the modal.
2648             static int item = 1;
2649             static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
2650             ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
2651             ImGui::ColorEdit4("color", color);
2652 
2653             if (ImGui::Button("Add another modal.."))
2654                 ImGui::OpenPopup("Stacked 2");
2655 
2656             // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which will close the popup.
2657             // Note that the visibility state of popups is owned by imgui, so the input value of the bool actually doesn't matter here.
2658             bool dummy_open = true;
2659             if (ImGui::BeginPopupModal("Stacked 2", &dummy_open))
2660             {
2661                 ImGui::Text("Hello from Stacked The Second!");
2662                 if (ImGui::Button("Close"))
2663                     ImGui::CloseCurrentPopup();
2664                 ImGui::EndPopup();
2665             }
2666 
2667             if (ImGui::Button("Close"))
2668                 ImGui::CloseCurrentPopup();
2669             ImGui::EndPopup();
2670         }
2671 
2672         ImGui::TreePop();
2673     }
2674 
2675     if (ImGui::TreeNode("Menus inside a regular window"))
2676     {
2677         ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
2678         ImGui::Separator();
2679         // 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.
2680         // 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
2681         // 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.
2682         ImGui::PushID("foo");
2683         ImGui::MenuItem("Menu item", "CTRL+M");
2684         if (ImGui::BeginMenu("Menu inside a regular window"))
2685         {
2686             ShowExampleMenuFile();
2687             ImGui::EndMenu();
2688         }
2689         ImGui::PopID();
2690         ImGui::Separator();
2691         ImGui::TreePop();
2692     }
2693 }
2694 
ShowDemoWindowColumns()2695 static void ShowDemoWindowColumns()
2696 {
2697     if (!ImGui::CollapsingHeader("Columns"))
2698         return;
2699 
2700     ImGui::PushID("Columns");
2701 
2702     static bool disable_indent = false;
2703     ImGui::Checkbox("Disable tree indentation", &disable_indent);
2704     ImGui::SameLine();
2705     HelpMarker("Disable the indenting of tree nodes so demo columns can use the full window width.");
2706     if (disable_indent)
2707         ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
2708 
2709     // Basic columns
2710     if (ImGui::TreeNode("Basic"))
2711     {
2712         ImGui::Text("Without border:");
2713         ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
2714         ImGui::Separator();
2715         for (int n = 0; n < 14; n++)
2716         {
2717             char label[32];
2718             sprintf(label, "Item %d", n);
2719             if (ImGui::Selectable(label)) {}
2720             //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {}
2721             ImGui::NextColumn();
2722         }
2723         ImGui::Columns(1);
2724         ImGui::Separator();
2725 
2726         ImGui::Text("With border:");
2727         ImGui::Columns(4, "mycolumns"); // 4-ways, with border
2728         ImGui::Separator();
2729         ImGui::Text("ID"); ImGui::NextColumn();
2730         ImGui::Text("Name"); ImGui::NextColumn();
2731         ImGui::Text("Path"); ImGui::NextColumn();
2732         ImGui::Text("Hovered"); ImGui::NextColumn();
2733         ImGui::Separator();
2734         const char* names[3] = { "One", "Two", "Three" };
2735         const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
2736         static int selected = -1;
2737         for (int i = 0; i < 3; i++)
2738         {
2739             char label[32];
2740             sprintf(label, "%04d", i);
2741             if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
2742                 selected = i;
2743             bool hovered = ImGui::IsItemHovered();
2744             ImGui::NextColumn();
2745             ImGui::Text(names[i]); ImGui::NextColumn();
2746             ImGui::Text(paths[i]); ImGui::NextColumn();
2747             ImGui::Text("%d", hovered); ImGui::NextColumn();
2748         }
2749         ImGui::Columns(1);
2750         ImGui::Separator();
2751         ImGui::TreePop();
2752     }
2753 
2754     if (ImGui::TreeNode("Borders"))
2755     {
2756         // NB: Future columns API should allow automatic horizontal borders.
2757         static bool h_borders = true;
2758         static bool v_borders = true;
2759         static int columns_count = 4;
2760         const int lines_count = 3;
2761         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
2762         ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns");
2763         if (columns_count < 2)
2764             columns_count = 2;
2765         ImGui::SameLine();
2766         ImGui::Checkbox("horizontal", &h_borders);
2767         ImGui::SameLine();
2768         ImGui::Checkbox("vertical", &v_borders);
2769         ImGui::Columns(columns_count, NULL, v_borders);
2770         for (int i = 0; i < columns_count * lines_count; i++)
2771         {
2772             if (h_borders && ImGui::GetColumnIndex() == 0)
2773                 ImGui::Separator();
2774             ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
2775             ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
2776             ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
2777             ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
2778             ImGui::Text("Long text that is likely to clip");
2779             ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f));
2780             ImGui::NextColumn();
2781         }
2782         ImGui::Columns(1);
2783         if (h_borders)
2784             ImGui::Separator();
2785         ImGui::TreePop();
2786     }
2787 
2788     // Create multiple items in a same cell before switching to next column
2789     if (ImGui::TreeNode("Mixed items"))
2790     {
2791         ImGui::Columns(3, "mixed");
2792         ImGui::Separator();
2793 
2794         ImGui::Text("Hello");
2795         ImGui::Button("Banana");
2796         ImGui::NextColumn();
2797 
2798         ImGui::Text("ImGui");
2799         ImGui::Button("Apple");
2800         static float foo = 1.0f;
2801         ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
2802         ImGui::Text("An extra line here.");
2803         ImGui::NextColumn();
2804 
2805         ImGui::Text("Sailor");
2806         ImGui::Button("Corniflower");
2807         static float bar = 1.0f;
2808         ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
2809         ImGui::NextColumn();
2810 
2811         if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2812         if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2813         if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2814         ImGui::Columns(1);
2815         ImGui::Separator();
2816         ImGui::TreePop();
2817     }
2818 
2819     // Word wrapping
2820     if (ImGui::TreeNode("Word-wrapping"))
2821     {
2822         ImGui::Columns(2, "word-wrapping");
2823         ImGui::Separator();
2824         ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2825         ImGui::TextWrapped("Hello Left");
2826         ImGui::NextColumn();
2827         ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2828         ImGui::TextWrapped("Hello Right");
2829         ImGui::Columns(1);
2830         ImGui::Separator();
2831         ImGui::TreePop();
2832     }
2833 
2834     // Scrolling columns
2835     /*
2836     if (ImGui::TreeNode("Vertical Scrolling"))
2837     {
2838         ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
2839         ImGui::Columns(3);
2840         ImGui::Text("ID"); ImGui::NextColumn();
2841         ImGui::Text("Name"); ImGui::NextColumn();
2842         ImGui::Text("Path"); ImGui::NextColumn();
2843         ImGui::Columns(1);
2844         ImGui::Separator();
2845         ImGui::EndChild();
2846         ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
2847         ImGui::Columns(3);
2848         for (int i = 0; i < 10; i++)
2849         {
2850             ImGui::Text("%04d", i); ImGui::NextColumn();
2851             ImGui::Text("Foobar"); ImGui::NextColumn();
2852             ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
2853         }
2854         ImGui::Columns(1);
2855         ImGui::EndChild();
2856         ImGui::TreePop();
2857     }
2858     */
2859 
2860     if (ImGui::TreeNode("Horizontal Scrolling"))
2861     {
2862         ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
2863         ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
2864         ImGui::Columns(10);
2865         int ITEMS_COUNT = 2000;
2866         ImGuiListClipper clipper(ITEMS_COUNT);  // Also demonstrate using the clipper for large list
2867         while (clipper.Step())
2868         {
2869             for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
2870                 for (int j = 0; j < 10; j++)
2871                 {
2872                     ImGui::Text("Line %d Column %d...", i, j);
2873                     ImGui::NextColumn();
2874                 }
2875         }
2876         ImGui::Columns(1);
2877         ImGui::EndChild();
2878         ImGui::TreePop();
2879     }
2880 
2881     if (ImGui::TreeNode("Tree"))
2882     {
2883         ImGui::Columns(2, "tree", true);
2884         for (int x = 0; x < 3; x++)
2885         {
2886             bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x);
2887             ImGui::NextColumn();
2888             ImGui::Text("Node contents");
2889             ImGui::NextColumn();
2890             if (open1)
2891             {
2892                 for (int y = 0; y < 3; y++)
2893                 {
2894                     bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y);
2895                     ImGui::NextColumn();
2896                     ImGui::Text("Node contents");
2897                     if (open2)
2898                     {
2899                         ImGui::Text("Even more contents");
2900                         if (ImGui::TreeNode("Tree in column"))
2901                         {
2902                             ImGui::Text("The quick brown fox jumps over the lazy dog");
2903                             ImGui::TreePop();
2904                         }
2905                     }
2906                     ImGui::NextColumn();
2907                     if (open2)
2908                         ImGui::TreePop();
2909                 }
2910                 ImGui::TreePop();
2911             }
2912         }
2913         ImGui::Columns(1);
2914         ImGui::TreePop();
2915     }
2916 
2917     if (disable_indent)
2918         ImGui::PopStyleVar();
2919     ImGui::PopID();
2920 }
2921 
ShowDemoWindowMisc()2922 static void ShowDemoWindowMisc()
2923 {
2924     if (ImGui::CollapsingHeader("Filtering"))
2925     {
2926         // Helper class to easy setup a text filter.
2927         // You may want to implement a more feature-full filtering scheme in your own application.
2928         static ImGuiTextFilter filter;
2929         ImGui::Text("Filter usage:\n"
2930                     "  \"\"         display all lines\n"
2931                     "  \"xxx\"      display lines containing \"xxx\"\n"
2932                     "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
2933                     "  \"-xxx\"     hide lines containing \"xxx\"");
2934         filter.Draw();
2935         const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
2936         for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
2937             if (filter.PassFilter(lines[i]))
2938                 ImGui::BulletText("%s", lines[i]);
2939     }
2940 
2941     if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
2942     {
2943         ImGuiIO& io = ImGui::GetIO();
2944 
2945         // Display ImGuiIO output flags
2946         ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
2947         ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
2948         ImGui::Text("WantTextInput: %d", io.WantTextInput);
2949         ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
2950         ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
2951 
2952         // Display Keyboard/Mouse state
2953         if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
2954         {
2955             if (ImGui::IsMousePosValid())
2956                 ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
2957             else
2958                 ImGui::Text("Mouse pos: <INVALID>");
2959             ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
2960             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]); }
2961             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); }
2962             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); }
2963             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); }
2964             ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
2965 
2966             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]); }
2967             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); }
2968             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); }
2969             ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
2970             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.
2971 
2972             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]); }
2973             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); }
2974             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]); }
2975 
2976             ImGui::Button("Hovering me sets the\nkeyboard capture flag");
2977             if (ImGui::IsItemHovered())
2978                 ImGui::CaptureKeyboardFromApp(true);
2979             ImGui::SameLine();
2980             ImGui::Button("Holding me clears the\nthe keyboard capture flag");
2981             if (ImGui::IsItemActive())
2982                 ImGui::CaptureKeyboardFromApp(false);
2983 
2984             ImGui::TreePop();
2985         }
2986 
2987         if (ImGui::TreeNode("Tabbing"))
2988         {
2989             ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
2990             static char buf[32] = "dummy";
2991             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
2992             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
2993             ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
2994             ImGui::PushAllowKeyboardFocus(false);
2995             ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
2996             //ImGui::SameLine(); HelpMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
2997             ImGui::PopAllowKeyboardFocus();
2998             ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
2999             ImGui::TreePop();
3000         }
3001 
3002         if (ImGui::TreeNode("Focus from code"))
3003         {
3004             bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
3005             bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
3006             bool focus_3 = ImGui::Button("Focus on 3");
3007             int has_focus = 0;
3008             static char buf[128] = "click on a button to set focus";
3009 
3010             if (focus_1) ImGui::SetKeyboardFocusHere();
3011             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
3012             if (ImGui::IsItemActive()) has_focus = 1;
3013 
3014             if (focus_2) ImGui::SetKeyboardFocusHere();
3015             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
3016             if (ImGui::IsItemActive()) has_focus = 2;
3017 
3018             ImGui::PushAllowKeyboardFocus(false);
3019             if (focus_3) ImGui::SetKeyboardFocusHere();
3020             ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
3021             if (ImGui::IsItemActive()) has_focus = 3;
3022             ImGui::PopAllowKeyboardFocus();
3023 
3024             if (has_focus)
3025                 ImGui::Text("Item with focus: %d", has_focus);
3026             else
3027                 ImGui::Text("Item with focus: <none>");
3028 
3029             // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
3030             static float f3[3] = { 0.0f, 0.0f, 0.0f };
3031             int focus_ahead = -1;
3032             if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
3033             if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
3034             if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
3035             if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
3036             ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
3037 
3038             ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
3039             ImGui::TreePop();
3040         }
3041 
3042         if (ImGui::TreeNode("Dragging"))
3043         {
3044             ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
3045             for (int button = 0; button < 3; button++)
3046                 ImGui::Text("IsMouseDragging(%d):\n  w/ default threshold: %d,\n  w/ zero threshold: %d\n  w/ large threshold: %d",
3047                     button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
3048 
3049             ImGui::Button("Drag Me");
3050             if (ImGui::IsItemActive())
3051                 ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor
3052 
3053             // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
3054             // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
3055             ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
3056             ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
3057             ImVec2 mouse_delta = io.MouseDelta;
3058             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);
3059             ImGui::TreePop();
3060         }
3061 
3062         if (ImGui::TreeNode("Mouse cursors"))
3063         {
3064             const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" };
3065             IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
3066 
3067             ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
3068             ImGui::Text("Hover to see mouse cursors:");
3069             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.");
3070             for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
3071             {
3072                 char label[32];
3073                 sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
3074                 ImGui::Bullet(); ImGui::Selectable(label, false);
3075                 if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
3076                     ImGui::SetMouseCursor(i);
3077             }
3078             ImGui::TreePop();
3079         }
3080     }
3081 }
3082 
3083 //-----------------------------------------------------------------------------
3084 // [SECTION] About Window / ShowAboutWindow()
3085 // Access from Dear ImGui Demo -> Tools -> About
3086 //-----------------------------------------------------------------------------
3087 
ShowAboutWindow(bool * p_open)3088 void ImGui::ShowAboutWindow(bool* p_open)
3089 {
3090     if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
3091     {
3092         ImGui::End();
3093         return;
3094     }
3095     ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
3096     ImGui::Separator();
3097     ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
3098     ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
3099 
3100     static bool show_config_info = false;
3101     ImGui::Checkbox("Config/Build Information", &show_config_info);
3102     if (show_config_info)
3103     {
3104         ImGuiIO& io = ImGui::GetIO();
3105         ImGuiStyle& style = ImGui::GetStyle();
3106 
3107         bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
3108         ImGui::BeginChildFrame(ImGui::GetID("cfginfos"), ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18), ImGuiWindowFlags_NoMove);
3109         if (copy_to_clipboard)
3110         {
3111             ImGui::LogToClipboard();
3112             ImGui::LogText("```\n"); // Back quotes will make the text appears without formatting when pasting to GitHub
3113         }
3114 
3115         ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
3116         ImGui::Separator();
3117         ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
3118         ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
3119 #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
3120         ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
3121 #endif
3122 #ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
3123         ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
3124 #endif
3125 #ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
3126         ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
3127 #endif
3128 #ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
3129         ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
3130 #endif
3131 #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
3132         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS");
3133 #endif
3134 #ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
3135         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS");
3136 #endif
3137 #ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
3138         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS");
3139 #endif
3140 #ifdef IMGUI_DISABLE_FILE_FUNCTIONS
3141         ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS");
3142 #endif
3143 #ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
3144         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
3145 #endif
3146 #ifdef IMGUI_USE_BGRA_PACKED_COLOR
3147         ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
3148 #endif
3149 #ifdef _WIN32
3150         ImGui::Text("define: _WIN32");
3151 #endif
3152 #ifdef _WIN64
3153         ImGui::Text("define: _WIN64");
3154 #endif
3155 #ifdef __linux__
3156         ImGui::Text("define: __linux__");
3157 #endif
3158 #ifdef __APPLE__
3159         ImGui::Text("define: __APPLE__");
3160 #endif
3161 #ifdef _MSC_VER
3162         ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
3163 #endif
3164 #ifdef __MINGW32__
3165         ImGui::Text("define: __MINGW32__");
3166 #endif
3167 #ifdef __MINGW64__
3168         ImGui::Text("define: __MINGW64__");
3169 #endif
3170 #ifdef __GNUC__
3171         ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
3172 #endif
3173 #ifdef __clang_version__
3174         ImGui::Text("define: __clang_version__=%s", __clang_version__);
3175 #endif
3176         ImGui::Separator();
3177         ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
3178         ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
3179         ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
3180         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)        ImGui::Text(" NavEnableKeyboard");
3181         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
3182         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)     ImGui::Text(" NavEnableSetMousePos");
3183         if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)     ImGui::Text(" NavNoCaptureKeyboard");
3184         if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
3185         if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
3186         if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
3187         if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
3188         if (io.ConfigInputTextCursorBlink)                              ImGui::Text("io.ConfigInputTextCursorBlink");
3189         if (io.ConfigWindowsResizeFromEdges)                            ImGui::Text("io.ConfigWindowsResizeFromEdges");
3190         if (io.ConfigWindowsMoveFromTitleBarOnly)                       ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
3191         if (io.ConfigWindowsMemoryCompactTimer >= 0.0f)                 ImGui::Text("io.ConfigWindowsMemoryCompactTimer = %.1ff", io.ConfigWindowsMemoryCompactTimer);
3192         ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
3193         if (io.BackendFlags & ImGuiBackendFlags_HasGamepad)             ImGui::Text(" HasGamepad");
3194         if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)        ImGui::Text(" HasMouseCursors");
3195         if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)         ImGui::Text(" HasSetMousePos");
3196         if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)   ImGui::Text(" RendererHasVtxOffset");
3197         ImGui::Separator();
3198         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);
3199         ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
3200         ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
3201         ImGui::Separator();
3202         ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
3203         ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
3204         ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
3205         ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
3206         ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
3207         ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
3208         ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
3209 
3210         if (copy_to_clipboard)
3211         {
3212             ImGui::LogText("\n```\n");
3213             ImGui::LogFinish();
3214         }
3215         ImGui::EndChildFrame();
3216     }
3217     ImGui::End();
3218 }
3219 
3220 //-----------------------------------------------------------------------------
3221 // [SECTION] Style Editor / ShowStyleEditor()
3222 //-----------------------------------------------------------------------------
3223 // - ShowStyleSelector()
3224 // - ShowFontSelector()
3225 // - ShowStyleEditor()
3226 //-----------------------------------------------------------------------------
3227 
3228 // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
3229 // 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)3230 bool ImGui::ShowStyleSelector(const char* label)
3231 {
3232     static int style_idx = -1;
3233     if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
3234     {
3235         switch (style_idx)
3236         {
3237         case 0: ImGui::StyleColorsClassic(); break;
3238         case 1: ImGui::StyleColorsDark(); break;
3239         case 2: ImGui::StyleColorsLight(); break;
3240         }
3241         return true;
3242     }
3243     return false;
3244 }
3245 
3246 // Demo helper function to select among loaded fonts.
3247 // Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
ShowFontSelector(const char * label)3248 void ImGui::ShowFontSelector(const char* label)
3249 {
3250     ImGuiIO& io = ImGui::GetIO();
3251     ImFont* font_current = ImGui::GetFont();
3252     if (ImGui::BeginCombo(label, font_current->GetDebugName()))
3253     {
3254         for (int n = 0; n < io.Fonts->Fonts.Size; n++)
3255         {
3256             ImFont* font = io.Fonts->Fonts[n];
3257             ImGui::PushID((void*)font);
3258             if (ImGui::Selectable(font->GetDebugName(), font == font_current))
3259                 io.FontDefault = font;
3260             ImGui::PopID();
3261         }
3262         ImGui::EndCombo();
3263     }
3264     ImGui::SameLine();
3265     HelpMarker(
3266         "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
3267         "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
3268         "- Read FAQ and docs/FONTS.txt for more details.\n"
3269         "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
3270 }
3271 
ShowStyleEditor(ImGuiStyle * ref)3272 void ImGui::ShowStyleEditor(ImGuiStyle* ref)
3273 {
3274     // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
3275     ImGuiStyle& style = ImGui::GetStyle();
3276     static ImGuiStyle ref_saved_style;
3277 
3278     // Default to using internal storage as reference
3279     static bool init = true;
3280     if (init && ref == NULL)
3281         ref_saved_style = style;
3282     init = false;
3283     if (ref == NULL)
3284         ref = &ref_saved_style;
3285 
3286     ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
3287 
3288     if (ImGui::ShowStyleSelector("Colors##Selector"))
3289         ref_saved_style = style;
3290     ImGui::ShowFontSelector("Fonts##Selector");
3291 
3292     // Simplified Settings
3293     if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
3294         style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
3295     { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
3296     ImGui::SameLine();
3297     { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
3298     ImGui::SameLine();
3299     { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
3300 
3301     // Save/Revert button
3302     if (ImGui::Button("Save Ref"))
3303         *ref = ref_saved_style = style;
3304     ImGui::SameLine();
3305     if (ImGui::Button("Revert Ref"))
3306         style = *ref;
3307     ImGui::SameLine();
3308     HelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export\" below to save them somewhere.");
3309 
3310     ImGui::Separator();
3311 
3312     if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
3313     {
3314         if (ImGui::BeginTabItem("Sizes"))
3315         {
3316             ImGui::Text("Main");
3317             ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
3318             ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
3319             ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
3320             ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
3321             ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
3322             ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
3323             ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
3324             ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
3325             ImGui::Text("Borders");
3326             ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
3327             ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
3328             ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
3329             ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
3330             ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
3331             ImGui::Text("Rounding");
3332             ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
3333             ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
3334             ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
3335             ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
3336             ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
3337             ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
3338             ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
3339             ImGui::Text("Alignment");
3340             ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
3341             int window_menu_button_position = style.WindowMenuButtonPosition + 1;
3342             if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
3343                 style.WindowMenuButtonPosition = window_menu_button_position - 1;
3344             ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
3345             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.");
3346             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.");
3347             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).");
3348             ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
3349             ImGui::EndTabItem();
3350         }
3351 
3352         if (ImGui::BeginTabItem("Colors"))
3353         {
3354             static int output_dest = 0;
3355             static bool output_only_modified = true;
3356             if (ImGui::Button("Export"))
3357             {
3358                 if (output_dest == 0)
3359                     ImGui::LogToClipboard();
3360                 else
3361                     ImGui::LogToTTY();
3362                 ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
3363                 for (int i = 0; i < ImGuiCol_COUNT; i++)
3364                 {
3365                     const ImVec4& col = style.Colors[i];
3366                     const char* name = ImGui::GetStyleColorName(i);
3367                     if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
3368                         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);
3369                 }
3370                 ImGui::LogFinish();
3371             }
3372             ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
3373             ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
3374 
3375             static ImGuiTextFilter filter;
3376             filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
3377 
3378             static ImGuiColorEditFlags alpha_flags = 0;
3379             if (ImGui::RadioButton("Opaque", alpha_flags == 0))                                     { alpha_flags = 0; } ImGui::SameLine();
3380             if (ImGui::RadioButton("Alpha",  alpha_flags == ImGuiColorEditFlags_AlphaPreview))      { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
3381             if (ImGui::RadioButton("Both",   alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf))  { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
3382             HelpMarker("In the color list:\nLeft-click on colored square to open color picker,\nRight-click to open edit options menu.");
3383 
3384             ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
3385             ImGui::PushItemWidth(-160);
3386             for (int i = 0; i < ImGuiCol_COUNT; i++)
3387             {
3388                 const char* name = ImGui::GetStyleColorName(i);
3389                 if (!filter.PassFilter(name))
3390                     continue;
3391                 ImGui::PushID(i);
3392                 ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
3393                 if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
3394                 {
3395                     // 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.
3396                     // Read the FAQ and docs/FONTS.txt about using icon fonts. It's really easy and super convenient!
3397                     ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
3398                     ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
3399                 }
3400                 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
3401                 ImGui::TextUnformatted(name);
3402                 ImGui::PopID();
3403             }
3404             ImGui::PopItemWidth();
3405             ImGui::EndChild();
3406 
3407             ImGui::EndTabItem();
3408         }
3409 
3410         if (ImGui::BeginTabItem("Fonts"))
3411         {
3412             ImGuiIO& io = ImGui::GetIO();
3413             ImFontAtlas* atlas = io.Fonts;
3414             HelpMarker("Read FAQ and docs/FONTS.txt for details on font loading.");
3415             ImGui::PushItemWidth(120);
3416             for (int i = 0; i < atlas->Fonts.Size; i++)
3417             {
3418                 ImFont* font = atlas->Fonts[i];
3419                 ImGui::PushID(font);
3420                 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);
3421                 ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { io.FontDefault = font; }
3422                 if (font_details_opened)
3423                 {
3424                     ImGui::PushFont(font);
3425                     ImGui::Text("The quick brown fox jumps over the lazy dog");
3426                     ImGui::PopFont();
3427                     ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");   // Scale only this font
3428                     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.)");
3429                     ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f");
3430                     ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
3431                     ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar);
3432                     ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar, font->EllipsisChar);
3433                     const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface);
3434                     ImGui::Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt);
3435                     for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
3436                         if (font->ConfigData)
3437                             if (const ImFontConfig* cfg = &font->ConfigData[config_i])
3438                                 ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
3439                     if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
3440                     {
3441                         // Display all glyphs of the fonts in separate pages of 256 characters
3442                         for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
3443                         {
3444                             int count = 0;
3445                             for (unsigned int n = 0; n < 256; n++)
3446                                 count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0;
3447                             if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
3448                             {
3449                                 float cell_size = font->FontSize * 1;
3450                                 float cell_spacing = style.ItemSpacing.y;
3451                                 ImVec2 base_pos = ImGui::GetCursorScreenPos();
3452                                 ImDrawList* draw_list = ImGui::GetWindowDrawList();
3453                                 for (unsigned int n = 0; n < 256; n++)
3454                                 {
3455                                     ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
3456                                     ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
3457                                     const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
3458                                     draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
3459                                     if (glyph)
3460                                         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.
3461                                     if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
3462                                     {
3463                                         ImGui::BeginTooltip();
3464                                         ImGui::Text("Codepoint: U+%04X", base + n);
3465                                         ImGui::Separator();
3466                                         ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
3467                                         ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
3468                                         ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
3469                                         ImGui::EndTooltip();
3470                                     }
3471                                 }
3472                                 ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
3473                                 ImGui::TreePop();
3474                             }
3475                         }
3476                         ImGui::TreePop();
3477                     }
3478                     ImGui::TreePop();
3479                 }
3480                 ImGui::PopID();
3481             }
3482             if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
3483             {
3484                 ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
3485                 ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
3486                 ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), tint_col, border_col);
3487                 ImGui::TreePop();
3488             }
3489 
3490             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.");
3491             static float window_scale = 1.0f;
3492             if (ImGui::DragFloat("window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.2f"))   // scale only this window
3493                 ImGui::SetWindowFontScale(window_scale);
3494             ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.2f");      // scale everything
3495             ImGui::PopItemWidth();
3496 
3497             ImGui::EndTabItem();
3498         }
3499 
3500         if (ImGui::BeginTabItem("Rendering"))
3501         {
3502             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.");
3503             ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
3504             ImGui::PushItemWidth(100);
3505             ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
3506             if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
3507             ImGui::DragFloat("Circle segment Max Error", &style.CircleSegmentMaxError, 0.01f, 0.10f, 10.0f, "%.2f");
3508             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.
3509             ImGui::PopItemWidth();
3510 
3511             ImGui::EndTabItem();
3512         }
3513 
3514         ImGui::EndTabBar();
3515     }
3516 
3517     ImGui::PopItemWidth();
3518 }
3519 
3520 //-----------------------------------------------------------------------------
3521 // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
3522 //-----------------------------------------------------------------------------
3523 // - ShowExampleAppMainMenuBar()
3524 // - ShowExampleMenuFile()
3525 //-----------------------------------------------------------------------------
3526 
3527 // Demonstrate creating a "main" fullscreen menu bar and populating it.
3528 // Note the difference between BeginMainMenuBar() and BeginMenuBar():
3529 // - BeginMenuBar() = menu-bar inside current window we Begin()-ed into (the window needs the ImGuiWindowFlags_MenuBar flag)
3530 // - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it.
ShowExampleAppMainMenuBar()3531 static void ShowExampleAppMainMenuBar()
3532 {
3533     if (ImGui::BeginMainMenuBar())
3534     {
3535         if (ImGui::BeginMenu("File"))
3536         {
3537             ShowExampleMenuFile();
3538             ImGui::EndMenu();
3539         }
3540         if (ImGui::BeginMenu("Edit"))
3541         {
3542             if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
3543             if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
3544             ImGui::Separator();
3545             if (ImGui::MenuItem("Cut", "CTRL+X")) {}
3546             if (ImGui::MenuItem("Copy", "CTRL+C")) {}
3547             if (ImGui::MenuItem("Paste", "CTRL+V")) {}
3548             ImGui::EndMenu();
3549         }
3550         ImGui::EndMainMenuBar();
3551     }
3552 }
3553 
3554 // Note that shortcuts are currently provided for display only (future version will add flags to BeginMenu to process shortcuts)
ShowExampleMenuFile()3555 static void ShowExampleMenuFile()
3556 {
3557     ImGui::MenuItem("(dummy menu)", NULL, false, false);
3558     if (ImGui::MenuItem("New")) {}
3559     if (ImGui::MenuItem("Open", "Ctrl+O")) {}
3560     if (ImGui::BeginMenu("Open Recent"))
3561     {
3562         ImGui::MenuItem("fish_hat.c");
3563         ImGui::MenuItem("fish_hat.inl");
3564         ImGui::MenuItem("fish_hat.h");
3565         if (ImGui::BeginMenu("More.."))
3566         {
3567             ImGui::MenuItem("Hello");
3568             ImGui::MenuItem("Sailor");
3569             if (ImGui::BeginMenu("Recurse.."))
3570             {
3571                 ShowExampleMenuFile();
3572                 ImGui::EndMenu();
3573             }
3574             ImGui::EndMenu();
3575         }
3576         ImGui::EndMenu();
3577     }
3578     if (ImGui::MenuItem("Save", "Ctrl+S")) {}
3579     if (ImGui::MenuItem("Save As..")) {}
3580     ImGui::Separator();
3581     if (ImGui::BeginMenu("Options"))
3582     {
3583         static bool enabled = true;
3584         ImGui::MenuItem("Enabled", "", &enabled);
3585         ImGui::BeginChild("child", ImVec2(0, 60), true);
3586         for (int i = 0; i < 10; i++)
3587             ImGui::Text("Scrolling Text %d", i);
3588         ImGui::EndChild();
3589         static float f = 0.5f;
3590         static int n = 0;
3591         static bool b = true;
3592         ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
3593         ImGui::InputFloat("Input", &f, 0.1f);
3594         ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
3595         ImGui::Checkbox("Check", &b);
3596         ImGui::EndMenu();
3597     }
3598     if (ImGui::BeginMenu("Colors"))
3599     {
3600         float sz = ImGui::GetTextLineHeight();
3601         for (int i = 0; i < ImGuiCol_COUNT; i++)
3602         {
3603             const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
3604             ImVec2 p = ImGui::GetCursorScreenPos();
3605             ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i));
3606             ImGui::Dummy(ImVec2(sz, sz));
3607             ImGui::SameLine();
3608             ImGui::MenuItem(name);
3609         }
3610         ImGui::EndMenu();
3611     }
3612     if (ImGui::BeginMenu("Disabled", false)) // Disabled
3613     {
3614         IM_ASSERT(0);
3615     }
3616     if (ImGui::MenuItem("Checked", NULL, true)) {}
3617     if (ImGui::MenuItem("Quit", "Alt+F4")) {}
3618 }
3619 
3620 //-----------------------------------------------------------------------------
3621 // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
3622 //-----------------------------------------------------------------------------
3623 
3624 // Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
3625 // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
3626 struct ExampleAppConsole
3627 {
3628     char                  InputBuf[256];
3629     ImVector<char*>       Items;
3630     ImVector<const char*> Commands;
3631     ImVector<char*>       History;
3632     int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
3633     ImGuiTextFilter       Filter;
3634     bool                  AutoScroll;
3635     bool                  ScrollToBottom;
3636 
ExampleAppConsoleExampleAppConsole3637     ExampleAppConsole()
3638     {
3639         ClearLog();
3640         memset(InputBuf, 0, sizeof(InputBuf));
3641         HistoryPos = -1;
3642         Commands.push_back("HELP");
3643         Commands.push_back("HISTORY");
3644         Commands.push_back("CLEAR");
3645         Commands.push_back("CLASSIFY");  // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
3646         AutoScroll = true;
3647         ScrollToBottom = false;
3648         AddLog("Welcome to Dear ImGui!");
3649     }
~ExampleAppConsoleExampleAppConsole3650     ~ExampleAppConsole()
3651     {
3652         ClearLog();
3653         for (int i = 0; i < History.Size; i++)
3654             free(History[i]);
3655     }
3656 
3657     // Portable helpers
StricmpExampleAppConsole3658     static int   Stricmp(const char* str1, const char* str2)         { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
StrnicmpExampleAppConsole3659     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; }
StrdupExampleAppConsole3660     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); }
StrtrimExampleAppConsole3661     static void  Strtrim(char* str)                                  { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; }
3662 
ClearLogExampleAppConsole3663     void    ClearLog()
3664     {
3665         for (int i = 0; i < Items.Size; i++)
3666             free(Items[i]);
3667         Items.clear();
3668     }
3669 
AddLogExampleAppConsole3670     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
3671     {
3672         // FIXME-OPT
3673         char buf[1024];
3674         va_list args;
3675         va_start(args, fmt);
3676         vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
3677         buf[IM_ARRAYSIZE(buf)-1] = 0;
3678         va_end(args);
3679         Items.push_back(Strdup(buf));
3680     }
3681 
DrawExampleAppConsole3682     void    Draw(const char* title, bool* p_open)
3683     {
3684         ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
3685         if (!ImGui::Begin(title, p_open))
3686         {
3687             ImGui::End();
3688             return;
3689         }
3690 
3691         // 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.
3692         // Here we create a context menu only available from the title bar.
3693         if (ImGui::BeginPopupContextItem())
3694         {
3695             if (ImGui::MenuItem("Close Console"))
3696                 *p_open = false;
3697             ImGui::EndPopup();
3698         }
3699 
3700         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.");
3701         ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
3702 
3703         // TODO: display items starting from the bottom
3704 
3705         if (ImGui::SmallButton("Add Dummy Text"))  { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
3706         if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
3707         if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
3708         bool copy_to_clipboard = ImGui::SmallButton("Copy");
3709         //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
3710 
3711         ImGui::Separator();
3712 
3713         // Options menu
3714         if (ImGui::BeginPopup("Options"))
3715         {
3716             ImGui::Checkbox("Auto-scroll", &AutoScroll);
3717             ImGui::EndPopup();
3718         }
3719 
3720         // Options, Filter
3721         if (ImGui::Button("Options"))
3722             ImGui::OpenPopup("Options");
3723         ImGui::SameLine();
3724         Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
3725         ImGui::Separator();
3726 
3727         const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
3728         ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText
3729         if (ImGui::BeginPopupContextWindow())
3730         {
3731             if (ImGui::Selectable("Clear")) ClearLog();
3732             ImGui::EndPopup();
3733         }
3734 
3735         // 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());
3736         // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
3737         // 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.
3738         // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
3739         //     ImGuiListClipper clipper(Items.Size);
3740         //     while (clipper.Step())
3741         //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
3742         // 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.
3743         // 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,
3744         // 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!
3745         // 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.
3746         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
3747         if (copy_to_clipboard)
3748             ImGui::LogToClipboard();
3749         for (int i = 0; i < Items.Size; i++)
3750         {
3751             const char* item = Items[i];
3752             if (!Filter.PassFilter(item))
3753                 continue;
3754 
3755             // Normally you would store more information in your item (e.g. make Items[] an array of structure, store color/type etc.)
3756             bool pop_color = false;
3757             if (strstr(item, "[error]"))            { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f)); pop_color = true; }
3758             else if (strncmp(item, "# ", 2) == 0)   { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.6f, 1.0f)); pop_color = true; }
3759             ImGui::TextUnformatted(item);
3760             if (pop_color)
3761                 ImGui::PopStyleColor();
3762         }
3763         if (copy_to_clipboard)
3764             ImGui::LogFinish();
3765 
3766         if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
3767             ImGui::SetScrollHereY(1.0f);
3768         ScrollToBottom = false;
3769 
3770         ImGui::PopStyleVar();
3771         ImGui::EndChild();
3772         ImGui::Separator();
3773 
3774         // Command-line
3775         bool reclaim_focus = false;
3776         if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
3777         {
3778             char* s = InputBuf;
3779             Strtrim(s);
3780             if (s[0])
3781                 ExecCommand(s);
3782             strcpy(s, "");
3783             reclaim_focus = true;
3784         }
3785 
3786         // Auto-focus on window apparition
3787         ImGui::SetItemDefaultFocus();
3788         if (reclaim_focus)
3789             ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
3790 
3791         ImGui::End();
3792     }
3793 
ExecCommandExampleAppConsole3794     void    ExecCommand(const char* command_line)
3795     {
3796         AddLog("# %s\n", command_line);
3797 
3798         // 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.
3799         HistoryPos = -1;
3800         for (int i = History.Size-1; i >= 0; i--)
3801             if (Stricmp(History[i], command_line) == 0)
3802             {
3803                 free(History[i]);
3804                 History.erase(History.begin() + i);
3805                 break;
3806             }
3807         History.push_back(Strdup(command_line));
3808 
3809         // Process command
3810         if (Stricmp(command_line, "CLEAR") == 0)
3811         {
3812             ClearLog();
3813         }
3814         else if (Stricmp(command_line, "HELP") == 0)
3815         {
3816             AddLog("Commands:");
3817             for (int i = 0; i < Commands.Size; i++)
3818                 AddLog("- %s", Commands[i]);
3819         }
3820         else if (Stricmp(command_line, "HISTORY") == 0)
3821         {
3822             int first = History.Size - 10;
3823             for (int i = first > 0 ? first : 0; i < History.Size; i++)
3824                 AddLog("%3d: %s\n", i, History[i]);
3825         }
3826         else
3827         {
3828             AddLog("Unknown command: '%s'\n", command_line);
3829         }
3830 
3831         // On commad input, we scroll to bottom even if AutoScroll==false
3832         ScrollToBottom = true;
3833     }
3834 
TextEditCallbackStubExampleAppConsole3835     static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
3836     {
3837         ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
3838         return console->TextEditCallback(data);
3839     }
3840 
TextEditCallbackExampleAppConsole3841     int     TextEditCallback(ImGuiInputTextCallbackData* data)
3842     {
3843         //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
3844         switch (data->EventFlag)
3845         {
3846         case ImGuiInputTextFlags_CallbackCompletion:
3847             {
3848                 // Example of TEXT COMPLETION
3849 
3850                 // Locate beginning of current word
3851                 const char* word_end = data->Buf + data->CursorPos;
3852                 const char* word_start = word_end;
3853                 while (word_start > data->Buf)
3854                 {
3855                     const char c = word_start[-1];
3856                     if (c == ' ' || c == '\t' || c == ',' || c == ';')
3857                         break;
3858                     word_start--;
3859                 }
3860 
3861                 // Build a list of candidates
3862                 ImVector<const char*> candidates;
3863                 for (int i = 0; i < Commands.Size; i++)
3864                     if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
3865                         candidates.push_back(Commands[i]);
3866 
3867                 if (candidates.Size == 0)
3868                 {
3869                     // No match
3870                     AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
3871                 }
3872                 else if (candidates.Size == 1)
3873                 {
3874                     // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
3875                     data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
3876                     data->InsertChars(data->CursorPos, candidates[0]);
3877                     data->InsertChars(data->CursorPos, " ");
3878                 }
3879                 else
3880                 {
3881                     // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
3882                     int match_len = (int)(word_end - word_start);
3883                     for (;;)
3884                     {
3885                         int c = 0;
3886                         bool all_candidates_matches = true;
3887                         for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
3888                             if (i == 0)
3889                                 c = toupper(candidates[i][match_len]);
3890                             else if (c == 0 || c != toupper(candidates[i][match_len]))
3891                                 all_candidates_matches = false;
3892                         if (!all_candidates_matches)
3893                             break;
3894                         match_len++;
3895                     }
3896 
3897                     if (match_len > 0)
3898                     {
3899                         data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
3900                         data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
3901                     }
3902 
3903                     // List matches
3904                     AddLog("Possible matches:\n");
3905                     for (int i = 0; i < candidates.Size; i++)
3906                         AddLog("- %s\n", candidates[i]);
3907                 }
3908 
3909                 break;
3910             }
3911         case ImGuiInputTextFlags_CallbackHistory:
3912             {
3913                 // Example of HISTORY
3914                 const int prev_history_pos = HistoryPos;
3915                 if (data->EventKey == ImGuiKey_UpArrow)
3916                 {
3917                     if (HistoryPos == -1)
3918                         HistoryPos = History.Size - 1;
3919                     else if (HistoryPos > 0)
3920                         HistoryPos--;
3921                 }
3922                 else if (data->EventKey == ImGuiKey_DownArrow)
3923                 {
3924                     if (HistoryPos != -1)
3925                         if (++HistoryPos >= History.Size)
3926                             HistoryPos = -1;
3927                 }
3928 
3929                 // A better implementation would preserve the data on the current input line along with cursor position.
3930                 if (prev_history_pos != HistoryPos)
3931                 {
3932                     const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
3933                     data->DeleteChars(0, data->BufTextLen);
3934                     data->InsertChars(0, history_str);
3935                 }
3936             }
3937         }
3938         return 0;
3939     }
3940 };
3941 
ShowExampleAppConsole(bool * p_open)3942 static void ShowExampleAppConsole(bool* p_open)
3943 {
3944     static ExampleAppConsole console;
3945     console.Draw("Example: Console", p_open);
3946 }
3947 
3948 //-----------------------------------------------------------------------------
3949 // [SECTION] Example App: Debug Log / ShowExampleAppLog()
3950 //-----------------------------------------------------------------------------
3951 
3952 // Usage:
3953 //  static ExampleAppLog my_log;
3954 //  my_log.AddLog("Hello %d world\n", 123);
3955 //  my_log.Draw("title");
3956 struct ExampleAppLog
3957 {
3958     ImGuiTextBuffer     Buf;
3959     ImGuiTextFilter     Filter;
3960     ImVector<int>       LineOffsets;        // Index to lines offset. We maintain this with AddLog() calls, allowing us to have a random access on lines
3961     bool                AutoScroll;     // Keep scrolling if already at the bottom
3962 
ExampleAppLogExampleAppLog3963     ExampleAppLog()
3964     {
3965         AutoScroll = true;
3966         Clear();
3967     }
3968 
ClearExampleAppLog3969     void    Clear()
3970     {
3971         Buf.clear();
3972         LineOffsets.clear();
3973         LineOffsets.push_back(0);
3974     }
3975 
AddLogExampleAppLog3976     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
3977     {
3978         int old_size = Buf.size();
3979         va_list args;
3980         va_start(args, fmt);
3981         Buf.appendfv(fmt, args);
3982         va_end(args);
3983         for (int new_size = Buf.size(); old_size < new_size; old_size++)
3984             if (Buf[old_size] == '\n')
3985                 LineOffsets.push_back(old_size + 1);
3986     }
3987 
DrawExampleAppLog3988     void    Draw(const char* title, bool* p_open = NULL)
3989     {
3990         if (!ImGui::Begin(title, p_open))
3991         {
3992             ImGui::End();
3993             return;
3994         }
3995 
3996         // Options menu
3997         if (ImGui::BeginPopup("Options"))
3998         {
3999             ImGui::Checkbox("Auto-scroll", &AutoScroll);
4000             ImGui::EndPopup();
4001         }
4002 
4003         // Main window
4004         if (ImGui::Button("Options"))
4005             ImGui::OpenPopup("Options");
4006         ImGui::SameLine();
4007         bool clear = ImGui::Button("Clear");
4008         ImGui::SameLine();
4009         bool copy = ImGui::Button("Copy");
4010         ImGui::SameLine();
4011         Filter.Draw("Filter", -100.0f);
4012 
4013         ImGui::Separator();
4014         ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
4015 
4016         if (clear)
4017             Clear();
4018         if (copy)
4019             ImGui::LogToClipboard();
4020 
4021         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
4022         const char* buf = Buf.begin();
4023         const char* buf_end = Buf.end();
4024         if (Filter.IsActive())
4025         {
4026             // In this example we don't use the clipper when Filter is enabled.
4027             // This is because we don't have a random access on the result on our filter.
4028             // A real application processing logs with ten of thousands of entries may want to store the result of search/filter.
4029             // especially if the filtering function is not trivial (e.g. reg-exp).
4030             for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
4031             {
4032                 const char* line_start = buf + LineOffsets[line_no];
4033                 const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
4034                 if (Filter.PassFilter(line_start, line_end))
4035                     ImGui::TextUnformatted(line_start, line_end);
4036             }
4037         }
4038         else
4039         {
4040             // The simplest and easy way to display the entire buffer:
4041             //   ImGui::TextUnformatted(buf_begin, buf_end);
4042             // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward to skip non-visible lines.
4043             // Here we instead demonstrate using the clipper to only process lines that are within the visible area.
4044             // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them on your side is recommended.
4045             // Using ImGuiListClipper requires A) random access into your data, and B) items all being the  same height,
4046             // both of which we can handle since we an array pointing to the beginning of each line of text.
4047             // 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.
4048             // 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)
4049             ImGuiListClipper clipper;
4050             clipper.Begin(LineOffsets.Size);
4051             while (clipper.Step())
4052             {
4053                 for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; 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                     ImGui::TextUnformatted(line_start, line_end);
4058                 }
4059             }
4060             clipper.End();
4061         }
4062         ImGui::PopStyleVar();
4063 
4064         if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
4065             ImGui::SetScrollHereY(1.0f);
4066 
4067         ImGui::EndChild();
4068         ImGui::End();
4069     }
4070 };
4071 
4072 // Demonstrate creating a simple log window with basic filtering.
ShowExampleAppLog(bool * p_open)4073 static void ShowExampleAppLog(bool* p_open)
4074 {
4075     static ExampleAppLog log;
4076 
4077     // For the demo: add a debug button _BEFORE_ the normal log window contents
4078     // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
4079     // Most of the contents of the window will be added by the log.Draw() call.
4080     ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
4081     ImGui::Begin("Example: Log", p_open);
4082     if (ImGui::SmallButton("[Debug] Add 5 entries"))
4083     {
4084         static int counter = 0;
4085         for (int n = 0; n < 5; n++)
4086         {
4087             const char* categories[3] = { "info", "warn", "error" };
4088             const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
4089             log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
4090                 ImGui::GetFrameCount(), categories[counter % IM_ARRAYSIZE(categories)], ImGui::GetTime(), words[counter % IM_ARRAYSIZE(words)]);
4091             counter++;
4092         }
4093     }
4094     ImGui::End();
4095 
4096     // Actually call in the regular Log helper (which will Begin() into the same window as we just did)
4097     log.Draw("Example: Log", p_open);
4098 }
4099 
4100 //-----------------------------------------------------------------------------
4101 // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
4102 //-----------------------------------------------------------------------------
4103 
4104 // Demonstrate create a window with multiple child windows.
ShowExampleAppLayout(bool * p_open)4105 static void ShowExampleAppLayout(bool* p_open)
4106 {
4107     ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
4108     if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
4109     {
4110         if (ImGui::BeginMenuBar())
4111         {
4112             if (ImGui::BeginMenu("File"))
4113             {
4114                 if (ImGui::MenuItem("Close")) *p_open = false;
4115                 ImGui::EndMenu();
4116             }
4117             ImGui::EndMenuBar();
4118         }
4119 
4120         // left
4121         static int selected = 0;
4122         ImGui::BeginChild("left pane", ImVec2(150, 0), true);
4123         for (int i = 0; i < 100; i++)
4124         {
4125             char label[128];
4126             sprintf(label, "MyObject %d", i);
4127             if (ImGui::Selectable(label, selected == i))
4128                 selected = i;
4129         }
4130         ImGui::EndChild();
4131         ImGui::SameLine();
4132 
4133         // right
4134         ImGui::BeginGroup();
4135             ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
4136                 ImGui::Text("MyObject: %d", selected);
4137                 ImGui::Separator();
4138                 if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
4139                 {
4140                     if (ImGui::BeginTabItem("Description"))
4141                     {
4142                         ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
4143                         ImGui::EndTabItem();
4144                     }
4145                     if (ImGui::BeginTabItem("Details"))
4146                     {
4147                         ImGui::Text("ID: 0123456789");
4148                         ImGui::EndTabItem();
4149                     }
4150                     ImGui::EndTabBar();
4151                 }
4152             ImGui::EndChild();
4153             if (ImGui::Button("Revert")) {}
4154             ImGui::SameLine();
4155             if (ImGui::Button("Save")) {}
4156         ImGui::EndGroup();
4157     }
4158     ImGui::End();
4159 }
4160 
4161 //-----------------------------------------------------------------------------
4162 // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
4163 //-----------------------------------------------------------------------------
4164 
4165 // Demonstrate create a simple property editor.
ShowExampleAppPropertyEditor(bool * p_open)4166 static void ShowExampleAppPropertyEditor(bool* p_open)
4167 {
4168     ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
4169     if (!ImGui::Begin("Example: Property editor", p_open))
4170     {
4171         ImGui::End();
4172         return;
4173     }
4174 
4175     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.");
4176 
4177     ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
4178     ImGui::Columns(2);
4179     ImGui::Separator();
4180 
4181     struct funcs
4182     {
4183         static void ShowDummyObject(const char* prefix, int uid)
4184         {
4185             ImGui::PushID(uid);                      // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
4186             ImGui::AlignTextToFramePadding();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
4187             bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
4188             ImGui::NextColumn();
4189             ImGui::AlignTextToFramePadding();
4190             ImGui::Text("my sailor is rich");
4191             ImGui::NextColumn();
4192             if (node_open)
4193             {
4194                 static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
4195                 for (int i = 0; i < 8; i++)
4196                 {
4197                     ImGui::PushID(i); // Use field index as identifier.
4198                     if (i < 2)
4199                     {
4200                         ShowDummyObject("Child", 424242);
4201                     }
4202                     else
4203                     {
4204                         // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
4205                         ImGui::AlignTextToFramePadding();
4206                         ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i);
4207                         ImGui::NextColumn();
4208                         ImGui::SetNextItemWidth(-1);
4209                         if (i >= 5)
4210                             ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
4211                         else
4212                             ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
4213                         ImGui::NextColumn();
4214                     }
4215                     ImGui::PopID();
4216                 }
4217                 ImGui::TreePop();
4218             }
4219             ImGui::PopID();
4220         }
4221     };
4222 
4223     // Iterate dummy objects with dummy members (all the same data)
4224     for (int obj_i = 0; obj_i < 3; obj_i++)
4225         funcs::ShowDummyObject("Object", obj_i);
4226 
4227     ImGui::Columns(1);
4228     ImGui::Separator();
4229     ImGui::PopStyleVar();
4230     ImGui::End();
4231 }
4232 
4233 //-----------------------------------------------------------------------------
4234 // [SECTION] Example App: Long Text / ShowExampleAppLongText()
4235 //-----------------------------------------------------------------------------
4236 
4237 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
ShowExampleAppLongText(bool * p_open)4238 static void ShowExampleAppLongText(bool* p_open)
4239 {
4240     ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
4241     if (!ImGui::Begin("Example: Long text display", p_open))
4242     {
4243         ImGui::End();
4244         return;
4245     }
4246 
4247     static int test_type = 0;
4248     static ImGuiTextBuffer log;
4249     static int lines = 0;
4250     ImGui::Text("Printing unusually long amount of text.");
4251     ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped\0Multiple calls to Text(), not clipped (slow)\0");
4252     ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
4253     if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
4254     ImGui::SameLine();
4255     if (ImGui::Button("Add 1000 lines"))
4256     {
4257         for (int i = 0; i < 1000; i++)
4258             log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
4259         lines += 1000;
4260     }
4261     ImGui::BeginChild("Log");
4262     switch (test_type)
4263     {
4264     case 0:
4265         // Single call to TextUnformatted() with a big buffer
4266         ImGui::TextUnformatted(log.begin(), log.end());
4267         break;
4268     case 1:
4269         {
4270             // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
4271             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
4272             ImGuiListClipper clipper(lines);
4273             while (clipper.Step())
4274                 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
4275                     ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
4276             ImGui::PopStyleVar();
4277             break;
4278         }
4279     case 2:
4280         // Multiple calls to Text(), not clipped (slow)
4281         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
4282         for (int i = 0; i < lines; i++)
4283             ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
4284         ImGui::PopStyleVar();
4285         break;
4286     }
4287     ImGui::EndChild();
4288     ImGui::End();
4289 }
4290 
4291 //-----------------------------------------------------------------------------
4292 // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
4293 //-----------------------------------------------------------------------------
4294 
4295 // Demonstrate creating a window which gets auto-resized according to its content.
ShowExampleAppAutoResize(bool * p_open)4296 static void ShowExampleAppAutoResize(bool* p_open)
4297 {
4298     if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
4299     {
4300         ImGui::End();
4301         return;
4302     }
4303 
4304     static int lines = 10;
4305     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.");
4306     ImGui::SliderInt("Number of lines", &lines, 1, 20);
4307     for (int i = 0; i < lines; i++)
4308         ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
4309     ImGui::End();
4310 }
4311 
4312 //-----------------------------------------------------------------------------
4313 // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
4314 //-----------------------------------------------------------------------------
4315 
4316 // Demonstrate creating a window with custom resize constraints.
ShowExampleAppConstrainedResize(bool * p_open)4317 static void ShowExampleAppConstrainedResize(bool* p_open)
4318 {
4319     struct CustomConstraints // Helper functions to demonstrate programmatic constraints
4320     {
4321         static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = (data->DesiredSize.x > data->DesiredSize.y ? data->DesiredSize.x : data->DesiredSize.y); }
4322         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); }
4323     };
4324 
4325     static bool auto_resize = false;
4326     static int type = 0;
4327     static int display_lines = 10;
4328     if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Vertical only
4329     if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Horizontal only
4330     if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
4331     if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width 400-500
4332     if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, 500));          // Height 400-500
4333     if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);                     // Always Square
4334     if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
4335 
4336     ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
4337     if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
4338     {
4339         const char* desc[] =
4340         {
4341             "Resize vertical only",
4342             "Resize horizontal only",
4343             "Width > 100, Height > 100",
4344             "Width 400-500",
4345             "Height 400-500",
4346             "Custom: Always Square",
4347             "Custom: Fixed Steps (100)",
4348         };
4349         if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
4350         if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
4351         if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
4352         ImGui::SetNextItemWidth(200);
4353         ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
4354         ImGui::SetNextItemWidth(200);
4355         ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
4356         ImGui::Checkbox("Auto-resize", &auto_resize);
4357         for (int i = 0; i < display_lines; i++)
4358             ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
4359     }
4360     ImGui::End();
4361 }
4362 
4363 //-----------------------------------------------------------------------------
4364 // [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
4365 //-----------------------------------------------------------------------------
4366 
4367 // 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)4368 static void ShowExampleAppSimpleOverlay(bool* p_open)
4369 {
4370     const float DISTANCE = 10.0f;
4371     static int corner = 0;
4372     ImGuiIO& io = ImGui::GetIO();
4373     if (corner != -1)
4374     {
4375         ImVec2 window_pos = ImVec2((corner & 1) ? io.DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? io.DisplaySize.y - DISTANCE : DISTANCE);
4376         ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
4377         ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
4378     }
4379     ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
4380     if (ImGui::Begin("Example: Simple overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
4381     {
4382         ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
4383         ImGui::Separator();
4384         if (ImGui::IsMousePosValid())
4385             ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
4386         else
4387             ImGui::Text("Mouse Position: <invalid>");
4388         if (ImGui::BeginPopupContextWindow())
4389         {
4390             if (ImGui::MenuItem("Custom",       NULL, corner == -1)) corner = -1;
4391             if (ImGui::MenuItem("Top-left",     NULL, corner == 0)) corner = 0;
4392             if (ImGui::MenuItem("Top-right",    NULL, corner == 1)) corner = 1;
4393             if (ImGui::MenuItem("Bottom-left",  NULL, corner == 2)) corner = 2;
4394             if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
4395             if (p_open && ImGui::MenuItem("Close")) *p_open = false;
4396             ImGui::EndPopup();
4397         }
4398     }
4399     ImGui::End();
4400 }
4401 
4402 //-----------------------------------------------------------------------------
4403 // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
4404 //-----------------------------------------------------------------------------
4405 
4406 // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
4407 // 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 *)4408 static void ShowExampleAppWindowTitles(bool*)
4409 {
4410     // By default, Windows are uniquely identified by their title.
4411     // You can use the "##" and "###" markers to manipulate the display/ID.
4412 
4413     // Using "##" to display same title but have unique identifier.
4414     ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
4415     ImGui::Begin("Same title as another window##1");
4416     ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
4417     ImGui::End();
4418 
4419     ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
4420     ImGui::Begin("Same title as another window##2");
4421     ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
4422     ImGui::End();
4423 
4424     // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
4425     char buf[128];
4426     sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
4427     ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
4428     ImGui::Begin(buf);
4429     ImGui::Text("This window has a changing title.");
4430     ImGui::End();
4431 }
4432 
4433 //-----------------------------------------------------------------------------
4434 // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
4435 //-----------------------------------------------------------------------------
4436 
4437 // Demonstrate using the low-level ImDrawList to draw custom shapes.
ShowExampleAppCustomRendering(bool * p_open)4438 static void ShowExampleAppCustomRendering(bool* p_open)
4439 {
4440     if (!ImGui::Begin("Example: Custom rendering", p_open))
4441     {
4442         ImGui::End();
4443         return;
4444     }
4445 
4446     // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
4447     // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
4448     // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
4449     // In this example we are not using the maths operators!
4450     ImDrawList* draw_list = ImGui::GetWindowDrawList();
4451 
4452     if (ImGui::BeginTabBar("##TabBar"))
4453     {
4454         // Primitives
4455         if (ImGui::BeginTabItem("Primitives"))
4456         {
4457             static float sz = 36.0f;
4458             static float thickness = 3.0f;
4459             static int ngon_sides = 6;
4460             static bool circle_segments_override = false;
4461             static int circle_segments_override_v = 12;
4462             static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
4463             ImGui::PushItemWidth(-ImGui::GetFontSize() * 10);
4464             ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
4465             ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
4466             ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
4467             ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
4468             ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
4469             if (ImGui::SliderInt("Circle segments", &circle_segments_override_v, 3, 40))
4470                 circle_segments_override = true;
4471             ImGui::ColorEdit4("Color", &colf.x);
4472             ImGui::PopItemWidth();
4473             const ImVec2 p = ImGui::GetCursorScreenPos();
4474             const ImU32 col = ImColor(colf);
4475             const float spacing = 10.0f;
4476             const ImDrawCornerFlags corners_none = 0;
4477             const ImDrawCornerFlags corners_all = ImDrawCornerFlags_All;
4478             const ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight;
4479             const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
4480             float x = p.x + 4.0f, y = p.y + 4.0f;
4481             for (int n = 0; n < 2; n++)
4482             {
4483                 // First line uses a thickness of 1.0f, second line uses the configurable thickness
4484                 float th = (n == 0) ? 1.0f : thickness;
4485                 draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th);         x += sz + spacing;  // N-gon
4486                 draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th);  x += sz + spacing;  // Circle
4487                 draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f,  corners_none, th);     x += sz + spacing;  // Square
4488                 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
4489                 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
4490                 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
4491                 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
4492                 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!)
4493                 draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th);                               x += spacing;       // Vertical line (note: drawing a filled rectangle will be faster!)
4494                 draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th);                          x += sz + spacing;  // Diagonal line
4495                 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);
4496                 x = p.x + 4;
4497                 y += sz + spacing;
4498             }
4499             draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides);   x += sz + spacing;  // N-gon
4500             draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments);x += sz + spacing;  // Circle
4501             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col);                        x += sz + spacing;  // Square
4502             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f);                 x += sz + spacing;  // Square with all rounded corners
4503             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
4504             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
4505             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
4506             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)
4507             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)
4508             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col);                          x += sz;            // Pixel (faster than AddLine)
4509             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));
4510             ImGui::Dummy(ImVec2((sz + spacing) * 9.8f, (sz + spacing) * 3));
4511             ImGui::EndTabItem();
4512         }
4513 
4514         if (ImGui::BeginTabItem("Canvas"))
4515         {
4516             static ImVector<ImVec2> points;
4517             static bool adding_line = false;
4518             if (ImGui::Button("Clear")) points.clear();
4519             if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
4520             ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
4521 
4522             // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
4523             // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
4524             // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
4525             ImVec2 canvas_pos = ImGui::GetCursorScreenPos();            // ImDrawList API uses screen coordinates!
4526             ImVec2 canvas_size = ImGui::GetContentRegionAvail();        // Resize canvas to what's available
4527             if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
4528             if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
4529             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));
4530             draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255));
4531 
4532             bool adding_preview = false;
4533             ImGui::InvisibleButton("canvas", canvas_size);
4534             ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
4535             if (adding_line)
4536             {
4537                 adding_preview = true;
4538                 points.push_back(mouse_pos_in_canvas);
4539                 if (!ImGui::IsMouseDown(0))
4540                     adding_line = adding_preview = false;
4541             }
4542             if (ImGui::IsItemHovered())
4543             {
4544                 if (!adding_line && ImGui::IsMouseClicked(0))
4545                 {
4546                     points.push_back(mouse_pos_in_canvas);
4547                     adding_line = true;
4548                 }
4549                 if (ImGui::IsMouseClicked(1) && !points.empty())
4550                 {
4551                     adding_line = adding_preview = false;
4552                     points.pop_back();
4553                     points.pop_back();
4554                 }
4555             }
4556             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.)
4557             for (int i = 0; i < points.Size - 1; i += 2)
4558                 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);
4559             draw_list->PopClipRect();
4560             if (adding_preview)
4561                 points.pop_back();
4562             ImGui::EndTabItem();
4563         }
4564 
4565         if (ImGui::BeginTabItem("BG/FG draw lists"))
4566         {
4567             static bool draw_bg = true;
4568             static bool draw_fg = true;
4569             ImGui::Checkbox("Draw in Background draw list", &draw_bg);
4570             ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows.");
4571             ImGui::Checkbox("Draw in Foreground draw list", &draw_fg);
4572             ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows.");
4573             ImVec2 window_pos = ImGui::GetWindowPos();
4574             ImVec2 window_size = ImGui::GetWindowSize();
4575             ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
4576             if (draw_bg)
4577                 ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 48, 10+4);
4578             if (draw_fg)
4579                 ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 48, 10);
4580             ImGui::EndTabItem();
4581         }
4582 
4583         ImGui::EndTabBar();
4584     }
4585 
4586     ImGui::End();
4587 }
4588 
4589 //-----------------------------------------------------------------------------
4590 // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
4591 //-----------------------------------------------------------------------------
4592 
4593 // Simplified structure to mimic a Document model
4594 struct MyDocument
4595 {
4596     const char* Name;           // Document title
4597     bool        Open;           // Set when the document is open (in this demo, we keep an array of all available documents to simplify the demo)
4598     bool        OpenPrev;       // Copy of Open from last update.
4599     bool        Dirty;          // Set when the document has been modified
4600     bool        WantClose;      // Set when the document
4601     ImVec4      Color;          // An arbitrary variable associated to the document
4602 
MyDocumentMyDocument4603     MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f,1.0f,1.0f,1.0f))
4604     {
4605         Name = name;
4606         Open = OpenPrev = open;
4607         Dirty = false;
4608         WantClose = false;
4609         Color = color;
4610     }
DoOpenMyDocument4611     void DoOpen()       { Open = true; }
DoQueueCloseMyDocument4612     void DoQueueClose() { WantClose = true; }
DoForceCloseMyDocument4613     void DoForceClose() { Open = false; Dirty = false; }
DoSaveMyDocument4614     void DoSave()       { Dirty = false; }
4615 
4616     // Display dummy contents for the Document
DisplayContentsMyDocument4617     static void DisplayContents(MyDocument* doc)
4618     {
4619         ImGui::PushID(doc);
4620         ImGui::Text("Document \"%s\"", doc->Name);
4621         ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
4622         ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
4623         ImGui::PopStyleColor();
4624         if (ImGui::Button("Modify", ImVec2(100, 0)))
4625             doc->Dirty = true;
4626         ImGui::SameLine();
4627         if (ImGui::Button("Save", ImVec2(100, 0)))
4628             doc->DoSave();
4629         ImGui::ColorEdit3("color", &doc->Color.x);  // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
4630         ImGui::PopID();
4631     }
4632 
4633     // Display context menu for the Document
DisplayContextMenuMyDocument4634     static void DisplayContextMenu(MyDocument* doc)
4635     {
4636         if (!ImGui::BeginPopupContextItem())
4637             return;
4638 
4639         char buf[256];
4640         sprintf(buf, "Save %s", doc->Name);
4641         if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
4642             doc->DoSave();
4643         if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
4644             doc->DoQueueClose();
4645         ImGui::EndPopup();
4646     }
4647 };
4648 
4649 struct ExampleAppDocuments
4650 {
4651     ImVector<MyDocument> Documents;
4652 
ExampleAppDocumentsExampleAppDocuments4653     ExampleAppDocuments()
4654     {
4655         Documents.push_back(MyDocument("Lettuce",             true,  ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
4656         Documents.push_back(MyDocument("Eggplant",            true,  ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
4657         Documents.push_back(MyDocument("Carrot",              true,  ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
4658         Documents.push_back(MyDocument("Tomato",              false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
4659         Documents.push_back(MyDocument("A Rather Long Title", false));
4660         Documents.push_back(MyDocument("Some Document",       false));
4661     }
4662 };
4663 
4664 // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
4665 // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, as opposed
4666 // 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.
4667 // 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
4668 // will report no selected tab during the frame. This will effectively give the impression of a flicker for one frame.
4669 // We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
4670 // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments & app)4671 static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
4672 {
4673     for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4674     {
4675         MyDocument* doc = &app.Documents[doc_n];
4676         if (!doc->Open && doc->OpenPrev)
4677             ImGui::SetTabItemClosed(doc->Name);
4678         doc->OpenPrev = doc->Open;
4679     }
4680 }
4681 
ShowExampleAppDocuments(bool * p_open)4682 void ShowExampleAppDocuments(bool* p_open)
4683 {
4684     static ExampleAppDocuments app;
4685 
4686     // Options
4687     static bool opt_reorderable = true;
4688     static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
4689 
4690     bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
4691     if (!window_contents_visible)
4692     {
4693         ImGui::End();
4694         return;
4695     }
4696 
4697     // Menu
4698     if (ImGui::BeginMenuBar())
4699     {
4700         if (ImGui::BeginMenu("File"))
4701         {
4702             int open_count = 0;
4703             for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4704                 open_count += app.Documents[doc_n].Open ? 1 : 0;
4705 
4706             if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
4707             {
4708                 for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4709                 {
4710                     MyDocument* doc = &app.Documents[doc_n];
4711                     if (!doc->Open)
4712                         if (ImGui::MenuItem(doc->Name))
4713                             doc->DoOpen();
4714                 }
4715                 ImGui::EndMenu();
4716             }
4717             if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
4718                 for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4719                     app.Documents[doc_n].DoQueueClose();
4720             if (ImGui::MenuItem("Exit", "Alt+F4")) {}
4721             ImGui::EndMenu();
4722         }
4723         ImGui::EndMenuBar();
4724     }
4725 
4726     // [Debug] List documents with one checkbox for each
4727     for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4728     {
4729         MyDocument* doc = &app.Documents[doc_n];
4730         if (doc_n > 0)
4731             ImGui::SameLine();
4732         ImGui::PushID(doc);
4733         if (ImGui::Checkbox(doc->Name, &doc->Open))
4734             if (!doc->Open)
4735                 doc->DoForceClose();
4736         ImGui::PopID();
4737     }
4738 
4739     ImGui::Separator();
4740 
4741     // Submit Tab Bar and Tabs
4742     {
4743         ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
4744         if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
4745         {
4746             if (opt_reorderable)
4747                 NotifyOfDocumentsClosedElsewhere(app);
4748 
4749             // [DEBUG] Stress tests
4750             //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1;            // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
4751             //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name);  // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
4752 
4753             // Submit Tabs
4754             for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4755             {
4756                 MyDocument* doc = &app.Documents[doc_n];
4757                 if (!doc->Open)
4758                     continue;
4759 
4760                 ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
4761                 bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
4762 
4763                 // Cancel attempt to close when unsaved add to save queue so we can display a popup.
4764                 if (!doc->Open && doc->Dirty)
4765                 {
4766                     doc->Open = true;
4767                     doc->DoQueueClose();
4768                 }
4769 
4770                 MyDocument::DisplayContextMenu(doc);
4771                 if (visible)
4772                 {
4773                     MyDocument::DisplayContents(doc);
4774                     ImGui::EndTabItem();
4775                 }
4776             }
4777 
4778             ImGui::EndTabBar();
4779         }
4780     }
4781 
4782     // Update closing queue
4783     static ImVector<MyDocument*> close_queue;
4784     if (close_queue.empty())
4785     {
4786         // Close queue is locked once we started a popup
4787         for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4788         {
4789             MyDocument* doc = &app.Documents[doc_n];
4790             if (doc->WantClose)
4791             {
4792                 doc->WantClose = false;
4793                 close_queue.push_back(doc);
4794             }
4795         }
4796     }
4797 
4798     // Display closing confirmation UI
4799     if (!close_queue.empty())
4800     {
4801         int close_queue_unsaved_documents = 0;
4802         for (int n = 0; n < close_queue.Size; n++)
4803             if (close_queue[n]->Dirty)
4804                 close_queue_unsaved_documents++;
4805 
4806         if (close_queue_unsaved_documents == 0)
4807         {
4808             // Close documents when all are unsaved
4809             for (int n = 0; n < close_queue.Size; n++)
4810                 close_queue[n]->DoForceClose();
4811             close_queue.clear();
4812         }
4813         else
4814         {
4815             if (!ImGui::IsPopupOpen("Save?"))
4816                 ImGui::OpenPopup("Save?");
4817             if (ImGui::BeginPopupModal("Save?"))
4818             {
4819                 ImGui::Text("Save change to the following items?");
4820                 ImGui::SetNextItemWidth(-1.0f);
4821                 if (ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6))
4822                 {
4823                     for (int n = 0; n < close_queue.Size; n++)
4824                         if (close_queue[n]->Dirty)
4825                             ImGui::Text("%s", close_queue[n]->Name);
4826                     ImGui::ListBoxFooter();
4827                 }
4828 
4829                 if (ImGui::Button("Yes", ImVec2(80, 0)))
4830                 {
4831                     for (int n = 0; n < close_queue.Size; n++)
4832                     {
4833                         if (close_queue[n]->Dirty)
4834                             close_queue[n]->DoSave();
4835                         close_queue[n]->DoForceClose();
4836                     }
4837                     close_queue.clear();
4838                     ImGui::CloseCurrentPopup();
4839                 }
4840                 ImGui::SameLine();
4841                 if (ImGui::Button("No", ImVec2(80, 0)))
4842                 {
4843                     for (int n = 0; n < close_queue.Size; n++)
4844                         close_queue[n]->DoForceClose();
4845                     close_queue.clear();
4846                     ImGui::CloseCurrentPopup();
4847                 }
4848                 ImGui::SameLine();
4849                 if (ImGui::Button("Cancel", ImVec2(80, 0)))
4850                 {
4851                     close_queue.clear();
4852                     ImGui::CloseCurrentPopup();
4853                 }
4854                 ImGui::EndPopup();
4855             }
4856         }
4857     }
4858 
4859     ImGui::End();
4860 }
4861 
4862 // End of Demo code
4863 #else
4864 
ShowAboutWindow(bool *)4865 void ImGui::ShowAboutWindow(bool*) {}
ShowDemoWindow(bool *)4866 void ImGui::ShowDemoWindow(bool*) {}
ShowUserGuide()4867 void ImGui::ShowUserGuide() {}
ShowStyleEditor(ImGuiStyle *)4868 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
4869 
4870 #endif
4871 
4872 #endif // #ifndef IMGUI_DISABLE
4873