imgui

FORK: Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
git clone https://git.neptards.moe/neptards/imgui.git
Log | Files | Refs

imgui_demo.cpp (390934B)


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