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