Home | History | Annotate | Line # | Download | only in imgui
      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 
     26 Index 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
    114 static void ShowExampleAppDocuments(bool* p_open);
    115 static void ShowExampleAppMainMenuBar();
    116 static void ShowExampleAppConsole(bool* p_open);
    117 static void ShowExampleAppLog(bool* p_open);
    118 static void ShowExampleAppLayout(bool* p_open);
    119 static void ShowExampleAppPropertyEditor(bool* p_open);
    120 static void ShowExampleAppLongText(bool* p_open);
    121 static void ShowExampleAppAutoResize(bool* p_open);
    122 static void ShowExampleAppConstrainedResize(bool* p_open);
    123 static void ShowExampleAppSimpleOverlay(bool* p_open);
    124 static void ShowExampleAppWindowTitles(bool* p_open);
    125 static void ShowExampleAppCustomRendering(bool* p_open);
    126 static void ShowExampleMenuFile();
    127 
    128 // Helper to display a little (?) mark which shows a tooltip when hovered.
    129 static 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.
    143 void 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)
    170 static void ShowDemoWindowWidgets();
    171 static void ShowDemoWindowLayout();
    172 static void ShowDemoWindowPopups();
    173 static void ShowDemoWindowColumns();
    174 static 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.
    178 void 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 
    400 static 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 
   1555 static 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 
   2040 static 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 
   2264 static 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 
   2447 static 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 
   2613 void 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.
   2737 bool 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.
   2755 void 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 
   2779 void 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.
   3022 static 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 
   3045 static 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.
   3116 struct 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 
   3436 static 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");
   3450 struct 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.
   3573 static 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.
   3604 static 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.
   3665 static 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.
   3738 static 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.
   3796 static 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.
   3817 static 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.
   3868 static 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.
   3908 static 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.
   3938 static 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
   4052 struct 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 
   4107 struct 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.
   4129 static 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 
   4140 void 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 
   4320 void ImGui::ShowAboutWindow(bool*) {}
   4321 void ImGui::ShowDemoWindow(bool*) {}
   4322 void ImGui::ShowUserGuide() {}
   4323 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
   4324 
   4325 #endif
   4326