duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

imgui_demo.cpp (538481B)


      1 // dear imgui, v1.91.0
      2 // (demo code)
      3 
      4 // Help:
      5 // - Read FAQ at http://dearimgui.com/faq
      6 // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
      7 // - Need help integrating Dear ImGui in your codebase?
      8 //   - Read Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started
      9 //   - Read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
     10 // Read top of imgui.cpp and imgui.h for many details, documentation, comments, links.
     11 // Get the latest version at https://github.com/ocornut/imgui
     12 
     13 // How to easily locate code?
     14 // - Use Tools->Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools
     15 // - Browse an online version the demo with code linked to hovered widgets: https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html
     16 // - Find a visible string and search for it in the code!
     17 
     18 //---------------------------------------------------
     19 // PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
     20 //---------------------------------------------------
     21 // Message to the person tempted to delete this file when integrating Dear ImGui into their codebase:
     22 // Think again! It is the most useful reference code that you and other coders will want to refer to and call.
     23 // Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of your game/app!
     24 // Also include Metrics! ItemPicker! DebugLog! and other debug features.
     25 // Removing this file from your project is hindering access to documentation for everyone in your team,
     26 // likely leading you to poorer usage of the library.
     27 // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
     28 // If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
     29 // linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
     30 // In another situation, whenever you have Dear ImGui available you probably want this to be available for reference.
     31 // Thank you,
     32 // -Your beloved friend, imgui_demo.cpp (which you won't delete)
     33 
     34 //--------------------------------------------
     35 // ABOUT THE MEANING OF THE 'static' KEYWORD:
     36 //--------------------------------------------
     37 // In this demo code, we frequently use 'static' variables inside functions.
     38 // A static variable persists across calls. It is essentially a global variable but declared inside the scope of the function.
     39 // Think of "static int n = 0;" as "global int n = 0;" !
     40 // We do this IN THE DEMO because we want:
     41 // - to gather code and data in the same place.
     42 // - to make the demo source code faster to read, faster to change, smaller in size.
     43 // - it is also a convenient way of storing simple UI related information as long as your function
     44 //   doesn't need to be reentrant or used in multiple threads.
     45 // This might be a pattern you will want to use in your code, but most of the data you would be working
     46 // with in a complex codebase is likely going to be stored outside your functions.
     47 
     48 //-----------------------------------------
     49 // ABOUT THE CODING STYLE OF OUR DEMO CODE
     50 //-----------------------------------------
     51 // The Demo code in this file is designed to be easy to copy-and-paste into your application!
     52 // Because of this:
     53 // - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
     54 // - We try to declare static variables in the local scope, as close as possible to the code using them.
     55 // - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
     56 // - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
     57 //   by imgui.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
     58 //   and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
     59 //   Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
     60 
     61 // Navigating this file:
     62 // - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
     63 // - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
     64 // - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
     65 // - You can search/grep for all sections listed in the index to find the section.
     66 
     67 /*
     68 
     69 Index of this file:
     70 
     71 // [SECTION] Forward Declarations
     72 // [SECTION] Helpers
     73 // [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos)
     74 // [SECTION] Demo Window / ShowDemoWindow()
     75 // [SECTION] ShowDemoWindowMenuBar()
     76 // [SECTION] ShowDemoWindowWidgets()
     77 // [SECTION] ShowDemoWindowMultiSelect()
     78 // [SECTION] ShowDemoWindowLayout()
     79 // [SECTION] ShowDemoWindowPopups()
     80 // [SECTION] ShowDemoWindowTables()
     81 // [SECTION] ShowDemoWindowInputs()
     82 // [SECTION] About Window / ShowAboutWindow()
     83 // [SECTION] Style Editor / ShowStyleEditor()
     84 // [SECTION] User Guide / ShowUserGuide()
     85 // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
     86 // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
     87 // [SECTION] Example App: Debug Log / ShowExampleAppLog()
     88 // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
     89 // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
     90 // [SECTION] Example App: Long Text / ShowExampleAppLongText()
     91 // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
     92 // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
     93 // [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
     94 // [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
     95 // [SECTION] Example App: Manipulating window titles / ShowExampleAppWindowTitles()
     96 // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
     97 // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
     98 // [SECTION] Example App: Assets Browser / ShowExampleAppAssetsBrowser()
     99 
    100 */
    101 
    102 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
    103 #define _CRT_SECURE_NO_WARNINGS
    104 #endif
    105 
    106 #include "imgui.h"
    107 #ifndef IMGUI_DISABLE
    108 
    109 // System includes
    110 #include <ctype.h>          // toupper
    111 #include <limits.h>         // INT_MIN, INT_MAX
    112 #include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
    113 #include <stdio.h>          // vsnprintf, sscanf, printf
    114 #include <stdlib.h>         // NULL, malloc, free, atoi
    115 #include <stdint.h>         // intptr_t
    116 #if !defined(_MSC_VER) || _MSC_VER >= 1800
    117 #include <inttypes.h>       // PRId64/PRIu64, not avail in some MinGW headers.
    118 #endif
    119 
    120 // Visual Studio warnings
    121 #ifdef _MSC_VER
    122 #pragma warning (disable: 4127)     // condition expression is constant
    123 #pragma warning (disable: 4996)     // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
    124 #pragma warning (disable: 26451)    // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to an 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
    125 #endif
    126 
    127 // Clang/GCC warnings with -Weverything
    128 #if defined(__clang__)
    129 #if __has_warning("-Wunknown-warning-option")
    130 #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!
    131 #endif
    132 #pragma clang diagnostic ignored "-Wunknown-pragmas"                // warning: unknown warning group 'xxx'
    133 #pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast                           // yes, they are more terse.
    134 #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)
    135 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"       // warning: cast to 'void *' from smaller integer type
    136 #pragma clang diagnostic ignored "-Wformat-security"                // warning: format string is not a string literal
    137 #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.
    138 #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.
    139 #pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant                   // some standard header variations use #define NULL 0
    140 #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.
    141 #pragma clang diagnostic ignored "-Wreserved-id-macro"              // warning: macro name is a reserved identifier
    142 #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
    143 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
    144 #elif defined(__GNUC__)
    145 #pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
    146 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
    147 #pragma GCC diagnostic ignored "-Wformat-security"          // warning: format string is not a string literal (potentially insecure)
    148 #pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
    149 #pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
    150 #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.
    151 #endif
    152 
    153 // Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
    154 #ifdef _WIN32
    155 #define IM_NEWLINE  "\r\n"
    156 #else
    157 #define IM_NEWLINE  "\n"
    158 #endif
    159 
    160 // Helpers
    161 #if defined(_MSC_VER) && !defined(snprintf)
    162 #define snprintf    _snprintf
    163 #endif
    164 #if defined(_MSC_VER) && !defined(vsnprintf)
    165 #define vsnprintf   _vsnprintf
    166 #endif
    167 
    168 // Format specifiers for 64-bit values (hasn't been decently standardized before VS2013)
    169 #if !defined(PRId64) && defined(_MSC_VER)
    170 #define PRId64 "I64d"
    171 #define PRIu64 "I64u"
    172 #elif !defined(PRId64)
    173 #define PRId64 "lld"
    174 #define PRIu64 "llu"
    175 #endif
    176 
    177 // Helpers macros
    178 // We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
    179 // but making an exception here as those are largely simplifying code...
    180 // In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo.
    181 #define IM_MIN(A, B)            (((A) < (B)) ? (A) : (B))
    182 #define IM_MAX(A, B)            (((A) >= (B)) ? (A) : (B))
    183 #define IM_CLAMP(V, MN, MX)     ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
    184 
    185 // Enforce cdecl calling convention for functions called by the standard library,
    186 // in case compilation settings changed the default to e.g. __vectorcall
    187 #ifndef IMGUI_CDECL
    188 #ifdef _MSC_VER
    189 #define IMGUI_CDECL __cdecl
    190 #else
    191 #define IMGUI_CDECL
    192 #endif
    193 #endif
    194 
    195 //-----------------------------------------------------------------------------
    196 // [SECTION] Forward Declarations
    197 //-----------------------------------------------------------------------------
    198 
    199 #if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
    200 
    201 // Forward Declarations
    202 struct ImGuiDemoWindowData;
    203 static void ShowExampleAppMainMenuBar();
    204 static void ShowExampleAppAssetsBrowser(bool* p_open);
    205 static void ShowExampleAppConsole(bool* p_open);
    206 static void ShowExampleAppCustomRendering(bool* p_open);
    207 static void ShowExampleAppDocuments(bool* p_open);
    208 static void ShowExampleAppLog(bool* p_open);
    209 static void ShowExampleAppLayout(bool* p_open);
    210 static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data);
    211 static void ShowExampleAppSimpleOverlay(bool* p_open);
    212 static void ShowExampleAppAutoResize(bool* p_open);
    213 static void ShowExampleAppConstrainedResize(bool* p_open);
    214 static void ShowExampleAppFullscreen(bool* p_open);
    215 static void ShowExampleAppLongText(bool* p_open);
    216 static void ShowExampleAppWindowTitles(bool* p_open);
    217 static void ShowExampleMenuFile();
    218 
    219 // We split the contents of the big ShowDemoWindow() function into smaller functions
    220 // (because the link time of very large functions tends to grow non-linearly)
    221 static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data);
    222 static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data);
    223 static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data);
    224 static void ShowDemoWindowLayout();
    225 static void ShowDemoWindowPopups();
    226 static void ShowDemoWindowTables();
    227 static void ShowDemoWindowColumns();
    228 static void ShowDemoWindowInputs();
    229 
    230 //-----------------------------------------------------------------------------
    231 // [SECTION] Helpers
    232 //-----------------------------------------------------------------------------
    233 
    234 // Helper to display a little (?) mark which shows a tooltip when hovered.
    235 // In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
    236 static void HelpMarker(const char* desc)
    237 {
    238     ImGui::TextDisabled("(?)");
    239     if (ImGui::BeginItemTooltip())
    240     {
    241         ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
    242         ImGui::TextUnformatted(desc);
    243         ImGui::PopTextWrapPos();
    244         ImGui::EndTooltip();
    245     }
    246 }
    247 
    248 // Helper to wire demo markers located in code to an interactive browser
    249 typedef void (*ImGuiDemoMarkerCallback)(const char* file, int line, const char* section, void* user_data);
    250 extern ImGuiDemoMarkerCallback      GImGuiDemoMarkerCallback;
    251 extern void*                        GImGuiDemoMarkerCallbackUserData;
    252 ImGuiDemoMarkerCallback             GImGuiDemoMarkerCallback = NULL;
    253 void*                               GImGuiDemoMarkerCallbackUserData = NULL;
    254 #define IMGUI_DEMO_MARKER(section)  do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback(__FILE__, __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0)
    255 
    256 //-----------------------------------------------------------------------------
    257 // [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor etc.)
    258 //-----------------------------------------------------------------------------
    259 
    260 // Simple representation for a tree
    261 // (this is designed to be simple to understand for our demos, not to be fancy or efficient etc.)
    262 struct ExampleTreeNode
    263 {
    264     // Tree structure
    265     char                        Name[28] = "";
    266     int                         UID = 0;
    267     ExampleTreeNode*            Parent = NULL;
    268     ImVector<ExampleTreeNode*>  Childs;
    269     unsigned short              IndexInParent = 0;  // Maintaining this allows us to implement linear traversal more easily
    270 
    271     // Leaf Data
    272     bool                        HasData = false;    // All leaves have data
    273     bool                        DataMyBool = true;
    274     int                         DataMyInt = 128;
    275     ImVec2                      DataMyVec2 = ImVec2(0.0f, 3.141592f);
    276 };
    277 
    278 // Simple representation of struct metadata/serialization data.
    279 // (this is a minimal version of what a typical advanced application may provide)
    280 struct ExampleMemberInfo
    281 {
    282     const char*     Name;       // Member name
    283     ImGuiDataType   DataType;   // Member type
    284     int             DataCount;  // Member count (1 when scalar)
    285     int             Offset;     // Offset inside parent structure
    286 };
    287 
    288 // Metadata description of ExampleTreeNode struct.
    289 static const ExampleMemberInfo ExampleTreeNodeMemberInfos[]
    290 {
    291     { "MyBool",     ImGuiDataType_Bool,    1, offsetof(ExampleTreeNode, DataMyBool) },
    292     { "MyInt",      ImGuiDataType_S32,     1, offsetof(ExampleTreeNode, DataMyInt) },
    293     { "MyVec2",     ImGuiDataType_Float,   2, offsetof(ExampleTreeNode, DataMyVec2) },
    294 };
    295 
    296 static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, ExampleTreeNode* parent)
    297 {
    298     ExampleTreeNode* node = IM_NEW(ExampleTreeNode);
    299     snprintf(node->Name, IM_ARRAYSIZE(node->Name), "%s", name);
    300     node->UID = uid;
    301     node->Parent = parent;
    302     node->IndexInParent = parent ? (unsigned short)parent->Childs.Size : 0;
    303     if (parent)
    304         parent->Childs.push_back(node);
    305     return node;
    306 }
    307 
    308 // Create example tree data
    309 // (this allocates _many_ more times than most other code in either Dear ImGui or others demo)
    310 static ExampleTreeNode* ExampleTree_CreateDemoTree()
    311 {
    312     static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" };
    313     char name_buf[32];
    314     int uid = 0;
    315     ExampleTreeNode* node_L0 = ExampleTree_CreateNode("<ROOT>", ++uid, NULL);
    316     const int root_items_multiplier = 2;
    317     for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++)
    318     {
    319         snprintf(name_buf, 32, "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier);
    320         ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0);
    321         const int number_of_childs = (int)strlen(node_L1->Name);
    322         for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++)
    323         {
    324             snprintf(name_buf, 32, "Child %d", idx_L1);
    325             ExampleTreeNode* node_L2 = ExampleTree_CreateNode(name_buf, ++uid, node_L1);
    326             node_L2->HasData = true;
    327             if (idx_L1 == 0)
    328             {
    329                 snprintf(name_buf, 32, "Sub-child %d", 0);
    330                 ExampleTreeNode* node_L3 = ExampleTree_CreateNode(name_buf, ++uid, node_L2);
    331                 node_L3->HasData = true;
    332             }
    333         }
    334     }
    335     return node_L0;
    336 }
    337 
    338 //-----------------------------------------------------------------------------
    339 // [SECTION] Demo Window / ShowDemoWindow()
    340 //-----------------------------------------------------------------------------
    341 
    342 // Data to be shared accross different functions of the demo.
    343 struct ImGuiDemoWindowData
    344 {
    345     // Examples Apps (accessible from the "Examples" menu)
    346     bool ShowMainMenuBar = false;
    347     bool ShowAppAssetsBrowser = false;
    348     bool ShowAppConsole = false;
    349     bool ShowAppCustomRendering = false;
    350     bool ShowAppDocuments = false;
    351     bool ShowAppLog = false;
    352     bool ShowAppLayout = false;
    353     bool ShowAppPropertyEditor = false;
    354     bool ShowAppSimpleOverlay = false;
    355     bool ShowAppAutoResize = false;
    356     bool ShowAppConstrainedResize = false;
    357     bool ShowAppFullscreen = false;
    358     bool ShowAppLongText = false;
    359     bool ShowAppWindowTitles = false;
    360 
    361     // Dear ImGui Tools (accessible from the "Tools" menu)
    362     bool ShowMetrics = false;
    363     bool ShowDebugLog = false;
    364     bool ShowIDStackTool = false;
    365     bool ShowStyleEditor = false;
    366     bool ShowAbout = false;
    367 
    368     // Other data
    369     ExampleTreeNode* DemoTree = NULL;
    370 };
    371 
    372 // Demonstrate most Dear ImGui features (this is big function!)
    373 // You may execute this function to experiment with the UI and understand what it does.
    374 // You may then search for keywords in the code when you are interested by a specific feature.
    375 void ImGui::ShowDemoWindow(bool* p_open)
    376 {
    377     // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
    378     // Most functions would normally just assert/crash if the context is missing.
    379     IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!");
    380 
    381     // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
    382     IMGUI_CHECKVERSION();
    383 
    384     // Stored data
    385     static ImGuiDemoWindowData demo_data;
    386 
    387     // Examples Apps (accessible from the "Examples" menu)
    388     if (demo_data.ShowMainMenuBar)          { ShowExampleAppMainMenuBar(); }
    389     if (demo_data.ShowAppDocuments)         { ShowExampleAppDocuments(&demo_data.ShowAppDocuments); }
    390     if (demo_data.ShowAppAssetsBrowser)     { ShowExampleAppAssetsBrowser(&demo_data.ShowAppAssetsBrowser); }
    391     if (demo_data.ShowAppConsole)           { ShowExampleAppConsole(&demo_data.ShowAppConsole); }
    392     if (demo_data.ShowAppCustomRendering)   { ShowExampleAppCustomRendering(&demo_data.ShowAppCustomRendering); }
    393     if (demo_data.ShowAppLog)               { ShowExampleAppLog(&demo_data.ShowAppLog); }
    394     if (demo_data.ShowAppLayout)            { ShowExampleAppLayout(&demo_data.ShowAppLayout); }
    395     if (demo_data.ShowAppPropertyEditor)    { ShowExampleAppPropertyEditor(&demo_data.ShowAppPropertyEditor, &demo_data); }
    396     if (demo_data.ShowAppSimpleOverlay)     { ShowExampleAppSimpleOverlay(&demo_data.ShowAppSimpleOverlay); }
    397     if (demo_data.ShowAppAutoResize)        { ShowExampleAppAutoResize(&demo_data.ShowAppAutoResize); }
    398     if (demo_data.ShowAppConstrainedResize) { ShowExampleAppConstrainedResize(&demo_data.ShowAppConstrainedResize); }
    399     if (demo_data.ShowAppFullscreen)        { ShowExampleAppFullscreen(&demo_data.ShowAppFullscreen); }
    400     if (demo_data.ShowAppLongText)          { ShowExampleAppLongText(&demo_data.ShowAppLongText); }
    401     if (demo_data.ShowAppWindowTitles)      { ShowExampleAppWindowTitles(&demo_data.ShowAppWindowTitles); }
    402 
    403     // Dear ImGui Tools (accessible from the "Tools" menu)
    404     if (demo_data.ShowMetrics)              { ImGui::ShowMetricsWindow(&demo_data.ShowMetrics); }
    405     if (demo_data.ShowDebugLog)             { ImGui::ShowDebugLogWindow(&demo_data.ShowDebugLog); }
    406     if (demo_data.ShowIDStackTool)          { ImGui::ShowIDStackToolWindow(&demo_data.ShowIDStackTool); }
    407     if (demo_data.ShowAbout)                { ImGui::ShowAboutWindow(&demo_data.ShowAbout); }
    408     if (demo_data.ShowStyleEditor)
    409     {
    410         ImGui::Begin("Dear ImGui Style Editor", &demo_data.ShowStyleEditor);
    411         ImGui::ShowStyleEditor();
    412         ImGui::End();
    413     }
    414 
    415     // Demonstrate the various window flags. Typically you would just use the default!
    416     static bool no_titlebar = false;
    417     static bool no_scrollbar = false;
    418     static bool no_menu = false;
    419     static bool no_move = false;
    420     static bool no_resize = false;
    421     static bool no_collapse = false;
    422     static bool no_close = false;
    423     static bool no_nav = false;
    424     static bool no_background = false;
    425     static bool no_bring_to_front = false;
    426     static bool unsaved_document = false;
    427 
    428     ImGuiWindowFlags window_flags = 0;
    429     if (no_titlebar)        window_flags |= ImGuiWindowFlags_NoTitleBar;
    430     if (no_scrollbar)       window_flags |= ImGuiWindowFlags_NoScrollbar;
    431     if (!no_menu)           window_flags |= ImGuiWindowFlags_MenuBar;
    432     if (no_move)            window_flags |= ImGuiWindowFlags_NoMove;
    433     if (no_resize)          window_flags |= ImGuiWindowFlags_NoResize;
    434     if (no_collapse)        window_flags |= ImGuiWindowFlags_NoCollapse;
    435     if (no_nav)             window_flags |= ImGuiWindowFlags_NoNav;
    436     if (no_background)      window_flags |= ImGuiWindowFlags_NoBackground;
    437     if (no_bring_to_front)  window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
    438     if (unsaved_document)   window_flags |= ImGuiWindowFlags_UnsavedDocument;
    439     if (no_close)           p_open = NULL; // Don't pass our bool* to Begin
    440 
    441     // We specify a default position/size in case there's no data in the .ini file.
    442     // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
    443     const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
    444     ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), ImGuiCond_FirstUseEver);
    445     ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
    446 
    447     // Main body of the Demo window starts here.
    448     if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags))
    449     {
    450         // Early out if the window is collapsed, as an optimization.
    451         ImGui::End();
    452         return;
    453     }
    454 
    455     // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
    456     ImGui::PushItemWidth(ImGui::GetFontSize() * -12);           // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
    457     //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f);   // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align)
    458 
    459     // Menu Bar
    460     ShowDemoWindowMenuBar(&demo_data);
    461 
    462     ImGui::Text("dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
    463     ImGui::Spacing();
    464 
    465     IMGUI_DEMO_MARKER("Help");
    466     if (ImGui::CollapsingHeader("Help"))
    467     {
    468         ImGui::SeparatorText("ABOUT THIS DEMO:");
    469         ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
    470         ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
    471         ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
    472                           "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
    473 
    474         ImGui::SeparatorText("PROGRAMMER GUIDE:");
    475         ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
    476         ImGui::BulletText("See comments in imgui.cpp.");
    477         ImGui::BulletText("See example applications in the examples/ folder.");
    478         ImGui::BulletText("Read the FAQ at ");
    479         ImGui::SameLine(0, 0);
    480         ImGui::TextLinkOpenURL("https://www.dearimgui.com/faq/");
    481         ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
    482         ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
    483 
    484         ImGui::SeparatorText("USER GUIDE:");
    485         ImGui::ShowUserGuide();
    486     }
    487 
    488     IMGUI_DEMO_MARKER("Configuration");
    489     if (ImGui::CollapsingHeader("Configuration"))
    490     {
    491         ImGuiIO& io = ImGui::GetIO();
    492 
    493         if (ImGui::TreeNode("Configuration##2"))
    494         {
    495             ImGui::SeparatorText("General");
    496             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard",    &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
    497             ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
    498             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad",     &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
    499             ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
    500             ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", &io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
    501             ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
    502             ImGui::CheckboxFlags("io.ConfigFlags: NoMouse",              &io.ConfigFlags, ImGuiConfigFlags_NoMouse);
    503             ImGui::SameLine(); HelpMarker("Instruct dear imgui to disable mouse inputs and interactions.");
    504 
    505             // The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it:
    506             if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
    507             {
    508                 if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
    509                 {
    510                     ImGui::SameLine();
    511                     ImGui::Text("<<PRESS SPACE TO DISABLE>>");
    512                 }
    513                 // Prevent both being checked
    514                 if (ImGui::IsKeyPressed(ImGuiKey_Space) || (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard))
    515                     io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
    516             }
    517 
    518             ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange",  &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
    519             ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
    520             ImGui::CheckboxFlags("io.ConfigFlags: NoKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NoKeyboard);
    521             ImGui::SameLine(); HelpMarker("Instruct dear imgui to disable keyboard inputs and interactions.");
    522 
    523             ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue);
    524             ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.");
    525             ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
    526             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).");
    527 
    528             ImGui::SeparatorText("Widgets");
    529             ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
    530             ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
    531             ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive);
    532             ImGui::SameLine(); HelpMarker("Pressing Enter will keep item active and select contents (single-line only).");
    533             ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
    534             ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
    535             ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
    536             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.");
    537             ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
    538             ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
    539             ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
    540             ImGui::Text("Also see Style->Rendering for rendering options.");
    541 
    542             ImGui::SeparatorText("Debug");
    543             ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent);
    544             ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.");
    545             ImGui::BeginDisabled();
    546             ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce); // .
    547             ImGui::EndDisabled();
    548             ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover.");
    549             ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop);
    550             ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
    551             ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss);
    552             ImGui::SameLine(); HelpMarker("Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.");
    553             ImGui::Checkbox("io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
    554             ImGui::SameLine(); HelpMarker("Option to save .ini data with extra comments (particularly helpful for Docking, but makes saving slower).");
    555 
    556             ImGui::TreePop();
    557             ImGui::Spacing();
    558         }
    559 
    560         IMGUI_DEMO_MARKER("Configuration/Backend Flags");
    561         if (ImGui::TreeNode("Backend Flags"))
    562         {
    563             HelpMarker(
    564                 "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
    565                 "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
    566 
    567             // FIXME: Maybe we need a BeginReadonly() equivalent to keep label bright?
    568             ImGui::BeginDisabled();
    569             ImGui::CheckboxFlags("io.BackendFlags: HasGamepad",           &io.BackendFlags, ImGuiBackendFlags_HasGamepad);
    570             ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors",      &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
    571             ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos",       &io.BackendFlags, ImGuiBackendFlags_HasSetMousePos);
    572             ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", &io.BackendFlags, ImGuiBackendFlags_RendererHasVtxOffset);
    573             ImGui::EndDisabled();
    574             ImGui::TreePop();
    575             ImGui::Spacing();
    576         }
    577 
    578         IMGUI_DEMO_MARKER("Configuration/Style");
    579         if (ImGui::TreeNode("Style"))
    580         {
    581             ImGui::Checkbox("Style Editor", &demo_data.ShowStyleEditor);
    582             ImGui::SameLine();
    583             HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
    584             ImGui::TreePop();
    585             ImGui::Spacing();
    586         }
    587 
    588         IMGUI_DEMO_MARKER("Configuration/Capture, Logging");
    589         if (ImGui::TreeNode("Capture/Logging"))
    590         {
    591             HelpMarker(
    592                 "The logging API redirects all text output so you can easily capture the content of "
    593                 "a window or a block. Tree nodes can be automatically expanded.\n"
    594                 "Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
    595             ImGui::LogButtons();
    596 
    597             HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output.");
    598             if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
    599             {
    600                 ImGui::LogToClipboard();
    601                 ImGui::LogText("Hello, world!");
    602                 ImGui::LogFinish();
    603             }
    604             ImGui::TreePop();
    605         }
    606     }
    607 
    608     IMGUI_DEMO_MARKER("Window options");
    609     if (ImGui::CollapsingHeader("Window options"))
    610     {
    611         if (ImGui::BeginTable("split", 3))
    612         {
    613             ImGui::TableNextColumn(); ImGui::Checkbox("No titlebar", &no_titlebar);
    614             ImGui::TableNextColumn(); ImGui::Checkbox("No scrollbar", &no_scrollbar);
    615             ImGui::TableNextColumn(); ImGui::Checkbox("No menu", &no_menu);
    616             ImGui::TableNextColumn(); ImGui::Checkbox("No move", &no_move);
    617             ImGui::TableNextColumn(); ImGui::Checkbox("No resize", &no_resize);
    618             ImGui::TableNextColumn(); ImGui::Checkbox("No collapse", &no_collapse);
    619             ImGui::TableNextColumn(); ImGui::Checkbox("No close", &no_close);
    620             ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav);
    621             ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background);
    622             ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front);
    623             ImGui::TableNextColumn(); ImGui::Checkbox("Unsaved document", &unsaved_document);
    624             ImGui::EndTable();
    625         }
    626     }
    627 
    628     // All demo contents
    629     ShowDemoWindowWidgets(&demo_data);
    630     ShowDemoWindowLayout();
    631     ShowDemoWindowPopups();
    632     ShowDemoWindowTables();
    633     ShowDemoWindowInputs();
    634 
    635     // End of ShowDemoWindow()
    636     ImGui::PopItemWidth();
    637     ImGui::End();
    638 }
    639 
    640 //-----------------------------------------------------------------------------
    641 // [SECTION] ShowDemoWindowMenuBar()
    642 //-----------------------------------------------------------------------------
    643 
    644 static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
    645 {
    646     IMGUI_DEMO_MARKER("Menu");
    647     if (ImGui::BeginMenuBar())
    648     {
    649         if (ImGui::BeginMenu("Menu"))
    650         {
    651             IMGUI_DEMO_MARKER("Menu/File");
    652             ShowExampleMenuFile();
    653             ImGui::EndMenu();
    654         }
    655         if (ImGui::BeginMenu("Examples"))
    656         {
    657             IMGUI_DEMO_MARKER("Menu/Examples");
    658             ImGui::MenuItem("Main menu bar", NULL, &demo_data->ShowMainMenuBar);
    659 
    660             ImGui::SeparatorText("Mini apps");
    661             ImGui::MenuItem("Assets Browser", NULL, &demo_data->ShowAppAssetsBrowser);
    662             ImGui::MenuItem("Console", NULL, &demo_data->ShowAppConsole);
    663             ImGui::MenuItem("Custom rendering", NULL, &demo_data->ShowAppCustomRendering);
    664             ImGui::MenuItem("Documents", NULL, &demo_data->ShowAppDocuments);
    665             ImGui::MenuItem("Log", NULL, &demo_data->ShowAppLog);
    666             ImGui::MenuItem("Property editor", NULL, &demo_data->ShowAppPropertyEditor);
    667             ImGui::MenuItem("Simple layout", NULL, &demo_data->ShowAppLayout);
    668             ImGui::MenuItem("Simple overlay", NULL, &demo_data->ShowAppSimpleOverlay);
    669 
    670             ImGui::SeparatorText("Concepts");
    671             ImGui::MenuItem("Auto-resizing window", NULL, &demo_data->ShowAppAutoResize);
    672             ImGui::MenuItem("Constrained-resizing window", NULL, &demo_data->ShowAppConstrainedResize);
    673             ImGui::MenuItem("Fullscreen window", NULL, &demo_data->ShowAppFullscreen);
    674             ImGui::MenuItem("Long text display", NULL, &demo_data->ShowAppLongText);
    675             ImGui::MenuItem("Manipulating window titles", NULL, &demo_data->ShowAppWindowTitles);
    676 
    677             ImGui::EndMenu();
    678         }
    679         //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar!
    680         if (ImGui::BeginMenu("Tools"))
    681         {
    682             IMGUI_DEMO_MARKER("Menu/Tools");
    683 #ifndef IMGUI_DISABLE_DEBUG_TOOLS
    684             const bool has_debug_tools = true;
    685 #else
    686             const bool has_debug_tools = false;
    687 #endif
    688             ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools);
    689             ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools);
    690             ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools);
    691             ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor);
    692             bool is_debugger_present = ImGui::GetIO().ConfigDebugIsDebuggerPresent;
    693             if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present))
    694                 ImGui::DebugStartItemPicker();
    695             if (!is_debugger_present)
    696                 ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools.");
    697             ImGui::Separator();
    698             ImGui::MenuItem("About Dear ImGui", NULL, &demo_data->ShowAbout);
    699             ImGui::EndMenu();
    700         }
    701         ImGui::EndMenuBar();
    702     }
    703 }
    704 
    705 //-----------------------------------------------------------------------------
    706 // [SECTION] ShowDemoWindowWidgets()
    707 //-----------------------------------------------------------------------------
    708 
    709 static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
    710 {
    711     IMGUI_DEMO_MARKER("Widgets");
    712     //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
    713     if (!ImGui::CollapsingHeader("Widgets"))
    714         return;
    715 
    716     static bool disable_all = false; // The Checkbox for that is inside the "Disabled" section at the bottom
    717     if (disable_all)
    718         ImGui::BeginDisabled();
    719 
    720     IMGUI_DEMO_MARKER("Widgets/Basic");
    721     if (ImGui::TreeNode("Basic"))
    722     {
    723         ImGui::SeparatorText("General");
    724 
    725         IMGUI_DEMO_MARKER("Widgets/Basic/Button");
    726         static int clicked = 0;
    727         if (ImGui::Button("Button"))
    728             clicked++;
    729         if (clicked & 1)
    730         {
    731             ImGui::SameLine();
    732             ImGui::Text("Thanks for clicking me!");
    733         }
    734 
    735         IMGUI_DEMO_MARKER("Widgets/Basic/Checkbox");
    736         static bool check = true;
    737         ImGui::Checkbox("checkbox", &check);
    738 
    739         IMGUI_DEMO_MARKER("Widgets/Basic/RadioButton");
    740         static int e = 0;
    741         ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
    742         ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
    743         ImGui::RadioButton("radio c", &e, 2);
    744 
    745         // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
    746         IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Colored)");
    747         for (int i = 0; i < 7; i++)
    748         {
    749             if (i > 0)
    750                 ImGui::SameLine();
    751             ImGui::PushID(i);
    752             ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
    753             ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
    754             ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
    755             ImGui::Button("Click");
    756             ImGui::PopStyleColor(3);
    757             ImGui::PopID();
    758         }
    759 
    760         // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
    761         // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
    762         // See 'Demo->Layout->Text Baseline Alignment' for details.
    763         ImGui::AlignTextToFramePadding();
    764         ImGui::Text("Hold to repeat:");
    765         ImGui::SameLine();
    766 
    767         // Arrow buttons with Repeater
    768         IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Repeating)");
    769         static int counter = 0;
    770         float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
    771         ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
    772         if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
    773         ImGui::SameLine(0.0f, spacing);
    774         if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
    775         ImGui::PopItemFlag();
    776         ImGui::SameLine();
    777         ImGui::Text("%d", counter);
    778 
    779         ImGui::Button("Tooltip");
    780         ImGui::SetItemTooltip("I am a tooltip");
    781 
    782         ImGui::LabelText("label", "Value");
    783 
    784         ImGui::SeparatorText("Inputs");
    785 
    786         {
    787             // To wire InputText() with std::string or any other custom string type,
    788             // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
    789             IMGUI_DEMO_MARKER("Widgets/Basic/InputText");
    790             static char str0[128] = "Hello, world!";
    791             ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
    792             ImGui::SameLine(); HelpMarker(
    793                 "USER:\n"
    794                 "Hold SHIFT or use mouse to select text.\n"
    795                 "CTRL+Left/Right to word jump.\n"
    796                 "CTRL+A or Double-Click to select all.\n"
    797                 "CTRL+X,CTRL+C,CTRL+V clipboard.\n"
    798                 "CTRL+Z,CTRL+Y undo/redo.\n"
    799                 "ESCAPE to revert.\n\n"
    800                 "PROGRAMMER:\n"
    801                 "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
    802                 "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
    803                 "in imgui_demo.cpp).");
    804 
    805             static char str1[128] = "";
    806             ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
    807 
    808             IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
    809             static int i0 = 123;
    810             ImGui::InputInt("input int", &i0);
    811 
    812             static float f0 = 0.001f;
    813             ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
    814 
    815             static double d0 = 999999.00000001;
    816             ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
    817 
    818             static float f1 = 1.e10f;
    819             ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
    820             ImGui::SameLine(); HelpMarker(
    821                 "You can input value using the scientific notation,\n"
    822                 "  e.g. \"1e+8\" becomes \"100000000\".");
    823 
    824             static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
    825             ImGui::InputFloat3("input float3", vec4a);
    826         }
    827 
    828         ImGui::SeparatorText("Drags");
    829 
    830         {
    831             IMGUI_DEMO_MARKER("Widgets/Basic/DragInt, DragFloat");
    832             static int i1 = 50, i2 = 42, i3 = 128;
    833             ImGui::DragInt("drag int", &i1, 1);
    834             ImGui::SameLine(); HelpMarker(
    835                 "Click and drag to edit value.\n"
    836                 "Hold SHIFT/ALT for faster/slower edit.\n"
    837                 "Double-click or CTRL+click to input value.");
    838             ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
    839             ImGui::DragInt("drag int wrap 100..200", &i3, 1, 100, 200, "%d", ImGuiSliderFlags_WrapAround);
    840 
    841             static float f1 = 1.00f, f2 = 0.0067f;
    842             ImGui::DragFloat("drag float", &f1, 0.005f);
    843             ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
    844             //ImGui::DragFloat("drag wrap -1..1", &f3, 0.005f, -1.0f, 1.0f, NULL, ImGuiSliderFlags_WrapAround);
    845         }
    846 
    847         ImGui::SeparatorText("Sliders");
    848 
    849         {
    850             IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat");
    851             static int i1 = 0;
    852             ImGui::SliderInt("slider int", &i1, -1, 3);
    853             ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
    854 
    855             static float f1 = 0.123f, f2 = 0.0f;
    856             ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
    857             ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic);
    858 
    859             IMGUI_DEMO_MARKER("Widgets/Basic/SliderAngle");
    860             static float angle = 0.0f;
    861             ImGui::SliderAngle("slider angle", &angle);
    862 
    863             // Using the format string to display a name instead of an integer.
    864             // Here we completely omit '%d' from the format string, so it'll only display a name.
    865             // This technique can also be used with DragInt().
    866             IMGUI_DEMO_MARKER("Widgets/Basic/Slider (enum)");
    867             enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
    868             static int elem = Element_Fire;
    869             const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
    870             const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
    871             ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here.
    872             ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
    873         }
    874 
    875         ImGui::SeparatorText("Selectors/Pickers");
    876 
    877         {
    878             IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4");
    879             static float col1[3] = { 1.0f, 0.0f, 0.2f };
    880             static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
    881             ImGui::ColorEdit3("color 1", col1);
    882             ImGui::SameLine(); HelpMarker(
    883                 "Click on the color square to open a color picker.\n"
    884                 "Click and hold to use drag and drop.\n"
    885                 "Right-click on the color square to show options.\n"
    886                 "CTRL+click on individual component to input value.\n");
    887 
    888             ImGui::ColorEdit4("color 2", col2);
    889         }
    890 
    891         {
    892             // Using the _simplified_ one-liner Combo() api here
    893             // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
    894             IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
    895             const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
    896             static int item_current = 0;
    897             ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
    898             ImGui::SameLine(); HelpMarker(
    899                 "Using the simplified one-liner Combo API here.\n"
    900                 "Refer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
    901         }
    902 
    903         {
    904             // Using the _simplified_ one-liner ListBox() api here
    905             // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
    906             IMGUI_DEMO_MARKER("Widgets/Basic/ListBox");
    907             const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
    908             static int item_current = 1;
    909             ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4);
    910             ImGui::SameLine(); HelpMarker(
    911                 "Using the simplified one-liner ListBox API here.\n"
    912                 "Refer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
    913         }
    914 
    915         ImGui::TreePop();
    916     }
    917 
    918     IMGUI_DEMO_MARKER("Widgets/Tooltips");
    919     if (ImGui::TreeNode("Tooltips"))
    920     {
    921         // Tooltips are windows following the mouse. They do not take focus away.
    922         ImGui::SeparatorText("General");
    923 
    924         // Typical use cases:
    925         // - Short-form (text only):      SetItemTooltip("Hello");
    926         // - Short-form (any contents):   if (BeginItemTooltip()) { Text("Hello"); EndTooltip(); }
    927 
    928         // - Full-form (text only):       if (IsItemHovered(...)) { SetTooltip("Hello"); }
    929         // - Full-form (any contents):    if (IsItemHovered(...) && BeginTooltip()) { Text("Hello"); EndTooltip(); }
    930 
    931         HelpMarker(
    932             "Tooltip are typically created by using a IsItemHovered() + SetTooltip() sequence.\n\n"
    933             "We provide a helper SetItemTooltip() function to perform the two with standards flags.");
    934 
    935         ImVec2 sz = ImVec2(-FLT_MIN, 0.0f);
    936 
    937         ImGui::Button("Basic", sz);
    938         ImGui::SetItemTooltip("I am a tooltip");
    939 
    940         ImGui::Button("Fancy", sz);
    941         if (ImGui::BeginItemTooltip())
    942         {
    943             ImGui::Text("I am a fancy tooltip");
    944             static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
    945             ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
    946             ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
    947             ImGui::EndTooltip();
    948         }
    949 
    950         ImGui::SeparatorText("Always On");
    951 
    952         // Showcase NOT relying on a IsItemHovered() to emit a tooltip.
    953         // Here the tooltip is always emitted when 'always_on == true'.
    954         static int always_on = 0;
    955         ImGui::RadioButton("Off", &always_on, 0);
    956         ImGui::SameLine();
    957         ImGui::RadioButton("Always On (Simple)", &always_on, 1);
    958         ImGui::SameLine();
    959         ImGui::RadioButton("Always On (Advanced)", &always_on, 2);
    960         if (always_on == 1)
    961             ImGui::SetTooltip("I am following you around.");
    962         else if (always_on == 2 && ImGui::BeginTooltip())
    963         {
    964             ImGui::ProgressBar(sinf((float)ImGui::GetTime()) * 0.5f + 0.5f, ImVec2(ImGui::GetFontSize() * 25, 0.0f));
    965             ImGui::EndTooltip();
    966         }
    967 
    968         ImGui::SeparatorText("Custom");
    969 
    970         HelpMarker(
    971             "Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() is the preferred way to standardize"
    972             "tooltip activation details across your application. You may however decide to use custom"
    973             "flags for a specific tooltip instance.");
    974 
    975         // The following examples are passed for documentation purpose but may not be useful to most users.
    976         // Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from
    977         // 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or gamepad/keyboard is being used.
    978         // With default settings, ImGuiHoveredFlags_ForTooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary.
    979         ImGui::Button("Manual", sz);
    980         if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
    981             ImGui::SetTooltip("I am a manually emitted tooltip.");
    982 
    983         ImGui::Button("DelayNone", sz);
    984         if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNone))
    985             ImGui::SetTooltip("I am a tooltip with no delay.");
    986 
    987         ImGui::Button("DelayShort", sz);
    988         if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_NoSharedDelay))
    989             ImGui::SetTooltip("I am a tooltip with a short delay (%0.2f sec).", ImGui::GetStyle().HoverDelayShort);
    990 
    991         ImGui::Button("DelayLong", sz);
    992         if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay))
    993             ImGui::SetTooltip("I am a tooltip with a long delay (%0.2f sec).", ImGui::GetStyle().HoverDelayNormal);
    994 
    995         ImGui::Button("Stationary", sz);
    996         if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary))
    997             ImGui::SetTooltip("I am a tooltip requiring mouse to be stationary before activating.");
    998 
    999         // Using ImGuiHoveredFlags_ForTooltip will pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav',
   1000         // which default value include the ImGuiHoveredFlags_AllowWhenDisabled flag.
   1001         ImGui::BeginDisabled();
   1002         ImGui::Button("Disabled item", sz);
   1003         if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
   1004             ImGui::SetTooltip("I am a a tooltip for a disabled item.");
   1005         ImGui::EndDisabled();
   1006 
   1007         ImGui::TreePop();
   1008     }
   1009 
   1010     // Testing ImGuiOnceUponAFrame helper.
   1011     //static ImGuiOnceUponAFrame once;
   1012     //for (int i = 0; i < 5; i++)
   1013     //    if (once)
   1014     //        ImGui::Text("This will be displayed only once.");
   1015 
   1016     IMGUI_DEMO_MARKER("Widgets/Tree Nodes");
   1017     if (ImGui::TreeNode("Tree Nodes"))
   1018     {
   1019         IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees");
   1020         if (ImGui::TreeNode("Basic trees"))
   1021         {
   1022             for (int i = 0; i < 5; i++)
   1023             {
   1024                 // Use SetNextItemOpen() so set the default state of a node to be open. We could
   1025                 // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
   1026                 if (i == 0)
   1027                     ImGui::SetNextItemOpen(true, ImGuiCond_Once);
   1028 
   1029                 // Here we use PushID() to generate a unique base ID, and then the "" used as TreeNode id won't conflict.
   1030                 // An alternative to using 'PushID() + TreeNode("", ...)' to generate a unique ID is to use 'TreeNode((void*)(intptr_t)i, ...)',
   1031                 // aka generate a dummy pointer-sized value to be hashed. The demo below uses that technique. Both are fine.
   1032                 ImGui::PushID(i);
   1033                 if (ImGui::TreeNode("", "Child %d", i))
   1034                 {
   1035                     ImGui::Text("blah blah");
   1036                     ImGui::SameLine();
   1037                     if (ImGui::SmallButton("button")) {}
   1038                     ImGui::TreePop();
   1039                 }
   1040                 ImGui::PopID();
   1041             }
   1042             ImGui::TreePop();
   1043         }
   1044 
   1045         IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes");
   1046         if (ImGui::TreeNode("Advanced, with Selectable nodes"))
   1047         {
   1048             HelpMarker(
   1049                 "This is a more typical looking tree with selectable nodes.\n"
   1050                 "Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
   1051             static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
   1052             static bool align_label_with_current_x_position = false;
   1053             static bool test_drag_and_drop = false;
   1054             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow",       &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
   1055             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
   1056             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.");
   1057             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth",     &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
   1058             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth",     &base_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin.");
   1059             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns",    &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only.");
   1060             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap",      &base_flags, ImGuiTreeNodeFlags_AllowOverlap);
   1061             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed",            &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)");
   1062             ImGui::CheckboxFlags("ImGuiTreeNodeFlags_NavLeftJumpsBackHere", &base_flags, ImGuiTreeNodeFlags_NavLeftJumpsBackHere);
   1063             ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
   1064             ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
   1065             ImGui::Text("Hello!");
   1066             if (align_label_with_current_x_position)
   1067                 ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
   1068 
   1069             // 'selection_mask' is dumb representation of what may be user-side selection state.
   1070             //  You may retain selection state inside or outside your objects in whatever format you see fit.
   1071             // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
   1072             /// of the loop. May be a pointer to your own node type, etc.
   1073             static int selection_mask = (1 << 2);
   1074             int node_clicked = -1;
   1075             for (int i = 0; i < 6; i++)
   1076             {
   1077                 // Disable the default "open on single-click behavior" + set Selected flag according to our selection.
   1078                 // To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection.
   1079                 ImGuiTreeNodeFlags node_flags = base_flags;
   1080                 const bool is_selected = (selection_mask & (1 << i)) != 0;
   1081                 if (is_selected)
   1082                     node_flags |= ImGuiTreeNodeFlags_Selected;
   1083                 if (i < 3)
   1084                 {
   1085                     // Items 0..2 are Tree Node
   1086                     bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
   1087                     if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
   1088                         node_clicked = i;
   1089                     if (test_drag_and_drop && ImGui::BeginDragDropSource())
   1090                     {
   1091                         ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
   1092                         ImGui::Text("This is a drag and drop source");
   1093                         ImGui::EndDragDropSource();
   1094                     }
   1095                     if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanTextWidth))
   1096                     {
   1097                         // Item 2 has an additional inline button to help demonstrate SpanTextWidth.
   1098                         ImGui::SameLine();
   1099                         if (ImGui::SmallButton("button")) {}
   1100                     }
   1101                     if (node_open)
   1102                     {
   1103                         ImGui::BulletText("Blah blah\nBlah Blah");
   1104                         ImGui::SameLine();
   1105                         ImGui::SmallButton("Button");
   1106                         ImGui::TreePop();
   1107                     }
   1108                 }
   1109                 else
   1110                 {
   1111                     // Items 3..5 are Tree Leaves
   1112                     // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
   1113                     // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
   1114                     node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
   1115                     ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
   1116                     if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
   1117                         node_clicked = i;
   1118                     if (test_drag_and_drop && ImGui::BeginDragDropSource())
   1119                     {
   1120                         ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
   1121                         ImGui::Text("This is a drag and drop source");
   1122                         ImGui::EndDragDropSource();
   1123                     }
   1124                 }
   1125             }
   1126             if (node_clicked != -1)
   1127             {
   1128                 // Update selection state
   1129                 // (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
   1130                 if (ImGui::GetIO().KeyCtrl)
   1131                     selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
   1132                 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
   1133                     selection_mask = (1 << node_clicked);           // Click to single-select
   1134             }
   1135             if (align_label_with_current_x_position)
   1136                 ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
   1137             ImGui::TreePop();
   1138         }
   1139         ImGui::TreePop();
   1140     }
   1141 
   1142     IMGUI_DEMO_MARKER("Widgets/Collapsing Headers");
   1143     if (ImGui::TreeNode("Collapsing Headers"))
   1144     {
   1145         static bool closable_group = true;
   1146         ImGui::Checkbox("Show 2nd header", &closable_group);
   1147         if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None))
   1148         {
   1149             ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
   1150             for (int i = 0; i < 5; i++)
   1151                 ImGui::Text("Some content %d", i);
   1152         }
   1153         if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
   1154         {
   1155             ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
   1156             for (int i = 0; i < 5; i++)
   1157                 ImGui::Text("More content %d", i);
   1158         }
   1159         /*
   1160         if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet))
   1161             ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
   1162         */
   1163         ImGui::TreePop();
   1164     }
   1165 
   1166     IMGUI_DEMO_MARKER("Widgets/Bullets");
   1167     if (ImGui::TreeNode("Bullets"))
   1168     {
   1169         ImGui::BulletText("Bullet point 1");
   1170         ImGui::BulletText("Bullet point 2\nOn multiple lines");
   1171         if (ImGui::TreeNode("Tree node"))
   1172         {
   1173             ImGui::BulletText("Another bullet point");
   1174             ImGui::TreePop();
   1175         }
   1176         ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
   1177         ImGui::Bullet(); ImGui::SmallButton("Button");
   1178         ImGui::TreePop();
   1179     }
   1180 
   1181     IMGUI_DEMO_MARKER("Widgets/Text");
   1182     if (ImGui::TreeNode("Text"))
   1183     {
   1184         IMGUI_DEMO_MARKER("Widgets/Text/Colored Text");
   1185         if (ImGui::TreeNode("Colorful Text"))
   1186         {
   1187             // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
   1188             ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
   1189             ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
   1190             ImGui::TextDisabled("Disabled");
   1191             ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
   1192             ImGui::TreePop();
   1193         }
   1194 
   1195         IMGUI_DEMO_MARKER("Widgets/Text/Word Wrapping");
   1196         if (ImGui::TreeNode("Word Wrapping"))
   1197         {
   1198             // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
   1199             ImGui::TextWrapped(
   1200                 "This text should automatically wrap on the edge of the window. The current implementation "
   1201                 "for text wrapping follows simple rules suitable for English and possibly other languages.");
   1202             ImGui::Spacing();
   1203 
   1204             static float wrap_width = 200.0f;
   1205             ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
   1206 
   1207             ImDrawList* draw_list = ImGui::GetWindowDrawList();
   1208             for (int n = 0; n < 2; n++)
   1209             {
   1210                 ImGui::Text("Test paragraph %d:", n);
   1211                 ImVec2 pos = ImGui::GetCursorScreenPos();
   1212                 ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y);
   1213                 ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight());
   1214                 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
   1215                 if (n == 0)
   1216                     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);
   1217                 else
   1218                     ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
   1219 
   1220                 // Draw actual text bounding box, following by marker of our expected limit (should not overlap!)
   1221                 draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
   1222                 draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255));
   1223                 ImGui::PopTextWrapPos();
   1224             }
   1225 
   1226             ImGui::TreePop();
   1227         }
   1228 
   1229         IMGUI_DEMO_MARKER("Widgets/Text/UTF-8 Text");
   1230         if (ImGui::TreeNode("UTF-8 Text"))
   1231         {
   1232             // UTF-8 test with Japanese characters
   1233             // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
   1234             // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
   1235             // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
   1236             //   can save your source files as 'UTF-8 without signature').
   1237             // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8
   1238             //   CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants.
   1239             //   Don't do this in your application! Please use u8"text in any language" in your application!
   1240             // Note that characters values are preserved even by InputText() if the font cannot be displayed,
   1241             // so you can safely copy & paste garbled characters into another application.
   1242             ImGui::TextWrapped(
   1243                 "CJK text will only appear if the font was loaded with the appropriate CJK character ranges. "
   1244                 "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. "
   1245                 "Read docs/FONTS.md for details.");
   1246             ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
   1247             ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
   1248             static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
   1249             //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
   1250             ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
   1251             ImGui::TreePop();
   1252         }
   1253         ImGui::TreePop();
   1254     }
   1255 
   1256     IMGUI_DEMO_MARKER("Widgets/Images");
   1257     if (ImGui::TreeNode("Images"))
   1258     {
   1259         ImGuiIO& io = ImGui::GetIO();
   1260         ImGui::TextWrapped(
   1261             "Below we are displaying the font texture (which is the only texture we have access to in this demo). "
   1262             "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. "
   1263             "Hover the texture for a zoomed view!");
   1264 
   1265         // Below we are displaying the font texture because it is the only texture we have access to inside the demo!
   1266         // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that
   1267         // will be passed to the rendering backend via the ImDrawCmd structure.
   1268         // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top
   1269         // of their respective source file to specify what they expect to be stored in ImTextureID, for example:
   1270         // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer
   1271         // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc.
   1272         // More:
   1273         // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers
   1274         //   to ImGui::Image(), and gather width/height through your own functions, etc.
   1275         // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer,
   1276         //   it will help you debug issues if you are confused about it.
   1277         // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
   1278         // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
   1279         // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
   1280         ImTextureID my_tex_id = io.Fonts->TexID;
   1281         float my_tex_w = (float)io.Fonts->TexWidth;
   1282         float my_tex_h = (float)io.Fonts->TexHeight;
   1283         {
   1284             static bool use_text_color_for_tint = false;
   1285             ImGui::Checkbox("Use Text Color for Tint", &use_text_color_for_tint);
   1286             ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
   1287             ImVec2 pos = ImGui::GetCursorScreenPos();
   1288             ImVec2 uv_min = ImVec2(0.0f, 0.0f);                 // Top-left
   1289             ImVec2 uv_max = ImVec2(1.0f, 1.0f);                 // Lower-right
   1290             ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
   1291             ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border);
   1292             ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
   1293             if (ImGui::BeginItemTooltip())
   1294             {
   1295                 float region_sz = 32.0f;
   1296                 float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
   1297                 float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
   1298                 float zoom = 4.0f;
   1299                 if (region_x < 0.0f) { region_x = 0.0f; }
   1300                 else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
   1301                 if (region_y < 0.0f) { region_y = 0.0f; }
   1302                 else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
   1303                 ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
   1304                 ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
   1305                 ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
   1306                 ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
   1307                 ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col);
   1308                 ImGui::EndTooltip();
   1309             }
   1310         }
   1311 
   1312         IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons");
   1313         ImGui::TextWrapped("And now some textured buttons..");
   1314         static int pressed_count = 0;
   1315         for (int i = 0; i < 8; i++)
   1316         {
   1317             // UV coordinates are often (0.0f, 0.0f) and (1.0f, 1.0f) to display an entire textures.
   1318             // Here are trying to display only a 32x32 pixels area of the texture, hence the UV computation.
   1319             // Read about UV coordinates here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
   1320             ImGui::PushID(i);
   1321             if (i > 0)
   1322                 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(i - 1.0f, i - 1.0f));
   1323             ImVec2 size = ImVec2(32.0f, 32.0f);                         // Size of the image we want to make visible
   1324             ImVec2 uv0 = ImVec2(0.0f, 0.0f);                            // UV coordinates for lower-left
   1325             ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h);    // UV coordinates for (32,32) in our texture
   1326             ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);             // Black background
   1327             ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);           // No tint
   1328             if (ImGui::ImageButton("", my_tex_id, size, uv0, uv1, bg_col, tint_col))
   1329                 pressed_count += 1;
   1330             if (i > 0)
   1331                 ImGui::PopStyleVar();
   1332             ImGui::PopID();
   1333             ImGui::SameLine();
   1334         }
   1335         ImGui::NewLine();
   1336         ImGui::Text("Pressed %d times.", pressed_count);
   1337         ImGui::TreePop();
   1338     }
   1339 
   1340     IMGUI_DEMO_MARKER("Widgets/Combo");
   1341     if (ImGui::TreeNode("Combo"))
   1342     {
   1343         // Combo Boxes are also called "Dropdown" in other systems
   1344         // Expose flags as checkbox for the demo
   1345         static ImGuiComboFlags flags = 0;
   1346         ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft);
   1347         ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
   1348         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton))
   1349             flags &= ~ImGuiComboFlags_NoPreview;     // Clear incompatible flags
   1350         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview))
   1351             flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear incompatible flags
   1352         if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview))
   1353             flags &= ~ImGuiComboFlags_NoPreview;
   1354 
   1355         // Override default popup height
   1356         if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightSmall", &flags, ImGuiComboFlags_HeightSmall))
   1357             flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightSmall);
   1358         if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightRegular", &flags, ImGuiComboFlags_HeightRegular))
   1359             flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightRegular);
   1360         if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightLargest", &flags, ImGuiComboFlags_HeightLargest))
   1361             flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightLargest);
   1362 
   1363         // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
   1364         // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
   1365         // stored in the object itself, etc.)
   1366         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
   1367         static int item_selected_idx = 0; // Here we store our selection data as an index.
   1368 
   1369         // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[])
   1370         const char* combo_preview_value = items[item_selected_idx];
   1371 
   1372         if (ImGui::BeginCombo("combo 1", combo_preview_value, flags))
   1373         {
   1374             for (int n = 0; n < IM_ARRAYSIZE(items); n++)
   1375             {
   1376                 const bool is_selected = (item_selected_idx == n);
   1377                 if (ImGui::Selectable(items[n], is_selected))
   1378                     item_selected_idx = n;
   1379 
   1380                 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
   1381                 if (is_selected)
   1382                     ImGui::SetItemDefaultFocus();
   1383             }
   1384             ImGui::EndCombo();
   1385         }
   1386 
   1387         ImGui::Spacing();
   1388         ImGui::SeparatorText("One-liner variants");
   1389         HelpMarker("Flags above don't apply to this section.");
   1390 
   1391         // Simplified one-liner Combo() API, using values packed in a single constant string
   1392         // This is a convenience for when the selection set is small and known at compile-time.
   1393         static int item_current_2 = 0;
   1394         ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
   1395 
   1396         // Simplified one-liner Combo() using an array of const char*
   1397         // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control.
   1398         static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
   1399         ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
   1400 
   1401         // Simplified one-liner Combo() using an accessor function
   1402         static int item_current_4 = 0;
   1403         ImGui::Combo("combo 4 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items));
   1404 
   1405         ImGui::TreePop();
   1406     }
   1407 
   1408     IMGUI_DEMO_MARKER("Widgets/List Boxes");
   1409     if (ImGui::TreeNode("List boxes"))
   1410     {
   1411         // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild()
   1412         // using the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
   1413         // You may be tempted to simply use BeginChild() directly. However note that BeginChild() requires EndChild()
   1414         // to always be called (inconsistent with BeginListBox()/EndListBox()).
   1415 
   1416         // Using the generic BeginListBox() API, you have full control over how to display the combo contents.
   1417         // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
   1418         // stored in the object itself, etc.)
   1419         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
   1420         static int item_selected_idx = 0; // Here we store our selected data as an index.
   1421 
   1422         static bool item_highlight = false;
   1423         int item_highlighted_idx = -1; // Here we store our highlighted data as an index.
   1424         ImGui::Checkbox("Highlight hovered item in second listbox", &item_highlight);
   1425 
   1426         if (ImGui::BeginListBox("listbox 1"))
   1427         {
   1428             for (int n = 0; n < IM_ARRAYSIZE(items); n++)
   1429             {
   1430                 const bool is_selected = (item_selected_idx == n);
   1431                 if (ImGui::Selectable(items[n], is_selected))
   1432                     item_selected_idx = n;
   1433 
   1434                 if (item_highlight && ImGui::IsItemHovered())
   1435                     item_highlighted_idx = n;
   1436 
   1437                 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
   1438                 if (is_selected)
   1439                     ImGui::SetItemDefaultFocus();
   1440             }
   1441             ImGui::EndListBox();
   1442         }
   1443         ImGui::SameLine(); HelpMarker("Here we are sharing selection state between both boxes.");
   1444 
   1445         // Custom size: use all width, 5 items tall
   1446         ImGui::Text("Full-width:");
   1447         if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing())))
   1448         {
   1449             for (int n = 0; n < IM_ARRAYSIZE(items); n++)
   1450             {
   1451                 bool is_selected = (item_selected_idx == n);
   1452                 ImGuiSelectableFlags flags = (item_highlighted_idx == n) ? ImGuiSelectableFlags_Highlight : 0;
   1453                 if (ImGui::Selectable(items[n], is_selected, flags))
   1454                     item_selected_idx = n;
   1455 
   1456                 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
   1457                 if (is_selected)
   1458                     ImGui::SetItemDefaultFocus();
   1459             }
   1460             ImGui::EndListBox();
   1461         }
   1462 
   1463         ImGui::TreePop();
   1464     }
   1465 
   1466     IMGUI_DEMO_MARKER("Widgets/Selectables");
   1467     //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
   1468     if (ImGui::TreeNode("Selectables"))
   1469     {
   1470         // Selectable() has 2 overloads:
   1471         // - The one taking "bool selected" as a read-only selection information.
   1472         //   When Selectable() has been clicked it returns true and you can alter selection state accordingly.
   1473         // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
   1474         // The earlier is more flexible, as in real application your selection may be stored in many different ways
   1475         // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc).
   1476         IMGUI_DEMO_MARKER("Widgets/Selectables/Basic");
   1477         if (ImGui::TreeNode("Basic"))
   1478         {
   1479             static bool selection[5] = { false, true, false, false };
   1480             ImGui::Selectable("1. I am selectable", &selection[0]);
   1481             ImGui::Selectable("2. I am selectable", &selection[1]);
   1482             ImGui::Selectable("3. I am selectable", &selection[2]);
   1483             if (ImGui::Selectable("4. I am double clickable", selection[3], ImGuiSelectableFlags_AllowDoubleClick))
   1484                 if (ImGui::IsMouseDoubleClicked(0))
   1485                     selection[3] = !selection[3];
   1486             ImGui::TreePop();
   1487         }
   1488 
   1489         IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more items on the same line");
   1490         if (ImGui::TreeNode("Rendering more items on the same line"))
   1491         {
   1492             // (1) Using SetNextItemAllowOverlap()
   1493             // (2) Using the Selectable() override that takes "bool* p_selected" parameter, the bool value is toggled automatically.
   1494             static bool selected[3] = { false, false, false };
   1495             ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("main.c",    &selected[0]); ImGui::SameLine(); ImGui::SmallButton("Link 1");
   1496             ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(); ImGui::SmallButton("Link 2");
   1497             ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.h",   &selected[2]); ImGui::SameLine(); ImGui::SmallButton("Link 3");
   1498             ImGui::TreePop();
   1499         }
   1500 
   1501         IMGUI_DEMO_MARKER("Widgets/Selectables/In Tables");
   1502         if (ImGui::TreeNode("In Tables"))
   1503         {
   1504             static bool selected[10] = {};
   1505 
   1506             if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
   1507             {
   1508                 for (int i = 0; i < 10; i++)
   1509                 {
   1510                     char label[32];
   1511                     sprintf(label, "Item %d", i);
   1512                     ImGui::TableNextColumn();
   1513                     ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap
   1514                 }
   1515                 ImGui::EndTable();
   1516             }
   1517             ImGui::Spacing();
   1518             if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
   1519             {
   1520                 for (int i = 0; i < 10; i++)
   1521                 {
   1522                     char label[32];
   1523                     sprintf(label, "Item %d", i);
   1524                     ImGui::TableNextRow();
   1525                     ImGui::TableNextColumn();
   1526                     ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns);
   1527                     ImGui::TableNextColumn();
   1528                     ImGui::Text("Some other contents");
   1529                     ImGui::TableNextColumn();
   1530                     ImGui::Text("123456");
   1531                 }
   1532                 ImGui::EndTable();
   1533             }
   1534             ImGui::TreePop();
   1535         }
   1536 
   1537         IMGUI_DEMO_MARKER("Widgets/Selectables/Grid");
   1538         if (ImGui::TreeNode("Grid"))
   1539         {
   1540             static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
   1541 
   1542             // Add in a bit of silly fun...
   1543             const float time = (float)ImGui::GetTime();
   1544             const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected...
   1545             if (winning_state)
   1546                 ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f)));
   1547 
   1548             for (int y = 0; y < 4; y++)
   1549                 for (int x = 0; x < 4; x++)
   1550                 {
   1551                     if (x > 0)
   1552                         ImGui::SameLine();
   1553                     ImGui::PushID(y * 4 + x);
   1554                     if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50)))
   1555                     {
   1556                         // Toggle clicked cell + toggle neighbors
   1557                         selected[y][x] ^= 1;
   1558                         if (x > 0) { selected[y][x - 1] ^= 1; }
   1559                         if (x < 3) { selected[y][x + 1] ^= 1; }
   1560                         if (y > 0) { selected[y - 1][x] ^= 1; }
   1561                         if (y < 3) { selected[y + 1][x] ^= 1; }
   1562                     }
   1563                     ImGui::PopID();
   1564                 }
   1565 
   1566             if (winning_state)
   1567                 ImGui::PopStyleVar();
   1568             ImGui::TreePop();
   1569         }
   1570         IMGUI_DEMO_MARKER("Widgets/Selectables/Alignment");
   1571         if (ImGui::TreeNode("Alignment"))
   1572         {
   1573             HelpMarker(
   1574                 "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item "
   1575                 "basis using PushStyleVar(). You'll probably want to always keep your default situation to "
   1576                 "left-align otherwise it becomes difficult to layout multiple items on a same line");
   1577             static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true };
   1578             for (int y = 0; y < 3; y++)
   1579             {
   1580                 for (int x = 0; x < 3; x++)
   1581                 {
   1582                     ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
   1583                     char name[32];
   1584                     sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
   1585                     if (x > 0) ImGui::SameLine();
   1586                     ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
   1587                     ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80));
   1588                     ImGui::PopStyleVar();
   1589                 }
   1590             }
   1591             ImGui::TreePop();
   1592         }
   1593         ImGui::TreePop();
   1594     }
   1595 
   1596     ShowDemoWindowMultiSelect(demo_data);
   1597 
   1598     // To wire InputText() with std::string or any other custom string type,
   1599     // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
   1600     IMGUI_DEMO_MARKER("Widgets/Text Input");
   1601     if (ImGui::TreeNode("Text Input"))
   1602     {
   1603         IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input");
   1604         if (ImGui::TreeNode("Multi-line Text Input"))
   1605         {
   1606             // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
   1607             // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
   1608             static char text[1024 * 16] =
   1609                 "/*\n"
   1610                 " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
   1611                 " the hexadecimal encoding of one offending instruction,\n"
   1612                 " more formally, the invalid operand with locked CMPXCHG8B\n"
   1613                 " instruction bug, is a design flaw in the majority of\n"
   1614                 " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
   1615                 " processors (all in the P5 microarchitecture).\n"
   1616                 "*/\n\n"
   1617                 "label:\n"
   1618                 "\tlock cmpxchg8b eax\n";
   1619 
   1620             static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
   1621             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)");
   1622             ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
   1623             ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
   1624             ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets.");
   1625             ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
   1626             ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
   1627             ImGui::TreePop();
   1628         }
   1629 
   1630         IMGUI_DEMO_MARKER("Widgets/Text Input/Filtered Text Input");
   1631         if (ImGui::TreeNode("Filtered Text Input"))
   1632         {
   1633             struct TextFilters
   1634             {
   1635                 // Modify character input by altering 'data->Eventchar' (ImGuiInputTextFlags_CallbackCharFilter callback)
   1636                 static int FilterCasingSwap(ImGuiInputTextCallbackData* data)
   1637                 {
   1638                     if (data->EventChar >= 'a' && data->EventChar <= 'z')       { data->EventChar -= 'a' - 'A'; } // Lowercase becomes uppercase
   1639                     else if (data->EventChar >= 'A' && data->EventChar <= 'Z')  { data->EventChar += 'a' - 'A'; } // Uppercase becomes lowercase
   1640                     return 0;
   1641                 }
   1642 
   1643                 // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i', otherwise return 1 (filter out)
   1644                 static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
   1645                 {
   1646                     if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
   1647                         return 0;
   1648                     return 1;
   1649                 }
   1650             };
   1651 
   1652             static char buf1[32] = ""; ImGui::InputText("default",     buf1, 32);
   1653             static char buf2[32] = ""; ImGui::InputText("decimal",     buf2, 32, ImGuiInputTextFlags_CharsDecimal);
   1654             static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
   1655             static char buf4[32] = ""; ImGui::InputText("uppercase",   buf4, 32, ImGuiInputTextFlags_CharsUppercase);
   1656             static char buf5[32] = ""; ImGui::InputText("no blank",    buf5, 32, ImGuiInputTextFlags_CharsNoBlank);
   1657             static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters.
   1658             static char buf7[32] = ""; ImGui::InputText("\"imgui\"",   buf7, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters.
   1659             ImGui::TreePop();
   1660         }
   1661 
   1662         IMGUI_DEMO_MARKER("Widgets/Text Input/Password input");
   1663         if (ImGui::TreeNode("Password Input"))
   1664         {
   1665             static char password[64] = "password123";
   1666             ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
   1667             ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
   1668             ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
   1669             ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password));
   1670             ImGui::TreePop();
   1671         }
   1672 
   1673         IMGUI_DEMO_MARKER("Widgets/Text Input/Completion, History, Edit Callbacks");
   1674         if (ImGui::TreeNode("Completion, History, Edit Callbacks"))
   1675         {
   1676             struct Funcs
   1677             {
   1678                 static int MyCallback(ImGuiInputTextCallbackData* data)
   1679                 {
   1680                     if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
   1681                     {
   1682                         data->InsertChars(data->CursorPos, "..");
   1683                     }
   1684                     else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
   1685                     {
   1686                         if (data->EventKey == ImGuiKey_UpArrow)
   1687                         {
   1688                             data->DeleteChars(0, data->BufTextLen);
   1689                             data->InsertChars(0, "Pressed Up!");
   1690                             data->SelectAll();
   1691                         }
   1692                         else if (data->EventKey == ImGuiKey_DownArrow)
   1693                         {
   1694                             data->DeleteChars(0, data->BufTextLen);
   1695                             data->InsertChars(0, "Pressed Down!");
   1696                             data->SelectAll();
   1697                         }
   1698                     }
   1699                     else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
   1700                     {
   1701                         // Toggle casing of first character
   1702                         char c = data->Buf[0];
   1703                         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32;
   1704                         data->BufDirty = true;
   1705 
   1706                         // Increment a counter
   1707                         int* p_int = (int*)data->UserData;
   1708                         *p_int = *p_int + 1;
   1709                     }
   1710                     return 0;
   1711                 }
   1712             };
   1713             static char buf1[64];
   1714             ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
   1715             ImGui::SameLine(); HelpMarker(
   1716                 "Here we append \"..\" each time Tab is pressed. "
   1717                 "See 'Examples>Console' for a more meaningful demonstration of using this callback.");
   1718 
   1719             static char buf2[64];
   1720             ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
   1721             ImGui::SameLine(); HelpMarker(
   1722                 "Here we replace and select text each time Up/Down are pressed. "
   1723                 "See 'Examples>Console' for a more meaningful demonstration of using this callback.");
   1724 
   1725             static char buf3[64];
   1726             static int edit_count = 0;
   1727             ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
   1728             ImGui::SameLine(); HelpMarker(
   1729                 "Here we toggle the casing of the first character on every edit + count edits.");
   1730             ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
   1731 
   1732             ImGui::TreePop();
   1733         }
   1734 
   1735         IMGUI_DEMO_MARKER("Widgets/Text Input/Resize Callback");
   1736         if (ImGui::TreeNode("Resize Callback"))
   1737         {
   1738             // To wire InputText() with std::string or any other custom string type,
   1739             // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper
   1740             // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string.
   1741             HelpMarker(
   1742                 "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n"
   1743                 "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string.");
   1744             struct Funcs
   1745             {
   1746                 static int MyResizeCallback(ImGuiInputTextCallbackData* data)
   1747                 {
   1748                     if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
   1749                     {
   1750                         ImVector<char>* my_str = (ImVector<char>*)data->UserData;
   1751                         IM_ASSERT(my_str->begin() == data->Buf);
   1752                         my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1
   1753                         data->Buf = my_str->begin();
   1754                     }
   1755                     return 0;
   1756                 }
   1757 
   1758                 // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace.
   1759                 // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)'
   1760                 static bool MyInputTextMultiline(const char* label, ImVector<char>* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
   1761                 {
   1762                     IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
   1763                     return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str);
   1764                 }
   1765             };
   1766 
   1767             // For this demo we are using ImVector as a string container.
   1768             // Note that because we need to store a terminating zero character, our size/capacity are 1 more
   1769             // than usually reported by a typical string class.
   1770             static ImVector<char> my_str;
   1771             if (my_str.empty())
   1772                 my_str.push_back(0);
   1773             Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16));
   1774             ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity());
   1775             ImGui::TreePop();
   1776         }
   1777 
   1778         IMGUI_DEMO_MARKER("Widgets/Text Input/Miscellaneous");
   1779         if (ImGui::TreeNode("Miscellaneous"))
   1780         {
   1781             static char buf1[16];
   1782             static ImGuiInputTextFlags flags = ImGuiInputTextFlags_EscapeClearsAll;
   1783             ImGui::CheckboxFlags("ImGuiInputTextFlags_EscapeClearsAll", &flags, ImGuiInputTextFlags_EscapeClearsAll);
   1784             ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
   1785             ImGui::CheckboxFlags("ImGuiInputTextFlags_NoUndoRedo", &flags, ImGuiInputTextFlags_NoUndoRedo);
   1786             ImGui::InputText("Hello", buf1, IM_ARRAYSIZE(buf1), flags);
   1787             ImGui::TreePop();
   1788         }
   1789 
   1790         ImGui::TreePop();
   1791     }
   1792 
   1793     // Tabs
   1794     IMGUI_DEMO_MARKER("Widgets/Tabs");
   1795     if (ImGui::TreeNode("Tabs"))
   1796     {
   1797         IMGUI_DEMO_MARKER("Widgets/Tabs/Basic");
   1798         if (ImGui::TreeNode("Basic"))
   1799         {
   1800             ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
   1801             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
   1802             {
   1803                 if (ImGui::BeginTabItem("Avocado"))
   1804                 {
   1805                     ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
   1806                     ImGui::EndTabItem();
   1807                 }
   1808                 if (ImGui::BeginTabItem("Broccoli"))
   1809                 {
   1810                     ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
   1811                     ImGui::EndTabItem();
   1812                 }
   1813                 if (ImGui::BeginTabItem("Cucumber"))
   1814                 {
   1815                     ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
   1816                     ImGui::EndTabItem();
   1817                 }
   1818                 ImGui::EndTabBar();
   1819             }
   1820             ImGui::Separator();
   1821             ImGui::TreePop();
   1822         }
   1823 
   1824         IMGUI_DEMO_MARKER("Widgets/Tabs/Advanced & Close Button");
   1825         if (ImGui::TreeNode("Advanced & Close Button"))
   1826         {
   1827             // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
   1828             static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
   1829             ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable);
   1830             ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
   1831             ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
   1832             ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
   1833             ImGui::CheckboxFlags("ImGuiTabBarFlags_DrawSelectedOverline", &tab_bar_flags, ImGuiTabBarFlags_DrawSelectedOverline);
   1834             if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
   1835                 tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
   1836             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
   1837                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
   1838             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
   1839                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
   1840 
   1841             // Tab Bar
   1842             ImGui::AlignTextToFramePadding();
   1843             ImGui::Text("Opened:");
   1844             const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
   1845             static bool opened[4] = { true, true, true, true }; // Persistent user state
   1846             for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
   1847             {
   1848                 ImGui::SameLine();
   1849                 ImGui::Checkbox(names[n], &opened[n]);
   1850             }
   1851 
   1852             // Passing a bool* to BeginTabItem() is similar to passing one to Begin():
   1853             // the underlying bool will be set to false when the tab is closed.
   1854             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
   1855             {
   1856                 for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
   1857                     if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
   1858                     {
   1859                         ImGui::Text("This is the %s tab!", names[n]);
   1860                         if (n & 1)
   1861                             ImGui::Text("I am an odd tab.");
   1862                         ImGui::EndTabItem();
   1863                     }
   1864                 ImGui::EndTabBar();
   1865             }
   1866             ImGui::Separator();
   1867             ImGui::TreePop();
   1868         }
   1869 
   1870         IMGUI_DEMO_MARKER("Widgets/Tabs/TabItemButton & Leading-Trailing flags");
   1871         if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags"))
   1872         {
   1873             static ImVector<int> active_tabs;
   1874             static int next_tab_id = 0;
   1875             if (next_tab_id == 0) // Initialize with some default tabs
   1876                 for (int i = 0; i < 3; i++)
   1877                     active_tabs.push_back(next_tab_id++);
   1878 
   1879             // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together.
   1880             // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags...
   1881             // but they tend to make more sense together)
   1882             static bool show_leading_button = true;
   1883             static bool show_trailing_button = true;
   1884             ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
   1885             ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
   1886 
   1887             // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
   1888             static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown;
   1889             ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
   1890             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
   1891                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
   1892             if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
   1893                 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
   1894 
   1895             if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
   1896             {
   1897                 // Demo a Leading TabItemButton(): click the "?" button to open a menu
   1898                 if (show_leading_button)
   1899                     if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip))
   1900                         ImGui::OpenPopup("MyHelpMenu");
   1901                 if (ImGui::BeginPopup("MyHelpMenu"))
   1902                 {
   1903                     ImGui::Selectable("Hello!");
   1904                     ImGui::EndPopup();
   1905                 }
   1906 
   1907                 // Demo Trailing Tabs: click the "+" button to add a new tab.
   1908                 // (In your app you may want to use a font icon instead of the "+")
   1909                 // We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
   1910                 if (show_trailing_button)
   1911                     if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
   1912                         active_tabs.push_back(next_tab_id++); // Add new tab
   1913 
   1914                 // Submit our regular tabs
   1915                 for (int n = 0; n < active_tabs.Size; )
   1916                 {
   1917                     bool open = true;
   1918                     char name[16];
   1919                     snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);
   1920                     if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
   1921                     {
   1922                         ImGui::Text("This is the %s tab!", name);
   1923                         ImGui::EndTabItem();
   1924                     }
   1925 
   1926                     if (!open)
   1927                         active_tabs.erase(active_tabs.Data + n);
   1928                     else
   1929                         n++;
   1930                 }
   1931 
   1932                 ImGui::EndTabBar();
   1933             }
   1934             ImGui::Separator();
   1935             ImGui::TreePop();
   1936         }
   1937         ImGui::TreePop();
   1938     }
   1939 
   1940     // Plot/Graph widgets are not very good.
   1941     // Consider using a third-party library such as ImPlot: https://github.com/epezent/implot
   1942     // (see others https://github.com/ocornut/imgui/wiki/Useful-Extensions)
   1943     IMGUI_DEMO_MARKER("Widgets/Plotting");
   1944     if (ImGui::TreeNode("Plotting"))
   1945     {
   1946         static bool animate = true;
   1947         ImGui::Checkbox("Animate", &animate);
   1948 
   1949         // Plot as lines and plot as histogram
   1950         static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
   1951         ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
   1952         ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
   1953         //ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!");
   1954 
   1955         // Fill an array of contiguous float values to plot
   1956         // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
   1957         // and the sizeof() of your structure in the "stride" parameter.
   1958         static float values[90] = {};
   1959         static int values_offset = 0;
   1960         static double refresh_time = 0.0;
   1961         if (!animate || refresh_time == 0.0)
   1962             refresh_time = ImGui::GetTime();
   1963         while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
   1964         {
   1965             static float phase = 0.0f;
   1966             values[values_offset] = cosf(phase);
   1967             values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
   1968             phase += 0.10f * values_offset;
   1969             refresh_time += 1.0f / 60.0f;
   1970         }
   1971 
   1972         // Plots can display overlay texts
   1973         // (in this example, we will display an average value)
   1974         {
   1975             float average = 0.0f;
   1976             for (int n = 0; n < IM_ARRAYSIZE(values); n++)
   1977                 average += values[n];
   1978             average /= (float)IM_ARRAYSIZE(values);
   1979             char overlay[32];
   1980             sprintf(overlay, "avg %f", average);
   1981             ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
   1982         }
   1983 
   1984         // Use functions to generate output
   1985         // FIXME: This is actually VERY awkward because current plot API only pass in indices.
   1986         // We probably want an API passing floats and user provide sample rate/count.
   1987         struct Funcs
   1988         {
   1989             static float Sin(void*, int i) { return sinf(i * 0.1f); }
   1990             static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
   1991         };
   1992         static int func_type = 0, display_count = 70;
   1993         ImGui::SeparatorText("Functions");
   1994         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   1995         ImGui::Combo("func", &func_type, "Sin\0Saw\0");
   1996         ImGui::SameLine();
   1997         ImGui::SliderInt("Sample count", &display_count, 1, 400);
   1998         float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
   1999         ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
   2000         ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
   2001         ImGui::Separator();
   2002 
   2003         ImGui::TreePop();
   2004     }
   2005 
   2006     IMGUI_DEMO_MARKER("Widgets/Progress Bars");
   2007     if (ImGui::TreeNode("Progress Bars"))
   2008     {
   2009         // Animate a simple progress bar
   2010         static float progress = 0.0f, progress_dir = 1.0f;
   2011         progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
   2012         if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
   2013         if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
   2014 
   2015         // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
   2016         // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
   2017         ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
   2018         ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
   2019         ImGui::Text("Progress Bar");
   2020 
   2021         float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
   2022         char buf[32];
   2023         sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
   2024         ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
   2025 
   2026         // Pass an animated negative value, e.g. -1.0f * (float)ImGui::GetTime() is the recommended value.
   2027         // Adjust the factor if you want to adjust the animation speed.
   2028         ImGui::ProgressBar(-1.0f * (float)ImGui::GetTime(), ImVec2(0.0f, 0.0f), "Searching..");
   2029         ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
   2030         ImGui::Text("Indeterminate");
   2031 
   2032         ImGui::TreePop();
   2033     }
   2034 
   2035     IMGUI_DEMO_MARKER("Widgets/Color");
   2036     if (ImGui::TreeNode("Color/Picker Widgets"))
   2037     {
   2038         static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
   2039 
   2040         static bool alpha_preview = true;
   2041         static bool alpha_half_preview = false;
   2042         static bool drag_and_drop = true;
   2043         static bool options_menu = true;
   2044         static bool hdr = false;
   2045         ImGui::SeparatorText("Options");
   2046         ImGui::Checkbox("With Alpha Preview", &alpha_preview);
   2047         ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
   2048         ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
   2049         ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
   2050         ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
   2051         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);
   2052 
   2053         IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit");
   2054         ImGui::SeparatorText("Inline color editor");
   2055         ImGui::Text("Color widget:");
   2056         ImGui::SameLine(); HelpMarker(
   2057             "Click on the color square to open a color picker.\n"
   2058             "CTRL+click on individual component to input value.\n");
   2059         ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
   2060 
   2061         IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)");
   2062         ImGui::Text("Color widget HSV with Alpha:");
   2063         ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags);
   2064 
   2065         IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (float display)");
   2066         ImGui::Text("Color widget with Float Display:");
   2067         ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
   2068 
   2069         IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with Picker)");
   2070         ImGui::Text("Color button with Picker:");
   2071         ImGui::SameLine(); HelpMarker(
   2072             "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n"
   2073             "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only "
   2074             "be used for the tooltip and picker popup.");
   2075         ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
   2076 
   2077         IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with custom Picker popup)");
   2078         ImGui::Text("Color button with Custom Picker Popup:");
   2079 
   2080         // Generate a default palette. The palette will persist and can be edited.
   2081         static bool saved_palette_init = true;
   2082         static ImVec4 saved_palette[32] = {};
   2083         if (saved_palette_init)
   2084         {
   2085             for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
   2086             {
   2087                 ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f,
   2088                     saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
   2089                 saved_palette[n].w = 1.0f; // Alpha
   2090             }
   2091             saved_palette_init = false;
   2092         }
   2093 
   2094         static ImVec4 backup_color;
   2095         bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
   2096         ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
   2097         open_popup |= ImGui::Button("Palette");
   2098         if (open_popup)
   2099         {
   2100             ImGui::OpenPopup("mypicker");
   2101             backup_color = color;
   2102         }
   2103         if (ImGui::BeginPopup("mypicker"))
   2104         {
   2105             ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
   2106             ImGui::Separator();
   2107             ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
   2108             ImGui::SameLine();
   2109 
   2110             ImGui::BeginGroup(); // Lock X position
   2111             ImGui::Text("Current");
   2112             ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
   2113             ImGui::Text("Previous");
   2114             if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
   2115                 color = backup_color;
   2116             ImGui::Separator();
   2117             ImGui::Text("Palette");
   2118             for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
   2119             {
   2120                 ImGui::PushID(n);
   2121                 if ((n % 8) != 0)
   2122                     ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
   2123 
   2124                 ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
   2125                 if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
   2126                     color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
   2127 
   2128                 // Allow user to drop colors into each palette entry. Note that ColorButton() is already a
   2129                 // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag.
   2130                 if (ImGui::BeginDragDropTarget())
   2131                 {
   2132                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
   2133                         memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
   2134                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
   2135                         memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
   2136                     ImGui::EndDragDropTarget();
   2137                 }
   2138 
   2139                 ImGui::PopID();
   2140             }
   2141             ImGui::EndGroup();
   2142             ImGui::EndPopup();
   2143         }
   2144 
   2145         IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (simple)");
   2146         ImGui::Text("Color button only:");
   2147         static bool no_border = false;
   2148         ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
   2149         ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
   2150 
   2151         IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker");
   2152         ImGui::SeparatorText("Color picker");
   2153         static bool alpha = true;
   2154         static bool alpha_bar = true;
   2155         static bool side_preview = true;
   2156         static bool ref_color = false;
   2157         static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
   2158         static int display_mode = 0;
   2159         static int picker_mode = 0;
   2160         ImGui::Checkbox("With Alpha", &alpha);
   2161         ImGui::Checkbox("With Alpha Bar", &alpha_bar);
   2162         ImGui::Checkbox("With Side Preview", &side_preview);
   2163         if (side_preview)
   2164         {
   2165             ImGui::SameLine();
   2166             ImGui::Checkbox("With Ref Color", &ref_color);
   2167             if (ref_color)
   2168             {
   2169                 ImGui::SameLine();
   2170                 ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
   2171             }
   2172         }
   2173         ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
   2174         ImGui::SameLine(); HelpMarker(
   2175             "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
   2176             "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
   2177             "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
   2178         ImGui::SameLine(); HelpMarker("When not specified explicitly (Auto/Current mode), user can right-click the picker to change mode.");
   2179         ImGuiColorEditFlags flags = misc_flags;
   2180         if (!alpha)            flags |= ImGuiColorEditFlags_NoAlpha;        // This is by default if you call ColorPicker3() instead of ColorPicker4()
   2181         if (alpha_bar)         flags |= ImGuiColorEditFlags_AlphaBar;
   2182         if (!side_preview)     flags |= ImGuiColorEditFlags_NoSidePreview;
   2183         if (picker_mode == 1)  flags |= ImGuiColorEditFlags_PickerHueBar;
   2184         if (picker_mode == 2)  flags |= ImGuiColorEditFlags_PickerHueWheel;
   2185         if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;       // Disable all RGB/HSV/Hex displays
   2186         if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB;     // Override display mode
   2187         if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
   2188         if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
   2189         ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
   2190 
   2191         ImGui::Text("Set defaults in code:");
   2192         ImGui::SameLine(); HelpMarker(
   2193             "SetColorEditOptions() is designed to allow you to set boot-time default.\n"
   2194             "We don't have Push/Pop functions because you can force options on a per-widget basis if needed,"
   2195             "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid"
   2196             "encouraging you to persistently save values that aren't forward-compatible.");
   2197         if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
   2198             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
   2199         if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
   2200             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
   2201 
   2202         // Always display a small version of both types of pickers
   2203         // (that's in order to make it more visible in the demo to people who are skimming quickly through it)
   2204         ImGui::Text("Both types:");
   2205         float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f;
   2206         ImGui::SetNextItemWidth(w);
   2207         ImGui::ColorPicker3("##MyColor##5", (float*)&color, ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
   2208         ImGui::SameLine();
   2209         ImGui::SetNextItemWidth(w);
   2210         ImGui::ColorPicker3("##MyColor##6", (float*)&color, ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
   2211 
   2212         // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
   2213         static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
   2214         ImGui::Spacing();
   2215         ImGui::Text("HSV encoded colors");
   2216         ImGui::SameLine(); HelpMarker(
   2217             "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV"
   2218             "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the"
   2219             "added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
   2220         ImGui::Text("Color widget with InputHSV:");
   2221         ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
   2222         ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
   2223         ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f);
   2224 
   2225         ImGui::TreePop();
   2226     }
   2227 
   2228     IMGUI_DEMO_MARKER("Widgets/Drag and Slider Flags");
   2229     if (ImGui::TreeNode("Drag/Slider Flags"))
   2230     {
   2231         // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
   2232         static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
   2233         ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp);
   2234         ImGui::SameLine(); HelpMarker("Always clamp value to min/max bounds (if any) when input manually with CTRL+Click.");
   2235         ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic);
   2236         ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values).");
   2237         ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat);
   2238         ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
   2239         ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
   2240         ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
   2241         ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround);
   2242         ImGui::SameLine(); HelpMarker("Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions)");
   2243 
   2244         // Drags
   2245         static float drag_f = 0.5f;
   2246         static int drag_i = 50;
   2247         ImGui::Text("Underlying float value: %f", drag_f);
   2248         ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags);
   2249         ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags);
   2250         ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags);
   2251         ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags);
   2252         ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
   2253 
   2254         // Sliders
   2255         static float slider_f = 0.5f;
   2256         static int slider_i = 50;
   2257         const ImGuiSliderFlags flags_for_sliders = flags & ~ImGuiSliderFlags_WrapAround;
   2258         ImGui::Text("Underlying float value: %f", slider_f);
   2259         ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags_for_sliders);
   2260         ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags_for_sliders);
   2261 
   2262         ImGui::TreePop();
   2263     }
   2264 
   2265     IMGUI_DEMO_MARKER("Widgets/Range Widgets");
   2266     if (ImGui::TreeNode("Range Widgets"))
   2267     {
   2268         static float begin = 10, end = 90;
   2269         static int begin_i = 100, end_i = 1000;
   2270         ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp);
   2271         ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units");
   2272         ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
   2273         ImGui::TreePop();
   2274     }
   2275 
   2276     IMGUI_DEMO_MARKER("Widgets/Data Types");
   2277     if (ImGui::TreeNode("Data Types"))
   2278     {
   2279         // DragScalar/InputScalar/SliderScalar functions allow various data types
   2280         // - signed/unsigned
   2281         // - 8/16/32/64-bits
   2282         // - integer/float/double
   2283         // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum
   2284         // to pass the type, and passing all arguments by pointer.
   2285         // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each type.
   2286         // In practice, if you frequently use a given type that is not covered by the normal API entry points,
   2287         // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*,
   2288         // and then pass their address to the generic function. For example:
   2289         //   bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
   2290         //   {
   2291         //      return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
   2292         //   }
   2293 
   2294         // Setup limits (as helper variables so we can take their address, as explained above)
   2295         // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
   2296         #ifndef LLONG_MIN
   2297         ImS64 LLONG_MIN = -9223372036854775807LL - 1;
   2298         ImS64 LLONG_MAX = 9223372036854775807LL;
   2299         ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
   2300         #endif
   2301         const char    s8_zero  = 0,   s8_one  = 1,   s8_fifty  = 50, s8_min  = -128,        s8_max = 127;
   2302         const ImU8    u8_zero  = 0,   u8_one  = 1,   u8_fifty  = 50, u8_min  = 0,           u8_max = 255;
   2303         const short   s16_zero = 0,   s16_one = 1,   s16_fifty = 50, s16_min = -32768,      s16_max = 32767;
   2304         const ImU16   u16_zero = 0,   u16_one = 1,   u16_fifty = 50, u16_min = 0,           u16_max = 65535;
   2305         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;
   2306         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;
   2307         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;
   2308         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;
   2309         const float   f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
   2310         const double  f64_zero = 0.,  f64_one = 1.,  f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
   2311 
   2312         // State
   2313         static char   s8_v  = 127;
   2314         static ImU8   u8_v  = 255;
   2315         static short  s16_v = 32767;
   2316         static ImU16  u16_v = 65535;
   2317         static ImS32  s32_v = -1;
   2318         static ImU32  u32_v = (ImU32)-1;
   2319         static ImS64  s64_v = -1;
   2320         static ImU64  u64_v = (ImU64)-1;
   2321         static float  f32_v = 0.123f;
   2322         static double f64_v = 90000.01234567890123456789;
   2323 
   2324         const float drag_speed = 0.2f;
   2325         static bool drag_clamp = false;
   2326         IMGUI_DEMO_MARKER("Widgets/Data Types/Drags");
   2327         ImGui::SeparatorText("Drags");
   2328         ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
   2329         ImGui::SameLine(); HelpMarker(
   2330             "As with every widget in dear imgui, we never modify values unless there is a user interaction.\n"
   2331             "You can override the clamping limits by using CTRL+Click to input a value.");
   2332         ImGui::DragScalar("drag s8",        ImGuiDataType_S8,     &s8_v,  drag_speed, drag_clamp ? &s8_zero  : NULL, drag_clamp ? &s8_fifty  : NULL);
   2333         ImGui::DragScalar("drag u8",        ImGuiDataType_U8,     &u8_v,  drag_speed, drag_clamp ? &u8_zero  : NULL, drag_clamp ? &u8_fifty  : NULL, "%u ms");
   2334         ImGui::DragScalar("drag s16",       ImGuiDataType_S16,    &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
   2335         ImGui::DragScalar("drag u16",       ImGuiDataType_U16,    &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
   2336         ImGui::DragScalar("drag s32",       ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
   2337         ImGui::DragScalar("drag s32 hex",   ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL, "0x%08X");
   2338         ImGui::DragScalar("drag u32",       ImGuiDataType_U32,    &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
   2339         ImGui::DragScalar("drag s64",       ImGuiDataType_S64,    &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
   2340         ImGui::DragScalar("drag u64",       ImGuiDataType_U64,    &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
   2341         ImGui::DragScalar("drag float",     ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f");
   2342         ImGui::DragScalar("drag float log", ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic);
   2343         ImGui::DragScalar("drag double",    ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL,     "%.10f grams");
   2344         ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic);
   2345 
   2346         IMGUI_DEMO_MARKER("Widgets/Data Types/Sliders");
   2347         ImGui::SeparatorText("Sliders");
   2348         ImGui::SliderScalar("slider s8 full",       ImGuiDataType_S8,     &s8_v,  &s8_min,   &s8_max,   "%d");
   2349         ImGui::SliderScalar("slider u8 full",       ImGuiDataType_U8,     &u8_v,  &u8_min,   &u8_max,   "%u");
   2350         ImGui::SliderScalar("slider s16 full",      ImGuiDataType_S16,    &s16_v, &s16_min,  &s16_max,  "%d");
   2351         ImGui::SliderScalar("slider u16 full",      ImGuiDataType_U16,    &u16_v, &u16_min,  &u16_max,  "%u");
   2352         ImGui::SliderScalar("slider s32 low",       ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty,"%d");
   2353         ImGui::SliderScalar("slider s32 high",      ImGuiDataType_S32,    &s32_v, &s32_hi_a, &s32_hi_b, "%d");
   2354         ImGui::SliderScalar("slider s32 full",      ImGuiDataType_S32,    &s32_v, &s32_min,  &s32_max,  "%d");
   2355         ImGui::SliderScalar("slider s32 hex",       ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty, "0x%04X");
   2356         ImGui::SliderScalar("slider u32 low",       ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u");
   2357         ImGui::SliderScalar("slider u32 high",      ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u");
   2358         ImGui::SliderScalar("slider u32 full",      ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u");
   2359         ImGui::SliderScalar("slider s64 low",       ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%" PRId64);
   2360         ImGui::SliderScalar("slider s64 high",      ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%" PRId64);
   2361         ImGui::SliderScalar("slider s64 full",      ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%" PRId64);
   2362         ImGui::SliderScalar("slider u64 low",       ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%" PRIu64 " ms");
   2363         ImGui::SliderScalar("slider u64 high",      ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%" PRIu64 " ms");
   2364         ImGui::SliderScalar("slider u64 full",      ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%" PRIu64 " ms");
   2365         ImGui::SliderScalar("slider float low",     ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one);
   2366         ImGui::SliderScalar("slider float low log", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
   2367         ImGui::SliderScalar("slider float high",    ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e");
   2368         ImGui::SliderScalar("slider double low",    ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f grams");
   2369         ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
   2370         ImGui::SliderScalar("slider double high",   ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
   2371 
   2372         ImGui::SeparatorText("Sliders (reverse)");
   2373         ImGui::SliderScalar("slider s8 reverse",    ImGuiDataType_S8,   &s8_v,  &s8_max,    &s8_min,   "%d");
   2374         ImGui::SliderScalar("slider u8 reverse",    ImGuiDataType_U8,   &u8_v,  &u8_max,    &u8_min,   "%u");
   2375         ImGui::SliderScalar("slider s32 reverse",   ImGuiDataType_S32,  &s32_v, &s32_fifty, &s32_zero, "%d");
   2376         ImGui::SliderScalar("slider u32 reverse",   ImGuiDataType_U32,  &u32_v, &u32_fifty, &u32_zero, "%u");
   2377         ImGui::SliderScalar("slider s64 reverse",   ImGuiDataType_S64,  &s64_v, &s64_fifty, &s64_zero, "%" PRId64);
   2378         ImGui::SliderScalar("slider u64 reverse",   ImGuiDataType_U64,  &u64_v, &u64_fifty, &u64_zero, "%" PRIu64 " ms");
   2379 
   2380         IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs");
   2381         static bool inputs_step = true;
   2382         static ImGuiInputTextFlags flags = ImGuiInputTextFlags_None;
   2383         ImGui::SeparatorText("Inputs");
   2384         ImGui::Checkbox("Show step buttons", &inputs_step);
   2385         ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
   2386         ImGui::CheckboxFlags("ImGuiInputTextFlags_ParseEmptyRefVal", &flags, ImGuiInputTextFlags_ParseEmptyRefVal);
   2387         ImGui::CheckboxFlags("ImGuiInputTextFlags_DisplayEmptyRefVal", &flags, ImGuiInputTextFlags_DisplayEmptyRefVal);
   2388         ImGui::InputScalar("input s8",      ImGuiDataType_S8,     &s8_v,  inputs_step ? &s8_one  : NULL, NULL, "%d", flags);
   2389         ImGui::InputScalar("input u8",      ImGuiDataType_U8,     &u8_v,  inputs_step ? &u8_one  : NULL, NULL, "%u", flags);
   2390         ImGui::InputScalar("input s16",     ImGuiDataType_S16,    &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d", flags);
   2391         ImGui::InputScalar("input u16",     ImGuiDataType_U16,    &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u", flags);
   2392         ImGui::InputScalar("input s32",     ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d", flags);
   2393         ImGui::InputScalar("input s32 hex", ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X", flags);
   2394         ImGui::InputScalar("input u32",     ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u", flags);
   2395         ImGui::InputScalar("input u32 hex", ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", flags);
   2396         ImGui::InputScalar("input s64",     ImGuiDataType_S64,    &s64_v, inputs_step ? &s64_one : NULL, NULL, NULL, flags);
   2397         ImGui::InputScalar("input u64",     ImGuiDataType_U64,    &u64_v, inputs_step ? &u64_one : NULL, NULL, NULL, flags);
   2398         ImGui::InputScalar("input float",   ImGuiDataType_Float,  &f32_v, inputs_step ? &f32_one : NULL, NULL, NULL, flags);
   2399         ImGui::InputScalar("input double",  ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL, NULL, NULL, flags);
   2400 
   2401         ImGui::TreePop();
   2402     }
   2403 
   2404     IMGUI_DEMO_MARKER("Widgets/Multi-component Widgets");
   2405     if (ImGui::TreeNode("Multi-component Widgets"))
   2406     {
   2407         static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
   2408         static int vec4i[4] = { 1, 5, 100, 255 };
   2409 
   2410         ImGui::SeparatorText("2-wide");
   2411         ImGui::InputFloat2("input float2", vec4f);
   2412         ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
   2413         ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
   2414         ImGui::InputInt2("input int2", vec4i);
   2415         ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
   2416         ImGui::SliderInt2("slider int2", vec4i, 0, 255);
   2417 
   2418         ImGui::SeparatorText("3-wide");
   2419         ImGui::InputFloat3("input float3", vec4f);
   2420         ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
   2421         ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
   2422         ImGui::InputInt3("input int3", vec4i);
   2423         ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
   2424         ImGui::SliderInt3("slider int3", vec4i, 0, 255);
   2425 
   2426         ImGui::SeparatorText("4-wide");
   2427         ImGui::InputFloat4("input float4", vec4f);
   2428         ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
   2429         ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
   2430         ImGui::InputInt4("input int4", vec4i);
   2431         ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
   2432         ImGui::SliderInt4("slider int4", vec4i, 0, 255);
   2433 
   2434         ImGui::TreePop();
   2435     }
   2436 
   2437     IMGUI_DEMO_MARKER("Widgets/Vertical Sliders");
   2438     if (ImGui::TreeNode("Vertical Sliders"))
   2439     {
   2440         const float spacing = 4;
   2441         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
   2442 
   2443         static int int_value = 0;
   2444         ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
   2445         ImGui::SameLine();
   2446 
   2447         static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
   2448         ImGui::PushID("set1");
   2449         for (int i = 0; i < 7; i++)
   2450         {
   2451             if (i > 0) ImGui::SameLine();
   2452             ImGui::PushID(i);
   2453             ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
   2454             ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
   2455             ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
   2456             ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
   2457             ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
   2458             if (ImGui::IsItemActive() || ImGui::IsItemHovered())
   2459                 ImGui::SetTooltip("%.3f", values[i]);
   2460             ImGui::PopStyleColor(4);
   2461             ImGui::PopID();
   2462         }
   2463         ImGui::PopID();
   2464 
   2465         ImGui::SameLine();
   2466         ImGui::PushID("set2");
   2467         static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
   2468         const int rows = 3;
   2469         const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
   2470         for (int nx = 0; nx < 4; nx++)
   2471         {
   2472             if (nx > 0) ImGui::SameLine();
   2473             ImGui::BeginGroup();
   2474             for (int ny = 0; ny < rows; ny++)
   2475             {
   2476                 ImGui::PushID(nx * rows + ny);
   2477                 ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
   2478                 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
   2479                     ImGui::SetTooltip("%.3f", values2[nx]);
   2480                 ImGui::PopID();
   2481             }
   2482             ImGui::EndGroup();
   2483         }
   2484         ImGui::PopID();
   2485 
   2486         ImGui::SameLine();
   2487         ImGui::PushID("set3");
   2488         for (int i = 0; i < 4; i++)
   2489         {
   2490             if (i > 0) ImGui::SameLine();
   2491             ImGui::PushID(i);
   2492             ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
   2493             ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
   2494             ImGui::PopStyleVar();
   2495             ImGui::PopID();
   2496         }
   2497         ImGui::PopID();
   2498         ImGui::PopStyleVar();
   2499         ImGui::TreePop();
   2500     }
   2501 
   2502     IMGUI_DEMO_MARKER("Widgets/Drag and drop");
   2503     if (ImGui::TreeNode("Drag and Drop"))
   2504     {
   2505         IMGUI_DEMO_MARKER("Widgets/Drag and drop/Standard widgets");
   2506         if (ImGui::TreeNode("Drag and drop in standard widgets"))
   2507         {
   2508             // ColorEdit widgets automatically act as drag source and drag target.
   2509             // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F
   2510             // to allow your own widgets to use colors in their drag and drop interaction.
   2511             // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo.
   2512             HelpMarker("You can drag from the color squares.");
   2513             static float col1[3] = { 1.0f, 0.0f, 0.2f };
   2514             static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
   2515             ImGui::ColorEdit3("color 1", col1);
   2516             ImGui::ColorEdit4("color 2", col2);
   2517             ImGui::TreePop();
   2518         }
   2519 
   2520         IMGUI_DEMO_MARKER("Widgets/Drag and drop/Copy-swap items");
   2521         if (ImGui::TreeNode("Drag and drop to copy/swap items"))
   2522         {
   2523             enum Mode
   2524             {
   2525                 Mode_Copy,
   2526                 Mode_Move,
   2527                 Mode_Swap
   2528             };
   2529             static int mode = 0;
   2530             if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
   2531             if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
   2532             if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
   2533             static const char* names[9] =
   2534             {
   2535                 "Bobby", "Beatrice", "Betty",
   2536                 "Brianna", "Barry", "Bernard",
   2537                 "Bibi", "Blaine", "Bryn"
   2538             };
   2539             for (int n = 0; n < IM_ARRAYSIZE(names); n++)
   2540             {
   2541                 ImGui::PushID(n);
   2542                 if ((n % 3) != 0)
   2543                     ImGui::SameLine();
   2544                 ImGui::Button(names[n], ImVec2(60, 60));
   2545 
   2546                 // Our buttons are both drag sources and drag targets here!
   2547                 if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
   2548                 {
   2549                     // Set payload to carry the index of our item (could be anything)
   2550                     ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));
   2551 
   2552                     // Display preview (could be anything, e.g. when dragging an image we could decide to display
   2553                     // the filename and a small preview of the image, etc.)
   2554                     if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }
   2555                     if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
   2556                     if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
   2557                     ImGui::EndDragDropSource();
   2558                 }
   2559                 if (ImGui::BeginDragDropTarget())
   2560                 {
   2561                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
   2562                     {
   2563                         IM_ASSERT(payload->DataSize == sizeof(int));
   2564                         int payload_n = *(const int*)payload->Data;
   2565                         if (mode == Mode_Copy)
   2566                         {
   2567                             names[n] = names[payload_n];
   2568                         }
   2569                         if (mode == Mode_Move)
   2570                         {
   2571                             names[n] = names[payload_n];
   2572                             names[payload_n] = "";
   2573                         }
   2574                         if (mode == Mode_Swap)
   2575                         {
   2576                             const char* tmp = names[n];
   2577                             names[n] = names[payload_n];
   2578                             names[payload_n] = tmp;
   2579                         }
   2580                     }
   2581                     ImGui::EndDragDropTarget();
   2582                 }
   2583                 ImGui::PopID();
   2584             }
   2585             ImGui::TreePop();
   2586         }
   2587 
   2588         IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)");
   2589         if (ImGui::TreeNode("Drag to reorder items (simple)"))
   2590         {
   2591             // Simple reordering
   2592             HelpMarker(
   2593                 "We don't use the drag and drop api at all here! "
   2594                 "Instead we query when the item is held but not hovered, and order items accordingly.");
   2595             static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
   2596             for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
   2597             {
   2598                 const char* item = item_names[n];
   2599                 ImGui::Selectable(item);
   2600 
   2601                 if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
   2602                 {
   2603                     int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
   2604                     if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
   2605                     {
   2606                         item_names[n] = item_names[n_next];
   2607                         item_names[n_next] = item;
   2608                         ImGui::ResetMouseDragDelta();
   2609                     }
   2610                 }
   2611             }
   2612             ImGui::TreePop();
   2613         }
   2614 
   2615         IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Tooltip at target location");
   2616         if (ImGui::TreeNode("Tooltip at target location"))
   2617         {
   2618             for (int n = 0; n < 2; n++)
   2619             {
   2620                 // Drop targets
   2621                 ImGui::Button(n ? "drop here##1" : "drop here##0");
   2622                 if (ImGui::BeginDragDropTarget())
   2623                 {
   2624                     ImGuiDragDropFlags drop_target_flags = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoPreviewTooltip;
   2625                     if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, drop_target_flags))
   2626                     {
   2627                         IM_UNUSED(payload);
   2628                         ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
   2629                         ImGui::SetTooltip("Cannot drop here!");
   2630                     }
   2631                     ImGui::EndDragDropTarget();
   2632                 }
   2633 
   2634                 // Drop source
   2635                 static ImVec4 col4 = { 1.0f, 0.0f, 0.2f, 1.0f };
   2636                 if (n == 0)
   2637                     ImGui::ColorButton("drag me", col4);
   2638 
   2639             }
   2640             ImGui::TreePop();
   2641         }
   2642 
   2643         ImGui::TreePop();
   2644     }
   2645 
   2646     IMGUI_DEMO_MARKER("Widgets/Querying Item Status (Edited,Active,Hovered etc.)");
   2647     if (ImGui::TreeNode("Querying Item Status (Edited/Active/Hovered etc.)"))
   2648     {
   2649         // Select an item type
   2650         const char* item_names[] =
   2651         {
   2652             "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputTextMultiline", "InputFloat",
   2653             "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"
   2654         };
   2655         static int item_type = 4;
   2656         static bool item_disabled = false;
   2657         ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
   2658         ImGui::SameLine();
   2659         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().");
   2660         ImGui::Checkbox("Item Disabled",  &item_disabled);
   2661 
   2662         // Submit selected items so we can query their status in the code following it.
   2663         bool ret = false;
   2664         static bool b = false;
   2665         static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
   2666         static char str[16] = {};
   2667         if (item_disabled)
   2668             ImGui::BeginDisabled(true);
   2669         if (item_type == 0) { ImGui::Text("ITEM: Text"); }                                              // Testing text items with no identifier/interaction
   2670         if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); }                                    // Testing button
   2671         if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater)
   2672         if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); }                            // Testing checkbox
   2673         if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
   2674         if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); }  // Testing input text (which handles tabbing)
   2675         if (item_type == 6) { ret = ImGui::InputTextMultiline("ITEM: InputTextMultiline", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which uses a child window)
   2676         if (item_type == 7) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); }               // Testing +/- buttons on scalar input
   2677         if (item_type == 8) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); }                   // Testing multi-component items (IsItemXXX flags are reported merged)
   2678         if (item_type == 9) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
   2679         if (item_type == 10){ ret = ImGui::Selectable("ITEM: Selectable"); }                            // Testing selectable item
   2680         if (item_type == 11){ ret = ImGui::MenuItem("ITEM: MenuItem"); }                                // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
   2681         if (item_type == 12){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); }     // Testing tree node
   2682         if (item_type == 13){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
   2683         if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); }
   2684         if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
   2685 
   2686         bool hovered_delay_none = ImGui::IsItemHovered();
   2687         bool hovered_delay_stationary = ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary);
   2688         bool hovered_delay_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort);
   2689         bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal);
   2690         bool hovered_delay_tooltip = ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip); // = Normal + Stationary
   2691 
   2692         // Display the values of IsItemHovered() and other common item state functions.
   2693         // Note that the ImGuiHoveredFlags_XXX flags can be combined.
   2694         // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
   2695         // we query every state in a single call to avoid storing them and to simplify the code.
   2696         ImGui::BulletText(
   2697             "Return value = %d\n"
   2698             "IsItemFocused() = %d\n"
   2699             "IsItemHovered() = %d\n"
   2700             "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
   2701             "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
   2702             "IsItemHovered(_AllowWhenOverlappedByItem) = %d\n"
   2703             "IsItemHovered(_AllowWhenOverlappedByWindow) = %d\n"
   2704             "IsItemHovered(_AllowWhenDisabled) = %d\n"
   2705             "IsItemHovered(_RectOnly) = %d\n"
   2706             "IsItemActive() = %d\n"
   2707             "IsItemEdited() = %d\n"
   2708             "IsItemActivated() = %d\n"
   2709             "IsItemDeactivated() = %d\n"
   2710             "IsItemDeactivatedAfterEdit() = %d\n"
   2711             "IsItemVisible() = %d\n"
   2712             "IsItemClicked() = %d\n"
   2713             "IsItemToggledOpen() = %d\n"
   2714             "GetItemRectMin() = (%.1f, %.1f)\n"
   2715             "GetItemRectMax() = (%.1f, %.1f)\n"
   2716             "GetItemRectSize() = (%.1f, %.1f)",
   2717             ret,
   2718             ImGui::IsItemFocused(),
   2719             ImGui::IsItemHovered(),
   2720             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
   2721             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
   2722             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByItem),
   2723             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByWindow),
   2724             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled),
   2725             ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
   2726             ImGui::IsItemActive(),
   2727             ImGui::IsItemEdited(),
   2728             ImGui::IsItemActivated(),
   2729             ImGui::IsItemDeactivated(),
   2730             ImGui::IsItemDeactivatedAfterEdit(),
   2731             ImGui::IsItemVisible(),
   2732             ImGui::IsItemClicked(),
   2733             ImGui::IsItemToggledOpen(),
   2734             ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
   2735             ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
   2736             ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
   2737         );
   2738         ImGui::BulletText(
   2739             "with Hovering Delay or Stationary test:\n"
   2740             "IsItemHovered() = = %d\n"
   2741             "IsItemHovered(_Stationary) = %d\n"
   2742             "IsItemHovered(_DelayShort) = %d\n"
   2743             "IsItemHovered(_DelayNormal) = %d\n"
   2744             "IsItemHovered(_Tooltip) = %d",
   2745             hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip);
   2746 
   2747         if (item_disabled)
   2748             ImGui::EndDisabled();
   2749 
   2750         char buf[1] = "";
   2751         ImGui::InputText("unused", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_ReadOnly);
   2752         ImGui::SameLine();
   2753         HelpMarker("This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status.");
   2754 
   2755         ImGui::TreePop();
   2756     }
   2757 
   2758     IMGUI_DEMO_MARKER("Widgets/Querying Window Status (Focused,Hovered etc.)");
   2759     if (ImGui::TreeNode("Querying Window Status (Focused/Hovered etc.)"))
   2760     {
   2761         static bool embed_all_inside_a_child_window = false;
   2762         ImGui::Checkbox("Embed everything inside a child window for testing _RootWindow flag.", &embed_all_inside_a_child_window);
   2763         if (embed_all_inside_a_child_window)
   2764             ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), ImGuiChildFlags_Border);
   2765 
   2766         // Testing IsWindowFocused() function with its various flags.
   2767         ImGui::BulletText(
   2768             "IsWindowFocused() = %d\n"
   2769             "IsWindowFocused(_ChildWindows) = %d\n"
   2770             "IsWindowFocused(_ChildWindows|_NoPopupHierarchy) = %d\n"
   2771             "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
   2772             "IsWindowFocused(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
   2773             "IsWindowFocused(_RootWindow) = %d\n"
   2774             "IsWindowFocused(_RootWindow|_NoPopupHierarchy) = %d\n"
   2775             "IsWindowFocused(_AnyWindow) = %d\n",
   2776             ImGui::IsWindowFocused(),
   2777             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
   2778             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy),
   2779             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
   2780             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
   2781             ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
   2782             ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
   2783             ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
   2784 
   2785         // Testing IsWindowHovered() function with its various flags.
   2786         ImGui::BulletText(
   2787             "IsWindowHovered() = %d\n"
   2788             "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
   2789             "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
   2790             "IsWindowHovered(_ChildWindows) = %d\n"
   2791             "IsWindowHovered(_ChildWindows|_NoPopupHierarchy) = %d\n"
   2792             "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
   2793             "IsWindowHovered(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
   2794             "IsWindowHovered(_RootWindow) = %d\n"
   2795             "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n"
   2796             "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
   2797             "IsWindowHovered(_AnyWindow) = %d\n"
   2798             "IsWindowHovered(_Stationary) = %d\n",
   2799             ImGui::IsWindowHovered(),
   2800             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
   2801             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
   2802             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
   2803             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy),
   2804             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
   2805             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
   2806             ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
   2807             ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
   2808             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
   2809             ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow),
   2810             ImGui::IsWindowHovered(ImGuiHoveredFlags_Stationary));
   2811 
   2812         ImGui::BeginChild("child", ImVec2(0, 50), ImGuiChildFlags_Border);
   2813         ImGui::Text("This is another child window for testing the _ChildWindows flag.");
   2814         ImGui::EndChild();
   2815         if (embed_all_inside_a_child_window)
   2816             ImGui::EndChild();
   2817 
   2818         // Calling IsItemHovered() after begin returns the hovered status of the title bar.
   2819         // This is useful in particular if you want to create a context menu associated to the title bar of a window.
   2820         static bool test_window = false;
   2821         ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
   2822         if (test_window)
   2823         {
   2824             ImGui::Begin("Title bar Hovered/Active tests", &test_window);
   2825             if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
   2826             {
   2827                 if (ImGui::MenuItem("Close")) { test_window = false; }
   2828                 ImGui::EndPopup();
   2829             }
   2830             ImGui::Text(
   2831                 "IsItemHovered() after begin = %d (== is title bar hovered)\n"
   2832                 "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
   2833                 ImGui::IsItemHovered(), ImGui::IsItemActive());
   2834             ImGui::End();
   2835         }
   2836 
   2837         ImGui::TreePop();
   2838     }
   2839 
   2840     // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd:
   2841     // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space)
   2842     if (disable_all)
   2843         ImGui::EndDisabled();
   2844 
   2845     IMGUI_DEMO_MARKER("Widgets/Disable Block");
   2846     if (ImGui::TreeNode("Disable block"))
   2847     {
   2848         ImGui::Checkbox("Disable entire section above", &disable_all);
   2849         ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across this section.");
   2850         ImGui::TreePop();
   2851     }
   2852 
   2853     IMGUI_DEMO_MARKER("Widgets/Text Filter");
   2854     if (ImGui::TreeNode("Text Filter"))
   2855     {
   2856         // Helper class to easy setup a text filter.
   2857         // You may want to implement a more feature-full filtering scheme in your own application.
   2858         HelpMarker("Not a widget per-se, but ImGuiTextFilter is a helper to perform simple filtering on text strings.");
   2859         static ImGuiTextFilter filter;
   2860         ImGui::Text("Filter usage:\n"
   2861             "  \"\"         display all lines\n"
   2862             "  \"xxx\"      display lines containing \"xxx\"\n"
   2863             "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
   2864             "  \"-xxx\"     hide lines containing \"xxx\"");
   2865         filter.Draw();
   2866         const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
   2867         for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
   2868             if (filter.PassFilter(lines[i]))
   2869                 ImGui::BulletText("%s", lines[i]);
   2870         ImGui::TreePop();
   2871     }
   2872 }
   2873 
   2874 static const char* ExampleNames[] =
   2875 {
   2876     "Artichoke", "Arugula", "Asparagus", "Avocado", "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", "Belgian Endive", "Bell Pepper",
   2877     "Bitter Gourd", "Bok Choy", "Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", "Calabash", "Capers", "Carrot", "Cassava",
   2878     "Cauliflower", "Celery", "Celery Root", "Celcuce", "Chayote", "Chinese Broccoli", "Corn", "Cucumber"
   2879 };
   2880 
   2881 // Extra functions to add deletion support to ImGuiSelectionBasicStorage
   2882 struct ExampleSelectionWithDeletion : ImGuiSelectionBasicStorage
   2883 {
   2884     // Find which item should be Focused after deletion.
   2885     // Call _before_ item submission. Retunr an index in the before-deletion item list, your item loop should call SetKeyboardFocusHere() on it.
   2886     // The subsequent ApplyDeletionPostLoop() code will use it to apply Selection.
   2887     // - We cannot provide this logic in core Dear ImGui because we don't have access to selection data.
   2888     // - We don't actually manipulate the ImVector<> here, only in ApplyDeletionPostLoop(), but using similar API for consistency and flexibility.
   2889     // - Important: Deletion only works if the underlying ImGuiID for your items are stable: aka not depend on their index, but on e.g. item id/ptr.
   2890     // FIXME-MULTISELECT: Doesn't take account of the possibility focus target will be moved during deletion. Need refocus or scroll offset.
   2891     int ApplyDeletionPreLoop(ImGuiMultiSelectIO* ms_io, int items_count)
   2892     {
   2893         if (Size == 0)
   2894             return -1;
   2895 
   2896         // If focused item is not selected...
   2897         const int focused_idx = (int)ms_io->NavIdItem;  // Index of currently focused item
   2898         if (ms_io->NavIdSelected == false)  // This is merely a shortcut, == Contains(adapter->IndexToStorage(items, focused_idx))
   2899         {
   2900             ms_io->RangeSrcReset = true;    // Request to recover RangeSrc from NavId next frame. Would be ok to reset even when NavIdSelected==true, but it would take an extra frame to recover RangeSrc when deleting a selected item.
   2901             return focused_idx;             // Request to focus same item after deletion.
   2902         }
   2903 
   2904         // If focused item is selected: land on first unselected item after focused item.
   2905         for (int idx = focused_idx + 1; idx < items_count; idx++)
   2906             if (!Contains(GetStorageIdFromIndex(idx)))
   2907                 return idx;
   2908 
   2909         // If focused item is selected: otherwise return last unselected item before focused item.
   2910         for (int idx = IM_MIN(focused_idx, items_count) - 1; idx >= 0; idx--)
   2911             if (!Contains(GetStorageIdFromIndex(idx)))
   2912                 return idx;
   2913 
   2914         return -1;
   2915     }
   2916 
   2917     // Rewrite item list (delete items) + update selection.
   2918     // - Call after EndMultiSelect()
   2919     // - We cannot provide this logic in core Dear ImGui because we don't have access to your items, nor to selection data.
   2920     template<typename ITEM_TYPE>
   2921     void ApplyDeletionPostLoop(ImGuiMultiSelectIO* ms_io, ImVector<ITEM_TYPE>& items, int item_curr_idx_to_select)
   2922     {
   2923         // Rewrite item list (delete items) + convert old selection index (before deletion) to new selection index (after selection).
   2924         // If NavId was not part of selection, we will stay on same item.
   2925         ImVector<ITEM_TYPE> new_items;
   2926         new_items.reserve(items.Size - Size);
   2927         int item_next_idx_to_select = -1;
   2928         for (int idx = 0; idx < items.Size; idx++)
   2929         {
   2930             if (!Contains(GetStorageIdFromIndex(idx)))
   2931                 new_items.push_back(items[idx]);
   2932             if (item_curr_idx_to_select == idx)
   2933                 item_next_idx_to_select = new_items.Size - 1;
   2934         }
   2935         items.swap(new_items);
   2936 
   2937         // Update selection
   2938         Clear();
   2939         if (item_next_idx_to_select != -1 && ms_io->NavIdSelected)
   2940             SetItemSelected(GetStorageIdFromIndex(item_next_idx_to_select), true);
   2941     }
   2942 };
   2943 
   2944 // Example: Implement dual list box storage and interface
   2945 struct ExampleDualListBox
   2946 {
   2947     ImVector<ImGuiID>           Items[2];               // ID is index into ExampleName[]
   2948     ImGuiSelectionBasicStorage  Selections[2];          // Store ExampleItemId into selection
   2949     bool                        OptKeepSorted = true;
   2950 
   2951     void MoveAll(int src, int dst)
   2952     {
   2953         IM_ASSERT((src == 0 && dst == 1) || (src == 1 && dst == 0));
   2954         for (ImGuiID item_id : Items[src])
   2955             Items[dst].push_back(item_id);
   2956         Items[src].clear();
   2957         SortItems(dst);
   2958         Selections[src].Swap(Selections[dst]);
   2959         Selections[src].Clear();
   2960     }
   2961     void MoveSelected(int src, int dst)
   2962     {
   2963         for (int src_n = 0; src_n < Items[src].Size; src_n++)
   2964         {
   2965             ImGuiID item_id = Items[src][src_n];
   2966             if (!Selections[src].Contains(item_id))
   2967                 continue;
   2968             Items[src].erase(&Items[src][src_n]); // FIXME-OPT: Could be implemented more optimally (rebuild src items and swap)
   2969             Items[dst].push_back(item_id);
   2970             src_n--;
   2971         }
   2972         if (OptKeepSorted)
   2973             SortItems(dst);
   2974         Selections[src].Swap(Selections[dst]);
   2975         Selections[src].Clear();
   2976     }
   2977     void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, int side)
   2978     {
   2979         // In this example we store item id in selection (instead of item index)
   2980         Selections[side].UserData = Items[side].Data;
   2981         Selections[side].AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImGuiID* items = (ImGuiID*)self->UserData; return items[idx]; };
   2982         Selections[side].ApplyRequests(ms_io);
   2983     }
   2984     static int IMGUI_CDECL CompareItemsByValue(const void* lhs, const void* rhs)
   2985     {
   2986         const int* a = (const int*)lhs;
   2987         const int* b = (const int*)rhs;
   2988         return (*a - *b) > 0 ? +1 : -1;
   2989     }
   2990     void SortItems(int n)
   2991     {
   2992         qsort(Items[n].Data, (size_t)Items[n].Size, sizeof(Items[n][0]), CompareItemsByValue);
   2993     }
   2994     void Show()
   2995     {
   2996         //ImGui::Checkbox("Sorted", &OptKeepSorted);
   2997         if (ImGui::BeginTable("split", 3, ImGuiTableFlags_None))
   2998         {
   2999             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);    // Left side
   3000             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);      // Buttons
   3001             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);    // Right side
   3002             ImGui::TableNextRow();
   3003 
   3004             int request_move_selected = -1;
   3005             int request_move_all = -1;
   3006             float child_height_0 = 0.0f;
   3007             for (int side = 0; side < 2; side++)
   3008             {
   3009                 // FIXME-MULTISELECT: Dual List Box: Add context menus
   3010                 // FIXME-NAV: Using ImGuiWindowFlags_NavFlattened exhibit many issues.
   3011                 ImVector<ImGuiID>& items = Items[side];
   3012                 ImGuiSelectionBasicStorage& selection = Selections[side];
   3013 
   3014                 ImGui::TableSetColumnIndex((side == 0) ? 0 : 2);
   3015                 ImGui::Text("%s (%d)", (side == 0) ? "Available" : "Basket", items.Size);
   3016 
   3017                 // Submit scrolling range to avoid glitches on moving/deletion
   3018                 const float items_height = ImGui::GetTextLineHeightWithSpacing();
   3019                 ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height));
   3020 
   3021                 bool child_visible;
   3022                 if (side == 0)
   3023                 {
   3024                     // Left child is resizable
   3025                     ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetFrameHeightWithSpacing() * 4), ImVec2(FLT_MAX, FLT_MAX));
   3026                     child_visible = ImGui::BeginChild("0", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY);
   3027                     child_height_0 = ImGui::GetWindowSize().y;
   3028                 }
   3029                 else
   3030                 {
   3031                     // Right child use same height as left one
   3032                     child_visible = ImGui::BeginChild("1", ImVec2(-FLT_MIN, child_height_0), ImGuiChildFlags_FrameStyle);
   3033                 }
   3034                 if (child_visible)
   3035                 {
   3036                     ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_None;
   3037                     ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
   3038                     ApplySelectionRequests(ms_io, side);
   3039 
   3040                     for (int item_n = 0; item_n < items.Size; item_n++)
   3041                     {
   3042                         ImGuiID item_id = items[item_n];
   3043                         bool item_is_selected = selection.Contains(item_id);
   3044                         ImGui::SetNextItemSelectionUserData(item_n);
   3045                         ImGui::Selectable(ExampleNames[item_id], item_is_selected, ImGuiSelectableFlags_AllowDoubleClick);
   3046                         if (ImGui::IsItemFocused())
   3047                         {
   3048                             // FIXME-MULTISELECT: Dual List Box: Transfer focus
   3049                             if (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))
   3050                                 request_move_selected = side;
   3051                             if (ImGui::IsMouseDoubleClicked(0)) // FIXME-MULTISELECT: Double-click on multi-selection?
   3052                                 request_move_selected = side;
   3053                         }
   3054                     }
   3055 
   3056                     ms_io = ImGui::EndMultiSelect();
   3057                     ApplySelectionRequests(ms_io, side);
   3058                 }
   3059                 ImGui::EndChild();
   3060             }
   3061 
   3062             // Buttons columns
   3063             ImGui::TableSetColumnIndex(1);
   3064             ImGui::NewLine();
   3065             //ImVec2 button_sz = { ImGui::CalcTextSize(">>").x + ImGui::GetStyle().FramePadding.x * 2.0f, ImGui::GetFrameHeight() + padding.y * 2.0f };
   3066             ImVec2 button_sz = { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() };
   3067 
   3068             // (Using BeginDisabled()/EndDisabled() works but feels distracting given how it is currently visualized)
   3069             if (ImGui::Button(">>", button_sz))
   3070                 request_move_all = 0;
   3071             if (ImGui::Button(">", button_sz))
   3072                 request_move_selected = 0;
   3073             if (ImGui::Button("<", button_sz))
   3074                 request_move_selected = 1;
   3075             if (ImGui::Button("<<", button_sz))
   3076                 request_move_all = 1;
   3077 
   3078             // Process requests
   3079             if (request_move_all != -1)
   3080                 MoveAll(request_move_all, request_move_all ^ 1);
   3081             if (request_move_selected != -1)
   3082                 MoveSelected(request_move_selected, request_move_selected ^ 1);
   3083 
   3084             // FIXME-MULTISELECT: Support action from outside
   3085             /*
   3086             if (OptKeepSorted == false)
   3087             {
   3088                 ImGui::NewLine();
   3089                 if (ImGui::ArrowButton("MoveUp", ImGuiDir_Up)) {}
   3090                 if (ImGui::ArrowButton("MoveDown", ImGuiDir_Down)) {}
   3091             }
   3092             */
   3093 
   3094             ImGui::EndTable();
   3095         }
   3096     }
   3097 };
   3098 
   3099 //-----------------------------------------------------------------------------
   3100 // [SECTION] ShowDemoWindowMultiSelect()
   3101 //-----------------------------------------------------------------------------
   3102 // Multi-selection demos
   3103 // Also read: https://github.com/ocornut/imgui/wiki/Multi-Select
   3104 //-----------------------------------------------------------------------------
   3105 
   3106 static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data)
   3107 {
   3108     IMGUI_DEMO_MARKER("Widgets/Selection State & Multi-Select");
   3109     if (ImGui::TreeNode("Selection State & Multi-Select"))
   3110     {
   3111         HelpMarker("Selections can be built using Selectable(), TreeNode() or other widgets. Selection state is owned by application code/data.");
   3112 
   3113         // Without any fancy API: manage single-selection yourself.
   3114         IMGUI_DEMO_MARKER("Widgets/Selection State/Single-Select");
   3115         if (ImGui::TreeNode("Single-Select"))
   3116         {
   3117             static int selected = -1;
   3118             for (int n = 0; n < 5; n++)
   3119             {
   3120                 char buf[32];
   3121                 sprintf(buf, "Object %d", n);
   3122                 if (ImGui::Selectable(buf, selected == n))
   3123                     selected = n;
   3124             }
   3125             ImGui::TreePop();
   3126         }
   3127 
   3128         // Demonstrate implementation a most-basic form of multi-selection manually
   3129         // This doesn't support the SHIFT modifier which requires BeginMultiSelect()!
   3130         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (manual/simplified, without BeginMultiSelect)");
   3131         if (ImGui::TreeNode("Multi-Select (manual/simplified, without BeginMultiSelect)"))
   3132         {
   3133             HelpMarker("Hold CTRL and click to select multiple items.");
   3134             static bool selection[5] = { false, false, false, false, false };
   3135             for (int n = 0; n < 5; n++)
   3136             {
   3137                 char buf[32];
   3138                 sprintf(buf, "Object %d", n);
   3139                 if (ImGui::Selectable(buf, selection[n]))
   3140                 {
   3141                     if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held
   3142                         memset(selection, 0, sizeof(selection));
   3143                     selection[n] ^= 1; // Toggle current item
   3144                 }
   3145             }
   3146             ImGui::TreePop();
   3147         }
   3148 
   3149         // Demonstrate handling proper multi-selection using the BeginMultiSelect/EndMultiSelect API.
   3150         // SHIFT+Click w/ CTRL and other standard features are supported.
   3151         // We use the ImGuiSelectionBasicStorage helper which you may freely reimplement.
   3152         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select");
   3153         if (ImGui::TreeNode("Multi-Select"))
   3154         {
   3155             ImGui::Text("Supported features:");
   3156             ImGui::BulletText("Keyboard navigation (arrows, page up/down, home/end, space).");
   3157             ImGui::BulletText("Ctrl modifier to preserve and toggle selection.");
   3158             ImGui::BulletText("Shift modifier for range selection.");
   3159             ImGui::BulletText("CTRL+A to select all.");
   3160             ImGui::BulletText("Escape to clear selection.");
   3161             ImGui::BulletText("Click and drag to box-select.");
   3162             ImGui::Text("Tip: Use 'Demo->Tools->Debug Log->Selection' to see selection requests as they happen.");
   3163 
   3164             // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection
   3165             const int ITEMS_COUNT = 50;
   3166             static ImGuiSelectionBasicStorage selection;
   3167             ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT);
   3168 
   3169             // The BeginChild() has no purpose for selection logic, other that offering a scrolling region.
   3170             if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
   3171             {
   3172                 ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
   3173                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
   3174                 selection.ApplyRequests(ms_io);
   3175 
   3176                 for (int n = 0; n < ITEMS_COUNT; n++)
   3177                 {
   3178                     char label[64];
   3179                     sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
   3180                     bool item_is_selected = selection.Contains((ImGuiID)n);
   3181                     ImGui::SetNextItemSelectionUserData(n);
   3182                     ImGui::Selectable(label, item_is_selected);
   3183                 }
   3184 
   3185                 ms_io = ImGui::EndMultiSelect();
   3186                 selection.ApplyRequests(ms_io);
   3187             }
   3188             ImGui::EndChild();
   3189             ImGui::TreePop();
   3190         }
   3191 
   3192         // Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect()
   3193         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (with clipper)");
   3194         if (ImGui::TreeNode("Multi-Select (with clipper)"))
   3195         {
   3196             // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection
   3197             static ImGuiSelectionBasicStorage selection;
   3198 
   3199             ImGui::Text("Added features:");
   3200             ImGui::BulletText("Using ImGuiListClipper.");
   3201 
   3202             const int ITEMS_COUNT = 10000;
   3203             ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT);
   3204             if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
   3205             {
   3206                 ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
   3207                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
   3208                 selection.ApplyRequests(ms_io);
   3209 
   3210                 ImGuiListClipper clipper;
   3211                 clipper.Begin(ITEMS_COUNT);
   3212                 if (ms_io->RangeSrcItem != -1)
   3213                     clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
   3214                 while (clipper.Step())
   3215                 {
   3216                     for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
   3217                     {
   3218                         char label[64];
   3219                         sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
   3220                         bool item_is_selected = selection.Contains((ImGuiID)n);
   3221                         ImGui::SetNextItemSelectionUserData(n);
   3222                         ImGui::Selectable(label, item_is_selected);
   3223                     }
   3224                 }
   3225 
   3226                 ms_io = ImGui::EndMultiSelect();
   3227                 selection.ApplyRequests(ms_io);
   3228             }
   3229             ImGui::EndChild();
   3230             ImGui::TreePop();
   3231         }
   3232 
   3233         // Demonstrate dynamic item list + deletion support using the BeginMultiSelect/EndMultiSelect API.
   3234         // In order to support Deletion without any glitches you need to:
   3235         // - (1) If items are submitted in their own scrolling area, submit contents size SetNextWindowContentSize() ahead of time to prevent one-frame readjustment of scrolling.
   3236         // - (2) Items needs to have persistent ID Stack identifier = ID needs to not depends on their index. PushID(index) = KO. PushID(item_id) = OK. This is in order to focus items reliably after a selection.
   3237         // - (3) BeginXXXX process
   3238         // - (4) Focus process
   3239         // - (5) EndXXXX process
   3240         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (with deletion)");
   3241         if (ImGui::TreeNode("Multi-Select (with deletion)"))
   3242         {
   3243             // Storing items data separately from selection data.
   3244             // (you may decide to store selection data inside your item (aka intrusive storage) if you don't need multiple views over same items)
   3245             // Use a custom selection.Adapter: store item identifier in Selection (instead of index)
   3246             static ImVector<ImGuiID> items;
   3247             static ExampleSelectionWithDeletion selection;
   3248             selection.UserData = (void*)&items;
   3249             selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImVector<ImGuiID>* p_items = (ImVector<ImGuiID>*)self->UserData; return (*p_items)[idx]; }; // Index -> ID
   3250 
   3251             ImGui::Text("Added features:");
   3252             ImGui::BulletText("Dynamic list with Delete key support.");
   3253             ImGui::Text("Selection size: %d/%d", selection.Size, items.Size);
   3254 
   3255             // Initialize default list with 50 items + button to add/remove items.
   3256             static ImGuiID items_next_id = 0;
   3257             if (items_next_id == 0)
   3258                 for (ImGuiID n = 0; n < 50; n++)
   3259                     items.push_back(items_next_id++);
   3260             if (ImGui::SmallButton("Add 20 items"))     { for (int n = 0; n < 20; n++) { items.push_back(items_next_id++); } }
   3261             ImGui::SameLine();
   3262             if (ImGui::SmallButton("Remove 20 items"))  { for (int n = IM_MIN(20, items.Size); n > 0; n--) { selection.SetItemSelected(items.back(), false); items.pop_back(); } }
   3263 
   3264             // (1) Extra to support deletion: Submit scrolling range to avoid glitches on deletion
   3265             const float items_height = ImGui::GetTextLineHeightWithSpacing();
   3266             ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height));
   3267 
   3268             if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
   3269             {
   3270                 ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
   3271                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
   3272                 selection.ApplyRequests(ms_io);
   3273 
   3274                 const bool want_delete = ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0);
   3275                 const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1;
   3276 
   3277                 for (int n = 0; n < items.Size; n++)
   3278                 {
   3279                     const ImGuiID item_id = items[n];
   3280                     char label[64];
   3281                     sprintf(label, "Object %05u: %s", item_id, ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)]);
   3282 
   3283                     bool item_is_selected = selection.Contains(item_id);
   3284                     ImGui::SetNextItemSelectionUserData(n);
   3285                     ImGui::Selectable(label, item_is_selected);
   3286                     if (item_curr_idx_to_focus == n)
   3287                         ImGui::SetKeyboardFocusHere(-1);
   3288                 }
   3289 
   3290                 // Apply multi-select requests
   3291                 ms_io = ImGui::EndMultiSelect();
   3292                 selection.ApplyRequests(ms_io);
   3293                 if (want_delete)
   3294                     selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus);
   3295             }
   3296             ImGui::EndChild();
   3297             ImGui::TreePop();
   3298         }
   3299 
   3300         // Implement a Dual List Box (#6648)
   3301         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (dual list box)");
   3302         if (ImGui::TreeNode("Multi-Select (dual list box)"))
   3303         {
   3304             // Init default state
   3305             static ExampleDualListBox dlb;
   3306             if (dlb.Items[0].Size == 0 && dlb.Items[1].Size == 0)
   3307                 for (int item_id = 0; item_id < IM_ARRAYSIZE(ExampleNames); item_id++)
   3308                     dlb.Items[0].push_back((ImGuiID)item_id);
   3309 
   3310             // Show
   3311             dlb.Show();
   3312 
   3313             ImGui::TreePop();
   3314         }
   3315 
   3316         // Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect()
   3317         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (in a table)");
   3318         if (ImGui::TreeNode("Multi-Select (in a table)"))
   3319         {
   3320             static ImGuiSelectionBasicStorage selection;
   3321 
   3322             const int ITEMS_COUNT = 10000;
   3323             ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT);
   3324             if (ImGui::BeginTable("##Basket", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter))
   3325             {
   3326                 ImGui::TableSetupColumn("Object");
   3327                 ImGui::TableSetupColumn("Action");
   3328                 ImGui::TableSetupScrollFreeze(0, 1);
   3329                 ImGui::TableHeadersRow();
   3330 
   3331                 ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
   3332                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
   3333                 selection.ApplyRequests(ms_io);
   3334 
   3335                 ImGuiListClipper clipper;
   3336                 clipper.Begin(ITEMS_COUNT);
   3337                 if (ms_io->RangeSrcItem != -1)
   3338                     clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
   3339                 while (clipper.Step())
   3340                 {
   3341                     for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
   3342                     {
   3343                         ImGui::TableNextRow();
   3344                         ImGui::TableNextColumn();
   3345                         char label[64];
   3346                         sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
   3347                         bool item_is_selected = selection.Contains((ImGuiID)n);
   3348                         ImGui::SetNextItemSelectionUserData(n);
   3349                         ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap);
   3350                         ImGui::TableNextColumn();
   3351                         ImGui::SmallButton("hello");
   3352                     }
   3353                 }
   3354 
   3355                 ms_io = ImGui::EndMultiSelect();
   3356                 selection.ApplyRequests(ms_io);
   3357                 ImGui::EndTable();
   3358             }
   3359             ImGui::TreePop();
   3360         }
   3361 
   3362         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (checkboxes)");
   3363         if (ImGui::TreeNode("Multi-Select (checkboxes)"))
   3364         {
   3365             ImGui::Text("In a list of checkboxes (not selectable):");
   3366             ImGui::BulletText("Using _NoAutoSelect + _NoAutoClear flags.");
   3367             ImGui::BulletText("Shift+Click to check multiple boxes.");
   3368             ImGui::BulletText("Shift+Keyboard to copy current value to other boxes.");
   3369 
   3370             // If you have an array of checkboxes, you may want to use NoAutoSelect + NoAutoClear and the ImGuiSelectionExternalStorage helper.
   3371             static bool items[20] = {};
   3372             static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_NoAutoSelect | ImGuiMultiSelectFlags_NoAutoClear | ImGuiMultiSelectFlags_ClearOnEscape;
   3373             ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect);
   3374             ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear);
   3375             ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d); // Cannot use ImGuiMultiSelectFlags_BoxSelect1d as checkboxes are varying width.
   3376 
   3377             if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY))
   3378             {
   3379                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, IM_ARRAYSIZE(items));
   3380                 ImGuiSelectionExternalStorage storage_wrapper;
   3381                 storage_wrapper.UserData = (void*)items;
   3382                 storage_wrapper.AdapterSetItemSelected = [](ImGuiSelectionExternalStorage* self, int n, bool selected) { bool* array = (bool*)self->UserData; array[n] = selected; };
   3383                 storage_wrapper.ApplyRequests(ms_io);
   3384                 for (int n = 0; n < 20; n++)
   3385                 {
   3386                     char label[32];
   3387                     sprintf(label, "Item %d", n);
   3388                     ImGui::SetNextItemSelectionUserData(n);
   3389                     ImGui::Checkbox(label, &items[n]);
   3390                 }
   3391                 ms_io = ImGui::EndMultiSelect();
   3392                 storage_wrapper.ApplyRequests(ms_io);
   3393             }
   3394             ImGui::EndChild();
   3395 
   3396             ImGui::TreePop();
   3397         }
   3398 
   3399         // Demonstrate individual selection scopes in same window
   3400         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (multiple scopes)");
   3401         if (ImGui::TreeNode("Multi-Select (multiple scopes)"))
   3402         {
   3403             // Use default select: Pass index to SetNextItemSelectionUserData(), store index in Selection
   3404             const int SCOPES_COUNT = 3;
   3405             const int ITEMS_COUNT = 8; // Per scope
   3406             static ImGuiSelectionBasicStorage selections_data[SCOPES_COUNT];
   3407 
   3408             // Use ImGuiMultiSelectFlags_ScopeRect to not affect other selections in same window.
   3409             static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ScopeRect | ImGuiMultiSelectFlags_ClearOnEscape;// | ImGuiMultiSelectFlags_ClearOnClickVoid;
   3410             if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeWindow", &flags, ImGuiMultiSelectFlags_ScopeWindow) && (flags & ImGuiMultiSelectFlags_ScopeWindow))
   3411                 flags &= ~ImGuiMultiSelectFlags_ScopeRect;
   3412             if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeRect", &flags, ImGuiMultiSelectFlags_ScopeRect) && (flags & ImGuiMultiSelectFlags_ScopeRect))
   3413                 flags &= ~ImGuiMultiSelectFlags_ScopeWindow;
   3414             ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickVoid);
   3415             ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d);
   3416 
   3417             for (int selection_scope_n = 0; selection_scope_n < SCOPES_COUNT; selection_scope_n++)
   3418             {
   3419                 ImGui::PushID(selection_scope_n);
   3420                 ImGuiSelectionBasicStorage* selection = &selections_data[selection_scope_n];
   3421                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection->Size, ITEMS_COUNT);
   3422                 selection->ApplyRequests(ms_io);
   3423 
   3424                 ImGui::SeparatorText("Selection scope");
   3425                 ImGui::Text("Selection size: %d/%d", selection->Size, ITEMS_COUNT);
   3426 
   3427                 for (int n = 0; n < ITEMS_COUNT; n++)
   3428                 {
   3429                     char label[64];
   3430                     sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
   3431                     bool item_is_selected = selection->Contains((ImGuiID)n);
   3432                     ImGui::SetNextItemSelectionUserData(n);
   3433                     ImGui::Selectable(label, item_is_selected);
   3434                 }
   3435 
   3436                 // Apply multi-select requests
   3437                 ms_io = ImGui::EndMultiSelect();
   3438                 selection->ApplyRequests(ms_io);
   3439                 ImGui::PopID();
   3440             }
   3441             ImGui::TreePop();
   3442         }
   3443 
   3444         // See ShowExampleAppAssetsBrowser()
   3445         if (ImGui::TreeNode("Multi-Select (tiled assets browser)"))
   3446         {
   3447             ImGui::Checkbox("Assets Browser", &demo_data->ShowAppAssetsBrowser);
   3448             ImGui::Text("(also access from 'Examples->Assets Browser' in menu)");
   3449             ImGui::TreePop();
   3450         }
   3451 
   3452         // Demonstrate supporting multiple-selection in a tree.
   3453         // - We don't use linear indices for selection user data, but our ExampleTreeNode* pointer directly!
   3454         //   This showcase how SetNextItemSelectionUserData() never assume indices!
   3455         // - The difficulty here is to "interpolate" from RangeSrcItem to RangeDstItem in the SetAll/SetRange request.
   3456         //   We want this interpolation to match what the user sees: in visible order, skipping closed nodes.
   3457         //   This is implemented by our TreeGetNextNodeInVisibleOrder() user-space helper.
   3458         // - Important: In a real codebase aiming to implement full-featured selectable tree with custom filtering, you
   3459         //   are more likely to build an array mapping sequential indices to visible tree nodes, since your
   3460         //   filtering/search + clipping process will benefit from it. Having this will make this interpolation much easier.
   3461         // - Consider this a prototype: we are working toward simplifying some of it.
   3462         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (trees)");
   3463         if (ImGui::TreeNode("Multi-Select (trees)"))
   3464         {
   3465             HelpMarker(
   3466                 "This is rather advanced and experimental. If you are getting started with multi-select,"
   3467                 "please don't start by looking at how to use it for a tree!\n\n"
   3468                 "Future versions will try to simplify and formalize some of this.");
   3469 
   3470             struct ExampleTreeFuncs
   3471             {
   3472                 static void DrawNode(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection)
   3473                 {
   3474                     ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
   3475                     tree_node_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Enable pressing left to jump to parent
   3476                     if (node->Childs.Size == 0)
   3477                         tree_node_flags |= ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_Leaf;
   3478                     if (selection->Contains((ImGuiID)node->UID))
   3479                         tree_node_flags |= ImGuiTreeNodeFlags_Selected;
   3480 
   3481                     // Using SetNextItemStorageID() to specify storage id, so we can easily peek into
   3482                     // the storage holding open/close stage, using our TreeNodeGetOpen/TreeNodeSetOpen() functions.
   3483                     ImGui::SetNextItemSelectionUserData((ImGuiSelectionUserData)(intptr_t)node);
   3484                     ImGui::SetNextItemStorageID((ImGuiID)node->UID);
   3485                     if (ImGui::TreeNodeEx(node->Name, tree_node_flags))
   3486                     {
   3487                         for (ExampleTreeNode* child : node->Childs)
   3488                             DrawNode(child, selection);
   3489                         ImGui::TreePop();
   3490                     }
   3491                     else if (ImGui::IsItemToggledOpen())
   3492                     {
   3493                         TreeCloseAndUnselectChildNodes(node, selection);
   3494                     }
   3495                 }
   3496 
   3497                 static bool TreeNodeGetOpen(ExampleTreeNode* node)
   3498                 {
   3499                     return ImGui::GetStateStorage()->GetBool((ImGuiID)node->UID);
   3500                 }
   3501 
   3502                 static void TreeNodeSetOpen(ExampleTreeNode* node, bool open)
   3503                 {
   3504                     ImGui::GetStateStorage()->SetBool((ImGuiID)node->UID, open);
   3505                 }
   3506 
   3507                 // When closing a node: 1) close and unselect all child nodes, 2) select parent if any child was selected.
   3508                 // FIXME: This is currently handled by user logic but I'm hoping to eventually provide tree node
   3509                 // features to do this automatically, e.g. a ImGuiTreeNodeFlags_AutoCloseChildNodes etc.
   3510                 static int TreeCloseAndUnselectChildNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, int depth = 0)
   3511                 {
   3512                     // Recursive close (the test for depth == 0 is because we call this on a node that was just closed!)
   3513                     int unselected_count = selection->Contains((ImGuiID)node->UID) ? 1 : 0;
   3514                     if (depth == 0 || TreeNodeGetOpen(node))
   3515                     {
   3516                         for (ExampleTreeNode* child : node->Childs)
   3517                             unselected_count += TreeCloseAndUnselectChildNodes(child, selection, depth + 1);
   3518                         TreeNodeSetOpen(node, false);
   3519                     }
   3520 
   3521                     // Select root node if any of its child was selected, otherwise unselect
   3522                     selection->SetItemSelected((ImGuiID)node->UID, (depth == 0 && unselected_count > 0));
   3523                     return unselected_count;
   3524                 }
   3525 
   3526                 // Apply multi-selection requests
   3527                 static void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, ExampleTreeNode* tree, ImGuiSelectionBasicStorage* selection)
   3528                 {
   3529                     for (ImGuiSelectionRequest& req : ms_io->Requests)
   3530                     {
   3531                         if (req.Type == ImGuiSelectionRequestType_SetAll)
   3532                         {
   3533                             if (req.Selected)
   3534                                 TreeSetAllInOpenNodes(tree, selection, req.Selected);
   3535                             else
   3536                                 selection->Clear();
   3537                         }
   3538                         else if (req.Type == ImGuiSelectionRequestType_SetRange)
   3539                         {
   3540                             ExampleTreeNode* first_node = (ExampleTreeNode*)(intptr_t)req.RangeFirstItem;
   3541                             ExampleTreeNode* last_node = (ExampleTreeNode*)(intptr_t)req.RangeLastItem;
   3542                             for (ExampleTreeNode* node = first_node; node != NULL; node = TreeGetNextNodeInVisibleOrder(node, last_node))
   3543                                 selection->SetItemSelected((ImGuiID)node->UID, req.Selected);
   3544                         }
   3545                     }
   3546                 }
   3547 
   3548                 static void TreeSetAllInOpenNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, bool selected)
   3549                 {
   3550                     if (node->Parent != NULL) // Root node isn't visible nor selectable in our scheme
   3551                         selection->SetItemSelected((ImGuiID)node->UID, selected);
   3552                     if (node->Parent == NULL || TreeNodeGetOpen(node))
   3553                         for (ExampleTreeNode* child : node->Childs)
   3554                             TreeSetAllInOpenNodes(child, selection, selected);
   3555                 }
   3556 
   3557                 // Interpolate in *user-visible order* AND only *over opened nodes*.
   3558                 // If you have a sequential mapping tables (e.g. generated after a filter/search pass) this would be simpler.
   3559                 // Here the tricks are that:
   3560                 // - we store/maintain ExampleTreeNode::IndexInParent which allows implementing a linear iterator easily, without searches, without recursion.
   3561                 //   this could be replaced by a search in parent, aka 'int index_in_parent = curr_node->Parent->Childs.find_index(curr_node)'
   3562                 //   which would only be called when crossing from child to a parent, aka not too much.
   3563                 // - we call SetNextItemStorageID() before our TreeNode() calls with an ID which doesn't relate to UI stack,
   3564                 //   making it easier to call TreeNodeGetOpen()/TreeNodeSetOpen() from any location.
   3565                 static ExampleTreeNode* TreeGetNextNodeInVisibleOrder(ExampleTreeNode* curr_node, ExampleTreeNode* last_node)
   3566                 {
   3567                     // Reached last node
   3568                     if (curr_node == last_node)
   3569                         return NULL;
   3570 
   3571                     // Recurse into childs. Query storage to tell if the node is open.
   3572                     if (curr_node->Childs.Size > 0 && TreeNodeGetOpen(curr_node))
   3573                         return curr_node->Childs[0];
   3574 
   3575                     // Next sibling, then into our own parent
   3576                     while (curr_node->Parent != NULL)
   3577                     {
   3578                         if (curr_node->IndexInParent + 1 < curr_node->Parent->Childs.Size)
   3579                             return curr_node->Parent->Childs[curr_node->IndexInParent + 1];
   3580                         curr_node = curr_node->Parent;
   3581                     }
   3582                     return NULL;
   3583                 }
   3584 
   3585             }; // ExampleTreeFuncs
   3586 
   3587             static ImGuiSelectionBasicStorage selection;
   3588             if (demo_data->DemoTree == NULL)
   3589                 demo_data->DemoTree = ExampleTree_CreateDemoTree(); // Create tree once
   3590             ImGui::Text("Selection size: %d", selection.Size);
   3591 
   3592             if (ImGui::BeginChild("##Tree", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
   3593             {
   3594                 ExampleTreeNode* tree = demo_data->DemoTree;
   3595                 ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d;
   3596                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, selection.Size, -1);
   3597                 ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection);
   3598                 for (ExampleTreeNode* node : tree->Childs)
   3599                     ExampleTreeFuncs::DrawNode(node, &selection);
   3600                 ms_io = ImGui::EndMultiSelect();
   3601                 ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection);
   3602             }
   3603             ImGui::EndChild();
   3604 
   3605             ImGui::TreePop();
   3606         }
   3607 
   3608         // Advanced demonstration of BeginMultiSelect()
   3609         // - Showcase clipping.
   3610         // - Showcase deletion.
   3611         // - Showcase basic drag and drop.
   3612         // - Showcase TreeNode variant (note that tree node don't expand in the demo: supporting expanding tree nodes + clipping a separate thing).
   3613         // - Showcase using inside a table.
   3614         IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (advanced)");
   3615         //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
   3616         if (ImGui::TreeNode("Multi-Select (advanced)"))
   3617         {
   3618             // Options
   3619             enum WidgetType { WidgetType_Selectable, WidgetType_TreeNode };
   3620             static bool use_clipper = true;
   3621             static bool use_deletion = true;
   3622             static bool use_drag_drop = true;
   3623             static bool show_in_table = false;
   3624             static bool show_color_button = true;
   3625             static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
   3626             static WidgetType widget_type = WidgetType_Selectable;
   3627 
   3628             if (ImGui::TreeNode("Options"))
   3629             {
   3630                 if (ImGui::RadioButton("Selectables", widget_type == WidgetType_Selectable)) { widget_type = WidgetType_Selectable; }
   3631                 ImGui::SameLine();
   3632                 if (ImGui::RadioButton("Tree nodes", widget_type == WidgetType_TreeNode)) { widget_type = WidgetType_TreeNode; }
   3633                 ImGui::SameLine();
   3634                 HelpMarker("TreeNode() is technically supported but... using this correctly is more complicated (you need some sort of linear/random access to your tree, which is suited to advanced trees setups already implementing filters and clipper. We will work toward simplifying and demoing this.\n\nFor now the tree demo is actually a little bit meaningless because it is an empty tree with only root nodes.");
   3635                 ImGui::Checkbox("Enable clipper", &use_clipper);
   3636                 ImGui::Checkbox("Enable deletion", &use_deletion);
   3637                 ImGui::Checkbox("Enable drag & drop", &use_drag_drop);
   3638                 ImGui::Checkbox("Show in a table", &show_in_table);
   3639                 ImGui::Checkbox("Show color button", &show_color_button);
   3640                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SingleSelect", &flags, ImGuiMultiSelectFlags_SingleSelect);
   3641                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectAll", &flags, ImGuiMultiSelectFlags_NoSelectAll);
   3642                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoRangeSelect", &flags, ImGuiMultiSelectFlags_NoRangeSelect);
   3643                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect);
   3644                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear);
   3645                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClearOnReselect", &flags, ImGuiMultiSelectFlags_NoAutoClearOnReselect);
   3646                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d);
   3647                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d);
   3648                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelectNoScroll", &flags, ImGuiMultiSelectFlags_BoxSelectNoScroll);
   3649                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnEscape", &flags, ImGuiMultiSelectFlags_ClearOnEscape);
   3650                 ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickVoid);
   3651                 if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeWindow", &flags, ImGuiMultiSelectFlags_ScopeWindow) && (flags & ImGuiMultiSelectFlags_ScopeWindow))
   3652                     flags &= ~ImGuiMultiSelectFlags_ScopeRect;
   3653                 if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeRect", &flags, ImGuiMultiSelectFlags_ScopeRect) && (flags & ImGuiMultiSelectFlags_ScopeRect))
   3654                     flags &= ~ImGuiMultiSelectFlags_ScopeWindow;
   3655                 if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SelectOnClick", &flags, ImGuiMultiSelectFlags_SelectOnClick) && (flags & ImGuiMultiSelectFlags_SelectOnClick))
   3656                     flags &= ~ImGuiMultiSelectFlags_SelectOnClickRelease;
   3657                 if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SelectOnClickRelease", &flags, ImGuiMultiSelectFlags_SelectOnClickRelease) && (flags & ImGuiMultiSelectFlags_SelectOnClickRelease))
   3658                     flags &= ~ImGuiMultiSelectFlags_SelectOnClick;
   3659                 ImGui::SameLine(); HelpMarker("Allow dragging an unselected item without altering selection.");
   3660                 ImGui::TreePop();
   3661             }
   3662 
   3663             // Initialize default list with 1000 items.
   3664             // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection
   3665             static ImVector<int> items;
   3666             static int items_next_id = 0;
   3667             if (items_next_id == 0) { for (int n = 0; n < 1000; n++) { items.push_back(items_next_id++); } }
   3668             static ExampleSelectionWithDeletion selection;
   3669             static bool request_deletion_from_menu = false; // Queue deletion triggered from context menu
   3670 
   3671             ImGui::Text("Selection size: %d/%d", selection.Size, items.Size);
   3672 
   3673             const float items_height = (widget_type == WidgetType_TreeNode) ? ImGui::GetTextLineHeight() : ImGui::GetTextLineHeightWithSpacing();
   3674             ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height));
   3675             if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
   3676             {
   3677                 ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize());
   3678                 if (widget_type == WidgetType_TreeNode)
   3679                     ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f));
   3680 
   3681                 ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
   3682                 selection.ApplyRequests(ms_io);
   3683 
   3684                 const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0)) || request_deletion_from_menu;
   3685                 const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1;
   3686                 request_deletion_from_menu = false;
   3687 
   3688                 if (show_in_table)
   3689                 {
   3690                     if (widget_type == WidgetType_TreeNode)
   3691                         ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.0f, 0.0f));
   3692                     ImGui::BeginTable("##Split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoPadOuterX);
   3693                     ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.70f);
   3694                     ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.30f);
   3695                     //ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f));
   3696                 }
   3697 
   3698                 ImGuiListClipper clipper;
   3699                 if (use_clipper)
   3700                 {
   3701                     clipper.Begin(items.Size);
   3702                     if (item_curr_idx_to_focus != -1)
   3703                         clipper.IncludeItemByIndex(item_curr_idx_to_focus); // Ensure focused item is not clipped.
   3704                     if (ms_io->RangeSrcItem != -1)
   3705                         clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
   3706                 }
   3707 
   3708                 while (!use_clipper || clipper.Step())
   3709                 {
   3710                     const int item_begin = use_clipper ? clipper.DisplayStart : 0;
   3711                     const int item_end = use_clipper ? clipper.DisplayEnd : items.Size;
   3712                     for (int n = item_begin; n < item_end; n++)
   3713                     {
   3714                         if (show_in_table)
   3715                             ImGui::TableNextColumn();
   3716 
   3717                         const int item_id = items[n];
   3718                         const char* item_category = ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)];
   3719                         char label[64];
   3720                         sprintf(label, "Object %05d: %s", item_id, item_category);
   3721 
   3722                         // IMPORTANT: for deletion refocus to work we need object ID to be stable,
   3723                         // aka not depend on their index in the list. Here we use our persistent item_id
   3724                         // instead of index to build a unique ID that will persist.
   3725                         // (If we used PushID(index) instead, focus wouldn't be restored correctly after deletion).
   3726                         ImGui::PushID(item_id);
   3727 
   3728                         // Emit a color button, to test that Shift+LeftArrow landing on an item that is not part
   3729                         // of the selection scope doesn't erroneously alter our selection.
   3730                         if (show_color_button)
   3731                         {
   3732                             ImU32 dummy_col = (ImU32)((unsigned int)n * 0xC250B74B) | IM_COL32_A_MASK;
   3733                             ImGui::ColorButton("##", ImColor(dummy_col), ImGuiColorEditFlags_NoTooltip, color_button_sz);
   3734                             ImGui::SameLine();
   3735                         }
   3736 
   3737                         // Submit item
   3738                         bool item_is_selected = selection.Contains((ImGuiID)n);
   3739                         bool item_is_open = false;
   3740                         ImGui::SetNextItemSelectionUserData(n);
   3741                         if (widget_type == WidgetType_Selectable)
   3742                         {
   3743                             ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_None);
   3744                         }
   3745                         else if (widget_type == WidgetType_TreeNode)
   3746                         {
   3747                             ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
   3748                             if (item_is_selected)
   3749                                 tree_node_flags |= ImGuiTreeNodeFlags_Selected;
   3750                             item_is_open = ImGui::TreeNodeEx(label, tree_node_flags);
   3751                         }
   3752 
   3753                         // Focus (for after deletion)
   3754                         if (item_curr_idx_to_focus == n)
   3755                             ImGui::SetKeyboardFocusHere(-1);
   3756 
   3757                         // Drag and Drop
   3758                         if (use_drag_drop && ImGui::BeginDragDropSource())
   3759                         {
   3760                             // Create payload with full selection OR single unselected item.
   3761                             // (the later is only possible when using ImGuiMultiSelectFlags_SelectOnClickRelease)
   3762                             if (ImGui::GetDragDropPayload() == NULL)
   3763                             {
   3764                                 ImVector<int> payload_items;
   3765                                 void* it = NULL;
   3766                                 ImGuiID id = 0;
   3767                                 if (!item_is_selected)
   3768                                     payload_items.push_back(item_id);
   3769                                 else
   3770                                     while (selection.GetNextSelectedItem(&it, &id))
   3771                                         payload_items.push_back((int)id);
   3772                                 ImGui::SetDragDropPayload("MULTISELECT_DEMO_ITEMS", payload_items.Data, (size_t)payload_items.size_in_bytes());
   3773                             }
   3774 
   3775                             // Display payload content in tooltip
   3776                             const ImGuiPayload* payload = ImGui::GetDragDropPayload();
   3777                             const int* payload_items = (int*)payload->Data;
   3778                             const int payload_count = (int)payload->DataSize / (int)sizeof(int);
   3779                             if (payload_count == 1)
   3780                                 ImGui::Text("Object %05d: %s", payload_items[0], ExampleNames[payload_items[0] % IM_ARRAYSIZE(ExampleNames)]);
   3781                             else
   3782                                 ImGui::Text("Dragging %d objects", payload_count);
   3783 
   3784                             ImGui::EndDragDropSource();
   3785                         }
   3786 
   3787                         if (widget_type == WidgetType_TreeNode && item_is_open)
   3788                             ImGui::TreePop();
   3789 
   3790                         // Right-click: context menu
   3791                         if (ImGui::BeginPopupContextItem())
   3792                         {
   3793                             ImGui::BeginDisabled(!use_deletion || selection.Size == 0);
   3794                             sprintf(label, "Delete %d item(s)###DeleteSelected", selection.Size);
   3795                             if (ImGui::Selectable(label))
   3796                                 request_deletion_from_menu = true;
   3797                             ImGui::EndDisabled();
   3798                             ImGui::Selectable("Close");
   3799                             ImGui::EndPopup();
   3800                         }
   3801 
   3802                         // Demo content within a table
   3803                         if (show_in_table)
   3804                         {
   3805                             ImGui::TableNextColumn();
   3806                             ImGui::SetNextItemWidth(-FLT_MIN);
   3807                             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
   3808                             ImGui::InputText("###NoLabel", (char*)(void*)item_category, strlen(item_category), ImGuiInputTextFlags_ReadOnly);
   3809                             ImGui::PopStyleVar();
   3810                         }
   3811 
   3812                         ImGui::PopID();
   3813                     }
   3814                     if (!use_clipper)
   3815                         break;
   3816                 }
   3817 
   3818                 if (show_in_table)
   3819                 {
   3820                     ImGui::EndTable();
   3821                     if (widget_type == WidgetType_TreeNode)
   3822                         ImGui::PopStyleVar();
   3823                 }
   3824 
   3825                 // Apply multi-select requests
   3826                 ms_io = ImGui::EndMultiSelect();
   3827                 selection.ApplyRequests(ms_io);
   3828                 if (want_delete)
   3829                     selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus);
   3830 
   3831                 if (widget_type == WidgetType_TreeNode)
   3832                     ImGui::PopStyleVar();
   3833             }
   3834             ImGui::EndChild();
   3835             ImGui::TreePop();
   3836         }
   3837         ImGui::TreePop();
   3838     }
   3839 }
   3840 
   3841 //-----------------------------------------------------------------------------
   3842 // [SECTION] ShowDemoWindowLayout()
   3843 //-----------------------------------------------------------------------------
   3844 
   3845 static void ShowDemoWindowLayout()
   3846 {
   3847     IMGUI_DEMO_MARKER("Layout");
   3848     if (!ImGui::CollapsingHeader("Layout & Scrolling"))
   3849         return;
   3850 
   3851     IMGUI_DEMO_MARKER("Layout/Child windows");
   3852     if (ImGui::TreeNode("Child windows"))
   3853     {
   3854         ImGui::SeparatorText("Child windows");
   3855 
   3856         HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
   3857         static bool disable_mouse_wheel = false;
   3858         static bool disable_menu = false;
   3859         ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
   3860         ImGui::Checkbox("Disable Menu", &disable_menu);
   3861 
   3862         // Child 1: no border, enable horizontal scrollbar
   3863         {
   3864             ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
   3865             if (disable_mouse_wheel)
   3866                 window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
   3867             ImGui::BeginChild("ChildL", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 260), ImGuiChildFlags_None, window_flags);
   3868             for (int i = 0; i < 100; i++)
   3869                 ImGui::Text("%04d: scrollable region", i);
   3870             ImGui::EndChild();
   3871         }
   3872 
   3873         ImGui::SameLine();
   3874 
   3875         // Child 2: rounded border
   3876         {
   3877             ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
   3878             if (disable_mouse_wheel)
   3879                 window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
   3880             if (!disable_menu)
   3881                 window_flags |= ImGuiWindowFlags_MenuBar;
   3882             ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
   3883             ImGui::BeginChild("ChildR", ImVec2(0, 260), ImGuiChildFlags_Border, window_flags);
   3884             if (!disable_menu && ImGui::BeginMenuBar())
   3885             {
   3886                 if (ImGui::BeginMenu("Menu"))
   3887                 {
   3888                     ShowExampleMenuFile();
   3889                     ImGui::EndMenu();
   3890                 }
   3891                 ImGui::EndMenuBar();
   3892             }
   3893             if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
   3894             {
   3895                 for (int i = 0; i < 100; i++)
   3896                 {
   3897                     char buf[32];
   3898                     sprintf(buf, "%03d", i);
   3899                     ImGui::TableNextColumn();
   3900                     ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
   3901                 }
   3902                 ImGui::EndTable();
   3903             }
   3904             ImGui::EndChild();
   3905             ImGui::PopStyleVar();
   3906         }
   3907 
   3908         // Child 3: manual-resize
   3909         ImGui::SeparatorText("Manual-resize");
   3910         {
   3911             HelpMarker("Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents.");
   3912             ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
   3913             if (ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY))
   3914                 for (int n = 0; n < 10; n++)
   3915                     ImGui::Text("Line %04d", n);
   3916             ImGui::PopStyleColor();
   3917             ImGui::EndChild();
   3918         }
   3919 
   3920         // Child 4: auto-resizing height with a limit
   3921         ImGui::SeparatorText("Auto-resize with constraints");
   3922         {
   3923             static int draw_lines = 3;
   3924             static int max_height_in_lines = 10;
   3925             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   3926             ImGui::DragInt("Lines Count", &draw_lines, 0.2f);
   3927             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   3928             ImGui::DragInt("Max Height (in Lines)", &max_height_in_lines, 0.2f);
   3929 
   3930             ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 1), ImVec2(FLT_MAX, ImGui::GetTextLineHeightWithSpacing() * max_height_in_lines));
   3931             if (ImGui::BeginChild("ConstrainedChild", ImVec2(-FLT_MIN, 0.0f), ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY))
   3932                 for (int n = 0; n < draw_lines; n++)
   3933                     ImGui::Text("Line %04d", n);
   3934             ImGui::EndChild();
   3935         }
   3936 
   3937         ImGui::SeparatorText("Misc/Advanced");
   3938 
   3939         // Demonstrate a few extra things
   3940         // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
   3941         // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window)
   3942         //   You can also call SetNextWindowPos() to position the child window. The parent window will effectively
   3943         //   layout from this position.
   3944         // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from
   3945         //   the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details.
   3946         {
   3947             static int offset_x = 0;
   3948             static bool override_bg_color = true;
   3949             static ImGuiChildFlags child_flags = ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY;
   3950             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   3951             ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
   3952             ImGui::Checkbox("Override ChildBg color", &override_bg_color);
   3953             ImGui::CheckboxFlags("ImGuiChildFlags_Border", &child_flags, ImGuiChildFlags_Border);
   3954             ImGui::CheckboxFlags("ImGuiChildFlags_AlwaysUseWindowPadding", &child_flags, ImGuiChildFlags_AlwaysUseWindowPadding);
   3955             ImGui::CheckboxFlags("ImGuiChildFlags_ResizeX", &child_flags, ImGuiChildFlags_ResizeX);
   3956             ImGui::CheckboxFlags("ImGuiChildFlags_ResizeY", &child_flags, ImGuiChildFlags_ResizeY);
   3957             ImGui::CheckboxFlags("ImGuiChildFlags_FrameStyle", &child_flags, ImGuiChildFlags_FrameStyle);
   3958             ImGui::SameLine(); HelpMarker("Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding.");
   3959             if (child_flags & ImGuiChildFlags_FrameStyle)
   3960                 override_bg_color = false;
   3961 
   3962             ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
   3963             if (override_bg_color)
   3964                 ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
   3965             ImGui::BeginChild("Red", ImVec2(200, 100), child_flags, ImGuiWindowFlags_None);
   3966             if (override_bg_color)
   3967                 ImGui::PopStyleColor();
   3968 
   3969             for (int n = 0; n < 50; n++)
   3970                 ImGui::Text("Some test %d", n);
   3971             ImGui::EndChild();
   3972             bool child_is_hovered = ImGui::IsItemHovered();
   3973             ImVec2 child_rect_min = ImGui::GetItemRectMin();
   3974             ImVec2 child_rect_max = ImGui::GetItemRectMax();
   3975             ImGui::Text("Hovered: %d", child_is_hovered);
   3976             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);
   3977         }
   3978 
   3979         ImGui::TreePop();
   3980     }
   3981 
   3982     IMGUI_DEMO_MARKER("Layout/Widgets Width");
   3983     if (ImGui::TreeNode("Widgets Width"))
   3984     {
   3985         static float f = 0.0f;
   3986         static bool show_indented_items = true;
   3987         ImGui::Checkbox("Show indented items", &show_indented_items);
   3988 
   3989         // Use SetNextItemWidth() to set the width of a single upcoming item.
   3990         // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
   3991         // In real code use you'll probably want to choose width values that are proportional to your font size
   3992         // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
   3993 
   3994         ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
   3995         ImGui::SameLine(); HelpMarker("Fixed width.");
   3996         ImGui::PushItemWidth(100);
   3997         ImGui::DragFloat("float##1b", &f);
   3998         if (show_indented_items)
   3999         {
   4000             ImGui::Indent();
   4001             ImGui::DragFloat("float (indented)##1b", &f);
   4002             ImGui::Unindent();
   4003         }
   4004         ImGui::PopItemWidth();
   4005 
   4006         ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
   4007         ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
   4008         ImGui::PushItemWidth(-100);
   4009         ImGui::DragFloat("float##2a", &f);
   4010         if (show_indented_items)
   4011         {
   4012             ImGui::Indent();
   4013             ImGui::DragFloat("float (indented)##2b", &f);
   4014             ImGui::Unindent();
   4015         }
   4016         ImGui::PopItemWidth();
   4017 
   4018         ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
   4019         ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
   4020         ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
   4021         ImGui::DragFloat("float##3a", &f);
   4022         if (show_indented_items)
   4023         {
   4024             ImGui::Indent();
   4025             ImGui::DragFloat("float (indented)##3b", &f);
   4026             ImGui::Unindent();
   4027         }
   4028         ImGui::PopItemWidth();
   4029 
   4030         ImGui::Text("SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)");
   4031         ImGui::SameLine(); HelpMarker("Align to right edge minus half");
   4032         ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
   4033         ImGui::DragFloat("float##4a", &f);
   4034         if (show_indented_items)
   4035         {
   4036             ImGui::Indent();
   4037             ImGui::DragFloat("float (indented)##4b", &f);
   4038             ImGui::Unindent();
   4039         }
   4040         ImGui::PopItemWidth();
   4041 
   4042         // Demonstrate using PushItemWidth to surround three items.
   4043         // Calling SetNextItemWidth() before each of them would have the same effect.
   4044         ImGui::Text("SetNextItemWidth/PushItemWidth(-FLT_MIN)");
   4045         ImGui::SameLine(); HelpMarker("Align to right edge");
   4046         ImGui::PushItemWidth(-FLT_MIN);
   4047         ImGui::DragFloat("##float5a", &f);
   4048         if (show_indented_items)
   4049         {
   4050             ImGui::Indent();
   4051             ImGui::DragFloat("float (indented)##5b", &f);
   4052             ImGui::Unindent();
   4053         }
   4054         ImGui::PopItemWidth();
   4055 
   4056         ImGui::TreePop();
   4057     }
   4058 
   4059     IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout");
   4060     if (ImGui::TreeNode("Basic Horizontal Layout"))
   4061     {
   4062         ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
   4063 
   4064         // Text
   4065         IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine");
   4066         ImGui::Text("Two items: Hello"); ImGui::SameLine();
   4067         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
   4068 
   4069         // Adjust spacing
   4070         ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
   4071         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
   4072 
   4073         // Button
   4074         ImGui::AlignTextToFramePadding();
   4075         ImGui::Text("Normal buttons"); ImGui::SameLine();
   4076         ImGui::Button("Banana"); ImGui::SameLine();
   4077         ImGui::Button("Apple"); ImGui::SameLine();
   4078         ImGui::Button("Corniflower");
   4079 
   4080         // Button
   4081         ImGui::Text("Small buttons"); ImGui::SameLine();
   4082         ImGui::SmallButton("Like this one"); ImGui::SameLine();
   4083         ImGui::Text("can fit within a text block.");
   4084 
   4085         // Aligned to arbitrary position. Easy/cheap column.
   4086         IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (with offset)");
   4087         ImGui::Text("Aligned");
   4088         ImGui::SameLine(150); ImGui::Text("x=150");
   4089         ImGui::SameLine(300); ImGui::Text("x=300");
   4090         ImGui::Text("Aligned");
   4091         ImGui::SameLine(150); ImGui::SmallButton("x=150");
   4092         ImGui::SameLine(300); ImGui::SmallButton("x=300");
   4093 
   4094         // Checkbox
   4095         IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (more)");
   4096         static bool c1 = false, c2 = false, c3 = false, c4 = false;
   4097         ImGui::Checkbox("My", &c1); ImGui::SameLine();
   4098         ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
   4099         ImGui::Checkbox("Is", &c3); ImGui::SameLine();
   4100         ImGui::Checkbox("Rich", &c4);
   4101 
   4102         // Various
   4103         static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
   4104         ImGui::PushItemWidth(80);
   4105         const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
   4106         static int item = -1;
   4107         ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
   4108         ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
   4109         ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
   4110         ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
   4111         ImGui::PopItemWidth();
   4112 
   4113         ImGui::PushItemWidth(80);
   4114         ImGui::Text("Lists:");
   4115         static int selection[4] = { 0, 1, 2, 3 };
   4116         for (int i = 0; i < 4; i++)
   4117         {
   4118             if (i > 0) ImGui::SameLine();
   4119             ImGui::PushID(i);
   4120             ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
   4121             ImGui::PopID();
   4122             //ImGui::SetItemTooltip("ListBox %d hovered", i);
   4123         }
   4124         ImGui::PopItemWidth();
   4125 
   4126         // Dummy
   4127         IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Dummy");
   4128         ImVec2 button_sz(40, 40);
   4129         ImGui::Button("A", button_sz); ImGui::SameLine();
   4130         ImGui::Dummy(button_sz); ImGui::SameLine();
   4131         ImGui::Button("B", button_sz);
   4132 
   4133         // Manually wrapping
   4134         // (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
   4135         IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Manual wrapping");
   4136         ImGui::Text("Manual wrapping:");
   4137         ImGuiStyle& style = ImGui::GetStyle();
   4138         int buttons_count = 20;
   4139         float window_visible_x2 = ImGui::GetCursorScreenPos().x + ImGui::GetContentRegionAvail().x;
   4140         for (int n = 0; n < buttons_count; n++)
   4141         {
   4142             ImGui::PushID(n);
   4143             ImGui::Button("Box", button_sz);
   4144             float last_button_x2 = ImGui::GetItemRectMax().x;
   4145             float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
   4146             if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
   4147                 ImGui::SameLine();
   4148             ImGui::PopID();
   4149         }
   4150 
   4151         ImGui::TreePop();
   4152     }
   4153 
   4154     IMGUI_DEMO_MARKER("Layout/Groups");
   4155     if (ImGui::TreeNode("Groups"))
   4156     {
   4157         HelpMarker(
   4158             "BeginGroup() basically locks the horizontal position for new line. "
   4159             "EndGroup() bundles the whole group so that you can use \"item\" functions such as "
   4160             "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group.");
   4161         ImGui::BeginGroup();
   4162         {
   4163             ImGui::BeginGroup();
   4164             ImGui::Button("AAA");
   4165             ImGui::SameLine();
   4166             ImGui::Button("BBB");
   4167             ImGui::SameLine();
   4168             ImGui::BeginGroup();
   4169             ImGui::Button("CCC");
   4170             ImGui::Button("DDD");
   4171             ImGui::EndGroup();
   4172             ImGui::SameLine();
   4173             ImGui::Button("EEE");
   4174             ImGui::EndGroup();
   4175             ImGui::SetItemTooltip("First group hovered");
   4176         }
   4177         // Capture the group size and create widgets using the same size
   4178         ImVec2 size = ImGui::GetItemRectSize();
   4179         const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
   4180         ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
   4181 
   4182         ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
   4183         ImGui::SameLine();
   4184         ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
   4185         ImGui::EndGroup();
   4186         ImGui::SameLine();
   4187 
   4188         ImGui::Button("LEVERAGE\nBUZZWORD", size);
   4189         ImGui::SameLine();
   4190 
   4191         if (ImGui::BeginListBox("List", size))
   4192         {
   4193             ImGui::Selectable("Selected", true);
   4194             ImGui::Selectable("Not Selected", false);
   4195             ImGui::EndListBox();
   4196         }
   4197 
   4198         ImGui::TreePop();
   4199     }
   4200 
   4201     IMGUI_DEMO_MARKER("Layout/Text Baseline Alignment");
   4202     if (ImGui::TreeNode("Text Baseline Alignment"))
   4203     {
   4204         {
   4205             ImGui::BulletText("Text baseline:");
   4206             ImGui::SameLine(); HelpMarker(
   4207                 "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. "
   4208                 "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets.");
   4209             ImGui::Indent();
   4210 
   4211             ImGui::Text("KO Blahblah"); ImGui::SameLine();
   4212             ImGui::Button("Some framed item"); ImGui::SameLine();
   4213             HelpMarker("Baseline of button will look misaligned with text..");
   4214 
   4215             // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
   4216             // (because we don't know what's coming after the Text() statement, we need to move the text baseline
   4217             // down by FramePadding.y ahead of time)
   4218             ImGui::AlignTextToFramePadding();
   4219             ImGui::Text("OK Blahblah"); ImGui::SameLine();
   4220             ImGui::Button("Some framed item"); ImGui::SameLine();
   4221             HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
   4222 
   4223             // SmallButton() uses the same vertical padding as Text
   4224             ImGui::Button("TEST##1"); ImGui::SameLine();
   4225             ImGui::Text("TEST"); ImGui::SameLine();
   4226             ImGui::SmallButton("TEST##2");
   4227 
   4228             // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
   4229             ImGui::AlignTextToFramePadding();
   4230             ImGui::Text("Text aligned to framed item"); ImGui::SameLine();
   4231             ImGui::Button("Item##1"); ImGui::SameLine();
   4232             ImGui::Text("Item"); ImGui::SameLine();
   4233             ImGui::SmallButton("Item##2"); ImGui::SameLine();
   4234             ImGui::Button("Item##3");
   4235 
   4236             ImGui::Unindent();
   4237         }
   4238 
   4239         ImGui::Spacing();
   4240 
   4241         {
   4242             ImGui::BulletText("Multi-line text:");
   4243             ImGui::Indent();
   4244             ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
   4245             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
   4246             ImGui::Text("Banana");
   4247 
   4248             ImGui::Text("Banana"); ImGui::SameLine();
   4249             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
   4250             ImGui::Text("One\nTwo\nThree");
   4251 
   4252             ImGui::Button("HOP##1"); ImGui::SameLine();
   4253             ImGui::Text("Banana"); ImGui::SameLine();
   4254             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
   4255             ImGui::Text("Banana");
   4256 
   4257             ImGui::Button("HOP##2"); ImGui::SameLine();
   4258             ImGui::Text("Hello\nWorld"); ImGui::SameLine();
   4259             ImGui::Text("Banana");
   4260             ImGui::Unindent();
   4261         }
   4262 
   4263         ImGui::Spacing();
   4264 
   4265         {
   4266             ImGui::BulletText("Misc items:");
   4267             ImGui::Indent();
   4268 
   4269             // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button.
   4270             ImGui::Button("80x80", ImVec2(80, 80));
   4271             ImGui::SameLine();
   4272             ImGui::Button("50x50", ImVec2(50, 50));
   4273             ImGui::SameLine();
   4274             ImGui::Button("Button()");
   4275             ImGui::SameLine();
   4276             ImGui::SmallButton("SmallButton()");
   4277 
   4278             // Tree
   4279             const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
   4280             ImGui::Button("Button##1");
   4281             ImGui::SameLine(0.0f, spacing);
   4282             if (ImGui::TreeNode("Node##1"))
   4283             {
   4284                 // Placeholder tree data
   4285                 for (int i = 0; i < 6; i++)
   4286                     ImGui::BulletText("Item %d..", i);
   4287                 ImGui::TreePop();
   4288             }
   4289 
   4290             // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget.
   4291             // Otherwise you can use SmallButton() (smaller fit).
   4292             ImGui::AlignTextToFramePadding();
   4293 
   4294             // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add
   4295             // other contents below the node.
   4296             bool node_open = ImGui::TreeNode("Node##2");
   4297             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
   4298             if (node_open)
   4299             {
   4300                 // Placeholder tree data
   4301                 for (int i = 0; i < 6; i++)
   4302                     ImGui::BulletText("Item %d..", i);
   4303                 ImGui::TreePop();
   4304             }
   4305 
   4306             // Bullet
   4307             ImGui::Button("Button##3");
   4308             ImGui::SameLine(0.0f, spacing);
   4309             ImGui::BulletText("Bullet text");
   4310 
   4311             ImGui::AlignTextToFramePadding();
   4312             ImGui::BulletText("Node");
   4313             ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
   4314             ImGui::Unindent();
   4315         }
   4316 
   4317         ImGui::TreePop();
   4318     }
   4319 
   4320     IMGUI_DEMO_MARKER("Layout/Scrolling");
   4321     if (ImGui::TreeNode("Scrolling"))
   4322     {
   4323         // Vertical scroll functions
   4324         IMGUI_DEMO_MARKER("Layout/Scrolling/Vertical");
   4325         HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
   4326 
   4327         static int track_item = 50;
   4328         static bool enable_track = true;
   4329         static bool enable_extra_decorations = false;
   4330         static float scroll_to_off_px = 0.0f;
   4331         static float scroll_to_pos_px = 200.0f;
   4332 
   4333         ImGui::Checkbox("Decoration", &enable_extra_decorations);
   4334 
   4335         ImGui::Checkbox("Track", &enable_track);
   4336         ImGui::PushItemWidth(100);
   4337         ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
   4338 
   4339         bool scroll_to_off = ImGui::Button("Scroll Offset");
   4340         ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
   4341 
   4342         bool scroll_to_pos = ImGui::Button("Scroll To Pos");
   4343         ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
   4344         ImGui::PopItemWidth();
   4345 
   4346         if (scroll_to_off || scroll_to_pos)
   4347             enable_track = false;
   4348 
   4349         ImGuiStyle& style = ImGui::GetStyle();
   4350         float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
   4351         if (child_w < 1.0f)
   4352             child_w = 1.0f;
   4353         ImGui::PushID("##VerticalScrolling");
   4354         for (int i = 0; i < 5; i++)
   4355         {
   4356             if (i > 0) ImGui::SameLine();
   4357             ImGui::BeginGroup();
   4358             const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
   4359             ImGui::TextUnformatted(names[i]);
   4360 
   4361             const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
   4362             const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
   4363             const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), ImGuiChildFlags_Border, child_flags);
   4364             if (ImGui::BeginMenuBar())
   4365             {
   4366                 ImGui::TextUnformatted("abc");
   4367                 ImGui::EndMenuBar();
   4368             }
   4369             if (scroll_to_off)
   4370                 ImGui::SetScrollY(scroll_to_off_px);
   4371             if (scroll_to_pos)
   4372                 ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
   4373             if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
   4374             {
   4375                 for (int item = 0; item < 100; item++)
   4376                 {
   4377                     if (enable_track && item == track_item)
   4378                     {
   4379                         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
   4380                         ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
   4381                     }
   4382                     else
   4383                     {
   4384                         ImGui::Text("Item %d", item);
   4385                     }
   4386                 }
   4387             }
   4388             float scroll_y = ImGui::GetScrollY();
   4389             float scroll_max_y = ImGui::GetScrollMaxY();
   4390             ImGui::EndChild();
   4391             ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
   4392             ImGui::EndGroup();
   4393         }
   4394         ImGui::PopID();
   4395 
   4396         // Horizontal scroll functions
   4397         IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal");
   4398         ImGui::Spacing();
   4399         HelpMarker(
   4400             "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n"
   4401             "Because the clipping rectangle of most window hides half worth of WindowPadding on the "
   4402             "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the "
   4403             "equivalent SetScrollFromPosY(+1) wouldn't.");
   4404         ImGui::PushID("##HorizontalScrolling");
   4405         for (int i = 0; i < 5; i++)
   4406         {
   4407             float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
   4408             ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
   4409             ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
   4410             bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), ImGuiChildFlags_Border, child_flags);
   4411             if (scroll_to_off)
   4412                 ImGui::SetScrollX(scroll_to_off_px);
   4413             if (scroll_to_pos)
   4414                 ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
   4415             if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
   4416             {
   4417                 for (int item = 0; item < 100; item++)
   4418                 {
   4419                     if (item > 0)
   4420                         ImGui::SameLine();
   4421                     if (enable_track && item == track_item)
   4422                     {
   4423                         ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
   4424                         ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
   4425                     }
   4426                     else
   4427                     {
   4428                         ImGui::Text("Item %d", item);
   4429                     }
   4430                 }
   4431             }
   4432             float scroll_x = ImGui::GetScrollX();
   4433             float scroll_max_x = ImGui::GetScrollMaxX();
   4434             ImGui::EndChild();
   4435             ImGui::SameLine();
   4436             const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
   4437             ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
   4438             ImGui::Spacing();
   4439         }
   4440         ImGui::PopID();
   4441 
   4442         // Miscellaneous Horizontal Scrolling Demo
   4443         IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal (more)");
   4444         HelpMarker(
   4445             "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n"
   4446             "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin().");
   4447         static int lines = 7;
   4448         ImGui::SliderInt("Lines", &lines, 1, 15);
   4449         ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
   4450         ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
   4451         ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
   4452         ImGui::BeginChild("scrolling", scrolling_child_size, ImGuiChildFlags_Border, ImGuiWindowFlags_HorizontalScrollbar);
   4453         for (int line = 0; line < lines; line++)
   4454         {
   4455             // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
   4456             // If you want to create your own time line for a real application you may be better off manipulating
   4457             // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
   4458             // yourself. You may also want to use the lower-level ImDrawList API.
   4459             int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
   4460             for (int n = 0; n < num_buttons; n++)
   4461             {
   4462                 if (n > 0) ImGui::SameLine();
   4463                 ImGui::PushID(n + line * 1000);
   4464                 char num_buf[16];
   4465                 sprintf(num_buf, "%d", n);
   4466                 const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
   4467                 float hue = n * 0.05f;
   4468                 ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
   4469                 ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
   4470                 ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
   4471                 ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
   4472                 ImGui::PopStyleColor(3);
   4473                 ImGui::PopID();
   4474             }
   4475         }
   4476         float scroll_x = ImGui::GetScrollX();
   4477         float scroll_max_x = ImGui::GetScrollMaxX();
   4478         ImGui::EndChild();
   4479         ImGui::PopStyleVar(2);
   4480         float scroll_x_delta = 0.0f;
   4481         ImGui::SmallButton("<<");
   4482         if (ImGui::IsItemActive())
   4483             scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
   4484         ImGui::SameLine();
   4485         ImGui::Text("Scroll from code"); ImGui::SameLine();
   4486         ImGui::SmallButton(">>");
   4487         if (ImGui::IsItemActive())
   4488             scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
   4489         ImGui::SameLine();
   4490         ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
   4491         if (scroll_x_delta != 0.0f)
   4492         {
   4493             // Demonstrate a trick: you can use Begin to set yourself in the context of another window
   4494             // (here we are already out of your child window)
   4495             ImGui::BeginChild("scrolling");
   4496             ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
   4497             ImGui::EndChild();
   4498         }
   4499         ImGui::Spacing();
   4500 
   4501         static bool show_horizontal_contents_size_demo_window = false;
   4502         ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
   4503 
   4504         if (show_horizontal_contents_size_demo_window)
   4505         {
   4506             static bool show_h_scrollbar = true;
   4507             static bool show_button = true;
   4508             static bool show_tree_nodes = true;
   4509             static bool show_text_wrapped = false;
   4510             static bool show_columns = true;
   4511             static bool show_tab_bar = true;
   4512             static bool show_child = false;
   4513             static bool explicit_content_size = false;
   4514             static float contents_size_x = 300.0f;
   4515             if (explicit_content_size)
   4516                 ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
   4517             ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
   4518             IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal contents size demo window");
   4519             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
   4520             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
   4521             HelpMarker(
   4522                 "Test how different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\n"
   4523                 "Use 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
   4524             ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
   4525             ImGui::Checkbox("Button", &show_button);            // Will grow contents size (unless explicitly overwritten)
   4526             ImGui::Checkbox("Tree nodes", &show_tree_nodes);    // Will grow contents size and display highlight over full width
   4527             ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
   4528             ImGui::Checkbox("Columns", &show_columns);          // Will use contents size
   4529             ImGui::Checkbox("Tab bar", &show_tab_bar);          // Will use contents size
   4530             ImGui::Checkbox("Child", &show_child);              // Will grow and use contents size
   4531             ImGui::Checkbox("Explicit content size", &explicit_content_size);
   4532             ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
   4533             if (explicit_content_size)
   4534             {
   4535                 ImGui::SameLine();
   4536                 ImGui::SetNextItemWidth(100);
   4537                 ImGui::DragFloat("##csx", &contents_size_x);
   4538                 ImVec2 p = ImGui::GetCursorScreenPos();
   4539                 ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
   4540                 ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
   4541                 ImGui::Dummy(ImVec2(0, 10));
   4542             }
   4543             ImGui::PopStyleVar(2);
   4544             ImGui::Separator();
   4545             if (show_button)
   4546             {
   4547                 ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
   4548             }
   4549             if (show_tree_nodes)
   4550             {
   4551                 bool open = true;
   4552                 if (ImGui::TreeNode("this is a tree node"))
   4553                 {
   4554                     if (ImGui::TreeNode("another one of those tree node..."))
   4555                     {
   4556                         ImGui::Text("Some tree contents");
   4557                         ImGui::TreePop();
   4558                     }
   4559                     ImGui::TreePop();
   4560                 }
   4561                 ImGui::CollapsingHeader("CollapsingHeader", &open);
   4562             }
   4563             if (show_text_wrapped)
   4564             {
   4565                 ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
   4566             }
   4567             if (show_columns)
   4568             {
   4569                 ImGui::Text("Tables:");
   4570                 if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders))
   4571                 {
   4572                     for (int n = 0; n < 4; n++)
   4573                     {
   4574                         ImGui::TableNextColumn();
   4575                         ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x);
   4576                     }
   4577                     ImGui::EndTable();
   4578                 }
   4579                 ImGui::Text("Columns:");
   4580                 ImGui::Columns(4);
   4581                 for (int n = 0; n < 4; n++)
   4582                 {
   4583                     ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
   4584                     ImGui::NextColumn();
   4585                 }
   4586                 ImGui::Columns(1);
   4587             }
   4588             if (show_tab_bar && ImGui::BeginTabBar("Hello"))
   4589             {
   4590                 if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
   4591                 if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
   4592                 if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
   4593                 if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
   4594                 ImGui::EndTabBar();
   4595             }
   4596             if (show_child)
   4597             {
   4598                 ImGui::BeginChild("child", ImVec2(0, 0), ImGuiChildFlags_Border);
   4599                 ImGui::EndChild();
   4600             }
   4601             ImGui::End();
   4602         }
   4603 
   4604         ImGui::TreePop();
   4605     }
   4606 
   4607     IMGUI_DEMO_MARKER("Layout/Text Clipping");
   4608     if (ImGui::TreeNode("Text Clipping"))
   4609     {
   4610         static ImVec2 size(100.0f, 100.0f);
   4611         static ImVec2 offset(30.0f, 30.0f);
   4612         ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
   4613         ImGui::TextWrapped("(Click and drag to scroll)");
   4614 
   4615         HelpMarker(
   4616             "(Left) Using ImGui::PushClipRect():\n"
   4617             "Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
   4618             "(use this if you want your clipping rectangle to affect interactions)\n\n"
   4619             "(Center) Using ImDrawList::PushClipRect():\n"
   4620             "Will alter ImDrawList rendering only.\n"
   4621             "(use this as a shortcut if you are only using ImDrawList calls)\n\n"
   4622             "(Right) Using ImDrawList::AddText() with a fine ClipRect:\n"
   4623             "Will alter only this specific ImDrawList::AddText() rendering.\n"
   4624             "This is often used internally to avoid altering the clipping rectangle and minimize draw calls.");
   4625 
   4626         for (int n = 0; n < 3; n++)
   4627         {
   4628             if (n > 0)
   4629                 ImGui::SameLine();
   4630 
   4631             ImGui::PushID(n);
   4632             ImGui::InvisibleButton("##canvas", size);
   4633             if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
   4634             {
   4635                 offset.x += ImGui::GetIO().MouseDelta.x;
   4636                 offset.y += ImGui::GetIO().MouseDelta.y;
   4637             }
   4638             ImGui::PopID();
   4639             if (!ImGui::IsItemVisible()) // Skip rendering as ImDrawList elements are not clipped.
   4640                 continue;
   4641 
   4642             const ImVec2 p0 = ImGui::GetItemRectMin();
   4643             const ImVec2 p1 = ImGui::GetItemRectMax();
   4644             const char* text_str = "Line 1 hello\nLine 2 clip me!";
   4645             const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y);
   4646             ImDrawList* draw_list = ImGui::GetWindowDrawList();
   4647             switch (n)
   4648             {
   4649             case 0:
   4650                 ImGui::PushClipRect(p0, p1, true);
   4651                 draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
   4652                 draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
   4653                 ImGui::PopClipRect();
   4654                 break;
   4655             case 1:
   4656                 draw_list->PushClipRect(p0, p1, true);
   4657                 draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
   4658                 draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
   4659                 draw_list->PopClipRect();
   4660                 break;
   4661             case 2:
   4662                 ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert.
   4663                 draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
   4664                 draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect);
   4665                 break;
   4666             }
   4667         }
   4668 
   4669         ImGui::TreePop();
   4670     }
   4671 
   4672     IMGUI_DEMO_MARKER("Layout/Overlap Mode");
   4673     if (ImGui::TreeNode("Overlap Mode"))
   4674     {
   4675         static bool enable_allow_overlap = true;
   4676 
   4677         HelpMarker(
   4678             "Hit-testing is by default performed in item submission order, which generally is perceived as 'back-to-front'.\n\n"
   4679             "By using SetNextItemAllowOverlap() you can notify that an item may be overlapped by another. "
   4680             "Doing so alters the hovering logic: items using AllowOverlap mode requires an extra frame to accept hovered state.");
   4681         ImGui::Checkbox("Enable AllowOverlap", &enable_allow_overlap);
   4682 
   4683         ImVec2 button1_pos = ImGui::GetCursorScreenPos();
   4684         ImVec2 button2_pos = ImVec2(button1_pos.x + 50.0f, button1_pos.y + 50.0f);
   4685         if (enable_allow_overlap)
   4686             ImGui::SetNextItemAllowOverlap();
   4687         ImGui::Button("Button 1", ImVec2(80, 80));
   4688         ImGui::SetCursorScreenPos(button2_pos);
   4689         ImGui::Button("Button 2", ImVec2(80, 80));
   4690 
   4691         // This is typically used with width-spanning items.
   4692         // (note that Selectable() has a dedicated flag ImGuiSelectableFlags_AllowOverlap, which is a shortcut
   4693         // for using SetNextItemAllowOverlap(). For demo purpose we use SetNextItemAllowOverlap() here.)
   4694         if (enable_allow_overlap)
   4695             ImGui::SetNextItemAllowOverlap();
   4696         ImGui::Selectable("Some Selectable", false);
   4697         ImGui::SameLine();
   4698         ImGui::SmallButton("++");
   4699 
   4700         ImGui::TreePop();
   4701     }
   4702 }
   4703 
   4704 //-----------------------------------------------------------------------------
   4705 // [SECTION] ShowDemoWindowPopups()
   4706 //-----------------------------------------------------------------------------
   4707 
   4708 static void ShowDemoWindowPopups()
   4709 {
   4710     IMGUI_DEMO_MARKER("Popups");
   4711     if (!ImGui::CollapsingHeader("Popups & Modal windows"))
   4712         return;
   4713 
   4714     // The properties of popups windows are:
   4715     // - They block normal mouse hovering detection outside them. (*)
   4716     // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
   4717     // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as
   4718     //   we are used to with regular Begin() calls. User can manipulate the visibility state by calling OpenPopup().
   4719     // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even
   4720     //     when normally blocked by a popup.
   4721     // Those three properties are connected. The library needs to hold their visibility state BECAUSE it can close
   4722     // popups at any time.
   4723 
   4724     // Typical use for regular windows:
   4725     //   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();
   4726     // Typical use for popups:
   4727     //   if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
   4728 
   4729     // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
   4730     // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
   4731 
   4732     IMGUI_DEMO_MARKER("Popups/Popups");
   4733     if (ImGui::TreeNode("Popups"))
   4734     {
   4735         ImGui::TextWrapped(
   4736             "When a popup is active, it inhibits interacting with windows that are behind the popup. "
   4737             "Clicking outside the popup closes it.");
   4738 
   4739         static int selected_fish = -1;
   4740         const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
   4741         static bool toggles[] = { true, false, false, false, false };
   4742 
   4743         // Simple selection popup (if you want to show the current selection inside the Button itself,
   4744         // you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
   4745         if (ImGui::Button("Select.."))
   4746             ImGui::OpenPopup("my_select_popup");
   4747         ImGui::SameLine();
   4748         ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
   4749         if (ImGui::BeginPopup("my_select_popup"))
   4750         {
   4751             ImGui::SeparatorText("Aquarium");
   4752             for (int i = 0; i < IM_ARRAYSIZE(names); i++)
   4753                 if (ImGui::Selectable(names[i]))
   4754                     selected_fish = i;
   4755             ImGui::EndPopup();
   4756         }
   4757 
   4758         // Showing a menu with toggles
   4759         if (ImGui::Button("Toggle.."))
   4760             ImGui::OpenPopup("my_toggle_popup");
   4761         if (ImGui::BeginPopup("my_toggle_popup"))
   4762         {
   4763             for (int i = 0; i < IM_ARRAYSIZE(names); i++)
   4764                 ImGui::MenuItem(names[i], "", &toggles[i]);
   4765             if (ImGui::BeginMenu("Sub-menu"))
   4766             {
   4767                 ImGui::MenuItem("Click me");
   4768                 ImGui::EndMenu();
   4769             }
   4770 
   4771             ImGui::Separator();
   4772             ImGui::Text("Tooltip here");
   4773             ImGui::SetItemTooltip("I am a tooltip over a popup");
   4774 
   4775             if (ImGui::Button("Stacked Popup"))
   4776                 ImGui::OpenPopup("another popup");
   4777             if (ImGui::BeginPopup("another popup"))
   4778             {
   4779                 for (int i = 0; i < IM_ARRAYSIZE(names); i++)
   4780                     ImGui::MenuItem(names[i], "", &toggles[i]);
   4781                 if (ImGui::BeginMenu("Sub-menu"))
   4782                 {
   4783                     ImGui::MenuItem("Click me");
   4784                     if (ImGui::Button("Stacked Popup"))
   4785                         ImGui::OpenPopup("another popup");
   4786                     if (ImGui::BeginPopup("another popup"))
   4787                     {
   4788                         ImGui::Text("I am the last one here.");
   4789                         ImGui::EndPopup();
   4790                     }
   4791                     ImGui::EndMenu();
   4792                 }
   4793                 ImGui::EndPopup();
   4794             }
   4795             ImGui::EndPopup();
   4796         }
   4797 
   4798         // Call the more complete ShowExampleMenuFile which we use in various places of this demo
   4799         if (ImGui::Button("With a menu.."))
   4800             ImGui::OpenPopup("my_file_popup");
   4801         if (ImGui::BeginPopup("my_file_popup", ImGuiWindowFlags_MenuBar))
   4802         {
   4803             if (ImGui::BeginMenuBar())
   4804             {
   4805                 if (ImGui::BeginMenu("File"))
   4806                 {
   4807                     ShowExampleMenuFile();
   4808                     ImGui::EndMenu();
   4809                 }
   4810                 if (ImGui::BeginMenu("Edit"))
   4811                 {
   4812                     ImGui::MenuItem("Dummy");
   4813                     ImGui::EndMenu();
   4814                 }
   4815                 ImGui::EndMenuBar();
   4816             }
   4817             ImGui::Text("Hello from popup!");
   4818             ImGui::Button("This is a dummy button..");
   4819             ImGui::EndPopup();
   4820         }
   4821 
   4822         ImGui::TreePop();
   4823     }
   4824 
   4825     IMGUI_DEMO_MARKER("Popups/Context menus");
   4826     if (ImGui::TreeNode("Context menus"))
   4827     {
   4828         HelpMarker("\"Context\" functions are simple helpers to associate a Popup to a given Item or Window identifier.");
   4829 
   4830         // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
   4831         //     if (id == 0)
   4832         //         id = GetItemID(); // Use last item id
   4833         //     if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
   4834         //         OpenPopup(id);
   4835         //     return BeginPopup(id);
   4836         // For advanced uses you may want to replicate and customize this code.
   4837         // See more details in BeginPopupContextItem().
   4838 
   4839         // Example 1
   4840         // When used after an item that has an ID (e.g. Button), we can skip providing an ID to BeginPopupContextItem(),
   4841         // and BeginPopupContextItem() will use the last item ID as the popup ID.
   4842         {
   4843             const char* names[5] = { "Label1", "Label2", "Label3", "Label4", "Label5" };
   4844             static int selected = -1;
   4845             for (int n = 0; n < 5; n++)
   4846             {
   4847                 if (ImGui::Selectable(names[n], selected == n))
   4848                     selected = n;
   4849                 if (ImGui::BeginPopupContextItem()) // <-- use last item id as popup id
   4850                 {
   4851                     selected = n;
   4852                     ImGui::Text("This a popup for \"%s\"!", names[n]);
   4853                     if (ImGui::Button("Close"))
   4854                         ImGui::CloseCurrentPopup();
   4855                     ImGui::EndPopup();
   4856                 }
   4857                 ImGui::SetItemTooltip("Right-click to open popup");
   4858             }
   4859         }
   4860 
   4861         // Example 2
   4862         // Popup on a Text() element which doesn't have an identifier: we need to provide an identifier to BeginPopupContextItem().
   4863         // Using an explicit identifier is also convenient if you want to activate the popups from different locations.
   4864         {
   4865             HelpMarker("Text() elements don't have stable identifiers so we need to provide one.");
   4866             static float value = 0.5f;
   4867             ImGui::Text("Value = %.3f <-- (1) right-click this text", value);
   4868             if (ImGui::BeginPopupContextItem("my popup"))
   4869             {
   4870                 if (ImGui::Selectable("Set to zero")) value = 0.0f;
   4871                 if (ImGui::Selectable("Set to PI")) value = 3.1415f;
   4872                 ImGui::SetNextItemWidth(-FLT_MIN);
   4873                 ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
   4874                 ImGui::EndPopup();
   4875             }
   4876 
   4877             // We can also use OpenPopupOnItemClick() to toggle the visibility of a given popup.
   4878             // Here we make it that right-clicking this other text element opens the same popup as above.
   4879             // The popup itself will be submitted by the code above.
   4880             ImGui::Text("(2) Or right-click this text");
   4881             ImGui::OpenPopupOnItemClick("my popup", ImGuiPopupFlags_MouseButtonRight);
   4882 
   4883             // Back to square one: manually open the same popup.
   4884             if (ImGui::Button("(3) Or click this button"))
   4885                 ImGui::OpenPopup("my popup");
   4886         }
   4887 
   4888         // Example 3
   4889         // When using BeginPopupContextItem() with an implicit identifier (NULL == use last item ID),
   4890         // we need to make sure your item identifier is stable.
   4891         // In this example we showcase altering the item label while preserving its identifier, using the ### operator (see FAQ).
   4892         {
   4893             HelpMarker("Showcase using a popup ID linked to item ID, with the item having a changing label + stable ID using the ### operator.");
   4894             static char name[32] = "Label1";
   4895             char buf[64];
   4896             sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
   4897             ImGui::Button(buf);
   4898             if (ImGui::BeginPopupContextItem())
   4899             {
   4900                 ImGui::Text("Edit name:");
   4901                 ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
   4902                 if (ImGui::Button("Close"))
   4903                     ImGui::CloseCurrentPopup();
   4904                 ImGui::EndPopup();
   4905             }
   4906             ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
   4907         }
   4908 
   4909         ImGui::TreePop();
   4910     }
   4911 
   4912     IMGUI_DEMO_MARKER("Popups/Modals");
   4913     if (ImGui::TreeNode("Modals"))
   4914     {
   4915         ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside.");
   4916 
   4917         if (ImGui::Button("Delete.."))
   4918             ImGui::OpenPopup("Delete?");
   4919 
   4920         // Always center this window when appearing
   4921         ImVec2 center = ImGui::GetMainViewport()->GetCenter();
   4922         ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
   4923 
   4924         if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
   4925         {
   4926             ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!");
   4927             ImGui::Separator();
   4928 
   4929             //static int unused_i = 0;
   4930             //ImGui::Combo("Combo", &unused_i, "Delete\0Delete harder\0");
   4931 
   4932             static bool dont_ask_me_next_time = false;
   4933             ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
   4934             ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
   4935             ImGui::PopStyleVar();
   4936 
   4937             if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
   4938             ImGui::SetItemDefaultFocus();
   4939             ImGui::SameLine();
   4940             if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
   4941             ImGui::EndPopup();
   4942         }
   4943 
   4944         if (ImGui::Button("Stacked modals.."))
   4945             ImGui::OpenPopup("Stacked 1");
   4946         if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
   4947         {
   4948             if (ImGui::BeginMenuBar())
   4949             {
   4950                 if (ImGui::BeginMenu("File"))
   4951                 {
   4952                     if (ImGui::MenuItem("Some menu item")) {}
   4953                     ImGui::EndMenu();
   4954                 }
   4955                 ImGui::EndMenuBar();
   4956             }
   4957             ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
   4958 
   4959             // Testing behavior of widgets stacking their own regular popups over the modal.
   4960             static int item = 1;
   4961             static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
   4962             ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
   4963             ImGui::ColorEdit4("Color", color);
   4964 
   4965             if (ImGui::Button("Add another modal.."))
   4966                 ImGui::OpenPopup("Stacked 2");
   4967 
   4968             // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which
   4969             // will close the popup. Note that the visibility state of popups is owned by imgui, so the input value
   4970             // of the bool actually doesn't matter here.
   4971             bool unused_open = true;
   4972             if (ImGui::BeginPopupModal("Stacked 2", &unused_open))
   4973             {
   4974                 ImGui::Text("Hello from Stacked The Second!");
   4975                 ImGui::ColorEdit4("Color", color); // Allow opening another nested popup
   4976                 if (ImGui::Button("Close"))
   4977                     ImGui::CloseCurrentPopup();
   4978                 ImGui::EndPopup();
   4979             }
   4980 
   4981             if (ImGui::Button("Close"))
   4982                 ImGui::CloseCurrentPopup();
   4983             ImGui::EndPopup();
   4984         }
   4985 
   4986         ImGui::TreePop();
   4987     }
   4988 
   4989     IMGUI_DEMO_MARKER("Popups/Menus inside a regular window");
   4990     if (ImGui::TreeNode("Menus inside a regular window"))
   4991     {
   4992         ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
   4993         ImGui::Separator();
   4994 
   4995         ImGui::MenuItem("Menu item", "CTRL+M");
   4996         if (ImGui::BeginMenu("Menu inside a regular window"))
   4997         {
   4998             ShowExampleMenuFile();
   4999             ImGui::EndMenu();
   5000         }
   5001         ImGui::Separator();
   5002         ImGui::TreePop();
   5003     }
   5004 }
   5005 
   5006 // Dummy data structure that we use for the Table demo.
   5007 // (pre-C++11 doesn't allow us to instantiate ImVector<MyItem> template if this structure is defined inside the demo function)
   5008 namespace
   5009 {
   5010 // We are passing our own identifier to TableSetupColumn() to facilitate identifying columns in the sorting code.
   5011 // This identifier will be passed down into ImGuiTableSortSpec::ColumnUserID.
   5012 // But it is possible to omit the user id parameter of TableSetupColumn() and just use the column index instead! (ImGuiTableSortSpec::ColumnIndex)
   5013 // If you don't use sorting, you will generally never care about giving column an ID!
   5014 enum MyItemColumnID
   5015 {
   5016     MyItemColumnID_ID,
   5017     MyItemColumnID_Name,
   5018     MyItemColumnID_Action,
   5019     MyItemColumnID_Quantity,
   5020     MyItemColumnID_Description
   5021 };
   5022 
   5023 struct MyItem
   5024 {
   5025     int         ID;
   5026     const char* Name;
   5027     int         Quantity;
   5028 
   5029     // We have a problem which is affecting _only this demo_ and should not affect your code:
   5030     // As we don't rely on std:: or other third-party library to compile dear imgui, we only have reliable access to qsort(),
   5031     // however qsort doesn't allow passing user data to comparing function.
   5032     // As a workaround, we are storing the sort specs in a static/global for the comparing function to access.
   5033     // In your own use case you would probably pass the sort specs to your sorting/comparing functions directly and not use a global.
   5034     // We could technically call ImGui::TableGetSortSpecs() in CompareWithSortSpecs(), but considering that this function is called
   5035     // very often by the sorting algorithm it would be a little wasteful.
   5036     static const ImGuiTableSortSpecs* s_current_sort_specs;
   5037 
   5038     static void SortWithSortSpecs(ImGuiTableSortSpecs* sort_specs, MyItem* items, int items_count)
   5039     {
   5040         s_current_sort_specs = sort_specs; // Store in variable accessible by the sort function.
   5041         if (items_count > 1)
   5042             qsort(items, (size_t)items_count, sizeof(items[0]), MyItem::CompareWithSortSpecs);
   5043         s_current_sort_specs = NULL;
   5044     }
   5045 
   5046     // Compare function to be used by qsort()
   5047     static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs)
   5048     {
   5049         const MyItem* a = (const MyItem*)lhs;
   5050         const MyItem* b = (const MyItem*)rhs;
   5051         for (int n = 0; n < s_current_sort_specs->SpecsCount; n++)
   5052         {
   5053             // Here we identify columns using the ColumnUserID value that we ourselves passed to TableSetupColumn()
   5054             // We could also choose to identify columns based on their index (sort_spec->ColumnIndex), which is simpler!
   5055             const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n];
   5056             int delta = 0;
   5057             switch (sort_spec->ColumnUserID)
   5058             {
   5059             case MyItemColumnID_ID:             delta = (a->ID - b->ID);                break;
   5060             case MyItemColumnID_Name:           delta = (strcmp(a->Name, b->Name));     break;
   5061             case MyItemColumnID_Quantity:       delta = (a->Quantity - b->Quantity);    break;
   5062             case MyItemColumnID_Description:    delta = (strcmp(a->Name, b->Name));     break;
   5063             default: IM_ASSERT(0); break;
   5064             }
   5065             if (delta > 0)
   5066                 return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1;
   5067             if (delta < 0)
   5068                 return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1;
   5069         }
   5070 
   5071         // qsort() is instable so always return a way to differenciate items.
   5072         // Your own compare function may want to avoid fallback on implicit sort specs.
   5073         // e.g. a Name compare if it wasn't already part of the sort specs.
   5074         return (a->ID - b->ID);
   5075     }
   5076 };
   5077 const ImGuiTableSortSpecs* MyItem::s_current_sort_specs = NULL;
   5078 }
   5079 
   5080 // Make the UI compact because there are so many fields
   5081 static void PushStyleCompact()
   5082 {
   5083     ImGuiStyle& style = ImGui::GetStyle();
   5084     ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(style.FramePadding.x, (float)(int)(style.FramePadding.y * 0.60f)));
   5085     ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x, (float)(int)(style.ItemSpacing.y * 0.60f)));
   5086 }
   5087 
   5088 static void PopStyleCompact()
   5089 {
   5090     ImGui::PopStyleVar(2);
   5091 }
   5092 
   5093 // Show a combo box with a choice of sizing policies
   5094 static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
   5095 {
   5096     struct EnumDesc { ImGuiTableFlags Value; const char* Name; const char* Tooltip; };
   5097     static const EnumDesc policies[] =
   5098     {
   5099         { 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." },
   5100         { ImGuiTableFlags_SizingFixedFit,     "ImGuiTableFlags_SizingFixedFit",     "Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width." },
   5101         { ImGuiTableFlags_SizingFixedSame,    "ImGuiTableFlags_SizingFixedSame",    "Columns are all the same width, matching the maximum contents width.\nImplicitly disable ImGuiTableFlags_Resizable and enable ImGuiTableFlags_NoKeepColumnsVisible." },
   5102         { ImGuiTableFlags_SizingStretchProp,  "ImGuiTableFlags_SizingStretchProp",  "Columns default to _WidthStretch with weights proportional to their widths." },
   5103         { ImGuiTableFlags_SizingStretchSame,  "ImGuiTableFlags_SizingStretchSame",  "Columns default to _WidthStretch with same weights." }
   5104     };
   5105     int idx;
   5106     for (idx = 0; idx < IM_ARRAYSIZE(policies); idx++)
   5107         if (policies[idx].Value == (*p_flags & ImGuiTableFlags_SizingMask_))
   5108             break;
   5109     const char* preview_text = (idx < IM_ARRAYSIZE(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : "";
   5110     if (ImGui::BeginCombo("Sizing Policy", preview_text))
   5111     {
   5112         for (int n = 0; n < IM_ARRAYSIZE(policies); n++)
   5113             if (ImGui::Selectable(policies[n].Name, idx == n))
   5114                 *p_flags = (*p_flags & ~ImGuiTableFlags_SizingMask_) | policies[n].Value;
   5115         ImGui::EndCombo();
   5116     }
   5117     ImGui::SameLine();
   5118     ImGui::TextDisabled("(?)");
   5119     if (ImGui::BeginItemTooltip())
   5120     {
   5121         ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
   5122         for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
   5123         {
   5124             ImGui::Separator();
   5125             ImGui::Text("%s:", policies[m].Name);
   5126             ImGui::Separator();
   5127             ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().IndentSpacing * 0.5f);
   5128             ImGui::TextUnformatted(policies[m].Tooltip);
   5129         }
   5130         ImGui::PopTextWrapPos();
   5131         ImGui::EndTooltip();
   5132     }
   5133 }
   5134 
   5135 static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
   5136 {
   5137     ImGui::CheckboxFlags("_Disabled", p_flags, ImGuiTableColumnFlags_Disabled); ImGui::SameLine(); HelpMarker("Master disable flag (also hide from context menu)");
   5138     ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide);
   5139     ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort);
   5140     if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch))
   5141         *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch);
   5142     if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed))
   5143         *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed);
   5144     ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize);
   5145     ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder);
   5146     ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide);
   5147     ImGui::CheckboxFlags("_NoClip", p_flags, ImGuiTableColumnFlags_NoClip);
   5148     ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort);
   5149     ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending);
   5150     ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending);
   5151     ImGui::CheckboxFlags("_NoHeaderLabel", p_flags, ImGuiTableColumnFlags_NoHeaderLabel);
   5152     ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth);
   5153     ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending);
   5154     ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending);
   5155     ImGui::CheckboxFlags("_IndentEnable", p_flags, ImGuiTableColumnFlags_IndentEnable); ImGui::SameLine(); HelpMarker("Default for column 0");
   5156     ImGui::CheckboxFlags("_IndentDisable", p_flags, ImGuiTableColumnFlags_IndentDisable); ImGui::SameLine(); HelpMarker("Default for column >0");
   5157     ImGui::CheckboxFlags("_AngledHeader", p_flags, ImGuiTableColumnFlags_AngledHeader);
   5158 }
   5159 
   5160 static void ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags)
   5161 {
   5162     ImGui::CheckboxFlags("_IsEnabled", &flags, ImGuiTableColumnFlags_IsEnabled);
   5163     ImGui::CheckboxFlags("_IsVisible", &flags, ImGuiTableColumnFlags_IsVisible);
   5164     ImGui::CheckboxFlags("_IsSorted", &flags, ImGuiTableColumnFlags_IsSorted);
   5165     ImGui::CheckboxFlags("_IsHovered", &flags, ImGuiTableColumnFlags_IsHovered);
   5166 }
   5167 
   5168 //-----------------------------------------------------------------------------
   5169 // [SECTION] ShowDemoWindowTables()
   5170 //-----------------------------------------------------------------------------
   5171 
   5172 static void ShowDemoWindowTables()
   5173 {
   5174     //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
   5175     IMGUI_DEMO_MARKER("Tables");
   5176     if (!ImGui::CollapsingHeader("Tables & Columns"))
   5177         return;
   5178 
   5179     // Using those as a base value to create width/height that are factor of the size of our font
   5180     const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
   5181     const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
   5182 
   5183     ImGui::PushID("Tables");
   5184 
   5185     int open_action = -1;
   5186     if (ImGui::Button("Expand all"))
   5187         open_action = 1;
   5188     ImGui::SameLine();
   5189     if (ImGui::Button("Collapse all"))
   5190         open_action = 0;
   5191     ImGui::SameLine();
   5192 
   5193     // Options
   5194     static bool disable_indent = false;
   5195     ImGui::Checkbox("Disable tree indentation", &disable_indent);
   5196     ImGui::SameLine();
   5197     HelpMarker("Disable the indenting of tree nodes so demo tables can use the full window width.");
   5198     ImGui::Separator();
   5199     if (disable_indent)
   5200         ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
   5201 
   5202     // About Styling of tables
   5203     // Most settings are configured on a per-table basis via the flags passed to BeginTable() and TableSetupColumns APIs.
   5204     // There are however a few settings that a shared and part of the ImGuiStyle structure:
   5205     //   style.CellPadding                          // Padding within each cell
   5206     //   style.Colors[ImGuiCol_TableHeaderBg]       // Table header background
   5207     //   style.Colors[ImGuiCol_TableBorderStrong]   // Table outer and header borders
   5208     //   style.Colors[ImGuiCol_TableBorderLight]    // Table inner borders
   5209     //   style.Colors[ImGuiCol_TableRowBg]          // Table row background when ImGuiTableFlags_RowBg is enabled (even rows)
   5210     //   style.Colors[ImGuiCol_TableRowBgAlt]       // Table row background when ImGuiTableFlags_RowBg is enabled (odds rows)
   5211 
   5212     // Demos
   5213     if (open_action != -1)
   5214         ImGui::SetNextItemOpen(open_action != 0);
   5215     IMGUI_DEMO_MARKER("Tables/Basic");
   5216     if (ImGui::TreeNode("Basic"))
   5217     {
   5218         // Here we will showcase three different ways to output a table.
   5219         // They are very simple variations of a same thing!
   5220 
   5221         // [Method 1] Using TableNextRow() to create a new row, and TableSetColumnIndex() to select the column.
   5222         // In many situations, this is the most flexible and easy to use pattern.
   5223         HelpMarker("Using TableNextRow() + calling TableSetColumnIndex() _before_ each cell, in a loop.");
   5224         if (ImGui::BeginTable("table1", 3))
   5225         {
   5226             for (int row = 0; row < 4; row++)
   5227             {
   5228                 ImGui::TableNextRow();
   5229                 for (int column = 0; column < 3; column++)
   5230                 {
   5231                     ImGui::TableSetColumnIndex(column);
   5232                     ImGui::Text("Row %d Column %d", row, column);
   5233                 }
   5234             }
   5235             ImGui::EndTable();
   5236         }
   5237 
   5238         // [Method 2] Using TableNextColumn() called multiple times, instead of using a for loop + TableSetColumnIndex().
   5239         // This is generally more convenient when you have code manually submitting the contents of each column.
   5240         HelpMarker("Using TableNextRow() + calling TableNextColumn() _before_ each cell, manually.");
   5241         if (ImGui::BeginTable("table2", 3))
   5242         {
   5243             for (int row = 0; row < 4; row++)
   5244             {
   5245                 ImGui::TableNextRow();
   5246                 ImGui::TableNextColumn();
   5247                 ImGui::Text("Row %d", row);
   5248                 ImGui::TableNextColumn();
   5249                 ImGui::Text("Some contents");
   5250                 ImGui::TableNextColumn();
   5251                 ImGui::Text("123.456");
   5252             }
   5253             ImGui::EndTable();
   5254         }
   5255 
   5256         // [Method 3] We call TableNextColumn() _before_ each cell. We never call TableNextRow(),
   5257         // as TableNextColumn() will automatically wrap around and create new rows as needed.
   5258         // This is generally more convenient when your cells all contains the same type of data.
   5259         HelpMarker(
   5260             "Only using TableNextColumn(), which tends to be convenient for tables where every cell contains "
   5261             "the same type of contents.\n This is also more similar to the old NextColumn() function of the "
   5262             "Columns API, and provided to facilitate the Columns->Tables API transition.");
   5263         if (ImGui::BeginTable("table3", 3))
   5264         {
   5265             for (int item = 0; item < 14; item++)
   5266             {
   5267                 ImGui::TableNextColumn();
   5268                 ImGui::Text("Item %d", item);
   5269             }
   5270             ImGui::EndTable();
   5271         }
   5272 
   5273         ImGui::TreePop();
   5274     }
   5275 
   5276     if (open_action != -1)
   5277         ImGui::SetNextItemOpen(open_action != 0);
   5278     IMGUI_DEMO_MARKER("Tables/Borders, background");
   5279     if (ImGui::TreeNode("Borders, background"))
   5280     {
   5281         // Expose a few Borders related flags interactively
   5282         enum ContentsType { CT_Text, CT_FillButton };
   5283         static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
   5284         static bool display_headers = false;
   5285         static int contents_type = CT_Text;
   5286 
   5287         PushStyleCompact();
   5288         ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
   5289         ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
   5290         ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerH\n | ImGuiTableFlags_BordersOuterH");
   5291         ImGui::Indent();
   5292 
   5293         ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
   5294         ImGui::Indent();
   5295         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
   5296         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
   5297         ImGui::Unindent();
   5298 
   5299         ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
   5300         ImGui::Indent();
   5301         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
   5302         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
   5303         ImGui::Unindent();
   5304 
   5305         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags, ImGuiTableFlags_BordersOuter);
   5306         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags, ImGuiTableFlags_BordersInner);
   5307         ImGui::Unindent();
   5308 
   5309         ImGui::AlignTextToFramePadding(); ImGui::Text("Cell contents:");
   5310         ImGui::SameLine(); ImGui::RadioButton("Text", &contents_type, CT_Text);
   5311         ImGui::SameLine(); ImGui::RadioButton("FillButton", &contents_type, CT_FillButton);
   5312         ImGui::Checkbox("Display headers", &display_headers);
   5313         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appear in Headers");
   5314         PopStyleCompact();
   5315 
   5316         if (ImGui::BeginTable("table1", 3, flags))
   5317         {
   5318             // Display headers so we can inspect their interaction with borders
   5319             // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them now. See other sections for details)
   5320             if (display_headers)
   5321             {
   5322                 ImGui::TableSetupColumn("One");
   5323                 ImGui::TableSetupColumn("Two");
   5324                 ImGui::TableSetupColumn("Three");
   5325                 ImGui::TableHeadersRow();
   5326             }
   5327 
   5328             for (int row = 0; row < 5; row++)
   5329             {
   5330                 ImGui::TableNextRow();
   5331                 for (int column = 0; column < 3; column++)
   5332                 {
   5333                     ImGui::TableSetColumnIndex(column);
   5334                     char buf[32];
   5335                     sprintf(buf, "Hello %d,%d", column, row);
   5336                     if (contents_type == CT_Text)
   5337                         ImGui::TextUnformatted(buf);
   5338                     else if (contents_type == CT_FillButton)
   5339                         ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
   5340                 }
   5341             }
   5342             ImGui::EndTable();
   5343         }
   5344         ImGui::TreePop();
   5345     }
   5346 
   5347     if (open_action != -1)
   5348         ImGui::SetNextItemOpen(open_action != 0);
   5349     IMGUI_DEMO_MARKER("Tables/Resizable, stretch");
   5350     if (ImGui::TreeNode("Resizable, stretch"))
   5351     {
   5352         // By default, if we don't enable ScrollX the sizing policy for each column is "Stretch"
   5353         // All columns maintain a sizing weight, and they will occupy all available width.
   5354         static ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
   5355         PushStyleCompact();
   5356         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
   5357         ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
   5358         ImGui::SameLine(); HelpMarker(
   5359             "Using the _Resizable flag automatically enables the _BordersInnerV flag as well, "
   5360             "this is why the resize borders are still showing when unchecking this.");
   5361         PopStyleCompact();
   5362 
   5363         if (ImGui::BeginTable("table1", 3, flags))
   5364         {
   5365             for (int row = 0; row < 5; row++)
   5366             {
   5367                 ImGui::TableNextRow();
   5368                 for (int column = 0; column < 3; column++)
   5369                 {
   5370                     ImGui::TableSetColumnIndex(column);
   5371                     ImGui::Text("Hello %d,%d", column, row);
   5372                 }
   5373             }
   5374             ImGui::EndTable();
   5375         }
   5376         ImGui::TreePop();
   5377     }
   5378 
   5379     if (open_action != -1)
   5380         ImGui::SetNextItemOpen(open_action != 0);
   5381     IMGUI_DEMO_MARKER("Tables/Resizable, fixed");
   5382     if (ImGui::TreeNode("Resizable, fixed"))
   5383     {
   5384         // Here we use ImGuiTableFlags_SizingFixedFit (even though _ScrollX is not set)
   5385         // So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small)
   5386         // If there is not enough available width to fit all columns, they will however be resized down.
   5387         // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings
   5388         HelpMarker(
   5389             "Using _Resizable + _SizingFixedFit flags.\n"
   5390             "Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n"
   5391             "Double-click a column border to auto-fit the column to its contents.");
   5392         PushStyleCompact();
   5393         static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
   5394         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
   5395         PopStyleCompact();
   5396 
   5397         if (ImGui::BeginTable("table1", 3, flags))
   5398         {
   5399             for (int row = 0; row < 5; row++)
   5400             {
   5401                 ImGui::TableNextRow();
   5402                 for (int column = 0; column < 3; column++)
   5403                 {
   5404                     ImGui::TableSetColumnIndex(column);
   5405                     ImGui::Text("Hello %d,%d", column, row);
   5406                 }
   5407             }
   5408             ImGui::EndTable();
   5409         }
   5410         ImGui::TreePop();
   5411     }
   5412 
   5413     if (open_action != -1)
   5414         ImGui::SetNextItemOpen(open_action != 0);
   5415     IMGUI_DEMO_MARKER("Tables/Resizable, mixed");
   5416     if (ImGui::TreeNode("Resizable, mixed"))
   5417     {
   5418         HelpMarker(
   5419             "Using TableSetupColumn() to alter resizing policy on a per-column basis.\n\n"
   5420             "When combining Fixed and Stretch columns, generally you only want one, maybe two trailing columns to use _WidthStretch.");
   5421         static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
   5422 
   5423         if (ImGui::BeginTable("table1", 3, flags))
   5424         {
   5425             ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
   5426             ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
   5427             ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthStretch);
   5428             ImGui::TableHeadersRow();
   5429             for (int row = 0; row < 5; row++)
   5430             {
   5431                 ImGui::TableNextRow();
   5432                 for (int column = 0; column < 3; column++)
   5433                 {
   5434                     ImGui::TableSetColumnIndex(column);
   5435                     ImGui::Text("%s %d,%d", (column == 2) ? "Stretch" : "Fixed", column, row);
   5436                 }
   5437             }
   5438             ImGui::EndTable();
   5439         }
   5440         if (ImGui::BeginTable("table2", 6, flags))
   5441         {
   5442             ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
   5443             ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
   5444             ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_DefaultHide);
   5445             ImGui::TableSetupColumn("DDD", ImGuiTableColumnFlags_WidthStretch);
   5446             ImGui::TableSetupColumn("EEE", ImGuiTableColumnFlags_WidthStretch);
   5447             ImGui::TableSetupColumn("FFF", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_DefaultHide);
   5448             ImGui::TableHeadersRow();
   5449             for (int row = 0; row < 5; row++)
   5450             {
   5451                 ImGui::TableNextRow();
   5452                 for (int column = 0; column < 6; column++)
   5453                 {
   5454                     ImGui::TableSetColumnIndex(column);
   5455                     ImGui::Text("%s %d,%d", (column >= 3) ? "Stretch" : "Fixed", column, row);
   5456                 }
   5457             }
   5458             ImGui::EndTable();
   5459         }
   5460         ImGui::TreePop();
   5461     }
   5462 
   5463     if (open_action != -1)
   5464         ImGui::SetNextItemOpen(open_action != 0);
   5465     IMGUI_DEMO_MARKER("Tables/Reorderable, hideable, with headers");
   5466     if (ImGui::TreeNode("Reorderable, hideable, with headers"))
   5467     {
   5468         HelpMarker(
   5469             "Click and drag column headers to reorder columns.\n\n"
   5470             "Right-click on a header to open a context menu.");
   5471         static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV;
   5472         PushStyleCompact();
   5473         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
   5474         ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
   5475         ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
   5476         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody);
   5477         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers)");
   5478         ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn);
   5479         PopStyleCompact();
   5480 
   5481         if (ImGui::BeginTable("table1", 3, flags))
   5482         {
   5483             // Submit columns name with TableSetupColumn() and call TableHeadersRow() to create a row with a header in each column.
   5484             // (Later we will show how TableSetupColumn() has other uses, optional flags, sizing weight etc.)
   5485             ImGui::TableSetupColumn("One");
   5486             ImGui::TableSetupColumn("Two");
   5487             ImGui::TableSetupColumn("Three");
   5488             ImGui::TableHeadersRow();
   5489             for (int row = 0; row < 6; row++)
   5490             {
   5491                 ImGui::TableNextRow();
   5492                 for (int column = 0; column < 3; column++)
   5493                 {
   5494                     ImGui::TableSetColumnIndex(column);
   5495                     ImGui::Text("Hello %d,%d", column, row);
   5496                 }
   5497             }
   5498             ImGui::EndTable();
   5499         }
   5500 
   5501         // Use outer_size.x == 0.0f instead of default to make the table as tight as possible
   5502         // (only valid when no scrolling and no stretch column)
   5503         if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f)))
   5504         {
   5505             ImGui::TableSetupColumn("One");
   5506             ImGui::TableSetupColumn("Two");
   5507             ImGui::TableSetupColumn("Three");
   5508             ImGui::TableHeadersRow();
   5509             for (int row = 0; row < 6; row++)
   5510             {
   5511                 ImGui::TableNextRow();
   5512                 for (int column = 0; column < 3; column++)
   5513                 {
   5514                     ImGui::TableSetColumnIndex(column);
   5515                     ImGui::Text("Fixed %d,%d", column, row);
   5516                 }
   5517             }
   5518             ImGui::EndTable();
   5519         }
   5520         ImGui::TreePop();
   5521     }
   5522 
   5523     if (open_action != -1)
   5524         ImGui::SetNextItemOpen(open_action != 0);
   5525     IMGUI_DEMO_MARKER("Tables/Padding");
   5526     if (ImGui::TreeNode("Padding"))
   5527     {
   5528         // First example: showcase use of padding flags and effect of BorderOuterV/BorderInnerV on X padding.
   5529         // We don't expose BorderOuterH/BorderInnerH here because they have no effect on X padding.
   5530         HelpMarker(
   5531             "We often want outer padding activated when any using features which makes the edges of a column visible:\n"
   5532             "e.g.:\n"
   5533             "- BorderOuterV\n"
   5534             "- any form of row selection\n"
   5535             "Because of this, activating BorderOuterV sets the default to PadOuterX. "
   5536             "Using PadOuterX or NoPadOuterX you can override the default.\n\n"
   5537             "Actual padding values are using style.CellPadding.\n\n"
   5538             "In this demo we don't show horizontal borders to emphasize how they don't affect default horizontal padding.");
   5539 
   5540         static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV;
   5541         PushStyleCompact();
   5542         ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags1, ImGuiTableFlags_PadOuterX);
   5543         ImGui::SameLine(); HelpMarker("Enable outer-most padding (default if ImGuiTableFlags_BordersOuterV is set)");
   5544         ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags1, ImGuiTableFlags_NoPadOuterX);
   5545         ImGui::SameLine(); HelpMarker("Disable outer-most padding (default if ImGuiTableFlags_BordersOuterV is not set)");
   5546         ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags1, ImGuiTableFlags_NoPadInnerX);
   5547         ImGui::SameLine(); HelpMarker("Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off)");
   5548         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags1, ImGuiTableFlags_BordersOuterV);
   5549         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags1, ImGuiTableFlags_BordersInnerV);
   5550         static bool show_headers = false;
   5551         ImGui::Checkbox("show_headers", &show_headers);
   5552         PopStyleCompact();
   5553 
   5554         if (ImGui::BeginTable("table_padding", 3, flags1))
   5555         {
   5556             if (show_headers)
   5557             {
   5558                 ImGui::TableSetupColumn("One");
   5559                 ImGui::TableSetupColumn("Two");
   5560                 ImGui::TableSetupColumn("Three");
   5561                 ImGui::TableHeadersRow();
   5562             }
   5563 
   5564             for (int row = 0; row < 5; row++)
   5565             {
   5566                 ImGui::TableNextRow();
   5567                 for (int column = 0; column < 3; column++)
   5568                 {
   5569                     ImGui::TableSetColumnIndex(column);
   5570                     if (row == 0)
   5571                     {
   5572                         ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
   5573                     }
   5574                     else
   5575                     {
   5576                         char buf[32];
   5577                         sprintf(buf, "Hello %d,%d", column, row);
   5578                         ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
   5579                     }
   5580                     //if (ImGui::TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered)
   5581                     //    ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, IM_COL32(0, 100, 0, 255));
   5582                 }
   5583             }
   5584             ImGui::EndTable();
   5585         }
   5586 
   5587         // Second example: set style.CellPadding to (0.0) or a custom value.
   5588         // FIXME-TABLE: Vertical border effectively not displayed the same way as horizontal one...
   5589         HelpMarker("Setting style.CellPadding to (0,0) or a custom value.");
   5590         static ImGuiTableFlags flags2 = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
   5591         static ImVec2 cell_padding(0.0f, 0.0f);
   5592         static bool show_widget_frame_bg = true;
   5593 
   5594         PushStyleCompact();
   5595         ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags2, ImGuiTableFlags_Borders);
   5596         ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags2, ImGuiTableFlags_BordersH);
   5597         ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags2, ImGuiTableFlags_BordersV);
   5598         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags2, ImGuiTableFlags_BordersInner);
   5599         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags2, ImGuiTableFlags_BordersOuter);
   5600         ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags2, ImGuiTableFlags_RowBg);
   5601         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags2, ImGuiTableFlags_Resizable);
   5602         ImGui::Checkbox("show_widget_frame_bg", &show_widget_frame_bg);
   5603         ImGui::SliderFloat2("CellPadding", &cell_padding.x, 0.0f, 10.0f, "%.0f");
   5604         PopStyleCompact();
   5605 
   5606         ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cell_padding);
   5607         if (ImGui::BeginTable("table_padding_2", 3, flags2))
   5608         {
   5609             static char text_bufs[3 * 5][16]; // Mini text storage for 3x5 cells
   5610             static bool init = true;
   5611             if (!show_widget_frame_bg)
   5612                 ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);
   5613             for (int cell = 0; cell < 3 * 5; cell++)
   5614             {
   5615                 ImGui::TableNextColumn();
   5616                 if (init)
   5617                     strcpy(text_bufs[cell], "edit me");
   5618                 ImGui::SetNextItemWidth(-FLT_MIN);
   5619                 ImGui::PushID(cell);
   5620                 ImGui::InputText("##cell", text_bufs[cell], IM_ARRAYSIZE(text_bufs[cell]));
   5621                 ImGui::PopID();
   5622             }
   5623             if (!show_widget_frame_bg)
   5624                 ImGui::PopStyleColor();
   5625             init = false;
   5626             ImGui::EndTable();
   5627         }
   5628         ImGui::PopStyleVar();
   5629 
   5630         ImGui::TreePop();
   5631     }
   5632 
   5633     if (open_action != -1)
   5634         ImGui::SetNextItemOpen(open_action != 0);
   5635     IMGUI_DEMO_MARKER("Tables/Explicit widths");
   5636     if (ImGui::TreeNode("Sizing policies"))
   5637     {
   5638         static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
   5639         PushStyleCompact();
   5640         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
   5641         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags1, ImGuiTableFlags_NoHostExtendX);
   5642         PopStyleCompact();
   5643 
   5644         static ImGuiTableFlags sizing_policy_flags[4] = { ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp, ImGuiTableFlags_SizingStretchSame };
   5645         for (int table_n = 0; table_n < 4; table_n++)
   5646         {
   5647             ImGui::PushID(table_n);
   5648             ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 30);
   5649             EditTableSizingFlags(&sizing_policy_flags[table_n]);
   5650 
   5651             // To make it easier to understand the different sizing policy,
   5652             // For each policy: we display one table where the columns have equal contents width,
   5653             // and one where the columns have different contents width.
   5654             if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1))
   5655             {
   5656                 for (int row = 0; row < 3; row++)
   5657                 {
   5658                     ImGui::TableNextRow();
   5659                     ImGui::TableNextColumn(); ImGui::Text("Oh dear");
   5660                     ImGui::TableNextColumn(); ImGui::Text("Oh dear");
   5661                     ImGui::TableNextColumn(); ImGui::Text("Oh dear");
   5662                 }
   5663                 ImGui::EndTable();
   5664             }
   5665             if (ImGui::BeginTable("table2", 3, sizing_policy_flags[table_n] | flags1))
   5666             {
   5667                 for (int row = 0; row < 3; row++)
   5668                 {
   5669                     ImGui::TableNextRow();
   5670                     ImGui::TableNextColumn(); ImGui::Text("AAAA");
   5671                     ImGui::TableNextColumn(); ImGui::Text("BBBBBBBB");
   5672                     ImGui::TableNextColumn(); ImGui::Text("CCCCCCCCCCCC");
   5673                 }
   5674                 ImGui::EndTable();
   5675             }
   5676             ImGui::PopID();
   5677         }
   5678 
   5679         ImGui::Spacing();
   5680         ImGui::TextUnformatted("Advanced");
   5681         ImGui::SameLine();
   5682         HelpMarker(
   5683             "This section allows you to interact and see the effect of various sizing policies "
   5684             "depending on whether Scroll is enabled and the contents of your columns.");
   5685 
   5686         enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText };
   5687         static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable;
   5688         static int contents_type = CT_ShowWidth;
   5689         static int column_count = 3;
   5690 
   5691         PushStyleCompact();
   5692         ImGui::PushID("Advanced");
   5693         ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
   5694         EditTableSizingFlags(&flags);
   5695         ImGui::Combo("Contents", &contents_type, "Show width\0Short Text\0Long Text\0Button\0Fill Button\0InputText\0");
   5696         if (contents_type == CT_FillButton)
   5697         {
   5698             ImGui::SameLine();
   5699             HelpMarker(
   5700                 "Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop "
   5701                 "where contents width can feed into auto-column width can feed into contents width.");
   5702         }
   5703         ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
   5704         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
   5705         ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
   5706         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.");
   5707         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
   5708         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
   5709         ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
   5710         ImGui::PopItemWidth();
   5711         ImGui::PopID();
   5712         PopStyleCompact();
   5713 
   5714         if (ImGui::BeginTable("table2", column_count, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 7)))
   5715         {
   5716             for (int cell = 0; cell < 10 * column_count; cell++)
   5717             {
   5718                 ImGui::TableNextColumn();
   5719                 int column = ImGui::TableGetColumnIndex();
   5720                 int row = ImGui::TableGetRowIndex();
   5721 
   5722                 ImGui::PushID(cell);
   5723                 char label[32];
   5724                 static char text_buf[32] = "";
   5725                 sprintf(label, "Hello %d,%d", column, row);
   5726                 switch (contents_type)
   5727                 {
   5728                 case CT_ShortText:  ImGui::TextUnformatted(label); break;
   5729                 case CT_LongText:   ImGui::Text("Some %s text %d,%d\nOver two lines..", column == 0 ? "long" : "longeeer", column, row); break;
   5730                 case CT_ShowWidth:  ImGui::Text("W: %.1f", ImGui::GetContentRegionAvail().x); break;
   5731                 case CT_Button:     ImGui::Button(label); break;
   5732                 case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
   5733                 case CT_InputText:  ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
   5734                 }
   5735                 ImGui::PopID();
   5736             }
   5737             ImGui::EndTable();
   5738         }
   5739         ImGui::TreePop();
   5740     }
   5741 
   5742     if (open_action != -1)
   5743         ImGui::SetNextItemOpen(open_action != 0);
   5744     IMGUI_DEMO_MARKER("Tables/Vertical scrolling, with clipping");
   5745     if (ImGui::TreeNode("Vertical scrolling, with clipping"))
   5746     {
   5747         HelpMarker(
   5748             "Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\n"
   5749             "We also demonstrate using ImGuiListClipper to virtualize the submission of many items.");
   5750         static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
   5751 
   5752         PushStyleCompact();
   5753         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
   5754         PopStyleCompact();
   5755 
   5756         // When using ScrollX or ScrollY we need to specify a size for our table container!
   5757         // Otherwise by default the table will fit all available space, like a BeginChild() call.
   5758         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
   5759         if (ImGui::BeginTable("table_scrolly", 3, flags, outer_size))
   5760         {
   5761             ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
   5762             ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None);
   5763             ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None);
   5764             ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None);
   5765             ImGui::TableHeadersRow();
   5766 
   5767             // Demonstrate using clipper for large vertical lists
   5768             ImGuiListClipper clipper;
   5769             clipper.Begin(1000);
   5770             while (clipper.Step())
   5771             {
   5772                 for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++)
   5773                 {
   5774                     ImGui::TableNextRow();
   5775                     for (int column = 0; column < 3; column++)
   5776                     {
   5777                         ImGui::TableSetColumnIndex(column);
   5778                         ImGui::Text("Hello %d,%d", column, row);
   5779                     }
   5780                 }
   5781             }
   5782             ImGui::EndTable();
   5783         }
   5784         ImGui::TreePop();
   5785     }
   5786 
   5787     if (open_action != -1)
   5788         ImGui::SetNextItemOpen(open_action != 0);
   5789     IMGUI_DEMO_MARKER("Tables/Horizontal scrolling");
   5790     if (ImGui::TreeNode("Horizontal scrolling"))
   5791     {
   5792         HelpMarker(
   5793             "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, "
   5794             "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n"
   5795             "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX, "
   5796             "because the container window won't automatically extend vertically to fix contents "
   5797             "(this may be improved in future versions).");
   5798         static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
   5799         static int freeze_cols = 1;
   5800         static int freeze_rows = 1;
   5801 
   5802         PushStyleCompact();
   5803         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
   5804         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
   5805         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
   5806         ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
   5807         ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
   5808         ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
   5809         ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
   5810         PopStyleCompact();
   5811 
   5812         // When using ScrollX or ScrollY we need to specify a size for our table container!
   5813         // Otherwise by default the table will fit all available space, like a BeginChild() call.
   5814         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
   5815         if (ImGui::BeginTable("table_scrollx", 7, flags, outer_size))
   5816         {
   5817             ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
   5818             ImGui::TableSetupColumn("Line #", ImGuiTableColumnFlags_NoHide); // Make the first column not hideable to match our use of TableSetupScrollFreeze()
   5819             ImGui::TableSetupColumn("One");
   5820             ImGui::TableSetupColumn("Two");
   5821             ImGui::TableSetupColumn("Three");
   5822             ImGui::TableSetupColumn("Four");
   5823             ImGui::TableSetupColumn("Five");
   5824             ImGui::TableSetupColumn("Six");
   5825             ImGui::TableHeadersRow();
   5826             for (int row = 0; row < 20; row++)
   5827             {
   5828                 ImGui::TableNextRow();
   5829                 for (int column = 0; column < 7; column++)
   5830                 {
   5831                     // Both TableNextColumn() and TableSetColumnIndex() return true when a column is visible or performing width measurement.
   5832                     // Because here we know that:
   5833                     // - A) all our columns are contributing the same to row height
   5834                     // - B) column 0 is always visible,
   5835                     // We only always submit this one column and can skip others.
   5836                     // More advanced per-column clipping behaviors may benefit from polling the status flags via TableGetColumnFlags().
   5837                     if (!ImGui::TableSetColumnIndex(column) && column > 0)
   5838                         continue;
   5839                     if (column == 0)
   5840                         ImGui::Text("Line %d", row);
   5841                     else
   5842                         ImGui::Text("Hello world %d,%d", column, row);
   5843                 }
   5844             }
   5845             ImGui::EndTable();
   5846         }
   5847 
   5848         ImGui::Spacing();
   5849         ImGui::TextUnformatted("Stretch + ScrollX");
   5850         ImGui::SameLine();
   5851         HelpMarker(
   5852             "Showcase using Stretch columns + ScrollX together: "
   5853             "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
   5854             "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns "
   5855             "along with ScrollX doesn't make sense.");
   5856         static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
   5857         static float inner_width = 1000.0f;
   5858         PushStyleCompact();
   5859         ImGui::PushID("flags3");
   5860         ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
   5861         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX);
   5862         ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
   5863         ImGui::PopItemWidth();
   5864         ImGui::PopID();
   5865         PopStyleCompact();
   5866         if (ImGui::BeginTable("table2", 7, flags2, outer_size, inner_width))
   5867         {
   5868             for (int cell = 0; cell < 20 * 7; cell++)
   5869             {
   5870                 ImGui::TableNextColumn();
   5871                 ImGui::Text("Hello world %d,%d", ImGui::TableGetColumnIndex(), ImGui::TableGetRowIndex());
   5872             }
   5873             ImGui::EndTable();
   5874         }
   5875         ImGui::TreePop();
   5876     }
   5877 
   5878     if (open_action != -1)
   5879         ImGui::SetNextItemOpen(open_action != 0);
   5880     IMGUI_DEMO_MARKER("Tables/Columns flags");
   5881     if (ImGui::TreeNode("Columns flags"))
   5882     {
   5883         // Create a first table just to show all the options/flags we want to make visible in our example!
   5884         const int column_count = 3;
   5885         const char* column_names[column_count] = { "One", "Two", "Three" };
   5886         static ImGuiTableColumnFlags column_flags[column_count] = { ImGuiTableColumnFlags_DefaultSort, ImGuiTableColumnFlags_None, ImGuiTableColumnFlags_DefaultHide };
   5887         static ImGuiTableColumnFlags column_flags_out[column_count] = { 0, 0, 0 }; // Output from TableGetColumnFlags()
   5888 
   5889         if (ImGui::BeginTable("table_columns_flags_checkboxes", column_count, ImGuiTableFlags_None))
   5890         {
   5891             PushStyleCompact();
   5892             for (int column = 0; column < column_count; column++)
   5893             {
   5894                 ImGui::TableNextColumn();
   5895                 ImGui::PushID(column);
   5896                 ImGui::AlignTextToFramePadding(); // FIXME-TABLE: Workaround for wrong text baseline propagation across columns
   5897                 ImGui::Text("'%s'", column_names[column]);
   5898                 ImGui::Spacing();
   5899                 ImGui::Text("Input flags:");
   5900                 EditTableColumnsFlags(&column_flags[column]);
   5901                 ImGui::Spacing();
   5902                 ImGui::Text("Output flags:");
   5903                 ImGui::BeginDisabled();
   5904                 ShowTableColumnsStatusFlags(column_flags_out[column]);
   5905                 ImGui::EndDisabled();
   5906                 ImGui::PopID();
   5907             }
   5908             PopStyleCompact();
   5909             ImGui::EndTable();
   5910         }
   5911 
   5912         // Create the real table we care about for the example!
   5913         // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above,
   5914         // otherwise in a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible
   5915         // + resizing the parent window down).
   5916         const ImGuiTableFlags flags
   5917             = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
   5918             | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV
   5919             | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable;
   5920         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 9);
   5921         if (ImGui::BeginTable("table_columns_flags", column_count, flags, outer_size))
   5922         {
   5923             bool has_angled_header = false;
   5924             for (int column = 0; column < column_count; column++)
   5925             {
   5926                 has_angled_header |= (column_flags[column] & ImGuiTableColumnFlags_AngledHeader) != 0;
   5927                 ImGui::TableSetupColumn(column_names[column], column_flags[column]);
   5928             }
   5929             if (has_angled_header)
   5930                 ImGui::TableAngledHeadersRow();
   5931             ImGui::TableHeadersRow();
   5932             for (int column = 0; column < column_count; column++)
   5933                 column_flags_out[column] = ImGui::TableGetColumnFlags(column);
   5934             float indent_step = (float)((int)TEXT_BASE_WIDTH / 2);
   5935             for (int row = 0; row < 8; row++)
   5936             {
   5937                 // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags.
   5938                 ImGui::Indent(indent_step);
   5939                 ImGui::TableNextRow();
   5940                 for (int column = 0; column < column_count; column++)
   5941                 {
   5942                     ImGui::TableSetColumnIndex(column);
   5943                     ImGui::Text("%s %s", (column == 0) ? "Indented" : "Hello", ImGui::TableGetColumnName(column));
   5944                 }
   5945             }
   5946             ImGui::Unindent(indent_step * 8.0f);
   5947 
   5948             ImGui::EndTable();
   5949         }
   5950         ImGui::TreePop();
   5951     }
   5952 
   5953     if (open_action != -1)
   5954         ImGui::SetNextItemOpen(open_action != 0);
   5955     IMGUI_DEMO_MARKER("Tables/Columns widths");
   5956     if (ImGui::TreeNode("Columns widths"))
   5957     {
   5958         HelpMarker("Using TableSetupColumn() to setup default width.");
   5959 
   5960         static ImGuiTableFlags flags1 = ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBodyUntilResize;
   5961         PushStyleCompact();
   5962         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
   5963         ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags1, ImGuiTableFlags_NoBordersInBodyUntilResize);
   5964         PopStyleCompact();
   5965         if (ImGui::BeginTable("table1", 3, flags1))
   5966         {
   5967             // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed.
   5968             ImGui::TableSetupColumn("one", ImGuiTableColumnFlags_WidthFixed, 100.0f); // Default to 100.0f
   5969             ImGui::TableSetupColumn("two", ImGuiTableColumnFlags_WidthFixed, 200.0f); // Default to 200.0f
   5970             ImGui::TableSetupColumn("three", ImGuiTableColumnFlags_WidthFixed);       // Default to auto
   5971             ImGui::TableHeadersRow();
   5972             for (int row = 0; row < 4; row++)
   5973             {
   5974                 ImGui::TableNextRow();
   5975                 for (int column = 0; column < 3; column++)
   5976                 {
   5977                     ImGui::TableSetColumnIndex(column);
   5978                     if (row == 0)
   5979                         ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
   5980                     else
   5981                         ImGui::Text("Hello %d,%d", column, row);
   5982                 }
   5983             }
   5984             ImGui::EndTable();
   5985         }
   5986 
   5987         HelpMarker(
   5988             "Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, "
   5989             "fixed columns with set width may still be shrunk down if there's not enough space in the host.");
   5990 
   5991         static ImGuiTableFlags flags2 = ImGuiTableFlags_None;
   5992         PushStyleCompact();
   5993         ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags2, ImGuiTableFlags_NoKeepColumnsVisible);
   5994         ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags2, ImGuiTableFlags_BordersInnerV);
   5995         ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags2, ImGuiTableFlags_BordersOuterV);
   5996         PopStyleCompact();
   5997         if (ImGui::BeginTable("table2", 4, flags2))
   5998         {
   5999             // We could also set ImGuiTableFlags_SizingFixedFit on the table and then all columns
   6000             // will default to ImGuiTableColumnFlags_WidthFixed.
   6001             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f);
   6002             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
   6003             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f);
   6004             ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
   6005             for (int row = 0; row < 5; row++)
   6006             {
   6007                 ImGui::TableNextRow();
   6008                 for (int column = 0; column < 4; column++)
   6009                 {
   6010                     ImGui::TableSetColumnIndex(column);
   6011                     if (row == 0)
   6012                         ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
   6013                     else
   6014                         ImGui::Text("Hello %d,%d", column, row);
   6015                 }
   6016             }
   6017             ImGui::EndTable();
   6018         }
   6019         ImGui::TreePop();
   6020     }
   6021 
   6022     if (open_action != -1)
   6023         ImGui::SetNextItemOpen(open_action != 0);
   6024     IMGUI_DEMO_MARKER("Tables/Nested tables");
   6025     if (ImGui::TreeNode("Nested tables"))
   6026     {
   6027         HelpMarker("This demonstrates embedding a table into another table cell.");
   6028 
   6029         if (ImGui::BeginTable("table_nested1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
   6030         {
   6031             ImGui::TableSetupColumn("A0");
   6032             ImGui::TableSetupColumn("A1");
   6033             ImGui::TableHeadersRow();
   6034 
   6035             ImGui::TableNextColumn();
   6036             ImGui::Text("A0 Row 0");
   6037             {
   6038                 float rows_height = TEXT_BASE_HEIGHT * 2;
   6039                 if (ImGui::BeginTable("table_nested2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
   6040                 {
   6041                     ImGui::TableSetupColumn("B0");
   6042                     ImGui::TableSetupColumn("B1");
   6043                     ImGui::TableHeadersRow();
   6044 
   6045                     ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
   6046                     ImGui::TableNextColumn();
   6047                     ImGui::Text("B0 Row 0");
   6048                     ImGui::TableNextColumn();
   6049                     ImGui::Text("B1 Row 0");
   6050                     ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
   6051                     ImGui::TableNextColumn();
   6052                     ImGui::Text("B0 Row 1");
   6053                     ImGui::TableNextColumn();
   6054                     ImGui::Text("B1 Row 1");
   6055 
   6056                     ImGui::EndTable();
   6057                 }
   6058             }
   6059             ImGui::TableNextColumn(); ImGui::Text("A1 Row 0");
   6060             ImGui::TableNextColumn(); ImGui::Text("A0 Row 1");
   6061             ImGui::TableNextColumn(); ImGui::Text("A1 Row 1");
   6062             ImGui::EndTable();
   6063         }
   6064         ImGui::TreePop();
   6065     }
   6066 
   6067     if (open_action != -1)
   6068         ImGui::SetNextItemOpen(open_action != 0);
   6069     IMGUI_DEMO_MARKER("Tables/Row height");
   6070     if (ImGui::TreeNode("Row height"))
   6071     {
   6072         HelpMarker(
   6073             "You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, "
   6074             "so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\n"
   6075             "We cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row.");
   6076         if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_Borders))
   6077         {
   6078             for (int row = 0; row < 8; row++)
   6079             {
   6080                 float min_row_height = (float)(int)(TEXT_BASE_HEIGHT * 0.30f * row);
   6081                 ImGui::TableNextRow(ImGuiTableRowFlags_None, min_row_height);
   6082                 ImGui::TableNextColumn();
   6083                 ImGui::Text("min_row_height = %.2f", min_row_height);
   6084             }
   6085             ImGui::EndTable();
   6086         }
   6087 
   6088         HelpMarker(
   6089             "Showcase using SameLine(0,0) to share Current Line Height between cells.\n\n"
   6090             "Please note that Tables Row Height is not the same thing as Current Line Height, "
   6091             "as a table cell may contains multiple lines.");
   6092         if (ImGui::BeginTable("table_share_lineheight", 2, ImGuiTableFlags_Borders))
   6093         {
   6094             ImGui::TableNextRow();
   6095             ImGui::TableNextColumn();
   6096             ImGui::ColorButton("##1", ImVec4(0.13f, 0.26f, 0.40f, 1.0f), ImGuiColorEditFlags_None, ImVec2(40, 40));
   6097             ImGui::TableNextColumn();
   6098             ImGui::Text("Line 1");
   6099             ImGui::Text("Line 2");
   6100 
   6101             ImGui::TableNextRow();
   6102             ImGui::TableNextColumn();
   6103             ImGui::ColorButton("##2", ImVec4(0.13f, 0.26f, 0.40f, 1.0f), ImGuiColorEditFlags_None, ImVec2(40, 40));
   6104             ImGui::TableNextColumn();
   6105             ImGui::SameLine(0.0f, 0.0f); // Reuse line height from previous column
   6106             ImGui::Text("Line 1, with SameLine(0,0)");
   6107             ImGui::Text("Line 2");
   6108 
   6109             ImGui::EndTable();
   6110         }
   6111 
   6112         HelpMarker("Showcase altering CellPadding.y between rows. Note that CellPadding.x is locked for the entire table.");
   6113         if (ImGui::BeginTable("table_changing_cellpadding_y", 1, ImGuiTableFlags_Borders))
   6114         {
   6115             ImGuiStyle& style = ImGui::GetStyle();
   6116             for (int row = 0; row < 8; row++)
   6117             {
   6118                 if ((row % 3) == 2)
   6119                     ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(style.CellPadding.x, 20.0f));
   6120                 ImGui::TableNextRow(ImGuiTableRowFlags_None);
   6121                 ImGui::TableNextColumn();
   6122                 ImGui::Text("CellPadding.y = %.2f", style.CellPadding.y);
   6123                 if ((row % 3) == 2)
   6124                     ImGui::PopStyleVar();
   6125             }
   6126             ImGui::EndTable();
   6127         }
   6128 
   6129         ImGui::TreePop();
   6130     }
   6131 
   6132     if (open_action != -1)
   6133         ImGui::SetNextItemOpen(open_action != 0);
   6134     IMGUI_DEMO_MARKER("Tables/Outer size");
   6135     if (ImGui::TreeNode("Outer size"))
   6136     {
   6137         // Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY
   6138         // Important to that note how the two flags have slightly different behaviors!
   6139         ImGui::Text("Using NoHostExtendX and NoHostExtendY:");
   6140         PushStyleCompact();
   6141         static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX;
   6142         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
   6143         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.");
   6144         ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
   6145         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.");
   6146         PopStyleCompact();
   6147 
   6148         ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f);
   6149         if (ImGui::BeginTable("table1", 3, flags, outer_size))
   6150         {
   6151             for (int row = 0; row < 10; row++)
   6152             {
   6153                 ImGui::TableNextRow();
   6154                 for (int column = 0; column < 3; column++)
   6155                 {
   6156                     ImGui::TableNextColumn();
   6157                     ImGui::Text("Cell %d,%d", column, row);
   6158                 }
   6159             }
   6160             ImGui::EndTable();
   6161         }
   6162         ImGui::SameLine();
   6163         ImGui::Text("Hello!");
   6164 
   6165         ImGui::Spacing();
   6166 
   6167         ImGui::Text("Using explicit size:");
   6168         if (ImGui::BeginTable("table2", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
   6169         {
   6170             for (int row = 0; row < 5; row++)
   6171             {
   6172                 ImGui::TableNextRow();
   6173                 for (int column = 0; column < 3; column++)
   6174                 {
   6175                     ImGui::TableNextColumn();
   6176                     ImGui::Text("Cell %d,%d", column, row);
   6177                 }
   6178             }
   6179             ImGui::EndTable();
   6180         }
   6181         ImGui::SameLine();
   6182         if (ImGui::BeginTable("table3", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
   6183         {
   6184             for (int row = 0; row < 3; row++)
   6185             {
   6186                 ImGui::TableNextRow(0, TEXT_BASE_HEIGHT * 1.5f);
   6187                 for (int column = 0; column < 3; column++)
   6188                 {
   6189                     ImGui::TableNextColumn();
   6190                     ImGui::Text("Cell %d,%d", column, row);
   6191                 }
   6192             }
   6193             ImGui::EndTable();
   6194         }
   6195 
   6196         ImGui::TreePop();
   6197     }
   6198 
   6199     if (open_action != -1)
   6200         ImGui::SetNextItemOpen(open_action != 0);
   6201     IMGUI_DEMO_MARKER("Tables/Background color");
   6202     if (ImGui::TreeNode("Background color"))
   6203     {
   6204         static ImGuiTableFlags flags = ImGuiTableFlags_RowBg;
   6205         static int row_bg_type = 1;
   6206         static int row_bg_target = 1;
   6207         static int cell_bg_type = 1;
   6208 
   6209         PushStyleCompact();
   6210         ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
   6211         ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
   6212         ImGui::SameLine(); HelpMarker("ImGuiTableFlags_RowBg automatically sets RowBg0 to alternative colors pulled from the Style.");
   6213         ImGui::Combo("row bg type", (int*)&row_bg_type, "None\0Red\0Gradient\0");
   6214         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.");
   6215         ImGui::Combo("cell bg type", (int*)&cell_bg_type, "None\0Blue\0"); ImGui::SameLine(); HelpMarker("We are colorizing cells to B1->C2 here.");
   6216         IM_ASSERT(row_bg_type >= 0 && row_bg_type <= 2);
   6217         IM_ASSERT(row_bg_target >= 0 && row_bg_target <= 1);
   6218         IM_ASSERT(cell_bg_type >= 0 && cell_bg_type <= 1);
   6219         PopStyleCompact();
   6220 
   6221         if (ImGui::BeginTable("table1", 5, flags))
   6222         {
   6223             for (int row = 0; row < 6; row++)
   6224             {
   6225                 ImGui::TableNextRow();
   6226 
   6227                 // Demonstrate setting a row background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBgX, ...)'
   6228                 // 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.
   6229                 if (row_bg_type != 0)
   6230                 {
   6231                     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?
   6232                     ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0 + row_bg_target, row_bg_color);
   6233                 }
   6234 
   6235                 // Fill cells
   6236                 for (int column = 0; column < 5; column++)
   6237                 {
   6238                     ImGui::TableSetColumnIndex(column);
   6239                     ImGui::Text("%c%c", 'A' + row, '0' + column);
   6240 
   6241                     // Change background of Cells B1->C2
   6242                     // Demonstrate setting a cell background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ...)'
   6243                     // (the CellBg color will be blended over the RowBg and ColumnBg colors)
   6244                     // We can also pass a column number as a third parameter to TableSetBgColor() and do this outside the column loop.
   6245                     if (row >= 1 && row <= 2 && column >= 1 && column <= 2 && cell_bg_type == 1)
   6246                     {
   6247                         ImU32 cell_bg_color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 0.7f, 0.65f));
   6248                         ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, cell_bg_color);
   6249                     }
   6250                 }
   6251             }
   6252             ImGui::EndTable();
   6253         }
   6254         ImGui::TreePop();
   6255     }
   6256 
   6257     if (open_action != -1)
   6258         ImGui::SetNextItemOpen(open_action != 0);
   6259     IMGUI_DEMO_MARKER("Tables/Tree view");
   6260     if (ImGui::TreeNode("Tree view"))
   6261     {
   6262         static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
   6263 
   6264         static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns;
   6265         ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth",  &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth);
   6266         ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth",  &tree_node_flags, ImGuiTreeNodeFlags_SpanTextWidth);
   6267         ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns);
   6268 
   6269         HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns.");
   6270         if (ImGui::BeginTable("3ways", 3, flags))
   6271         {
   6272             // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On
   6273             ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
   6274             ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f);
   6275             ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 18.0f);
   6276             ImGui::TableHeadersRow();
   6277 
   6278             // Simple storage to output a dummy file-system.
   6279             struct MyTreeNode
   6280             {
   6281                 const char*     Name;
   6282                 const char*     Type;
   6283                 int             Size;
   6284                 int             ChildIdx;
   6285                 int             ChildCount;
   6286                 static void DisplayNode(const MyTreeNode* node, const MyTreeNode* all_nodes)
   6287                 {
   6288                     ImGui::TableNextRow();
   6289                     ImGui::TableNextColumn();
   6290                     const bool is_folder = (node->ChildCount > 0);
   6291                     if (is_folder)
   6292                     {
   6293                         bool open = ImGui::TreeNodeEx(node->Name, tree_node_flags);
   6294                         ImGui::TableNextColumn();
   6295                         ImGui::TextDisabled("--");
   6296                         ImGui::TableNextColumn();
   6297                         ImGui::TextUnformatted(node->Type);
   6298                         if (open)
   6299                         {
   6300                             for (int child_n = 0; child_n < node->ChildCount; child_n++)
   6301                                 DisplayNode(&all_nodes[node->ChildIdx + child_n], all_nodes);
   6302                             ImGui::TreePop();
   6303                         }
   6304                     }
   6305                     else
   6306                     {
   6307                         ImGui::TreeNodeEx(node->Name, tree_node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen);
   6308                         ImGui::TableNextColumn();
   6309                         ImGui::Text("%d", node->Size);
   6310                         ImGui::TableNextColumn();
   6311                         ImGui::TextUnformatted(node->Type);
   6312                     }
   6313                 }
   6314             };
   6315             static const MyTreeNode nodes[] =
   6316             {
   6317                 { "Root",                         "Folder",       -1,       1, 3    }, // 0
   6318                 { "Music",                        "Folder",       -1,       4, 2    }, // 1
   6319                 { "Textures",                     "Folder",       -1,       6, 3    }, // 2
   6320                 { "desktop.ini",                  "System file",  1024,    -1,-1    }, // 3
   6321                 { "File1_a.wav",                  "Audio file",   123000,  -1,-1    }, // 4
   6322                 { "File1_b.wav",                  "Audio file",   456000,  -1,-1    }, // 5
   6323                 { "Image001.png",                 "Image file",   203128,  -1,-1    }, // 6
   6324                 { "Copy of Image001.png",         "Image file",   203256,  -1,-1    }, // 7
   6325                 { "Copy of Image001 (Final2).png","Image file",   203512,  -1,-1    }, // 8
   6326             };
   6327 
   6328             MyTreeNode::DisplayNode(&nodes[0], nodes);
   6329 
   6330             ImGui::EndTable();
   6331         }
   6332         ImGui::TreePop();
   6333     }
   6334 
   6335     if (open_action != -1)
   6336         ImGui::SetNextItemOpen(open_action != 0);
   6337     IMGUI_DEMO_MARKER("Tables/Item width");
   6338     if (ImGui::TreeNode("Item width"))
   6339     {
   6340         HelpMarker(
   6341             "Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n"
   6342             "Note that on auto-resizing non-resizable fixed columns, querying the content width for "
   6343             "e.g. right-alignment doesn't make sense.");
   6344         if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders))
   6345         {
   6346             ImGui::TableSetupColumn("small");
   6347             ImGui::TableSetupColumn("half");
   6348             ImGui::TableSetupColumn("right-align");
   6349             ImGui::TableHeadersRow();
   6350 
   6351             for (int row = 0; row < 3; row++)
   6352             {
   6353                 ImGui::TableNextRow();
   6354                 if (row == 0)
   6355                 {
   6356                     // Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient)
   6357                     ImGui::TableSetColumnIndex(0);
   6358                     ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small
   6359                     ImGui::TableSetColumnIndex(1);
   6360                     ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
   6361                     ImGui::TableSetColumnIndex(2);
   6362                     ImGui::PushItemWidth(-FLT_MIN); // Right-aligned
   6363                 }
   6364 
   6365                 // Draw our contents
   6366                 static float dummy_f = 0.0f;
   6367                 ImGui::PushID(row);
   6368                 ImGui::TableSetColumnIndex(0);
   6369                 ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f);
   6370                 ImGui::TableSetColumnIndex(1);
   6371                 ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
   6372                 ImGui::TableSetColumnIndex(2);
   6373                 ImGui::SliderFloat("##float2", &dummy_f, 0.0f, 1.0f); // No visible label since right-aligned
   6374                 ImGui::PopID();
   6375             }
   6376             ImGui::EndTable();
   6377         }
   6378         ImGui::TreePop();
   6379     }
   6380 
   6381     // Demonstrate using TableHeader() calls instead of TableHeadersRow()
   6382     if (open_action != -1)
   6383         ImGui::SetNextItemOpen(open_action != 0);
   6384     IMGUI_DEMO_MARKER("Tables/Custom headers");
   6385     if (ImGui::TreeNode("Custom headers"))
   6386     {
   6387         const int COLUMNS_COUNT = 3;
   6388         if (ImGui::BeginTable("table_custom_headers", COLUMNS_COUNT, ImGuiTableFlags_Borders | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
   6389         {
   6390             ImGui::TableSetupColumn("Apricot");
   6391             ImGui::TableSetupColumn("Banana");
   6392             ImGui::TableSetupColumn("Cherry");
   6393 
   6394             // Dummy entire-column selection storage
   6395             // FIXME: It would be nice to actually demonstrate full-featured selection using those checkbox.
   6396             static bool column_selected[3] = {};
   6397 
   6398             // Instead of calling TableHeadersRow() we'll submit custom headers ourselves
   6399             ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
   6400             for (int column = 0; column < COLUMNS_COUNT; column++)
   6401             {
   6402                 ImGui::TableSetColumnIndex(column);
   6403                 const char* column_name = ImGui::TableGetColumnName(column); // Retrieve name passed to TableSetupColumn()
   6404                 ImGui::PushID(column);
   6405                 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
   6406                 ImGui::Checkbox("##checkall", &column_selected[column]);
   6407                 ImGui::PopStyleVar();
   6408                 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
   6409                 ImGui::TableHeader(column_name);
   6410                 ImGui::PopID();
   6411             }
   6412 
   6413             for (int row = 0; row < 5; row++)
   6414             {
   6415                 ImGui::TableNextRow();
   6416                 for (int column = 0; column < 3; column++)
   6417                 {
   6418                     char buf[32];
   6419                     sprintf(buf, "Cell %d,%d", column, row);
   6420                     ImGui::TableSetColumnIndex(column);
   6421                     ImGui::Selectable(buf, column_selected[column]);
   6422                 }
   6423             }
   6424             ImGui::EndTable();
   6425         }
   6426         ImGui::TreePop();
   6427     }
   6428 
   6429     // Demonstrate using ImGuiTableColumnFlags_AngledHeader flag to create angled headers
   6430     if (open_action != -1)
   6431         ImGui::SetNextItemOpen(open_action != 0);
   6432     IMGUI_DEMO_MARKER("Tables/Angled headers");
   6433     if (ImGui::TreeNode("Angled headers"))
   6434     {
   6435         const char* column_names[] = { "Track", "cabasa", "ride", "smash", "tom-hi", "tom-mid", "tom-low", "hihat-o", "hihat-c", "snare-s", "snare-c", "clap", "rim", "kick" };
   6436         const int columns_count = IM_ARRAYSIZE(column_names);
   6437         const int rows_count = 12;
   6438 
   6439         static ImGuiTableFlags table_flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_HighlightHoveredColumn;
   6440         static ImGuiTableColumnFlags column_flags = ImGuiTableColumnFlags_AngledHeader | ImGuiTableColumnFlags_WidthFixed;
   6441         static bool bools[columns_count * rows_count] = {}; // Dummy storage selection storage
   6442         static int frozen_cols = 1;
   6443         static int frozen_rows = 2;
   6444         ImGui::CheckboxFlags("_ScrollX", &table_flags, ImGuiTableFlags_ScrollX);
   6445         ImGui::CheckboxFlags("_ScrollY", &table_flags, ImGuiTableFlags_ScrollY);
   6446         ImGui::CheckboxFlags("_Resizable", &table_flags, ImGuiTableFlags_Resizable);
   6447         ImGui::CheckboxFlags("_NoBordersInBody", &table_flags, ImGuiTableFlags_NoBordersInBody);
   6448         ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn);
   6449         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   6450         ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2);
   6451         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   6452         ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2);
   6453         ImGui::CheckboxFlags("Disable header contributing to column width", &column_flags, ImGuiTableColumnFlags_NoHeaderWidth);
   6454 
   6455         if (ImGui::TreeNode("Style settings"))
   6456         {
   6457             ImGui::SameLine();
   6458             HelpMarker("Giving access to some ImGuiStyle value in this demo for convenience.");
   6459             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   6460             ImGui::SliderAngle("style.TableAngledHeadersAngle", &ImGui::GetStyle().TableAngledHeadersAngle, -50.0f, +50.0f);
   6461             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   6462             ImGui::SliderFloat2("style.TableAngledHeadersTextAlign", (float*)&ImGui::GetStyle().TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
   6463             ImGui::TreePop();
   6464         }
   6465 
   6466         if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12)))
   6467         {
   6468             ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder);
   6469             for (int n = 1; n < columns_count; n++)
   6470                 ImGui::TableSetupColumn(column_names[n], column_flags);
   6471             ImGui::TableSetupScrollFreeze(frozen_cols, frozen_rows);
   6472 
   6473             ImGui::TableAngledHeadersRow(); // Draw angled headers for all columns with the ImGuiTableColumnFlags_AngledHeader flag.
   6474             ImGui::TableHeadersRow();       // Draw remaining headers and allow access to context-menu and other functions.
   6475             for (int row = 0; row < rows_count; row++)
   6476             {
   6477                 ImGui::PushID(row);
   6478                 ImGui::TableNextRow();
   6479                 ImGui::TableSetColumnIndex(0);
   6480                 ImGui::AlignTextToFramePadding();
   6481                 ImGui::Text("Track %d", row);
   6482                 for (int column = 1; column < columns_count; column++)
   6483                     if (ImGui::TableSetColumnIndex(column))
   6484                     {
   6485                         ImGui::PushID(column);
   6486                         ImGui::Checkbox("", &bools[row * columns_count + column]);
   6487                         ImGui::PopID();
   6488                     }
   6489                 ImGui::PopID();
   6490             }
   6491             ImGui::EndTable();
   6492         }
   6493         ImGui::TreePop();
   6494     }
   6495 
   6496     // Demonstrate creating custom context menus inside columns,
   6497     // while playing it nice with context menus provided by TableHeadersRow()/TableHeader()
   6498     if (open_action != -1)
   6499         ImGui::SetNextItemOpen(open_action != 0);
   6500     IMGUI_DEMO_MARKER("Tables/Context menus");
   6501     if (ImGui::TreeNode("Context menus"))
   6502     {
   6503         HelpMarker(
   6504             "By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\n"
   6505             "Using ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body.");
   6506         static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody;
   6507 
   6508         PushStyleCompact();
   6509         ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags1, ImGuiTableFlags_ContextMenuInBody);
   6510         PopStyleCompact();
   6511 
   6512         // Context Menus: first example
   6513         // [1.1] Right-click on the TableHeadersRow() line to open the default table context menu.
   6514         // [1.2] Right-click in columns also open the default table context menu (if ImGuiTableFlags_ContextMenuInBody is set)
   6515         const int COLUMNS_COUNT = 3;
   6516         if (ImGui::BeginTable("table_context_menu", COLUMNS_COUNT, flags1))
   6517         {
   6518             ImGui::TableSetupColumn("One");
   6519             ImGui::TableSetupColumn("Two");
   6520             ImGui::TableSetupColumn("Three");
   6521 
   6522             // [1.1]] Right-click on the TableHeadersRow() line to open the default table context menu.
   6523             ImGui::TableHeadersRow();
   6524 
   6525             // Submit dummy contents
   6526             for (int row = 0; row < 4; row++)
   6527             {
   6528                 ImGui::TableNextRow();
   6529                 for (int column = 0; column < COLUMNS_COUNT; column++)
   6530                 {
   6531                     ImGui::TableSetColumnIndex(column);
   6532                     ImGui::Text("Cell %d,%d", column, row);
   6533                 }
   6534             }
   6535             ImGui::EndTable();
   6536         }
   6537 
   6538         // Context Menus: second example
   6539         // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
   6540         // [2.2] Right-click on the ".." to open a custom popup
   6541         // [2.3] Right-click in columns to open another custom popup
   6542         HelpMarker(
   6543             "Demonstrate mixing table context menu (over header), item context button (over button) "
   6544             "and custom per-colunm context menu (over column body).");
   6545         ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders;
   6546         if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2))
   6547         {
   6548             ImGui::TableSetupColumn("One");
   6549             ImGui::TableSetupColumn("Two");
   6550             ImGui::TableSetupColumn("Three");
   6551 
   6552             // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
   6553             ImGui::TableHeadersRow();
   6554             for (int row = 0; row < 4; row++)
   6555             {
   6556                 ImGui::TableNextRow();
   6557                 for (int column = 0; column < COLUMNS_COUNT; column++)
   6558                 {
   6559                     // Submit dummy contents
   6560                     ImGui::TableSetColumnIndex(column);
   6561                     ImGui::Text("Cell %d,%d", column, row);
   6562                     ImGui::SameLine();
   6563 
   6564                     // [2.2] Right-click on the ".." to open a custom popup
   6565                     ImGui::PushID(row * COLUMNS_COUNT + column);
   6566                     ImGui::SmallButton("..");
   6567                     if (ImGui::BeginPopupContextItem())
   6568                     {
   6569                         ImGui::Text("This is the popup for Button(\"..\") in Cell %d,%d", column, row);
   6570                         if (ImGui::Button("Close"))
   6571                             ImGui::CloseCurrentPopup();
   6572                         ImGui::EndPopup();
   6573                     }
   6574                     ImGui::PopID();
   6575                 }
   6576             }
   6577 
   6578             // [2.3] Right-click anywhere in columns to open another custom popup
   6579             // (instead of testing for !IsAnyItemHovered() we could also call OpenPopup() with ImGuiPopupFlags_NoOpenOverExistingPopup
   6580             // to manage popup priority as the popups triggers, here "are we hovering a column" are overlapping)
   6581             int hovered_column = -1;
   6582             for (int column = 0; column < COLUMNS_COUNT + 1; column++)
   6583             {
   6584                 ImGui::PushID(column);
   6585                 if (ImGui::TableGetColumnFlags(column) & ImGuiTableColumnFlags_IsHovered)
   6586                     hovered_column = column;
   6587                 if (hovered_column == column && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(1))
   6588                     ImGui::OpenPopup("MyPopup");
   6589                 if (ImGui::BeginPopup("MyPopup"))
   6590                 {
   6591                     if (column == COLUMNS_COUNT)
   6592                         ImGui::Text("This is a custom popup for unused space after the last column.");
   6593                     else
   6594                         ImGui::Text("This is a custom popup for Column %d", column);
   6595                     if (ImGui::Button("Close"))
   6596                         ImGui::CloseCurrentPopup();
   6597                     ImGui::EndPopup();
   6598                 }
   6599                 ImGui::PopID();
   6600             }
   6601 
   6602             ImGui::EndTable();
   6603             ImGui::Text("Hovered column: %d", hovered_column);
   6604         }
   6605         ImGui::TreePop();
   6606     }
   6607 
   6608     // Demonstrate creating multiple tables with the same ID
   6609     if (open_action != -1)
   6610         ImGui::SetNextItemOpen(open_action != 0);
   6611     IMGUI_DEMO_MARKER("Tables/Synced instances");
   6612     if (ImGui::TreeNode("Synced instances"))
   6613     {
   6614         HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc.");
   6615 
   6616         static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings;
   6617         ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
   6618         ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
   6619         ImGui::CheckboxFlags("ImGuiTableFlags_SizingFixedFit", &flags, ImGuiTableFlags_SizingFixedFit);
   6620         ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn);
   6621         for (int n = 0; n < 3; n++)
   6622         {
   6623             char buf[32];
   6624             sprintf(buf, "Synced Table %d", n);
   6625             bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen);
   6626             if (open && ImGui::BeginTable("Table", 3, flags, ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 5)))
   6627             {
   6628                 ImGui::TableSetupColumn("One");
   6629                 ImGui::TableSetupColumn("Two");
   6630                 ImGui::TableSetupColumn("Three");
   6631                 ImGui::TableHeadersRow();
   6632                 const int cell_count = (n == 1) ? 27 : 9; // Make second table have a scrollbar to verify that additional decoration is not affecting column positions.
   6633                 for (int cell = 0; cell < cell_count; cell++)
   6634                 {
   6635                     ImGui::TableNextColumn();
   6636                     ImGui::Text("this cell %d", cell);
   6637                 }
   6638                 ImGui::EndTable();
   6639             }
   6640         }
   6641         ImGui::TreePop();
   6642     }
   6643 
   6644     // Demonstrate using Sorting facilities
   6645     // This is a simplified version of the "Advanced" example, where we mostly focus on the code necessary to handle sorting.
   6646     // Note that the "Advanced" example also showcase manually triggering a sort (e.g. if item quantities have been modified)
   6647     static const char* template_items_names[] =
   6648     {
   6649         "Banana", "Apple", "Cherry", "Watermelon", "Grapefruit", "Strawberry", "Mango",
   6650         "Kiwi", "Orange", "Pineapple", "Blueberry", "Plum", "Coconut", "Pear", "Apricot"
   6651     };
   6652     if (open_action != -1)
   6653         ImGui::SetNextItemOpen(open_action != 0);
   6654     IMGUI_DEMO_MARKER("Tables/Sorting");
   6655     if (ImGui::TreeNode("Sorting"))
   6656     {
   6657         // Create item list
   6658         static ImVector<MyItem> items;
   6659         if (items.Size == 0)
   6660         {
   6661             items.resize(50, MyItem());
   6662             for (int n = 0; n < items.Size; n++)
   6663             {
   6664                 const int template_n = n % IM_ARRAYSIZE(template_items_names);
   6665                 MyItem& item = items[n];
   6666                 item.ID = n;
   6667                 item.Name = template_items_names[template_n];
   6668                 item.Quantity = (n * n - n) % 20; // Assign default quantities
   6669             }
   6670         }
   6671 
   6672         // Options
   6673         static ImGuiTableFlags flags =
   6674             ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
   6675             | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody
   6676             | ImGuiTableFlags_ScrollY;
   6677         PushStyleCompact();
   6678         ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
   6679         ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
   6680         ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
   6681         ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
   6682         PopStyleCompact();
   6683 
   6684         if (ImGui::BeginTable("table_sorting", 4, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 15), 0.0f))
   6685         {
   6686             // Declare columns
   6687             // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
   6688             // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
   6689             // Demonstrate using a mixture of flags among available sort-related flags:
   6690             // - ImGuiTableColumnFlags_DefaultSort
   6691             // - ImGuiTableColumnFlags_NoSort / ImGuiTableColumnFlags_NoSortAscending / ImGuiTableColumnFlags_NoSortDescending
   6692             // - ImGuiTableColumnFlags_PreferSortAscending / ImGuiTableColumnFlags_PreferSortDescending
   6693             ImGui::TableSetupColumn("ID",       ImGuiTableColumnFlags_DefaultSort          | ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_ID);
   6694             ImGui::TableSetupColumn("Name",                                                  ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_Name);
   6695             ImGui::TableSetupColumn("Action",   ImGuiTableColumnFlags_NoSort               | ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_Action);
   6696             ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Quantity);
   6697             ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible
   6698             ImGui::TableHeadersRow();
   6699 
   6700             // Sort our data if sort specs have been changed!
   6701             if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs())
   6702                 if (sort_specs->SpecsDirty)
   6703                 {
   6704                     MyItem::SortWithSortSpecs(sort_specs, items.Data, items.Size);
   6705                     sort_specs->SpecsDirty = false;
   6706                 }
   6707 
   6708             // Demonstrate using clipper for large vertical lists
   6709             ImGuiListClipper clipper;
   6710             clipper.Begin(items.Size);
   6711             while (clipper.Step())
   6712                 for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
   6713                 {
   6714                     // Display a data item
   6715                     MyItem* item = &items[row_n];
   6716                     ImGui::PushID(item->ID);
   6717                     ImGui::TableNextRow();
   6718                     ImGui::TableNextColumn();
   6719                     ImGui::Text("%04d", item->ID);
   6720                     ImGui::TableNextColumn();
   6721                     ImGui::TextUnformatted(item->Name);
   6722                     ImGui::TableNextColumn();
   6723                     ImGui::SmallButton("None");
   6724                     ImGui::TableNextColumn();
   6725                     ImGui::Text("%d", item->Quantity);
   6726                     ImGui::PopID();
   6727                 }
   6728             ImGui::EndTable();
   6729         }
   6730         ImGui::TreePop();
   6731     }
   6732 
   6733     // In this example we'll expose most table flags and settings.
   6734     // For specific flags and settings refer to the corresponding section for more detailed explanation.
   6735     // This section is mostly useful to experiment with combining certain flags or settings with each others.
   6736     //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // [DEBUG]
   6737     if (open_action != -1)
   6738         ImGui::SetNextItemOpen(open_action != 0);
   6739     IMGUI_DEMO_MARKER("Tables/Advanced");
   6740     if (ImGui::TreeNode("Advanced"))
   6741     {
   6742         static ImGuiTableFlags flags =
   6743             ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable
   6744             | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
   6745             | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody
   6746             | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
   6747             | ImGuiTableFlags_SizingFixedFit;
   6748         static ImGuiTableColumnFlags columns_base_flags = ImGuiTableColumnFlags_None;
   6749 
   6750         enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow };
   6751         static int contents_type = CT_SelectableSpanRow;
   6752         const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable", "Selectable (span row)" };
   6753         static int freeze_cols = 1;
   6754         static int freeze_rows = 1;
   6755         static int items_count = IM_ARRAYSIZE(template_items_names) * 2;
   6756         static ImVec2 outer_size_value = ImVec2(0.0f, TEXT_BASE_HEIGHT * 12);
   6757         static float row_min_height = 0.0f; // Auto
   6758         static float inner_width_with_scroll = 0.0f; // Auto-extend
   6759         static bool outer_size_enabled = true;
   6760         static bool show_headers = true;
   6761         static bool show_wrapped_text = false;
   6762         //static ImGuiTextFilter filter;
   6763         //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // FIXME-TABLE: Enabling this results in initial clipped first pass on table which tend to affect column sizing
   6764         if (ImGui::TreeNode("Options"))
   6765         {
   6766             // Make the UI compact because there are so many fields
   6767             PushStyleCompact();
   6768             ImGui::PushItemWidth(TEXT_BASE_WIDTH * 28.0f);
   6769 
   6770             if (ImGui::TreeNodeEx("Features:", ImGuiTreeNodeFlags_DefaultOpen))
   6771             {
   6772                 ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
   6773                 ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
   6774                 ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
   6775                 ImGui::CheckboxFlags("ImGuiTableFlags_Sortable", &flags, ImGuiTableFlags_Sortable);
   6776                 ImGui::CheckboxFlags("ImGuiTableFlags_NoSavedSettings", &flags, ImGuiTableFlags_NoSavedSettings);
   6777                 ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags, ImGuiTableFlags_ContextMenuInBody);
   6778                 ImGui::TreePop();
   6779             }
   6780 
   6781             if (ImGui::TreeNodeEx("Decorations:", ImGuiTreeNodeFlags_DefaultOpen))
   6782             {
   6783                 ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
   6784                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
   6785                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
   6786                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
   6787                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
   6788                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
   6789                 ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
   6790                 ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appear in Headers");
   6791                 ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers)");
   6792                 ImGui::TreePop();
   6793             }
   6794 
   6795             if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen))
   6796             {
   6797                 EditTableSizingFlags(&flags);
   6798                 ImGui::SameLine(); HelpMarker("In the Advanced demo we override the policy of each column so those table-wide settings have less effect that typical.");
   6799                 ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
   6800                 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.");
   6801                 ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
   6802                 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.");
   6803                 ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible);
   6804                 ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled.");
   6805                 ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
   6806                 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.");
   6807                 ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
   6808                 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.");
   6809                 ImGui::TreePop();
   6810             }
   6811 
   6812             if (ImGui::TreeNodeEx("Padding:", ImGuiTreeNodeFlags_DefaultOpen))
   6813             {
   6814                 ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags, ImGuiTableFlags_PadOuterX);
   6815                 ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags, ImGuiTableFlags_NoPadOuterX);
   6816                 ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags, ImGuiTableFlags_NoPadInnerX);
   6817                 ImGui::TreePop();
   6818             }
   6819 
   6820             if (ImGui::TreeNodeEx("Scrolling:", ImGuiTreeNodeFlags_DefaultOpen))
   6821             {
   6822                 ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
   6823                 ImGui::SameLine();
   6824                 ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
   6825                 ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
   6826                 ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
   6827                 ImGui::SameLine();
   6828                 ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
   6829                 ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
   6830                 ImGui::TreePop();
   6831             }
   6832 
   6833             if (ImGui::TreeNodeEx("Sorting:", ImGuiTreeNodeFlags_DefaultOpen))
   6834             {
   6835                 ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
   6836                 ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
   6837                 ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
   6838                 ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
   6839                 ImGui::TreePop();
   6840             }
   6841 
   6842             if (ImGui::TreeNodeEx("Headers:", ImGuiTreeNodeFlags_DefaultOpen))
   6843             {
   6844                 ImGui::Checkbox("show_headers", &show_headers);
   6845                 ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn);
   6846                 ImGui::CheckboxFlags("ImGuiTableColumnFlags_AngledHeader", &columns_base_flags, ImGuiTableColumnFlags_AngledHeader);
   6847                 ImGui::SameLine(); HelpMarker("Enable AngledHeader on all columns. Best enabled on selected narrow columns (see \"Angled headers\" section of the demo).");
   6848                 ImGui::TreePop();
   6849             }
   6850 
   6851             if (ImGui::TreeNodeEx("Other:", ImGuiTreeNodeFlags_DefaultOpen))
   6852             {
   6853                 ImGui::Checkbox("show_wrapped_text", &show_wrapped_text);
   6854 
   6855                 ImGui::DragFloat2("##OuterSize", &outer_size_value.x);
   6856                 ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
   6857                 ImGui::Checkbox("outer_size", &outer_size_enabled);
   6858                 ImGui::SameLine();
   6859                 HelpMarker("If scrolling is disabled (ScrollX and ScrollY not set):\n"
   6860                     "- The table is output directly in the parent window.\n"
   6861                     "- OuterSize.x < 0.0f will right-align the table.\n"
   6862                     "- OuterSize.x = 0.0f will narrow fit the table unless there are any Stretch columns.\n"
   6863                     "- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set).");
   6864 
   6865                 // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling.
   6866                 // To facilitate toying with this demo we will actually pass 0.0f to the BeginTable() when ScrollX is disabled.
   6867                 ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX);
   6868 
   6869                 ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX);
   6870                 ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
   6871 
   6872                 ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999);
   6873                 ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names));
   6874                 //filter.Draw("filter");
   6875                 ImGui::TreePop();
   6876             }
   6877 
   6878             ImGui::PopItemWidth();
   6879             PopStyleCompact();
   6880             ImGui::Spacing();
   6881             ImGui::TreePop();
   6882         }
   6883 
   6884         // Update item list if we changed the number of items
   6885         static ImVector<MyItem> items;
   6886         static ImVector<int> selection;
   6887         static bool items_need_sort = false;
   6888         if (items.Size != items_count)
   6889         {
   6890             items.resize(items_count, MyItem());
   6891             for (int n = 0; n < items_count; n++)
   6892             {
   6893                 const int template_n = n % IM_ARRAYSIZE(template_items_names);
   6894                 MyItem& item = items[n];
   6895                 item.ID = n;
   6896                 item.Name = template_items_names[template_n];
   6897                 item.Quantity = (template_n == 3) ? 10 : (template_n == 4) ? 20 : 0; // Assign default quantities
   6898             }
   6899         }
   6900 
   6901         const ImDrawList* parent_draw_list = ImGui::GetWindowDrawList();
   6902         const int parent_draw_list_draw_cmd_count = parent_draw_list->CmdBuffer.Size;
   6903         ImVec2 table_scroll_cur, table_scroll_max; // For debug display
   6904         const ImDrawList* table_draw_list = NULL;  // "
   6905 
   6906         // Submit table
   6907         const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : 0.0f;
   6908         if (ImGui::BeginTable("table_advanced", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use))
   6909         {
   6910             // Declare columns
   6911             // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
   6912             // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
   6913             ImGui::TableSetupColumn("ID",           columns_base_flags | ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, 0.0f, MyItemColumnID_ID);
   6914             ImGui::TableSetupColumn("Name",         columns_base_flags | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name);
   6915             ImGui::TableSetupColumn("Action",       columns_base_flags | ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action);
   6916             ImGui::TableSetupColumn("Quantity",     columns_base_flags | ImGuiTableColumnFlags_PreferSortDescending, 0.0f, MyItemColumnID_Quantity);
   6917             ImGui::TableSetupColumn("Description",  columns_base_flags | ((flags & ImGuiTableFlags_NoHostExtendX) ? 0 : ImGuiTableColumnFlags_WidthStretch), 0.0f, MyItemColumnID_Description);
   6918             ImGui::TableSetupColumn("Hidden",       columns_base_flags |  ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort);
   6919             ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
   6920 
   6921             // Sort our data if sort specs have been changed!
   6922             ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs();
   6923             if (sort_specs && sort_specs->SpecsDirty)
   6924                 items_need_sort = true;
   6925             if (sort_specs && items_need_sort && items.Size > 1)
   6926             {
   6927                 MyItem::SortWithSortSpecs(sort_specs, items.Data, items.Size);
   6928                 sort_specs->SpecsDirty = false;
   6929             }
   6930             items_need_sort = false;
   6931 
   6932             // Take note of whether we are currently sorting based on the Quantity field,
   6933             // we will use this to trigger sorting when we know the data of this column has been modified.
   6934             const bool sorts_specs_using_quantity = (ImGui::TableGetColumnFlags(3) & ImGuiTableColumnFlags_IsSorted) != 0;
   6935 
   6936             // Show headers
   6937             if (show_headers && (columns_base_flags & ImGuiTableColumnFlags_AngledHeader) != 0)
   6938                 ImGui::TableAngledHeadersRow();
   6939             if (show_headers)
   6940                 ImGui::TableHeadersRow();
   6941 
   6942             // Show data
   6943             // FIXME-TABLE FIXME-NAV: How we can get decent up/down even though we have the buttons here?
   6944 #if 1
   6945             // Demonstrate using clipper for large vertical lists
   6946             ImGuiListClipper clipper;
   6947             clipper.Begin(items.Size);
   6948             while (clipper.Step())
   6949             {
   6950                 for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
   6951 #else
   6952             // Without clipper
   6953             {
   6954                 for (int row_n = 0; row_n < items.Size; row_n++)
   6955 #endif
   6956                 {
   6957                     MyItem* item = &items[row_n];
   6958                     //if (!filter.PassFilter(item->Name))
   6959                     //    continue;
   6960 
   6961                     const bool item_is_selected = selection.contains(item->ID);
   6962                     ImGui::PushID(item->ID);
   6963                     ImGui::TableNextRow(ImGuiTableRowFlags_None, row_min_height);
   6964 
   6965                     // For the demo purpose we can select among different type of items submitted in the first column
   6966                     ImGui::TableSetColumnIndex(0);
   6967                     char label[32];
   6968                     sprintf(label, "%04d", item->ID);
   6969                     if (contents_type == CT_Text)
   6970                         ImGui::TextUnformatted(label);
   6971                     else if (contents_type == CT_Button)
   6972                         ImGui::Button(label);
   6973                     else if (contents_type == CT_SmallButton)
   6974                         ImGui::SmallButton(label);
   6975                     else if (contents_type == CT_FillButton)
   6976                         ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f));
   6977                     else if (contents_type == CT_Selectable || contents_type == CT_SelectableSpanRow)
   6978                     {
   6979                         ImGuiSelectableFlags selectable_flags = (contents_type == CT_SelectableSpanRow) ? ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap : ImGuiSelectableFlags_None;
   6980                         if (ImGui::Selectable(label, item_is_selected, selectable_flags, ImVec2(0, row_min_height)))
   6981                         {
   6982                             if (ImGui::GetIO().KeyCtrl)
   6983                             {
   6984                                 if (item_is_selected)
   6985                                     selection.find_erase_unsorted(item->ID);
   6986                                 else
   6987                                     selection.push_back(item->ID);
   6988                             }
   6989                             else
   6990                             {
   6991                                 selection.clear();
   6992                                 selection.push_back(item->ID);
   6993                             }
   6994                         }
   6995                     }
   6996 
   6997                     if (ImGui::TableSetColumnIndex(1))
   6998                         ImGui::TextUnformatted(item->Name);
   6999 
   7000                     // Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity,
   7001                     // and we are currently sorting on the column showing the Quantity.
   7002                     // To avoid triggering a sort while holding the button, we only trigger it when the button has been released.
   7003                     // You will probably need some extra logic if you want to automatically sort when a specific entry changes.
   7004                     if (ImGui::TableSetColumnIndex(2))
   7005                     {
   7006                         if (ImGui::SmallButton("Chop")) { item->Quantity += 1; }
   7007                         if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
   7008                         ImGui::SameLine();
   7009                         if (ImGui::SmallButton("Eat")) { item->Quantity -= 1; }
   7010                         if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
   7011                     }
   7012 
   7013                     if (ImGui::TableSetColumnIndex(3))
   7014                         ImGui::Text("%d", item->Quantity);
   7015 
   7016                     ImGui::TableSetColumnIndex(4);
   7017                     if (show_wrapped_text)
   7018                         ImGui::TextWrapped("Lorem ipsum dolor sit amet");
   7019                     else
   7020                         ImGui::Text("Lorem ipsum dolor sit amet");
   7021 
   7022                     if (ImGui::TableSetColumnIndex(5))
   7023                         ImGui::Text("1234");
   7024 
   7025                     ImGui::PopID();
   7026                 }
   7027             }
   7028 
   7029             // Store some info to display debug details below
   7030             table_scroll_cur = ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY());
   7031             table_scroll_max = ImVec2(ImGui::GetScrollMaxX(), ImGui::GetScrollMaxY());
   7032             table_draw_list = ImGui::GetWindowDrawList();
   7033             ImGui::EndTable();
   7034         }
   7035         static bool show_debug_details = false;
   7036         ImGui::Checkbox("Debug details", &show_debug_details);
   7037         if (show_debug_details && table_draw_list)
   7038         {
   7039             ImGui::SameLine(0.0f, 0.0f);
   7040             const int table_draw_list_draw_cmd_count = table_draw_list->CmdBuffer.Size;
   7041             if (table_draw_list == parent_draw_list)
   7042                 ImGui::Text(": DrawCmd: +%d (in same window)",
   7043                     table_draw_list_draw_cmd_count - parent_draw_list_draw_cmd_count);
   7044             else
   7045                 ImGui::Text(": DrawCmd: +%d (in child window), Scroll: (%.f/%.f) (%.f/%.f)",
   7046                     table_draw_list_draw_cmd_count - 1, table_scroll_cur.x, table_scroll_max.x, table_scroll_cur.y, table_scroll_max.y);
   7047         }
   7048         ImGui::TreePop();
   7049     }
   7050 
   7051     ImGui::PopID();
   7052 
   7053     ShowDemoWindowColumns();
   7054 
   7055     if (disable_indent)
   7056         ImGui::PopStyleVar();
   7057 }
   7058 
   7059 // Demonstrate old/legacy Columns API!
   7060 // [2020: Columns are under-featured and not maintained. Prefer using the more flexible and powerful BeginTable() API!]
   7061 static void ShowDemoWindowColumns()
   7062 {
   7063     IMGUI_DEMO_MARKER("Columns (legacy API)");
   7064     bool open = ImGui::TreeNode("Legacy Columns API");
   7065     ImGui::SameLine();
   7066     HelpMarker("Columns() is an old API! Prefer using the more flexible and powerful BeginTable() API!");
   7067     if (!open)
   7068         return;
   7069 
   7070     // Basic columns
   7071     IMGUI_DEMO_MARKER("Columns (legacy API)/Basic");
   7072     if (ImGui::TreeNode("Basic"))
   7073     {
   7074         ImGui::Text("Without border:");
   7075         ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
   7076         ImGui::Separator();
   7077         for (int n = 0; n < 14; n++)
   7078         {
   7079             char label[32];
   7080             sprintf(label, "Item %d", n);
   7081             if (ImGui::Selectable(label)) {}
   7082             //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {}
   7083             ImGui::NextColumn();
   7084         }
   7085         ImGui::Columns(1);
   7086         ImGui::Separator();
   7087 
   7088         ImGui::Text("With border:");
   7089         ImGui::Columns(4, "mycolumns"); // 4-ways, with border
   7090         ImGui::Separator();
   7091         ImGui::Text("ID"); ImGui::NextColumn();
   7092         ImGui::Text("Name"); ImGui::NextColumn();
   7093         ImGui::Text("Path"); ImGui::NextColumn();
   7094         ImGui::Text("Hovered"); ImGui::NextColumn();
   7095         ImGui::Separator();
   7096         const char* names[3] = { "One", "Two", "Three" };
   7097         const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
   7098         static int selected = -1;
   7099         for (int i = 0; i < 3; i++)
   7100         {
   7101             char label[32];
   7102             sprintf(label, "%04d", i);
   7103             if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
   7104                 selected = i;
   7105             bool hovered = ImGui::IsItemHovered();
   7106             ImGui::NextColumn();
   7107             ImGui::Text(names[i]); ImGui::NextColumn();
   7108             ImGui::Text(paths[i]); ImGui::NextColumn();
   7109             ImGui::Text("%d", hovered); ImGui::NextColumn();
   7110         }
   7111         ImGui::Columns(1);
   7112         ImGui::Separator();
   7113         ImGui::TreePop();
   7114     }
   7115 
   7116     IMGUI_DEMO_MARKER("Columns (legacy API)/Borders");
   7117     if (ImGui::TreeNode("Borders"))
   7118     {
   7119         // NB: Future columns API should allow automatic horizontal borders.
   7120         static bool h_borders = true;
   7121         static bool v_borders = true;
   7122         static int columns_count = 4;
   7123         const int lines_count = 3;
   7124         ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
   7125         ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns");
   7126         if (columns_count < 2)
   7127             columns_count = 2;
   7128         ImGui::SameLine();
   7129         ImGui::Checkbox("horizontal", &h_borders);
   7130         ImGui::SameLine();
   7131         ImGui::Checkbox("vertical", &v_borders);
   7132         ImGui::Columns(columns_count, NULL, v_borders);
   7133         for (int i = 0; i < columns_count * lines_count; i++)
   7134         {
   7135             if (h_borders && ImGui::GetColumnIndex() == 0)
   7136                 ImGui::Separator();
   7137             ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
   7138             ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
   7139             ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
   7140             ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
   7141             ImGui::Text("Long text that is likely to clip");
   7142             ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f));
   7143             ImGui::NextColumn();
   7144         }
   7145         ImGui::Columns(1);
   7146         if (h_borders)
   7147             ImGui::Separator();
   7148         ImGui::TreePop();
   7149     }
   7150 
   7151     // Create multiple items in a same cell before switching to next column
   7152     IMGUI_DEMO_MARKER("Columns (legacy API)/Mixed items");
   7153     if (ImGui::TreeNode("Mixed items"))
   7154     {
   7155         ImGui::Columns(3, "mixed");
   7156         ImGui::Separator();
   7157 
   7158         ImGui::Text("Hello");
   7159         ImGui::Button("Banana");
   7160         ImGui::NextColumn();
   7161 
   7162         ImGui::Text("ImGui");
   7163         ImGui::Button("Apple");
   7164         static float foo = 1.0f;
   7165         ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
   7166         ImGui::Text("An extra line here.");
   7167         ImGui::NextColumn();
   7168 
   7169         ImGui::Text("Sailor");
   7170         ImGui::Button("Corniflower");
   7171         static float bar = 1.0f;
   7172         ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
   7173         ImGui::NextColumn();
   7174 
   7175         if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
   7176         if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
   7177         if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
   7178         ImGui::Columns(1);
   7179         ImGui::Separator();
   7180         ImGui::TreePop();
   7181     }
   7182 
   7183     // Word wrapping
   7184     IMGUI_DEMO_MARKER("Columns (legacy API)/Word-wrapping");
   7185     if (ImGui::TreeNode("Word-wrapping"))
   7186     {
   7187         ImGui::Columns(2, "word-wrapping");
   7188         ImGui::Separator();
   7189         ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
   7190         ImGui::TextWrapped("Hello Left");
   7191         ImGui::NextColumn();
   7192         ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
   7193         ImGui::TextWrapped("Hello Right");
   7194         ImGui::Columns(1);
   7195         ImGui::Separator();
   7196         ImGui::TreePop();
   7197     }
   7198 
   7199     IMGUI_DEMO_MARKER("Columns (legacy API)/Horizontal Scrolling");
   7200     if (ImGui::TreeNode("Horizontal Scrolling"))
   7201     {
   7202         ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
   7203         ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f);
   7204         ImGui::BeginChild("##ScrollingRegion", child_size, ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar);
   7205         ImGui::Columns(10);
   7206 
   7207         // Also demonstrate using clipper for large vertical lists
   7208         int ITEMS_COUNT = 2000;
   7209         ImGuiListClipper clipper;
   7210         clipper.Begin(ITEMS_COUNT);
   7211         while (clipper.Step())
   7212         {
   7213             for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
   7214                 for (int j = 0; j < 10; j++)
   7215                 {
   7216                     ImGui::Text("Line %d Column %d...", i, j);
   7217                     ImGui::NextColumn();
   7218                 }
   7219         }
   7220         ImGui::Columns(1);
   7221         ImGui::EndChild();
   7222         ImGui::TreePop();
   7223     }
   7224 
   7225     IMGUI_DEMO_MARKER("Columns (legacy API)/Tree");
   7226     if (ImGui::TreeNode("Tree"))
   7227     {
   7228         ImGui::Columns(2, "tree", true);
   7229         for (int x = 0; x < 3; x++)
   7230         {
   7231             bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x);
   7232             ImGui::NextColumn();
   7233             ImGui::Text("Node contents");
   7234             ImGui::NextColumn();
   7235             if (open1)
   7236             {
   7237                 for (int y = 0; y < 3; y++)
   7238                 {
   7239                     bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y);
   7240                     ImGui::NextColumn();
   7241                     ImGui::Text("Node contents");
   7242                     if (open2)
   7243                     {
   7244                         ImGui::Text("Even more contents");
   7245                         if (ImGui::TreeNode("Tree in column"))
   7246                         {
   7247                             ImGui::Text("The quick brown fox jumps over the lazy dog");
   7248                             ImGui::TreePop();
   7249                         }
   7250                     }
   7251                     ImGui::NextColumn();
   7252                     if (open2)
   7253                         ImGui::TreePop();
   7254                 }
   7255                 ImGui::TreePop();
   7256             }
   7257         }
   7258         ImGui::Columns(1);
   7259         ImGui::TreePop();
   7260     }
   7261 
   7262     ImGui::TreePop();
   7263 }
   7264 
   7265 //-----------------------------------------------------------------------------
   7266 // [SECTION] ShowDemoWindowInputs()
   7267 //-----------------------------------------------------------------------------
   7268 
   7269 static void ShowDemoWindowInputs()
   7270 {
   7271     IMGUI_DEMO_MARKER("Inputs & Focus");
   7272     if (ImGui::CollapsingHeader("Inputs & Focus"))
   7273     {
   7274         ImGuiIO& io = ImGui::GetIO();
   7275 
   7276         // Display inputs submitted to ImGuiIO
   7277         IMGUI_DEMO_MARKER("Inputs & Focus/Inputs");
   7278         ImGui::SetNextItemOpen(true, ImGuiCond_Once);
   7279         bool inputs_opened = ImGui::TreeNode("Inputs");
   7280         ImGui::SameLine();
   7281         HelpMarker(
   7282             "This is a simplified view. See more detailed input state:\n"
   7283             "- in 'Tools->Metrics/Debugger->Inputs'.\n"
   7284             "- in 'Tools->Debug Log->IO'.");
   7285         if (inputs_opened)
   7286         {
   7287             if (ImGui::IsMousePosValid())
   7288                 ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
   7289             else
   7290                 ImGui::Text("Mouse pos: <INVALID>");
   7291             ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
   7292             ImGui::Text("Mouse down:");
   7293             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]); }
   7294             ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
   7295 
   7296             // We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows
   7297             // displaying the data for old/new backends.
   7298             // User code should never have to go through such hoops!
   7299             // You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END.
   7300 #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
   7301             struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
   7302             ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN;
   7303 #else
   7304             struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
   7305             ImGuiKey start_key = (ImGuiKey)0;
   7306 #endif
   7307             ImGui::Text("Keys down:");         for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); }
   7308             ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
   7309             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.
   7310 
   7311             ImGui::TreePop();
   7312         }
   7313 
   7314         // Display ImGuiIO output flags
   7315         IMGUI_DEMO_MARKER("Inputs & Focus/Outputs");
   7316         ImGui::SetNextItemOpen(true, ImGuiCond_Once);
   7317         bool outputs_opened = ImGui::TreeNode("Outputs");
   7318         ImGui::SameLine();
   7319         HelpMarker(
   7320             "The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui "
   7321             "to instruct your application of how to route inputs. Typically, when a value is true, it means "
   7322             "Dear ImGui wants the corresponding inputs and we expect the underlying application to ignore them.\n\n"
   7323             "The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, "
   7324             "and underlying application should ignore mouse inputs (in practice there are many and more subtle "
   7325             "rules leading to how those flags are set).");
   7326         if (outputs_opened)
   7327         {
   7328             ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
   7329             ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
   7330             ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
   7331             ImGui::Text("io.WantTextInput: %d", io.WantTextInput);
   7332             ImGui::Text("io.WantSetMousePos: %d", io.WantSetMousePos);
   7333             ImGui::Text("io.NavActive: %d, io.NavVisible: %d", io.NavActive, io.NavVisible);
   7334 
   7335             IMGUI_DEMO_MARKER("Inputs & Focus/Outputs/WantCapture override");
   7336             if (ImGui::TreeNode("WantCapture override"))
   7337             {
   7338                 HelpMarker(
   7339                     "Hovering the colored canvas will override io.WantCaptureXXX fields.\n"
   7340                     "Notice how normally (when set to none), the value of io.WantCaptureKeyboard would be false when hovering "
   7341                     "and true when clicking.");
   7342                 static int capture_override_mouse = -1;
   7343                 static int capture_override_keyboard = -1;
   7344                 const char* capture_override_desc[] = { "None", "Set to false", "Set to true" };
   7345                 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
   7346                 ImGui::SliderInt("SetNextFrameWantCaptureMouse() on hover", &capture_override_mouse, -1, +1, capture_override_desc[capture_override_mouse + 1], ImGuiSliderFlags_AlwaysClamp);
   7347                 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
   7348                 ImGui::SliderInt("SetNextFrameWantCaptureKeyboard() on hover", &capture_override_keyboard, -1, +1, capture_override_desc[capture_override_keyboard + 1], ImGuiSliderFlags_AlwaysClamp);
   7349 
   7350                 ImGui::ColorButton("##panel", ImVec4(0.7f, 0.1f, 0.7f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, ImVec2(128.0f, 96.0f)); // Dummy item
   7351                 if (ImGui::IsItemHovered() && capture_override_mouse != -1)
   7352                     ImGui::SetNextFrameWantCaptureMouse(capture_override_mouse == 1);
   7353                 if (ImGui::IsItemHovered() && capture_override_keyboard != -1)
   7354                     ImGui::SetNextFrameWantCaptureKeyboard(capture_override_keyboard == 1);
   7355 
   7356                 ImGui::TreePop();
   7357             }
   7358             ImGui::TreePop();
   7359         }
   7360 
   7361         // Demonstrate using Shortcut() and Routing Policies.
   7362         // The general flow is:
   7363         // - Code interested in a chord (e.g. "Ctrl+A") declares their intent.
   7364         // - Multiple locations may be interested in same chord! Routing helps find a winner.
   7365         // - Every frame, we resolve all claims and assign one owner if the modifiers are matching.
   7366         // - The lower-level function is 'bool SetShortcutRouting()', returns true when caller got the route.
   7367         // - Most of the times, SetShortcutRouting() is not called directly. User mostly calls Shortcut() with routing flags.
   7368         // - If you call Shortcut() WITHOUT any routing option, it uses ImGuiInputFlags_RouteFocused.
   7369         // TL;DR: Most uses will simply be:
   7370         // - Shortcut(ImGuiMod_Ctrl | ImGuiKey_A); // Use ImGuiInputFlags_RouteFocused policy.
   7371         IMGUI_DEMO_MARKER("Inputs & Focus/Shortcuts");
   7372         if (ImGui::TreeNode("Shortcuts"))
   7373         {
   7374             static ImGuiInputFlags route_options = ImGuiInputFlags_Repeat;
   7375             static ImGuiInputFlags route_type = ImGuiInputFlags_RouteFocused;
   7376             ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &route_options, ImGuiInputFlags_Repeat);
   7377             ImGui::RadioButton("ImGuiInputFlags_RouteActive", &route_type, ImGuiInputFlags_RouteActive);
   7378             ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &route_type, ImGuiInputFlags_RouteFocused);
   7379             ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &route_type, ImGuiInputFlags_RouteGlobal);
   7380             ImGui::Indent();
   7381             ImGui::BeginDisabled(route_type != ImGuiInputFlags_RouteGlobal);
   7382             ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverFocused", &route_options, ImGuiInputFlags_RouteOverFocused);
   7383             ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverActive", &route_options, ImGuiInputFlags_RouteOverActive);
   7384             ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &route_options, ImGuiInputFlags_RouteUnlessBgFocused);
   7385             ImGui::EndDisabled();
   7386             ImGui::Unindent();
   7387             ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways);
   7388             ImGuiInputFlags flags = route_type | route_options; // Merged flags
   7389             if (route_type != ImGuiInputFlags_RouteGlobal)
   7390                 flags &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused);
   7391 
   7392             ImGui::SeparatorText("Using SetNextItemShortcut()");
   7393             ImGui::Text("Ctrl+S");
   7394             ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, flags | ImGuiInputFlags_Tooltip);
   7395             ImGui::Button("Save");
   7396             ImGui::Text("Alt+F");
   7397             ImGui::SetNextItemShortcut(ImGuiMod_Alt | ImGuiKey_F, flags | ImGuiInputFlags_Tooltip);
   7398             static float f = 0.5f;
   7399             ImGui::SliderFloat("Factor", &f, 0.0f, 1.0f);
   7400 
   7401             ImGui::SeparatorText("Using Shortcut()");
   7402             const float line_height = ImGui::GetTextLineHeightWithSpacing();
   7403             const ImGuiKeyChord key_chord = ImGuiMod_Ctrl | ImGuiKey_A;
   7404 
   7405             ImGui::Text("Ctrl+A");
   7406             ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
   7407 
   7408             ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 0.0f, 1.0f, 0.1f));
   7409 
   7410             ImGui::BeginChild("WindowA", ImVec2(-FLT_MIN, line_height * 14), true);
   7411             ImGui::Text("Press CTRL+A and see who receives it!");
   7412             ImGui::Separator();
   7413 
   7414             // 1: Window polling for CTRL+A
   7415             ImGui::Text("(in WindowA)");
   7416             ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
   7417 
   7418             // 2: InputText also polling for CTRL+A: it always uses _RouteFocused internally (gets priority when active)
   7419             // (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
   7420             //char str[16] = "Press CTRL+A";
   7421             //ImGui::Spacing();
   7422             //ImGui::InputText("InputTextB", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
   7423             //ImGuiID item_id = ImGui::GetItemID();
   7424             //ImGui::SameLine(); HelpMarker("Internal widgets always use _RouteFocused");
   7425             //ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, item_id) ? "PRESSED" : "...");
   7426 
   7427             // 3: Dummy child is not claiming the route: focusing them shouldn't steal route away from WindowA
   7428             ImGui::BeginChild("ChildD", ImVec2(-FLT_MIN, line_height * 4), true);
   7429             ImGui::Text("(in ChildD: not using same Shortcut)");
   7430             ImGui::Text("IsWindowFocused: %d", ImGui::IsWindowFocused());
   7431             ImGui::EndChild();
   7432 
   7433             // 4: Child window polling for CTRL+A. It is deeper than WindowA and gets priority when focused.
   7434             ImGui::BeginChild("ChildE", ImVec2(-FLT_MIN, line_height * 4), true);
   7435             ImGui::Text("(in ChildE: using same Shortcut)");
   7436             ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
   7437             ImGui::EndChild();
   7438 
   7439             // 5: In a popup
   7440             if (ImGui::Button("Open Popup"))
   7441                 ImGui::OpenPopup("PopupF");
   7442             if (ImGui::BeginPopup("PopupF"))
   7443             {
   7444                 ImGui::Text("(in PopupF)");
   7445                 ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
   7446                 // (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
   7447                 //ImGui::InputText("InputTextG", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
   7448                 //ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, ImGui::GetItemID()) ? "PRESSED" : "...");
   7449                 ImGui::EndPopup();
   7450             }
   7451             ImGui::EndChild();
   7452             ImGui::PopStyleColor();
   7453 
   7454             ImGui::TreePop();
   7455         }
   7456 
   7457         // Display mouse cursors
   7458         IMGUI_DEMO_MARKER("Inputs & Focus/Mouse Cursors");
   7459         if (ImGui::TreeNode("Mouse Cursors"))
   7460         {
   7461             const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" };
   7462             IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
   7463 
   7464             ImGuiMouseCursor current = ImGui::GetMouseCursor();
   7465             ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]);
   7466             ImGui::BeginDisabled(true);
   7467             ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
   7468             ImGui::EndDisabled();
   7469 
   7470             ImGui::Text("Hover to see mouse cursors:");
   7471             ImGui::SameLine(); HelpMarker(
   7472                 "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. "
   7473                 "If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, "
   7474                 "otherwise your backend needs to handle it.");
   7475             for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
   7476             {
   7477                 char label[32];
   7478                 sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
   7479                 ImGui::Bullet(); ImGui::Selectable(label, false);
   7480                 if (ImGui::IsItemHovered())
   7481                     ImGui::SetMouseCursor(i);
   7482             }
   7483             ImGui::TreePop();
   7484         }
   7485 
   7486         IMGUI_DEMO_MARKER("Inputs & Focus/Tabbing");
   7487         if (ImGui::TreeNode("Tabbing"))
   7488         {
   7489             ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
   7490             static char buf[32] = "hello";
   7491             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
   7492             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
   7493             ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
   7494             ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true);
   7495             ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
   7496             ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
   7497             ImGui::PopItemFlag();
   7498             ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
   7499             ImGui::TreePop();
   7500         }
   7501 
   7502         IMGUI_DEMO_MARKER("Inputs & Focus/Focus from code");
   7503         if (ImGui::TreeNode("Focus from code"))
   7504         {
   7505             bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
   7506             bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
   7507             bool focus_3 = ImGui::Button("Focus on 3");
   7508             int has_focus = 0;
   7509             static char buf[128] = "click on a button to set focus";
   7510 
   7511             if (focus_1) ImGui::SetKeyboardFocusHere();
   7512             ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
   7513             if (ImGui::IsItemActive()) has_focus = 1;
   7514 
   7515             if (focus_2) ImGui::SetKeyboardFocusHere();
   7516             ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
   7517             if (ImGui::IsItemActive()) has_focus = 2;
   7518 
   7519             ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true);
   7520             if (focus_3) ImGui::SetKeyboardFocusHere();
   7521             ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
   7522             if (ImGui::IsItemActive()) has_focus = 3;
   7523             ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
   7524             ImGui::PopItemFlag();
   7525 
   7526             if (has_focus)
   7527                 ImGui::Text("Item with focus: %d", has_focus);
   7528             else
   7529                 ImGui::Text("Item with focus: <none>");
   7530 
   7531             // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
   7532             static float f3[3] = { 0.0f, 0.0f, 0.0f };
   7533             int focus_ahead = -1;
   7534             if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
   7535             if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
   7536             if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
   7537             if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
   7538             ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
   7539 
   7540             ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
   7541             ImGui::TreePop();
   7542         }
   7543 
   7544         IMGUI_DEMO_MARKER("Inputs & Focus/Dragging");
   7545         if (ImGui::TreeNode("Dragging"))
   7546         {
   7547             ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
   7548             for (int button = 0; button < 3; button++)
   7549             {
   7550                 ImGui::Text("IsMouseDragging(%d):", button);
   7551                 ImGui::Text("  w/ default threshold: %d,", ImGui::IsMouseDragging(button));
   7552                 ImGui::Text("  w/ zero threshold: %d,", ImGui::IsMouseDragging(button, 0.0f));
   7553                 ImGui::Text("  w/ large threshold: %d,", ImGui::IsMouseDragging(button, 20.0f));
   7554             }
   7555 
   7556             ImGui::Button("Drag Me");
   7557             if (ImGui::IsItemActive())
   7558                 ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor
   7559 
   7560             // Drag operations gets "unlocked" when the mouse has moved past a certain threshold
   7561             // (the default threshold is stored in io.MouseDragThreshold). You can request a lower or higher
   7562             // threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta().
   7563             ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
   7564             ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
   7565             ImVec2 mouse_delta = io.MouseDelta;
   7566             ImGui::Text("GetMouseDragDelta(0):");
   7567             ImGui::Text("  w/ default threshold: (%.1f, %.1f)", value_with_lock_threshold.x, value_with_lock_threshold.y);
   7568             ImGui::Text("  w/ zero threshold: (%.1f, %.1f)", value_raw.x, value_raw.y);
   7569             ImGui::Text("io.MouseDelta: (%.1f, %.1f)", mouse_delta.x, mouse_delta.y);
   7570             ImGui::TreePop();
   7571         }
   7572     }
   7573 }
   7574 
   7575 //-----------------------------------------------------------------------------
   7576 // [SECTION] About Window / ShowAboutWindow()
   7577 // Access from Dear ImGui Demo -> Tools -> About
   7578 //-----------------------------------------------------------------------------
   7579 
   7580 void ImGui::ShowAboutWindow(bool* p_open)
   7581 {
   7582     if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
   7583     {
   7584         ImGui::End();
   7585         return;
   7586     }
   7587     IMGUI_DEMO_MARKER("Tools/About Dear ImGui");
   7588     ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
   7589 
   7590     ImGui::TextLinkOpenURL("Homepage", "https://github.com/ocornut/imgui");
   7591     ImGui::SameLine();
   7592     ImGui::TextLinkOpenURL("FAQ", "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md");
   7593     ImGui::SameLine();
   7594     ImGui::TextLinkOpenURL("Wiki", "https://github.com/ocornut/imgui/wiki");
   7595     ImGui::SameLine();
   7596     ImGui::TextLinkOpenURL("Releases", "https://github.com/ocornut/imgui/releases");
   7597     ImGui::SameLine();
   7598     ImGui::TextLinkOpenURL("Funding", "https://github.com/ocornut/imgui/wiki/Funding");
   7599 
   7600     ImGui::Separator();
   7601     ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
   7602     ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
   7603     ImGui::Text("If your company uses this, please consider funding the project.");
   7604 
   7605     static bool show_config_info = false;
   7606     ImGui::Checkbox("Config/Build Information", &show_config_info);
   7607     if (show_config_info)
   7608     {
   7609         ImGuiIO& io = ImGui::GetIO();
   7610         ImGuiStyle& style = ImGui::GetStyle();
   7611 
   7612         bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
   7613         ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18);
   7614         ImGui::BeginChild(ImGui::GetID("cfg_infos"), child_size, ImGuiChildFlags_FrameStyle);
   7615         if (copy_to_clipboard)
   7616         {
   7617             ImGui::LogToClipboard();
   7618             ImGui::LogText("```\n"); // Back quotes will make text appears without formatting when pasting on GitHub
   7619         }
   7620 
   7621         ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
   7622         ImGui::Separator();
   7623         ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
   7624         ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
   7625 #ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
   7626         ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
   7627 #endif
   7628 #ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
   7629         ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_KEYIO");
   7630 #endif
   7631 #ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
   7632         ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
   7633 #endif
   7634 #ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
   7635         ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
   7636 #endif
   7637 #ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
   7638         ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
   7639 #endif
   7640 #ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
   7641         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS");
   7642 #endif
   7643 #ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
   7644         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS");
   7645 #endif
   7646 #ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
   7647         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS");
   7648 #endif
   7649 #ifdef IMGUI_DISABLE_FILE_FUNCTIONS
   7650         ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS");
   7651 #endif
   7652 #ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
   7653         ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
   7654 #endif
   7655 #ifdef IMGUI_USE_BGRA_PACKED_COLOR
   7656         ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
   7657 #endif
   7658 #ifdef _WIN32
   7659         ImGui::Text("define: _WIN32");
   7660 #endif
   7661 #ifdef _WIN64
   7662         ImGui::Text("define: _WIN64");
   7663 #endif
   7664 #ifdef __linux__
   7665         ImGui::Text("define: __linux__");
   7666 #endif
   7667 #ifdef __APPLE__
   7668         ImGui::Text("define: __APPLE__");
   7669 #endif
   7670 #ifdef _MSC_VER
   7671         ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
   7672 #endif
   7673 #ifdef _MSVC_LANG
   7674         ImGui::Text("define: _MSVC_LANG=%d", (int)_MSVC_LANG);
   7675 #endif
   7676 #ifdef __MINGW32__
   7677         ImGui::Text("define: __MINGW32__");
   7678 #endif
   7679 #ifdef __MINGW64__
   7680         ImGui::Text("define: __MINGW64__");
   7681 #endif
   7682 #ifdef __GNUC__
   7683         ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
   7684 #endif
   7685 #ifdef __clang_version__
   7686         ImGui::Text("define: __clang_version__=%s", __clang_version__);
   7687 #endif
   7688 #ifdef __EMSCRIPTEN__
   7689         ImGui::Text("define: __EMSCRIPTEN__");
   7690 #endif
   7691         ImGui::Separator();
   7692         ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
   7693         ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
   7694         ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
   7695         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)        ImGui::Text(" NavEnableKeyboard");
   7696         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
   7697         if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)     ImGui::Text(" NavEnableSetMousePos");
   7698         if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)     ImGui::Text(" NavNoCaptureKeyboard");
   7699         if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
   7700         if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
   7701         if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
   7702         if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
   7703         if (io.ConfigInputTextCursorBlink)                              ImGui::Text("io.ConfigInputTextCursorBlink");
   7704         if (io.ConfigWindowsResizeFromEdges)                            ImGui::Text("io.ConfigWindowsResizeFromEdges");
   7705         if (io.ConfigWindowsMoveFromTitleBarOnly)                       ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
   7706         if (io.ConfigMemoryCompactTimer >= 0.0f)                        ImGui::Text("io.ConfigMemoryCompactTimer = %.1f", io.ConfigMemoryCompactTimer);
   7707         ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
   7708         if (io.BackendFlags & ImGuiBackendFlags_HasGamepad)             ImGui::Text(" HasGamepad");
   7709         if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)        ImGui::Text(" HasMouseCursors");
   7710         if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)         ImGui::Text(" HasSetMousePos");
   7711         if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)   ImGui::Text(" RendererHasVtxOffset");
   7712         ImGui::Separator();
   7713         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);
   7714         ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
   7715         ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
   7716         ImGui::Separator();
   7717         ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
   7718         ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
   7719         ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
   7720         ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
   7721         ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
   7722         ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
   7723         ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
   7724 
   7725         if (copy_to_clipboard)
   7726         {
   7727             ImGui::LogText("\n```\n");
   7728             ImGui::LogFinish();
   7729         }
   7730         ImGui::EndChild();
   7731     }
   7732     ImGui::End();
   7733 }
   7734 
   7735 //-----------------------------------------------------------------------------
   7736 // [SECTION] Style Editor / ShowStyleEditor()
   7737 //-----------------------------------------------------------------------------
   7738 // - ShowFontSelector()
   7739 // - ShowStyleSelector()
   7740 // - ShowStyleEditor()
   7741 //-----------------------------------------------------------------------------
   7742 
   7743 // Forward declare ShowFontAtlas() which isn't worth putting in public API yet
   7744 namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); }
   7745 
   7746 // Demo helper function to select among loaded fonts.
   7747 // Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one.
   7748 void ImGui::ShowFontSelector(const char* label)
   7749 {
   7750     ImGuiIO& io = ImGui::GetIO();
   7751     ImFont* font_current = ImGui::GetFont();
   7752     if (ImGui::BeginCombo(label, font_current->GetDebugName()))
   7753     {
   7754         for (ImFont* font : io.Fonts->Fonts)
   7755         {
   7756             ImGui::PushID((void*)font);
   7757             if (ImGui::Selectable(font->GetDebugName(), font == font_current))
   7758                 io.FontDefault = font;
   7759             ImGui::PopID();
   7760         }
   7761         ImGui::EndCombo();
   7762     }
   7763     ImGui::SameLine();
   7764     HelpMarker(
   7765         "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
   7766         "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
   7767         "- Read FAQ and docs/FONTS.md for more details.\n"
   7768         "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
   7769 }
   7770 
   7771 // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
   7772 // Here we use the simplified Combo() api that packs items into a single literal string.
   7773 // Useful for quick combo boxes where the choices are known locally.
   7774 bool ImGui::ShowStyleSelector(const char* label)
   7775 {
   7776     static int style_idx = -1;
   7777     if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0"))
   7778     {
   7779         switch (style_idx)
   7780         {
   7781         case 0: ImGui::StyleColorsDark(); break;
   7782         case 1: ImGui::StyleColorsLight(); break;
   7783         case 2: ImGui::StyleColorsClassic(); break;
   7784         }
   7785         return true;
   7786     }
   7787     return false;
   7788 }
   7789 
   7790 void ImGui::ShowStyleEditor(ImGuiStyle* ref)
   7791 {
   7792     IMGUI_DEMO_MARKER("Tools/Style Editor");
   7793     // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
   7794     // (without a reference style pointer, we will use one compared locally as a reference)
   7795     ImGuiStyle& style = ImGui::GetStyle();
   7796     static ImGuiStyle ref_saved_style;
   7797 
   7798     // Default to using internal storage as reference
   7799     static bool init = true;
   7800     if (init && ref == NULL)
   7801         ref_saved_style = style;
   7802     init = false;
   7803     if (ref == NULL)
   7804         ref = &ref_saved_style;
   7805 
   7806     ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
   7807 
   7808     if (ImGui::ShowStyleSelector("Colors##Selector"))
   7809         ref_saved_style = style;
   7810     ImGui::ShowFontSelector("Fonts##Selector");
   7811 
   7812     // Simplified Settings (expose floating-pointer border sizes as boolean representing 0.0f or 1.0f)
   7813     if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
   7814         style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
   7815     { bool border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &border)) { style.WindowBorderSize = border ? 1.0f : 0.0f; } }
   7816     ImGui::SameLine();
   7817     { bool border = (style.FrameBorderSize > 0.0f);  if (ImGui::Checkbox("FrameBorder",  &border)) { style.FrameBorderSize  = border ? 1.0f : 0.0f; } }
   7818     ImGui::SameLine();
   7819     { bool border = (style.PopupBorderSize > 0.0f);  if (ImGui::Checkbox("PopupBorder",  &border)) { style.PopupBorderSize  = border ? 1.0f : 0.0f; } }
   7820 
   7821     // Save/Revert button
   7822     if (ImGui::Button("Save Ref"))
   7823         *ref = ref_saved_style = style;
   7824     ImGui::SameLine();
   7825     if (ImGui::Button("Revert Ref"))
   7826         style = *ref;
   7827     ImGui::SameLine();
   7828     HelpMarker(
   7829         "Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
   7830         "Use \"Export\" below to save them somewhere.");
   7831 
   7832     ImGui::Separator();
   7833 
   7834     if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
   7835     {
   7836         if (ImGui::BeginTabItem("Sizes"))
   7837         {
   7838             ImGui::SeparatorText("Main");
   7839             ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
   7840             ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
   7841             ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
   7842             ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
   7843             ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
   7844             ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
   7845             ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
   7846             ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
   7847 
   7848             ImGui::SeparatorText("Borders");
   7849             ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
   7850             ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
   7851             ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
   7852             ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
   7853             ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
   7854             ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f");
   7855             ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 2.0f, "%.0f");
   7856             ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set.");
   7857 
   7858             ImGui::SeparatorText("Rounding");
   7859             ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
   7860             ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
   7861             ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
   7862             ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
   7863             ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
   7864             ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
   7865             ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
   7866 
   7867             ImGui::SeparatorText("Tables");
   7868             ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f");
   7869             ImGui::SliderAngle("TableAngledHeadersAngle", &style.TableAngledHeadersAngle, -50.0f, +50.0f);
   7870             ImGui::SliderFloat2("TableAngledHeadersTextAlign", (float*)&style.TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
   7871 
   7872             ImGui::SeparatorText("Widgets");
   7873             ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
   7874             int window_menu_button_position = style.WindowMenuButtonPosition + 1;
   7875             if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
   7876                 style.WindowMenuButtonPosition = (ImGuiDir)(window_menu_button_position - 1);
   7877             ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
   7878             ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
   7879             ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
   7880             ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
   7881             ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
   7882             ImGui::SliderFloat("SeparatorTextBorderSize", &style.SeparatorTextBorderSize, 0.0f, 10.0f, "%.0f");
   7883             ImGui::SliderFloat2("SeparatorTextAlign", (float*)&style.SeparatorTextAlign, 0.0f, 1.0f, "%.2f");
   7884             ImGui::SliderFloat2("SeparatorTextPadding", (float*)&style.SeparatorTextPadding, 0.0f, 40.0f, "%.0f");
   7885             ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
   7886 
   7887             ImGui::SeparatorText("Tooltips");
   7888             for (int n = 0; n < 2; n++)
   7889                 if (ImGui::TreeNodeEx(n == 0 ? "HoverFlagsForTooltipMouse" : "HoverFlagsForTooltipNav"))
   7890                 {
   7891                     ImGuiHoveredFlags* p = (n == 0) ? &style.HoverFlagsForTooltipMouse : &style.HoverFlagsForTooltipNav;
   7892                     ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNone", p, ImGuiHoveredFlags_DelayNone);
   7893                     ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayShort", p, ImGuiHoveredFlags_DelayShort);
   7894                     ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNormal", p, ImGuiHoveredFlags_DelayNormal);
   7895                     ImGui::CheckboxFlags("ImGuiHoveredFlags_Stationary", p, ImGuiHoveredFlags_Stationary);
   7896                     ImGui::CheckboxFlags("ImGuiHoveredFlags_NoSharedDelay", p, ImGuiHoveredFlags_NoSharedDelay);
   7897                     ImGui::TreePop();
   7898                 }
   7899 
   7900             ImGui::SeparatorText("Misc");
   7901             ImGui::SliderFloat2("DisplayWindowPadding", (float*)&style.DisplayWindowPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen.");
   7902             ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Apply to every windows, menus, popups, tooltips: amount where we avoid displaying contents. Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
   7903 
   7904             ImGui::EndTabItem();
   7905         }
   7906 
   7907         if (ImGui::BeginTabItem("Colors"))
   7908         {
   7909             static int output_dest = 0;
   7910             static bool output_only_modified = true;
   7911             if (ImGui::Button("Export"))
   7912             {
   7913                 if (output_dest == 0)
   7914                     ImGui::LogToClipboard();
   7915                 else
   7916                     ImGui::LogToTTY();
   7917                 ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
   7918                 for (int i = 0; i < ImGuiCol_COUNT; i++)
   7919                 {
   7920                     const ImVec4& col = style.Colors[i];
   7921                     const char* name = ImGui::GetStyleColorName(i);
   7922                     if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
   7923                         ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE,
   7924                             name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
   7925                 }
   7926                 ImGui::LogFinish();
   7927             }
   7928             ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
   7929             ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
   7930 
   7931             static ImGuiTextFilter filter;
   7932             filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
   7933 
   7934             static ImGuiColorEditFlags alpha_flags = 0;
   7935             if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None))             { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();
   7936             if (ImGui::RadioButton("Alpha",  alpha_flags == ImGuiColorEditFlags_AlphaPreview))     { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
   7937             if (ImGui::RadioButton("Both",   alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
   7938             HelpMarker(
   7939                 "In the color list:\n"
   7940                 "Left-click on color square to open color picker,\n"
   7941                 "Right-click to open edit options menu.");
   7942 
   7943             ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 10), ImVec2(FLT_MAX, FLT_MAX));
   7944             ImGui::BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Border | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
   7945             ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
   7946             for (int i = 0; i < ImGuiCol_COUNT; i++)
   7947             {
   7948                 const char* name = ImGui::GetStyleColorName(i);
   7949                 if (!filter.PassFilter(name))
   7950                     continue;
   7951                 ImGui::PushID(i);
   7952 #ifndef IMGUI_DISABLE_DEBUG_TOOLS
   7953                 if (ImGui::Button("?"))
   7954                     ImGui::DebugFlashStyleColor((ImGuiCol)i);
   7955                 ImGui::SetItemTooltip("Flash given color to identify places where it is used.");
   7956                 ImGui::SameLine();
   7957 #endif
   7958                 ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
   7959                 if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
   7960                 {
   7961                     // Tips: in a real user application, you may want to merge and use an icon font into the main font,
   7962                     // so instead of "Save"/"Revert" you'd use icons!
   7963                     // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
   7964                     ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
   7965                     ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
   7966                 }
   7967                 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
   7968                 ImGui::TextUnformatted(name);
   7969                 ImGui::PopID();
   7970             }
   7971             ImGui::PopItemWidth();
   7972             ImGui::EndChild();
   7973 
   7974             ImGui::EndTabItem();
   7975         }
   7976 
   7977         if (ImGui::BeginTabItem("Fonts"))
   7978         {
   7979             ImGuiIO& io = ImGui::GetIO();
   7980             ImFontAtlas* atlas = io.Fonts;
   7981             HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
   7982             ImGui::ShowFontAtlas(atlas);
   7983 
   7984             // Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
   7985             // (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
   7986             const float MIN_SCALE = 0.3f;
   7987             const float MAX_SCALE = 2.0f;
   7988             HelpMarker(
   7989                 "Those are old settings provided for convenience.\n"
   7990                 "However, the _correct_ way of scaling your UI is currently to reload your font at the designed size, "
   7991                 "rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n"
   7992                 "Using those settings here will give you poor quality results.");
   7993             static float window_scale = 1.0f;
   7994             ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
   7995             if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
   7996                 ImGui::SetWindowFontScale(window_scale);
   7997             ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything
   7998             ImGui::PopItemWidth();
   7999 
   8000             ImGui::EndTabItem();
   8001         }
   8002 
   8003         if (ImGui::BeginTabItem("Rendering"))
   8004         {
   8005             ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
   8006             ImGui::SameLine();
   8007             HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
   8008 
   8009             ImGui::Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex);
   8010             ImGui::SameLine();
   8011             HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
   8012 
   8013             ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
   8014             ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
   8015             ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
   8016             if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
   8017 
   8018             // When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
   8019             ImGui::DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
   8020             const bool show_samples = ImGui::IsItemActive();
   8021             if (show_samples)
   8022                 ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
   8023             if (show_samples && ImGui::BeginTooltip())
   8024             {
   8025                 ImGui::TextUnformatted("(R = radius, N = approx number of segments)");
   8026                 ImGui::Spacing();
   8027                 ImDrawList* draw_list = ImGui::GetWindowDrawList();
   8028                 const float min_widget_width = ImGui::CalcTextSize("R: MMM\nN: MMM").x;
   8029                 for (int n = 0; n < 8; n++)
   8030                 {
   8031                     const float RAD_MIN = 5.0f;
   8032                     const float RAD_MAX = 70.0f;
   8033                     const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
   8034 
   8035                     ImGui::BeginGroup();
   8036 
   8037                     // N is not always exact here due to how PathArcTo() function work internally
   8038                     ImGui::Text("R: %.f\nN: %d", rad, draw_list->_CalcCircleAutoSegmentCount(rad));
   8039 
   8040                     const float canvas_width = IM_MAX(min_widget_width, rad * 2.0f);
   8041                     const float offset_x     = floorf(canvas_width * 0.5f);
   8042                     const float offset_y     = floorf(RAD_MAX);
   8043 
   8044                     const ImVec2 p1 = ImGui::GetCursorScreenPos();
   8045                     draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
   8046                     ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
   8047 
   8048                     /*
   8049                     const ImVec2 p2 = ImGui::GetCursorScreenPos();
   8050                     draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
   8051                     ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
   8052                     */
   8053 
   8054                     ImGui::EndGroup();
   8055                     ImGui::SameLine();
   8056                 }
   8057                 ImGui::EndTooltip();
   8058             }
   8059             ImGui::SameLine();
   8060             HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically.");
   8061 
   8062             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.
   8063             ImGui::DragFloat("Disabled Alpha", &style.DisabledAlpha, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Additional alpha multiplier for disabled items (multiply over current value of Alpha).");
   8064             ImGui::PopItemWidth();
   8065 
   8066             ImGui::EndTabItem();
   8067         }
   8068 
   8069         ImGui::EndTabBar();
   8070     }
   8071 
   8072     ImGui::PopItemWidth();
   8073 }
   8074 
   8075 //-----------------------------------------------------------------------------
   8076 // [SECTION] User Guide / ShowUserGuide()
   8077 //-----------------------------------------------------------------------------
   8078 
   8079 void ImGui::ShowUserGuide()
   8080 {
   8081     ImGuiIO& io = ImGui::GetIO();
   8082     ImGui::BulletText("Double-click on title bar to collapse window.");
   8083     ImGui::BulletText(
   8084         "Click and drag on lower corner to resize window\n"
   8085         "(double-click to auto fit window to its contents).");
   8086     ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
   8087     ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
   8088     ImGui::BulletText("CTRL+Tab to select a window.");
   8089     if (io.FontAllowUserScaling)
   8090         ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
   8091     ImGui::BulletText("While inputing text:\n");
   8092     ImGui::Indent();
   8093     ImGui::BulletText("CTRL+Left/Right to word jump.");
   8094     ImGui::BulletText("CTRL+A or double-click to select all.");
   8095     ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
   8096     ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
   8097     ImGui::BulletText("ESCAPE to revert.");
   8098     ImGui::Unindent();
   8099     ImGui::BulletText("With keyboard navigation enabled:");
   8100     ImGui::Indent();
   8101     ImGui::BulletText("Arrow keys to navigate.");
   8102     ImGui::BulletText("Space to activate a widget.");
   8103     ImGui::BulletText("Return to input text into a widget.");
   8104     ImGui::BulletText("Escape to deactivate a widget, close popup, exit child window.");
   8105     ImGui::BulletText("Alt to jump to the menu layer of a window.");
   8106     ImGui::Unindent();
   8107 }
   8108 
   8109 //-----------------------------------------------------------------------------
   8110 // [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
   8111 //-----------------------------------------------------------------------------
   8112 // - ShowExampleAppMainMenuBar()
   8113 // - ShowExampleMenuFile()
   8114 //-----------------------------------------------------------------------------
   8115 
   8116 // Demonstrate creating a "main" fullscreen menu bar and populating it.
   8117 // Note the difference between BeginMainMenuBar() and BeginMenuBar():
   8118 // - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!)
   8119 // - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it.
   8120 static void ShowExampleAppMainMenuBar()
   8121 {
   8122     if (ImGui::BeginMainMenuBar())
   8123     {
   8124         if (ImGui::BeginMenu("File"))
   8125         {
   8126             ShowExampleMenuFile();
   8127             ImGui::EndMenu();
   8128         }
   8129         if (ImGui::BeginMenu("Edit"))
   8130         {
   8131             if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
   8132             if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
   8133             ImGui::Separator();
   8134             if (ImGui::MenuItem("Cut", "CTRL+X")) {}
   8135             if (ImGui::MenuItem("Copy", "CTRL+C")) {}
   8136             if (ImGui::MenuItem("Paste", "CTRL+V")) {}
   8137             ImGui::EndMenu();
   8138         }
   8139         ImGui::EndMainMenuBar();
   8140     }
   8141 }
   8142 
   8143 // Note that shortcuts are currently provided for display only
   8144 // (future version will add explicit flags to BeginMenu() to request processing shortcuts)
   8145 static void ShowExampleMenuFile()
   8146 {
   8147     IMGUI_DEMO_MARKER("Examples/Menu");
   8148     ImGui::MenuItem("(demo menu)", NULL, false, false);
   8149     if (ImGui::MenuItem("New")) {}
   8150     if (ImGui::MenuItem("Open", "Ctrl+O")) {}
   8151     if (ImGui::BeginMenu("Open Recent"))
   8152     {
   8153         ImGui::MenuItem("fish_hat.c");
   8154         ImGui::MenuItem("fish_hat.inl");
   8155         ImGui::MenuItem("fish_hat.h");
   8156         if (ImGui::BeginMenu("More.."))
   8157         {
   8158             ImGui::MenuItem("Hello");
   8159             ImGui::MenuItem("Sailor");
   8160             if (ImGui::BeginMenu("Recurse.."))
   8161             {
   8162                 ShowExampleMenuFile();
   8163                 ImGui::EndMenu();
   8164             }
   8165             ImGui::EndMenu();
   8166         }
   8167         ImGui::EndMenu();
   8168     }
   8169     if (ImGui::MenuItem("Save", "Ctrl+S")) {}
   8170     if (ImGui::MenuItem("Save As..")) {}
   8171 
   8172     ImGui::Separator();
   8173     IMGUI_DEMO_MARKER("Examples/Menu/Options");
   8174     if (ImGui::BeginMenu("Options"))
   8175     {
   8176         static bool enabled = true;
   8177         ImGui::MenuItem("Enabled", "", &enabled);
   8178         ImGui::BeginChild("child", ImVec2(0, 60), ImGuiChildFlags_Border);
   8179         for (int i = 0; i < 10; i++)
   8180             ImGui::Text("Scrolling Text %d", i);
   8181         ImGui::EndChild();
   8182         static float f = 0.5f;
   8183         static int n = 0;
   8184         ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
   8185         ImGui::InputFloat("Input", &f, 0.1f);
   8186         ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
   8187         ImGui::EndMenu();
   8188     }
   8189 
   8190     IMGUI_DEMO_MARKER("Examples/Menu/Colors");
   8191     if (ImGui::BeginMenu("Colors"))
   8192     {
   8193         float sz = ImGui::GetTextLineHeight();
   8194         for (int i = 0; i < ImGuiCol_COUNT; i++)
   8195         {
   8196             const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
   8197             ImVec2 p = ImGui::GetCursorScreenPos();
   8198             ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
   8199             ImGui::Dummy(ImVec2(sz, sz));
   8200             ImGui::SameLine();
   8201             ImGui::MenuItem(name);
   8202         }
   8203         ImGui::EndMenu();
   8204     }
   8205 
   8206     // Here we demonstrate appending again to the "Options" menu (which we already created above)
   8207     // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice.
   8208     // In a real code-base using it would make senses to use this feature from very different code locations.
   8209     if (ImGui::BeginMenu("Options")) // <-- Append!
   8210     {
   8211         IMGUI_DEMO_MARKER("Examples/Menu/Append to an existing menu");
   8212         static bool b = true;
   8213         ImGui::Checkbox("SomeOption", &b);
   8214         ImGui::EndMenu();
   8215     }
   8216 
   8217     if (ImGui::BeginMenu("Disabled", false)) // Disabled
   8218     {
   8219         IM_ASSERT(0);
   8220     }
   8221     if (ImGui::MenuItem("Checked", NULL, true)) {}
   8222     ImGui::Separator();
   8223     if (ImGui::MenuItem("Quit", "Alt+F4")) {}
   8224 }
   8225 
   8226 //-----------------------------------------------------------------------------
   8227 // [SECTION] Example App: Debug Console / ShowExampleAppConsole()
   8228 //-----------------------------------------------------------------------------
   8229 
   8230 // Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
   8231 // For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
   8232 struct ExampleAppConsole
   8233 {
   8234     char                  InputBuf[256];
   8235     ImVector<char*>       Items;
   8236     ImVector<const char*> Commands;
   8237     ImVector<char*>       History;
   8238     int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
   8239     ImGuiTextFilter       Filter;
   8240     bool                  AutoScroll;
   8241     bool                  ScrollToBottom;
   8242 
   8243     ExampleAppConsole()
   8244     {
   8245         IMGUI_DEMO_MARKER("Examples/Console");
   8246         ClearLog();
   8247         memset(InputBuf, 0, sizeof(InputBuf));
   8248         HistoryPos = -1;
   8249 
   8250         // "CLASSIFY" is here to provide the test case where "C"+[tab] completes to "CL" and display multiple matches.
   8251         Commands.push_back("HELP");
   8252         Commands.push_back("HISTORY");
   8253         Commands.push_back("CLEAR");
   8254         Commands.push_back("CLASSIFY");
   8255         AutoScroll = true;
   8256         ScrollToBottom = false;
   8257         AddLog("Welcome to Dear ImGui!");
   8258     }
   8259     ~ExampleAppConsole()
   8260     {
   8261         ClearLog();
   8262         for (int i = 0; i < History.Size; i++)
   8263             ImGui::MemFree(History[i]);
   8264     }
   8265 
   8266     // Portable helpers
   8267     static int   Stricmp(const char* s1, const char* s2)         { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
   8268     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; }
   8269     static char* Strdup(const char* s)                           { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = ImGui::MemAlloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
   8270     static void  Strtrim(char* s)                                { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
   8271 
   8272     void    ClearLog()
   8273     {
   8274         for (int i = 0; i < Items.Size; i++)
   8275             ImGui::MemFree(Items[i]);
   8276         Items.clear();
   8277     }
   8278 
   8279     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
   8280     {
   8281         // FIXME-OPT
   8282         char buf[1024];
   8283         va_list args;
   8284         va_start(args, fmt);
   8285         vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
   8286         buf[IM_ARRAYSIZE(buf)-1] = 0;
   8287         va_end(args);
   8288         Items.push_back(Strdup(buf));
   8289     }
   8290 
   8291     void    Draw(const char* title, bool* p_open)
   8292     {
   8293         ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
   8294         if (!ImGui::Begin(title, p_open))
   8295         {
   8296             ImGui::End();
   8297             return;
   8298         }
   8299 
   8300         // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar.
   8301         // So e.g. IsItemHovered() will return true when hovering the title bar.
   8302         // Here we create a context menu only available from the title bar.
   8303         if (ImGui::BeginPopupContextItem())
   8304         {
   8305             if (ImGui::MenuItem("Close Console"))
   8306                 *p_open = false;
   8307             ImGui::EndPopup();
   8308         }
   8309 
   8310         ImGui::TextWrapped(
   8311             "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate "
   8312             "implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
   8313         ImGui::TextWrapped("Enter 'HELP' for help.");
   8314 
   8315         // TODO: display items starting from the bottom
   8316 
   8317         if (ImGui::SmallButton("Add Debug Text"))  { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); }
   8318         ImGui::SameLine();
   8319         if (ImGui::SmallButton("Add Debug Error")) { AddLog("[error] something went wrong"); }
   8320         ImGui::SameLine();
   8321         if (ImGui::SmallButton("Clear"))           { ClearLog(); }
   8322         ImGui::SameLine();
   8323         bool copy_to_clipboard = ImGui::SmallButton("Copy");
   8324         //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
   8325 
   8326         ImGui::Separator();
   8327 
   8328         // Options menu
   8329         if (ImGui::BeginPopup("Options"))
   8330         {
   8331             ImGui::Checkbox("Auto-scroll", &AutoScroll);
   8332             ImGui::EndPopup();
   8333         }
   8334 
   8335         // Options, Filter
   8336         ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_O, ImGuiInputFlags_Tooltip);
   8337         if (ImGui::Button("Options"))
   8338             ImGui::OpenPopup("Options");
   8339         ImGui::SameLine();
   8340         Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
   8341         ImGui::Separator();
   8342 
   8343         // Reserve enough left-over height for 1 separator + 1 input text
   8344         const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
   8345         if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_HorizontalScrollbar))
   8346         {
   8347             if (ImGui::BeginPopupContextWindow())
   8348             {
   8349                 if (ImGui::Selectable("Clear")) ClearLog();
   8350                 ImGui::EndPopup();
   8351             }
   8352 
   8353             // Display every line as a separate entry so we can change their color or add custom widgets.
   8354             // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
   8355             // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
   8356             // to only process visible items. The clipper will automatically measure the height of your first item and then
   8357             // "seek" to display only items in the visible area.
   8358             // To use the clipper we can replace your standard loop:
   8359             //      for (int i = 0; i < Items.Size; i++)
   8360             //   With:
   8361             //      ImGuiListClipper clipper;
   8362             //      clipper.Begin(Items.Size);
   8363             //      while (clipper.Step())
   8364             //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
   8365             // - That your items are evenly spaced (same height)
   8366             // - That you have cheap random access to your elements (you can access them given their index,
   8367             //   without processing all the ones before)
   8368             // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
   8369             // We would need random-access on the post-filtered list.
   8370             // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
   8371             // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
   8372             // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
   8373             // to improve this example code!
   8374             // If your items are of variable height:
   8375             // - Split them into same height items would be simpler and facilitate random-seeking into your list.
   8376             // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
   8377             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
   8378             if (copy_to_clipboard)
   8379                 ImGui::LogToClipboard();
   8380             for (const char* item : Items)
   8381             {
   8382                 if (!Filter.PassFilter(item))
   8383                     continue;
   8384 
   8385                 // Normally you would store more information in your item than just a string.
   8386                 // (e.g. make Items[] an array of structure, store color/type etc.)
   8387                 ImVec4 color;
   8388                 bool has_color = false;
   8389                 if (strstr(item, "[error]")) { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
   8390                 else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
   8391                 if (has_color)
   8392                     ImGui::PushStyleColor(ImGuiCol_Text, color);
   8393                 ImGui::TextUnformatted(item);
   8394                 if (has_color)
   8395                     ImGui::PopStyleColor();
   8396             }
   8397             if (copy_to_clipboard)
   8398                 ImGui::LogFinish();
   8399 
   8400             // Keep up at the bottom of the scroll region if we were already at the bottom at the beginning of the frame.
   8401             // Using a scrollbar or mouse-wheel will take away from the bottom edge.
   8402             if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
   8403                 ImGui::SetScrollHereY(1.0f);
   8404             ScrollToBottom = false;
   8405 
   8406             ImGui::PopStyleVar();
   8407         }
   8408         ImGui::EndChild();
   8409         ImGui::Separator();
   8410 
   8411         // Command-line
   8412         bool reclaim_focus = false;
   8413         ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_EscapeClearsAll | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
   8414         if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
   8415         {
   8416             char* s = InputBuf;
   8417             Strtrim(s);
   8418             if (s[0])
   8419                 ExecCommand(s);
   8420             strcpy(s, "");
   8421             reclaim_focus = true;
   8422         }
   8423 
   8424         // Auto-focus on window apparition
   8425         ImGui::SetItemDefaultFocus();
   8426         if (reclaim_focus)
   8427             ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
   8428 
   8429         ImGui::End();
   8430     }
   8431 
   8432     void    ExecCommand(const char* command_line)
   8433     {
   8434         AddLog("# %s\n", command_line);
   8435 
   8436         // Insert into history. First find match and delete it so it can be pushed to the back.
   8437         // This isn't trying to be smart or optimal.
   8438         HistoryPos = -1;
   8439         for (int i = History.Size - 1; i >= 0; i--)
   8440             if (Stricmp(History[i], command_line) == 0)
   8441             {
   8442                 ImGui::MemFree(History[i]);
   8443                 History.erase(History.begin() + i);
   8444                 break;
   8445             }
   8446         History.push_back(Strdup(command_line));
   8447 
   8448         // Process command
   8449         if (Stricmp(command_line, "CLEAR") == 0)
   8450         {
   8451             ClearLog();
   8452         }
   8453         else if (Stricmp(command_line, "HELP") == 0)
   8454         {
   8455             AddLog("Commands:");
   8456             for (int i = 0; i < Commands.Size; i++)
   8457                 AddLog("- %s", Commands[i]);
   8458         }
   8459         else if (Stricmp(command_line, "HISTORY") == 0)
   8460         {
   8461             int first = History.Size - 10;
   8462             for (int i = first > 0 ? first : 0; i < History.Size; i++)
   8463                 AddLog("%3d: %s\n", i, History[i]);
   8464         }
   8465         else
   8466         {
   8467             AddLog("Unknown command: '%s'\n", command_line);
   8468         }
   8469 
   8470         // On command input, we scroll to bottom even if AutoScroll==false
   8471         ScrollToBottom = true;
   8472     }
   8473 
   8474     // In C++11 you'd be better off using lambdas for this sort of forwarding callbacks
   8475     static int TextEditCallbackStub(ImGuiInputTextCallbackData* data)
   8476     {
   8477         ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
   8478         return console->TextEditCallback(data);
   8479     }
   8480 
   8481     int     TextEditCallback(ImGuiInputTextCallbackData* data)
   8482     {
   8483         //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
   8484         switch (data->EventFlag)
   8485         {
   8486         case ImGuiInputTextFlags_CallbackCompletion:
   8487             {
   8488                 // Example of TEXT COMPLETION
   8489 
   8490                 // Locate beginning of current word
   8491                 const char* word_end = data->Buf + data->CursorPos;
   8492                 const char* word_start = word_end;
   8493                 while (word_start > data->Buf)
   8494                 {
   8495                     const char c = word_start[-1];
   8496                     if (c == ' ' || c == '\t' || c == ',' || c == ';')
   8497                         break;
   8498                     word_start--;
   8499                 }
   8500 
   8501                 // Build a list of candidates
   8502                 ImVector<const char*> candidates;
   8503                 for (int i = 0; i < Commands.Size; i++)
   8504                     if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
   8505                         candidates.push_back(Commands[i]);
   8506 
   8507                 if (candidates.Size == 0)
   8508                 {
   8509                     // No match
   8510                     AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
   8511                 }
   8512                 else if (candidates.Size == 1)
   8513                 {
   8514                     // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing.
   8515                     data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
   8516                     data->InsertChars(data->CursorPos, candidates[0]);
   8517                     data->InsertChars(data->CursorPos, " ");
   8518                 }
   8519                 else
   8520                 {
   8521                     // Multiple matches. Complete as much as we can..
   8522                     // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches.
   8523                     int match_len = (int)(word_end - word_start);
   8524                     for (;;)
   8525                     {
   8526                         int c = 0;
   8527                         bool all_candidates_matches = true;
   8528                         for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
   8529                             if (i == 0)
   8530                                 c = toupper(candidates[i][match_len]);
   8531                             else if (c == 0 || c != toupper(candidates[i][match_len]))
   8532                                 all_candidates_matches = false;
   8533                         if (!all_candidates_matches)
   8534                             break;
   8535                         match_len++;
   8536                     }
   8537 
   8538                     if (match_len > 0)
   8539                     {
   8540                         data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
   8541                         data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
   8542                     }
   8543 
   8544                     // List matches
   8545                     AddLog("Possible matches:\n");
   8546                     for (int i = 0; i < candidates.Size; i++)
   8547                         AddLog("- %s\n", candidates[i]);
   8548                 }
   8549 
   8550                 break;
   8551             }
   8552         case ImGuiInputTextFlags_CallbackHistory:
   8553             {
   8554                 // Example of HISTORY
   8555                 const int prev_history_pos = HistoryPos;
   8556                 if (data->EventKey == ImGuiKey_UpArrow)
   8557                 {
   8558                     if (HistoryPos == -1)
   8559                         HistoryPos = History.Size - 1;
   8560                     else if (HistoryPos > 0)
   8561                         HistoryPos--;
   8562                 }
   8563                 else if (data->EventKey == ImGuiKey_DownArrow)
   8564                 {
   8565                     if (HistoryPos != -1)
   8566                         if (++HistoryPos >= History.Size)
   8567                             HistoryPos = -1;
   8568                 }
   8569 
   8570                 // A better implementation would preserve the data on the current input line along with cursor position.
   8571                 if (prev_history_pos != HistoryPos)
   8572                 {
   8573                     const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
   8574                     data->DeleteChars(0, data->BufTextLen);
   8575                     data->InsertChars(0, history_str);
   8576                 }
   8577             }
   8578         }
   8579         return 0;
   8580     }
   8581 };
   8582 
   8583 static void ShowExampleAppConsole(bool* p_open)
   8584 {
   8585     static ExampleAppConsole console;
   8586     console.Draw("Example: Console", p_open);
   8587 }
   8588 
   8589 //-----------------------------------------------------------------------------
   8590 // [SECTION] Example App: Debug Log / ShowExampleAppLog()
   8591 //-----------------------------------------------------------------------------
   8592 
   8593 // Usage:
   8594 //  static ExampleAppLog my_log;
   8595 //  my_log.AddLog("Hello %d world\n", 123);
   8596 //  my_log.Draw("title");
   8597 struct ExampleAppLog
   8598 {
   8599     ImGuiTextBuffer     Buf;
   8600     ImGuiTextFilter     Filter;
   8601     ImVector<int>       LineOffsets; // Index to lines offset. We maintain this with AddLog() calls.
   8602     bool                AutoScroll;  // Keep scrolling if already at the bottom.
   8603 
   8604     ExampleAppLog()
   8605     {
   8606         AutoScroll = true;
   8607         Clear();
   8608     }
   8609 
   8610     void    Clear()
   8611     {
   8612         Buf.clear();
   8613         LineOffsets.clear();
   8614         LineOffsets.push_back(0);
   8615     }
   8616 
   8617     void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
   8618     {
   8619         int old_size = Buf.size();
   8620         va_list args;
   8621         va_start(args, fmt);
   8622         Buf.appendfv(fmt, args);
   8623         va_end(args);
   8624         for (int new_size = Buf.size(); old_size < new_size; old_size++)
   8625             if (Buf[old_size] == '\n')
   8626                 LineOffsets.push_back(old_size + 1);
   8627     }
   8628 
   8629     void    Draw(const char* title, bool* p_open = NULL)
   8630     {
   8631         if (!ImGui::Begin(title, p_open))
   8632         {
   8633             ImGui::End();
   8634             return;
   8635         }
   8636 
   8637         // Options menu
   8638         if (ImGui::BeginPopup("Options"))
   8639         {
   8640             ImGui::Checkbox("Auto-scroll", &AutoScroll);
   8641             ImGui::EndPopup();
   8642         }
   8643 
   8644         // Main window
   8645         if (ImGui::Button("Options"))
   8646             ImGui::OpenPopup("Options");
   8647         ImGui::SameLine();
   8648         bool clear = ImGui::Button("Clear");
   8649         ImGui::SameLine();
   8650         bool copy = ImGui::Button("Copy");
   8651         ImGui::SameLine();
   8652         Filter.Draw("Filter", -100.0f);
   8653 
   8654         ImGui::Separator();
   8655 
   8656         if (ImGui::BeginChild("scrolling", ImVec2(0, 0), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar))
   8657         {
   8658             if (clear)
   8659                 Clear();
   8660             if (copy)
   8661                 ImGui::LogToClipboard();
   8662 
   8663             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
   8664             const char* buf = Buf.begin();
   8665             const char* buf_end = Buf.end();
   8666             if (Filter.IsActive())
   8667             {
   8668                 // In this example we don't use the clipper when Filter is enabled.
   8669                 // This is because we don't have random access to the result of our filter.
   8670                 // A real application processing logs with ten of thousands of entries may want to store the result of
   8671                 // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
   8672                 for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
   8673                 {
   8674                     const char* line_start = buf + LineOffsets[line_no];
   8675                     const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
   8676                     if (Filter.PassFilter(line_start, line_end))
   8677                         ImGui::TextUnformatted(line_start, line_end);
   8678                 }
   8679             }
   8680             else
   8681             {
   8682                 // The simplest and easy way to display the entire buffer:
   8683                 //   ImGui::TextUnformatted(buf_begin, buf_end);
   8684                 // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
   8685                 // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
   8686                 // within the visible area.
   8687                 // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
   8688                 // on your side is recommended. Using ImGuiListClipper requires
   8689                 // - A) random access into your data
   8690                 // - B) items all being the  same height,
   8691                 // both of which we can handle since we have an array pointing to the beginning of each line of text.
   8692                 // When using the filter (in the block of code above) we don't have random access into the data to display
   8693                 // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
   8694                 // it possible (and would be recommended if you want to search through tens of thousands of entries).
   8695                 ImGuiListClipper clipper;
   8696                 clipper.Begin(LineOffsets.Size);
   8697                 while (clipper.Step())
   8698                 {
   8699                     for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
   8700                     {
   8701                         const char* line_start = buf + LineOffsets[line_no];
   8702                         const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
   8703                         ImGui::TextUnformatted(line_start, line_end);
   8704                     }
   8705                 }
   8706                 clipper.End();
   8707             }
   8708             ImGui::PopStyleVar();
   8709 
   8710             // Keep up at the bottom of the scroll region if we were already at the bottom at the beginning of the frame.
   8711             // Using a scrollbar or mouse-wheel will take away from the bottom edge.
   8712             if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
   8713                 ImGui::SetScrollHereY(1.0f);
   8714         }
   8715         ImGui::EndChild();
   8716         ImGui::End();
   8717     }
   8718 };
   8719 
   8720 // Demonstrate creating a simple log window with basic filtering.
   8721 static void ShowExampleAppLog(bool* p_open)
   8722 {
   8723     static ExampleAppLog log;
   8724 
   8725     // For the demo: add a debug button _BEFORE_ the normal log window contents
   8726     // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
   8727     // Most of the contents of the window will be added by the log.Draw() call.
   8728     ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
   8729     ImGui::Begin("Example: Log", p_open);
   8730     IMGUI_DEMO_MARKER("Examples/Log");
   8731     if (ImGui::SmallButton("[Debug] Add 5 entries"))
   8732     {
   8733         static int counter = 0;
   8734         const char* categories[3] = { "info", "warn", "error" };
   8735         const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
   8736         for (int n = 0; n < 5; n++)
   8737         {
   8738             const char* category = categories[counter % IM_ARRAYSIZE(categories)];
   8739             const char* word = words[counter % IM_ARRAYSIZE(words)];
   8740             log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
   8741                 ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
   8742             counter++;
   8743         }
   8744     }
   8745     ImGui::End();
   8746 
   8747     // Actually call in the regular Log helper (which will Begin() into the same window as we just did)
   8748     log.Draw("Example: Log", p_open);
   8749 }
   8750 
   8751 //-----------------------------------------------------------------------------
   8752 // [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
   8753 //-----------------------------------------------------------------------------
   8754 
   8755 // Demonstrate create a window with multiple child windows.
   8756 static void ShowExampleAppLayout(bool* p_open)
   8757 {
   8758     ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
   8759     if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
   8760     {
   8761         IMGUI_DEMO_MARKER("Examples/Simple layout");
   8762         if (ImGui::BeginMenuBar())
   8763         {
   8764             if (ImGui::BeginMenu("File"))
   8765             {
   8766                 if (ImGui::MenuItem("Close", "Ctrl+W")) { *p_open = false; }
   8767                 ImGui::EndMenu();
   8768             }
   8769             ImGui::EndMenuBar();
   8770         }
   8771 
   8772         // Left
   8773         static int selected = 0;
   8774         {
   8775             ImGui::BeginChild("left pane", ImVec2(150, 0), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX);
   8776             for (int i = 0; i < 100; i++)
   8777             {
   8778                 // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav
   8779                 char label[128];
   8780                 sprintf(label, "MyObject %d", i);
   8781                 if (ImGui::Selectable(label, selected == i))
   8782                     selected = i;
   8783             }
   8784             ImGui::EndChild();
   8785         }
   8786         ImGui::SameLine();
   8787 
   8788         // Right
   8789         {
   8790             ImGui::BeginGroup();
   8791             ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
   8792             ImGui::Text("MyObject: %d", selected);
   8793             ImGui::Separator();
   8794             if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
   8795             {
   8796                 if (ImGui::BeginTabItem("Description"))
   8797                 {
   8798                     ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
   8799                     ImGui::EndTabItem();
   8800                 }
   8801                 if (ImGui::BeginTabItem("Details"))
   8802                 {
   8803                     ImGui::Text("ID: 0123456789");
   8804                     ImGui::EndTabItem();
   8805                 }
   8806                 ImGui::EndTabBar();
   8807             }
   8808             ImGui::EndChild();
   8809             if (ImGui::Button("Revert")) {}
   8810             ImGui::SameLine();
   8811             if (ImGui::Button("Save")) {}
   8812             ImGui::EndGroup();
   8813         }
   8814     }
   8815     ImGui::End();
   8816 }
   8817 
   8818 //-----------------------------------------------------------------------------
   8819 // [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
   8820 //-----------------------------------------------------------------------------
   8821 // Some of the interactions are a bit lack-luster:
   8822 // - We would want pressing validating or leaving the filter to somehow restore focus.
   8823 // - We may want more advanced filtering (child nodes) and clipper support: both will need extra work.
   8824 // - We would want to customize some keyboard interactions to easily keyboard navigate between the tree and the properties.
   8825 //-----------------------------------------------------------------------------
   8826 
   8827 struct ExampleAppPropertyEditor
   8828 {
   8829     ImGuiTextFilter     Filter;
   8830     ExampleTreeNode*    VisibleNode = NULL;
   8831 
   8832     void Draw(ExampleTreeNode* root_node)
   8833     {
   8834         // Left side: draw tree
   8835         // - Currently using a table to benefit from RowBg feature
   8836         if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Border | ImGuiChildFlags_NavFlattened))
   8837         {
   8838             ImGui::SetNextItemWidth(-FLT_MIN);
   8839             ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip);
   8840             ImGui::PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
   8841             if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_ARRAYSIZE(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll))
   8842                 Filter.Build();
   8843             ImGui::PopItemFlag();
   8844 
   8845             if (ImGui::BeginTable("##bg", 1, ImGuiTableFlags_RowBg))
   8846             {
   8847                 for (ExampleTreeNode* node : root_node->Childs)
   8848                     if (Filter.PassFilter(node->Name)) // Filter root node
   8849                         DrawTreeNode(node);
   8850                 ImGui::EndTable();
   8851             }
   8852         }
   8853         ImGui::EndChild();
   8854 
   8855         // Right side: draw properties
   8856         ImGui::SameLine();
   8857 
   8858         ImGui::BeginGroup(); // Lock X position
   8859         if (ExampleTreeNode* node = VisibleNode)
   8860         {
   8861             ImGui::Text("%s", node->Name);
   8862             ImGui::TextDisabled("UID: 0x%08X", node->UID);
   8863             ImGui::Separator();
   8864             if (ImGui::BeginTable("##properties", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY))
   8865             {
   8866                 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
   8867                 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger
   8868                 if (node->HasData)
   8869                 {
   8870                     // In a typical application, the structure description would be derived from a data-driven system.
   8871                     // - We try to mimic this with our ExampleMemberInfo structure and the ExampleTreeNodeMemberInfos[] array.
   8872                     // - Limits and some details are hard-coded to simplify the demo.
   8873                     for (const ExampleMemberInfo& field_desc : ExampleTreeNodeMemberInfos)
   8874                     {
   8875                         ImGui::TableNextRow();
   8876                         ImGui::PushID(field_desc.Name);
   8877                         ImGui::TableNextColumn();
   8878                         ImGui::AlignTextToFramePadding();
   8879                         ImGui::TextUnformatted(field_desc.Name);
   8880                         ImGui::TableNextColumn();
   8881                         void* field_ptr = (void*)(((unsigned char*)node) + field_desc.Offset);
   8882                         switch (field_desc.DataType)
   8883                         {
   8884                         case ImGuiDataType_Bool:
   8885                         {
   8886                             IM_ASSERT(field_desc.DataCount == 1);
   8887                             ImGui::Checkbox("##Editor", (bool*)field_ptr);
   8888                             break;
   8889                         }
   8890                         case ImGuiDataType_S32:
   8891                         {
   8892                             int v_min = INT_MIN, v_max = INT_MAX;
   8893                             ImGui::SetNextItemWidth(-FLT_MIN);
   8894                             ImGui::DragScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, 1.0f, &v_min, &v_max);
   8895                             break;
   8896                         }
   8897                         case ImGuiDataType_Float:
   8898                         {
   8899                             float v_min = 0.0f, v_max = 1.0f;
   8900                             ImGui::SetNextItemWidth(-FLT_MIN);
   8901                             ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max);
   8902                             break;
   8903                         }
   8904                         }
   8905                         ImGui::PopID();
   8906                     }
   8907                 }
   8908                 ImGui::EndTable();
   8909             }
   8910         }
   8911         ImGui::EndGroup();
   8912     }
   8913 
   8914     void DrawTreeNode(ExampleTreeNode* node)
   8915     {
   8916         ImGui::TableNextRow();
   8917         ImGui::TableNextColumn();
   8918         ImGui::PushID(node->UID);
   8919         ImGuiTreeNodeFlags tree_flags = ImGuiTreeNodeFlags_None;
   8920         tree_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;    // Standard opening mode as we are likely to want to add selection afterwards
   8921         tree_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere;                                  // Left arrow support
   8922         if (node == VisibleNode)
   8923             tree_flags |= ImGuiTreeNodeFlags_Selected;
   8924         if (node->Childs.Size == 0)
   8925             tree_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet;
   8926         if (node->DataMyBool == false)
   8927             ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
   8928         bool node_open = ImGui::TreeNodeEx("", tree_flags, "%s", node->Name);
   8929         if (node->DataMyBool == false)
   8930             ImGui::PopStyleColor();
   8931         if (ImGui::IsItemFocused())
   8932             VisibleNode = node;
   8933         if (node_open)
   8934         {
   8935             for (ExampleTreeNode* child : node->Childs)
   8936                 DrawTreeNode(child);
   8937             ImGui::TreePop();
   8938         }
   8939         ImGui::PopID();
   8940     }
   8941 };
   8942 
   8943 // Demonstrate creating a simple property editor.
   8944 static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data)
   8945 {
   8946     ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
   8947     if (!ImGui::Begin("Example: Property editor", p_open))
   8948     {
   8949         ImGui::End();
   8950         return;
   8951     }
   8952 
   8953     IMGUI_DEMO_MARKER("Examples/Property Editor");
   8954     static ExampleAppPropertyEditor property_editor;
   8955     if (demo_data->DemoTree == NULL)
   8956         demo_data->DemoTree = ExampleTree_CreateDemoTree();
   8957     property_editor.Draw(demo_data->DemoTree);
   8958 
   8959     ImGui::End();
   8960 }
   8961 
   8962 //-----------------------------------------------------------------------------
   8963 // [SECTION] Example App: Long Text / ShowExampleAppLongText()
   8964 //-----------------------------------------------------------------------------
   8965 
   8966 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
   8967 static void ShowExampleAppLongText(bool* p_open)
   8968 {
   8969     ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
   8970     if (!ImGui::Begin("Example: Long text display", p_open))
   8971     {
   8972         ImGui::End();
   8973         return;
   8974     }
   8975     IMGUI_DEMO_MARKER("Examples/Long text display");
   8976 
   8977     static int test_type = 0;
   8978     static ImGuiTextBuffer log;
   8979     static int lines = 0;
   8980     ImGui::Text("Printing unusually long amount of text.");
   8981     ImGui::Combo("Test type", &test_type,
   8982         "Single call to TextUnformatted()\0"
   8983         "Multiple calls to Text(), clipped\0"
   8984         "Multiple calls to Text(), not clipped (slow)\0");
   8985     ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
   8986     if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
   8987     ImGui::SameLine();
   8988     if (ImGui::Button("Add 1000 lines"))
   8989     {
   8990         for (int i = 0; i < 1000; i++)
   8991             log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
   8992         lines += 1000;
   8993     }
   8994     ImGui::BeginChild("Log");
   8995     switch (test_type)
   8996     {
   8997     case 0:
   8998         // Single call to TextUnformatted() with a big buffer
   8999         ImGui::TextUnformatted(log.begin(), log.end());
   9000         break;
   9001     case 1:
   9002         {
   9003             // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
   9004             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
   9005             ImGuiListClipper clipper;
   9006             clipper.Begin(lines);
   9007             while (clipper.Step())
   9008                 for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
   9009                     ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
   9010             ImGui::PopStyleVar();
   9011             break;
   9012         }
   9013     case 2:
   9014         // Multiple calls to Text(), not clipped (slow)
   9015         ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
   9016         for (int i = 0; i < lines; i++)
   9017             ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
   9018         ImGui::PopStyleVar();
   9019         break;
   9020     }
   9021     ImGui::EndChild();
   9022     ImGui::End();
   9023 }
   9024 
   9025 //-----------------------------------------------------------------------------
   9026 // [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
   9027 //-----------------------------------------------------------------------------
   9028 
   9029 // Demonstrate creating a window which gets auto-resized according to its content.
   9030 static void ShowExampleAppAutoResize(bool* p_open)
   9031 {
   9032     if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
   9033     {
   9034         ImGui::End();
   9035         return;
   9036     }
   9037     IMGUI_DEMO_MARKER("Examples/Auto-resizing window");
   9038 
   9039     static int lines = 10;
   9040     ImGui::TextUnformatted(
   9041         "Window will resize every-frame to the size of its content.\n"
   9042         "Note that you probably don't want to query the window size to\n"
   9043         "output your content because that would create a feedback loop.");
   9044     ImGui::SliderInt("Number of lines", &lines, 1, 20);
   9045     for (int i = 0; i < lines; i++)
   9046         ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
   9047     ImGui::End();
   9048 }
   9049 
   9050 //-----------------------------------------------------------------------------
   9051 // [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
   9052 //-----------------------------------------------------------------------------
   9053 
   9054 // Demonstrate creating a window with custom resize constraints.
   9055 // Note that size constraints currently don't work on a docked window (when in 'docking' branch)
   9056 static void ShowExampleAppConstrainedResize(bool* p_open)
   9057 {
   9058     struct CustomConstraints
   9059     {
   9060         // Helper functions to demonstrate programmatic constraints
   9061         // FIXME: This doesn't take account of decoration size (e.g. title bar), library should make this easier.
   9062         // FIXME: None of the three demos works consistently when resizing from borders.
   9063         static void AspectRatio(ImGuiSizeCallbackData* data)
   9064         {
   9065             float aspect_ratio = *(float*)data->UserData;
   9066             data->DesiredSize.y = (float)(int)(data->DesiredSize.x / aspect_ratio);
   9067         }
   9068         static void Square(ImGuiSizeCallbackData* data)
   9069         {
   9070             data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y);
   9071         }
   9072         static void Step(ImGuiSizeCallbackData* data)
   9073         {
   9074             float step = *(float*)data->UserData;
   9075             data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step);
   9076         }
   9077     };
   9078 
   9079     const char* test_desc[] =
   9080     {
   9081         "Between 100x100 and 500x500",
   9082         "At least 100x100",
   9083         "Resize vertical + lock current width",
   9084         "Resize horizontal + lock current height",
   9085         "Width Between 400 and 500",
   9086         "Height at least 400",
   9087         "Custom: Aspect Ratio 16:9",
   9088         "Custom: Always Square",
   9089         "Custom: Fixed Steps (100)",
   9090     };
   9091 
   9092     // Options
   9093     static bool auto_resize = false;
   9094     static bool window_padding = true;
   9095     static int type = 6; // Aspect Ratio
   9096     static int display_lines = 10;
   9097 
   9098     // Submit constraint
   9099     float aspect_ratio = 16.0f / 9.0f;
   9100     float fixed_step = 100.0f;
   9101     if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(500, 500));         // Between 100x100 and 500x500
   9102     if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
   9103     if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Resize vertical + lock current width
   9104     if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Resize horizontal + lock current height
   9105     if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width Between and 400 and 500
   9106     if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, FLT_MAX));      // Height at least 400
   9107     if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::AspectRatio, (void*)&aspect_ratio);   // Aspect ratio
   9108     if (type == 7) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);                              // Always Square
   9109     if (type == 8) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)&fixed_step);            // Fixed Step
   9110 
   9111     // Submit window
   9112     if (!window_padding)
   9113         ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
   9114     const ImGuiWindowFlags window_flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
   9115     const bool window_open = ImGui::Begin("Example: Constrained Resize", p_open, window_flags);
   9116     if (!window_padding)
   9117         ImGui::PopStyleVar();
   9118     if (window_open)
   9119     {
   9120         IMGUI_DEMO_MARKER("Examples/Constrained Resizing window");
   9121         if (ImGui::GetIO().KeyShift)
   9122         {
   9123             // Display a dummy viewport (in your real app you would likely use ImageButton() to display a texture.
   9124             ImVec2 avail_size = ImGui::GetContentRegionAvail();
   9125             ImVec2 pos = ImGui::GetCursorScreenPos();
   9126             ImGui::ColorButton("viewport", ImVec4(0.5f, 0.2f, 0.5f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, avail_size);
   9127             ImGui::SetCursorScreenPos(ImVec2(pos.x + 10, pos.y + 10));
   9128             ImGui::Text("%.2f x %.2f", avail_size.x, avail_size.y);
   9129         }
   9130         else
   9131         {
   9132             ImGui::Text("(Hold SHIFT to display a dummy viewport)");
   9133             if (ImGui::Button("Set 200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
   9134             if (ImGui::Button("Set 500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
   9135             if (ImGui::Button("Set 800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
   9136             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
   9137             ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
   9138             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
   9139             ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
   9140             ImGui::Checkbox("Auto-resize", &auto_resize);
   9141             ImGui::Checkbox("Window padding", &window_padding);
   9142             for (int i = 0; i < display_lines; i++)
   9143                 ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
   9144         }
   9145     }
   9146     ImGui::End();
   9147 }
   9148 
   9149 //-----------------------------------------------------------------------------
   9150 // [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
   9151 //-----------------------------------------------------------------------------
   9152 
   9153 // Demonstrate creating a simple static window with no decoration
   9154 // + a context-menu to choose which corner of the screen to use.
   9155 static void ShowExampleAppSimpleOverlay(bool* p_open)
   9156 {
   9157     static int location = 0;
   9158     ImGuiIO& io = ImGui::GetIO();
   9159     ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
   9160     if (location >= 0)
   9161     {
   9162         const float PAD = 10.0f;
   9163         const ImGuiViewport* viewport = ImGui::GetMainViewport();
   9164         ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
   9165         ImVec2 work_size = viewport->WorkSize;
   9166         ImVec2 window_pos, window_pos_pivot;
   9167         window_pos.x = (location & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
   9168         window_pos.y = (location & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
   9169         window_pos_pivot.x = (location & 1) ? 1.0f : 0.0f;
   9170         window_pos_pivot.y = (location & 2) ? 1.0f : 0.0f;
   9171         ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
   9172         window_flags |= ImGuiWindowFlags_NoMove;
   9173     }
   9174     else if (location == -2)
   9175     {
   9176         // Center window
   9177         ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
   9178         window_flags |= ImGuiWindowFlags_NoMove;
   9179     }
   9180     ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
   9181     if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
   9182     {
   9183         IMGUI_DEMO_MARKER("Examples/Simple Overlay");
   9184         ImGui::Text("Simple overlay\n" "(right-click to change position)");
   9185         ImGui::Separator();
   9186         if (ImGui::IsMousePosValid())
   9187             ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
   9188         else
   9189             ImGui::Text("Mouse Position: <invalid>");
   9190         if (ImGui::BeginPopupContextWindow())
   9191         {
   9192             if (ImGui::MenuItem("Custom",       NULL, location == -1)) location = -1;
   9193             if (ImGui::MenuItem("Center",       NULL, location == -2)) location = -2;
   9194             if (ImGui::MenuItem("Top-left",     NULL, location == 0)) location = 0;
   9195             if (ImGui::MenuItem("Top-right",    NULL, location == 1)) location = 1;
   9196             if (ImGui::MenuItem("Bottom-left",  NULL, location == 2)) location = 2;
   9197             if (ImGui::MenuItem("Bottom-right", NULL, location == 3)) location = 3;
   9198             if (p_open && ImGui::MenuItem("Close")) *p_open = false;
   9199             ImGui::EndPopup();
   9200         }
   9201     }
   9202     ImGui::End();
   9203 }
   9204 
   9205 //-----------------------------------------------------------------------------
   9206 // [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
   9207 //-----------------------------------------------------------------------------
   9208 
   9209 // Demonstrate creating a window covering the entire screen/viewport
   9210 static void ShowExampleAppFullscreen(bool* p_open)
   9211 {
   9212     static bool use_work_area = true;
   9213     static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
   9214 
   9215     // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
   9216     // Based on your use case you may want one or the other.
   9217     const ImGuiViewport* viewport = ImGui::GetMainViewport();
   9218     ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
   9219     ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
   9220 
   9221     if (ImGui::Begin("Example: Fullscreen window", p_open, flags))
   9222     {
   9223         ImGui::Checkbox("Use work area instead of main area", &use_work_area);
   9224         ImGui::SameLine();
   9225         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.");
   9226 
   9227         ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground);
   9228         ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration);
   9229         ImGui::Indent();
   9230         ImGui::CheckboxFlags("ImGuiWindowFlags_NoTitleBar", &flags, ImGuiWindowFlags_NoTitleBar);
   9231         ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse);
   9232         ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar);
   9233         ImGui::Unindent();
   9234 
   9235         if (p_open && ImGui::Button("Close this window"))
   9236             *p_open = false;
   9237     }
   9238     ImGui::End();
   9239 }
   9240 
   9241 //-----------------------------------------------------------------------------
   9242 // [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
   9243 //-----------------------------------------------------------------------------
   9244 
   9245 // Demonstrate the use of "##" and "###" in identifiers to manipulate ID generation.
   9246 // This applies to all regular items as well.
   9247 // Read FAQ section "How can I have multiple widgets with the same label?" for details.
   9248 static void ShowExampleAppWindowTitles(bool*)
   9249 {
   9250     const ImGuiViewport* viewport = ImGui::GetMainViewport();
   9251     const ImVec2 base_pos = viewport->Pos;
   9252 
   9253     // By default, Windows are uniquely identified by their title.
   9254     // You can use the "##" and "###" markers to manipulate the display/ID.
   9255 
   9256     // Using "##" to display same title but have unique identifier.
   9257     ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 100), ImGuiCond_FirstUseEver);
   9258     ImGui::Begin("Same title as another window##1");
   9259     IMGUI_DEMO_MARKER("Examples/Manipulating window titles");
   9260     ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
   9261     ImGui::End();
   9262 
   9263     ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 200), ImGuiCond_FirstUseEver);
   9264     ImGui::Begin("Same title as another window##2");
   9265     ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
   9266     ImGui::End();
   9267 
   9268     // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
   9269     char buf[128];
   9270     sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
   9271     ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 300), ImGuiCond_FirstUseEver);
   9272     ImGui::Begin(buf);
   9273     ImGui::Text("This window has a changing title.");
   9274     ImGui::End();
   9275 }
   9276 
   9277 //-----------------------------------------------------------------------------
   9278 // [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
   9279 //-----------------------------------------------------------------------------
   9280 
   9281 // Add a |_| looking shape
   9282 static void PathConcaveShape(ImDrawList* draw_list, float x, float y, float sz)
   9283 {
   9284     const ImVec2 pos_norms[] = { { 0.0f, 0.0f }, { 0.3f, 0.0f }, { 0.3f, 0.7f }, { 0.7f, 0.7f }, { 0.7f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } };
   9285     for (const ImVec2& p : pos_norms)
   9286         draw_list->PathLineTo(ImVec2(x + 0.5f + (int)(sz * p.x), y + 0.5f + (int)(sz * p.y)));
   9287 }
   9288 
   9289 // Demonstrate using the low-level ImDrawList to draw custom shapes.
   9290 static void ShowExampleAppCustomRendering(bool* p_open)
   9291 {
   9292     if (!ImGui::Begin("Example: Custom rendering", p_open))
   9293     {
   9294         ImGui::End();
   9295         return;
   9296     }
   9297     IMGUI_DEMO_MARKER("Examples/Custom Rendering");
   9298 
   9299     // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of
   9300     // overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your
   9301     // types and ImVec2/ImVec4. Dear ImGui defines overloaded operators but they are internal to imgui.cpp and not
   9302     // exposed outside (to avoid messing with your types) In this example we are not using the maths operators!
   9303 
   9304     if (ImGui::BeginTabBar("##TabBar"))
   9305     {
   9306         if (ImGui::BeginTabItem("Primitives"))
   9307         {
   9308             ImGui::PushItemWidth(-ImGui::GetFontSize() * 15);
   9309             ImDrawList* draw_list = ImGui::GetWindowDrawList();
   9310 
   9311             // Draw gradients
   9312             // (note that those are currently exacerbating our sRGB/Linear issues)
   9313             // Calling ImGui::GetColorU32() multiplies the given colors by the current Style Alpha, but you may pass the IM_COL32() directly as well..
   9314             ImGui::Text("Gradients");
   9315             ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight());
   9316             {
   9317                 ImVec2 p0 = ImGui::GetCursorScreenPos();
   9318                 ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
   9319                 ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255));
   9320                 ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255));
   9321                 draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
   9322                 ImGui::InvisibleButton("##gradient1", gradient_size);
   9323             }
   9324             {
   9325                 ImVec2 p0 = ImGui::GetCursorScreenPos();
   9326                 ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
   9327                 ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255));
   9328                 ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255));
   9329                 draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
   9330                 ImGui::InvisibleButton("##gradient2", gradient_size);
   9331             }
   9332 
   9333             // Draw a bunch of primitives
   9334             ImGui::Text("All primitives");
   9335             static float sz = 36.0f;
   9336             static float thickness = 3.0f;
   9337             static int ngon_sides = 6;
   9338             static bool circle_segments_override = false;
   9339             static int circle_segments_override_v = 12;
   9340             static bool curve_segments_override = false;
   9341             static int curve_segments_override_v = 8;
   9342             static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
   9343             ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 100.0f, "%.0f");
   9344             ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
   9345             ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
   9346             ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
   9347             ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
   9348             circle_segments_override |= ImGui::SliderInt("Circle segments override", &circle_segments_override_v, 3, 40);
   9349             ImGui::Checkbox("##curvessegmentoverride", &curve_segments_override);
   9350             ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
   9351             curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 40);
   9352             ImGui::ColorEdit4("Color", &colf.x);
   9353 
   9354             const ImVec2 p = ImGui::GetCursorScreenPos();
   9355             const ImU32 col = ImColor(colf);
   9356             const float spacing = 10.0f;
   9357             const ImDrawFlags corners_tl_br = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomRight;
   9358             const float rounding = sz / 5.0f;
   9359             const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
   9360             const int curve_segments = curve_segments_override ? curve_segments_override_v : 0;
   9361             const ImVec2 cp3[3] = { ImVec2(0.0f, sz * 0.6f), ImVec2(sz * 0.5f, -sz * 0.4f), ImVec2(sz, sz) }; // Control points for curves
   9362             const ImVec2 cp4[4] = { ImVec2(0.0f, 0.0f), ImVec2(sz * 1.3f, sz * 0.3f), ImVec2(sz - sz * 1.3f, sz - sz * 0.3f), ImVec2(sz, sz) };
   9363 
   9364             float x = p.x + 4.0f;
   9365             float y = p.y + 4.0f;
   9366             for (int n = 0; n < 2; n++)
   9367             {
   9368                 // First line uses a thickness of 1.0f, second line uses the configurable thickness
   9369                 float th = (n == 0) ? 1.0f : thickness;
   9370                 draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th);                 x += sz + spacing;  // N-gon
   9371                 draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th);          x += sz + spacing;  // Circle
   9372                 draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing;	// Ellipse
   9373                 draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th);          x += sz + spacing;  // Square
   9374                 draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th);      x += sz + spacing;  // Square with all rounded corners
   9375                 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
   9376                 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
   9377                 //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
   9378                 PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th);          x += sz + spacing;  // Concave Shape
   9379                 //draw_list->AddPolyline(concave_shape, IM_ARRAYSIZE(concave_shape), col, ImDrawFlags_Closed, th);
   9380                 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!)
   9381                 draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th);                                       x += spacing;       // Vertical line (note: drawing a filled rectangle will be faster!)
   9382                 draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th);                                  x += sz + spacing;  // Diagonal line
   9383 
   9384                 // Path
   9385                 draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f);
   9386                 draw_list->PathStroke(col, ImDrawFlags_None, th);
   9387                 x += sz + spacing;
   9388 
   9389                 // Quadratic Bezier Curve (3 control points)
   9390                 draw_list->AddBezierQuadratic(ImVec2(x + cp3[0].x, y + cp3[0].y), ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), col, th, curve_segments);
   9391                 x += sz + spacing;
   9392 
   9393                 // Cubic Bezier Curve (4 control points)
   9394                 draw_list->AddBezierCubic(ImVec2(x + cp4[0].x, y + cp4[0].y), ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), col, th, curve_segments);
   9395 
   9396                 x = p.x + 4;
   9397                 y += sz + spacing;
   9398             }
   9399 
   9400             // Filled shapes
   9401             draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides);             x += sz + spacing;  // N-gon
   9402             draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments);      x += sz + spacing;  // Circle
   9403             draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), ImVec2(sz * 0.5f, sz * 0.3f), col, -0.3f, circle_segments); x += sz + spacing;// Ellipse
   9404             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col);                                    x += sz + spacing;  // Square
   9405             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f);                             x += sz + spacing;  // Square with all rounded corners
   9406             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
   9407             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
   9408             //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
   9409             PathConcaveShape(draw_list, x, y, sz); draw_list->PathFillConcave(col);                                 x += sz + spacing;  // Concave shape
   9410             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)
   9411             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)
   9412             draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col);                                      x += sz;            // Pixel (faster than AddLine)
   9413 
   9414             // Path
   9415             draw_list->PathArcTo(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, 3.141592f * -0.5f, 3.141592f);
   9416             draw_list->PathFillConvex(col);
   9417             x += sz + spacing;
   9418 
   9419             // Quadratic Bezier Curve (3 control points)
   9420             draw_list->PathLineTo(ImVec2(x + cp3[0].x, y + cp3[0].y));
   9421             draw_list->PathBezierQuadraticCurveTo(ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), curve_segments);
   9422             draw_list->PathFillConvex(col);
   9423             x += sz + spacing;
   9424 
   9425             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));
   9426             x += sz + spacing;
   9427 
   9428             ImGui::Dummy(ImVec2((sz + spacing) * 13.2f, (sz + spacing) * 3.0f));
   9429             ImGui::PopItemWidth();
   9430             ImGui::EndTabItem();
   9431         }
   9432 
   9433         if (ImGui::BeginTabItem("Canvas"))
   9434         {
   9435             static ImVector<ImVec2> points;
   9436             static ImVec2 scrolling(0.0f, 0.0f);
   9437             static bool opt_enable_grid = true;
   9438             static bool opt_enable_context_menu = true;
   9439             static bool adding_line = false;
   9440 
   9441             ImGui::Checkbox("Enable grid", &opt_enable_grid);
   9442             ImGui::Checkbox("Enable context menu", &opt_enable_context_menu);
   9443             ImGui::Text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.");
   9444 
   9445             // Typically you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling.
   9446             // Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls.
   9447             // To use a child window instead we could use, e.g:
   9448             //      ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));      // Disable padding
   9449             //      ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255));  // Set a background color
   9450             //      ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Border, ImGuiWindowFlags_NoMove);
   9451             //      ImGui::PopStyleColor();
   9452             //      ImGui::PopStyleVar();
   9453             //      [...]
   9454             //      ImGui::EndChild();
   9455 
   9456             // Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive()
   9457             ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();      // ImDrawList API uses screen coordinates!
   9458             ImVec2 canvas_sz = ImGui::GetContentRegionAvail();   // Resize canvas to what's available
   9459             if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
   9460             if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f;
   9461             ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
   9462 
   9463             // Draw border and background color
   9464             ImGuiIO& io = ImGui::GetIO();
   9465             ImDrawList* draw_list = ImGui::GetWindowDrawList();
   9466             draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
   9467             draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
   9468 
   9469             // This will catch our interactions
   9470             ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
   9471             const bool is_hovered = ImGui::IsItemHovered(); // Hovered
   9472             const bool is_active = ImGui::IsItemActive();   // Held
   9473             const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y); // Lock scrolled origin
   9474             const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
   9475 
   9476             // Add first and second point
   9477             if (is_hovered && !adding_line && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
   9478             {
   9479                 points.push_back(mouse_pos_in_canvas);
   9480                 points.push_back(mouse_pos_in_canvas);
   9481                 adding_line = true;
   9482             }
   9483             if (adding_line)
   9484             {
   9485                 points.back() = mouse_pos_in_canvas;
   9486                 if (!ImGui::IsMouseDown(ImGuiMouseButton_Left))
   9487                     adding_line = false;
   9488             }
   9489 
   9490             // Pan (we use a zero mouse threshold when there's no context menu)
   9491             // You may decide to make that threshold dynamic based on whether the mouse is hovering something etc.
   9492             const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
   9493             if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan))
   9494             {
   9495                 scrolling.x += io.MouseDelta.x;
   9496                 scrolling.y += io.MouseDelta.y;
   9497             }
   9498 
   9499             // Context menu (under default mouse threshold)
   9500             ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
   9501             if (opt_enable_context_menu && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
   9502                 ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
   9503             if (ImGui::BeginPopup("context"))
   9504             {
   9505                 if (adding_line)
   9506                     points.resize(points.size() - 2);
   9507                 adding_line = false;
   9508                 if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) { points.resize(points.size() - 2); }
   9509                 if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) { points.clear(); }
   9510                 ImGui::EndPopup();
   9511             }
   9512 
   9513             // Draw grid + all lines in the canvas
   9514             draw_list->PushClipRect(canvas_p0, canvas_p1, true);
   9515             if (opt_enable_grid)
   9516             {
   9517                 const float GRID_STEP = 64.0f;
   9518                 for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
   9519                     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));
   9520                 for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
   9521                     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));
   9522             }
   9523             for (int n = 0; n < points.Size; n += 2)
   9524                 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);
   9525             draw_list->PopClipRect();
   9526 
   9527             ImGui::EndTabItem();
   9528         }
   9529 
   9530         if (ImGui::BeginTabItem("BG/FG draw lists"))
   9531         {
   9532             static bool draw_bg = true;
   9533             static bool draw_fg = true;
   9534             ImGui::Checkbox("Draw in Background draw list", &draw_bg);
   9535             ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows.");
   9536             ImGui::Checkbox("Draw in Foreground draw list", &draw_fg);
   9537             ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows.");
   9538             ImVec2 window_pos = ImGui::GetWindowPos();
   9539             ImVec2 window_size = ImGui::GetWindowSize();
   9540             ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
   9541             if (draw_bg)
   9542                 ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4);
   9543             if (draw_fg)
   9544                 ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10);
   9545             ImGui::EndTabItem();
   9546         }
   9547 
   9548         // Demonstrate out-of-order rendering via channels splitting
   9549         // We use functions in ImDrawList as each draw list contains a convenience splitter,
   9550         // but you can also instantiate your own ImDrawListSplitter if you need to nest them.
   9551         if (ImGui::BeginTabItem("Draw Channels"))
   9552         {
   9553             ImDrawList* draw_list = ImGui::GetWindowDrawList();
   9554             {
   9555                 ImGui::Text("Blue shape is drawn first: appears in back");
   9556                 ImGui::Text("Red shape is drawn after: appears in front");
   9557                 ImVec2 p0 = ImGui::GetCursorScreenPos();
   9558                 draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50), IM_COL32(0, 0, 255, 255)); // Blue
   9559                 draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25), ImVec2(p0.x + 75, p0.y + 75), IM_COL32(255, 0, 0, 255)); // Red
   9560                 ImGui::Dummy(ImVec2(75, 75));
   9561             }
   9562             ImGui::Separator();
   9563             {
   9564                 ImGui::Text("Blue shape is drawn first, into channel 1: appears in front");
   9565                 ImGui::Text("Red shape is drawn after, into channel 0: appears in back");
   9566                 ImVec2 p1 = ImGui::GetCursorScreenPos();
   9567 
   9568                 // Create 2 channels and draw a Blue shape THEN a Red shape.
   9569                 // You can create any number of channels. Tables API use 1 channel per column in order to better batch draw calls.
   9570                 draw_list->ChannelsSplit(2);
   9571                 draw_list->ChannelsSetCurrent(1);
   9572                 draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50), IM_COL32(0, 0, 255, 255)); // Blue
   9573                 draw_list->ChannelsSetCurrent(0);
   9574                 draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25), ImVec2(p1.x + 75, p1.y + 75), IM_COL32(255, 0, 0, 255)); // Red
   9575 
   9576                 // Flatten/reorder channels. Red shape is in channel 0 and it appears below the Blue shape in channel 1.
   9577                 // This works by copying draw indices only (vertices are not copied).
   9578                 draw_list->ChannelsMerge();
   9579                 ImGui::Dummy(ImVec2(75, 75));
   9580                 ImGui::Text("After reordering, contents of channel 0 appears below channel 1.");
   9581             }
   9582             ImGui::EndTabItem();
   9583         }
   9584 
   9585         ImGui::EndTabBar();
   9586     }
   9587 
   9588     ImGui::End();
   9589 }
   9590 
   9591 //-----------------------------------------------------------------------------
   9592 // [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
   9593 //-----------------------------------------------------------------------------
   9594 
   9595 // Simplified structure to mimic a Document model
   9596 struct MyDocument
   9597 {
   9598     char        Name[32];   // Document title
   9599     int         UID;        // Unique ID (necessary as we can change title)
   9600     bool        Open;       // Set when open (we keep an array of all available documents to simplify demo code!)
   9601     bool        OpenPrev;   // Copy of Open from last update.
   9602     bool        Dirty;      // Set when the document has been modified
   9603     ImVec4      Color;      // An arbitrary variable associated to the document
   9604 
   9605     MyDocument(int uid, const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
   9606     {
   9607         UID = uid;
   9608         snprintf(Name, sizeof(Name), "%s", name);
   9609         Open = OpenPrev = open;
   9610         Dirty = false;
   9611         Color = color;
   9612     }
   9613     void DoOpen()       { Open = true; }
   9614     void DoForceClose() { Open = false; Dirty = false; }
   9615     void DoSave()       { Dirty = false; }
   9616 };
   9617 
   9618 struct ExampleAppDocuments
   9619 {
   9620     ImVector<MyDocument>    Documents;
   9621     ImVector<MyDocument*>   CloseQueue;
   9622     MyDocument*             RenamingDoc = NULL;
   9623     bool                    RenamingStarted = false;
   9624 
   9625     ExampleAppDocuments()
   9626     {
   9627         Documents.push_back(MyDocument(0, "Lettuce",             true,  ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
   9628         Documents.push_back(MyDocument(1, "Eggplant",            true,  ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
   9629         Documents.push_back(MyDocument(2, "Carrot",              true,  ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
   9630         Documents.push_back(MyDocument(3, "Tomato",              false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
   9631         Documents.push_back(MyDocument(4, "A Rather Long Title", false, ImVec4(0.4f, 0.8f, 0.8f, 1.0f)));
   9632         Documents.push_back(MyDocument(5, "Some Document",       false, ImVec4(0.8f, 0.8f, 1.0f, 1.0f)));
   9633     }
   9634 
   9635     // As we allow to change document name, we append a never-changing document ID so tabs are stable
   9636     void GetTabName(MyDocument* doc, char* out_buf, size_t out_buf_size)
   9637     {
   9638         snprintf(out_buf, out_buf_size, "%s###doc%d", doc->Name, doc->UID);
   9639     }
   9640 
   9641     // Display placeholder contents for the Document
   9642     void DisplayDocContents(MyDocument* doc)
   9643     {
   9644         ImGui::PushID(doc);
   9645         ImGui::Text("Document \"%s\"", doc->Name);
   9646         ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
   9647         ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
   9648         ImGui::PopStyleColor();
   9649 
   9650         ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_R, ImGuiInputFlags_Tooltip);
   9651         if (ImGui::Button("Rename.."))
   9652         {
   9653             RenamingDoc = doc;
   9654             RenamingStarted = true;
   9655         }
   9656         ImGui::SameLine();
   9657 
   9658         ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_M, ImGuiInputFlags_Tooltip);
   9659         if (ImGui::Button("Modify"))
   9660             doc->Dirty = true;
   9661 
   9662         ImGui::SameLine();
   9663         ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, ImGuiInputFlags_Tooltip);
   9664         if (ImGui::Button("Save"))
   9665             doc->DoSave();
   9666 
   9667         ImGui::SameLine();
   9668         ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_W, ImGuiInputFlags_Tooltip);
   9669         if (ImGui::Button("Close"))
   9670             CloseQueue.push_back(doc);
   9671         ImGui::ColorEdit3("color", &doc->Color.x);  // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
   9672         ImGui::PopID();
   9673     }
   9674 
   9675     // Display context menu for the Document
   9676     void DisplayDocContextMenu(MyDocument* doc)
   9677     {
   9678         if (!ImGui::BeginPopupContextItem())
   9679             return;
   9680 
   9681         char buf[256];
   9682         sprintf(buf, "Save %s", doc->Name);
   9683         if (ImGui::MenuItem(buf, "Ctrl+S", false, doc->Open))
   9684             doc->DoSave();
   9685         if (ImGui::MenuItem("Rename...", "Ctrl+R", false, doc->Open))
   9686             RenamingDoc = doc;
   9687         if (ImGui::MenuItem("Close", "Ctrl+W", false, doc->Open))
   9688             CloseQueue.push_back(doc);
   9689         ImGui::EndPopup();
   9690     }
   9691 
   9692     // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
   9693     // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
   9694     // as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
   9695     // 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
   9696     // disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
   9697     // give the impression of a flicker for one frame.
   9698     // We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
   9699     // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
   9700     void NotifyOfDocumentsClosedElsewhere()
   9701     {
   9702         for (MyDocument& doc : Documents)
   9703         {
   9704             if (!doc.Open && doc.OpenPrev)
   9705                 ImGui::SetTabItemClosed(doc.Name);
   9706             doc.OpenPrev = doc.Open;
   9707         }
   9708     }
   9709 };
   9710 
   9711 void ShowExampleAppDocuments(bool* p_open)
   9712 {
   9713     static ExampleAppDocuments app;
   9714 
   9715     // Options
   9716     static bool opt_reorderable = true;
   9717     static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
   9718 
   9719     bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
   9720     if (!window_contents_visible)
   9721     {
   9722         ImGui::End();
   9723         return;
   9724     }
   9725 
   9726     // Menu
   9727     if (ImGui::BeginMenuBar())
   9728     {
   9729         if (ImGui::BeginMenu("File"))
   9730         {
   9731             int open_count = 0;
   9732             for (MyDocument& doc : app.Documents)
   9733                 open_count += doc.Open ? 1 : 0;
   9734 
   9735             if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
   9736             {
   9737                 for (MyDocument& doc : app.Documents)
   9738                     if (!doc.Open && ImGui::MenuItem(doc.Name))
   9739                         doc.DoOpen();
   9740                 ImGui::EndMenu();
   9741             }
   9742             if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
   9743                 for (MyDocument& doc : app.Documents)
   9744                     app.CloseQueue.push_back(&doc);
   9745             if (ImGui::MenuItem("Exit") && p_open)
   9746                 *p_open = false;
   9747             ImGui::EndMenu();
   9748         }
   9749         ImGui::EndMenuBar();
   9750     }
   9751 
   9752     // [Debug] List documents with one checkbox for each
   9753     for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
   9754     {
   9755         MyDocument& doc = app.Documents[doc_n];
   9756         if (doc_n > 0)
   9757             ImGui::SameLine();
   9758         ImGui::PushID(&doc);
   9759         if (ImGui::Checkbox(doc.Name, &doc.Open))
   9760             if (!doc.Open)
   9761                 doc.DoForceClose();
   9762         ImGui::PopID();
   9763     }
   9764 
   9765     ImGui::Separator();
   9766 
   9767     // About the ImGuiWindowFlags_UnsavedDocument / ImGuiTabItemFlags_UnsavedDocument flags.
   9768     // They have multiple effects:
   9769     // - Display a dot next to the title.
   9770     // - Tab is selected when clicking the X close button.
   9771     // - Closure is not assumed (will wait for user to stop submitting the tab).
   9772     //   Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
   9773     //   We need to assume closure by default otherwise waiting for "lack of submission" on the next frame would leave an empty
   9774     //   hole for one-frame, both in the tab-bar and in tab-contents when closing a tab/window.
   9775     //   The rarely used SetTabItemClosed() function is a way to notify of programmatic closure to avoid the one-frame hole.
   9776 
   9777     // Submit Tab Bar and Tabs
   9778     {
   9779         ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
   9780         tab_bar_flags |= ImGuiTabBarFlags_DrawSelectedOverline;
   9781         if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
   9782         {
   9783             if (opt_reorderable)
   9784                 app.NotifyOfDocumentsClosedElsewhere();
   9785 
   9786             // [DEBUG] Stress tests
   9787             //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1;            // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
   9788             //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name);  // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
   9789 
   9790             // Submit Tabs
   9791             for (MyDocument& doc : app.Documents)
   9792             {
   9793                 if (!doc.Open)
   9794                     continue;
   9795 
   9796                 // As we allow to change document name, we append a never-changing document id so tabs are stable
   9797                 char doc_name_buf[64];
   9798                 app.GetTabName(&doc, doc_name_buf, sizeof(doc_name_buf));
   9799                 ImGuiTabItemFlags tab_flags = (doc.Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
   9800                 bool visible = ImGui::BeginTabItem(doc_name_buf, &doc.Open, tab_flags);
   9801 
   9802                 // Cancel attempt to close when unsaved add to save queue so we can display a popup.
   9803                 if (!doc.Open && doc.Dirty)
   9804                 {
   9805                     doc.Open = true;
   9806                     app.CloseQueue.push_back(&doc);
   9807                 }
   9808 
   9809                 app.DisplayDocContextMenu(&doc);
   9810                 if (visible)
   9811                 {
   9812                     app.DisplayDocContents(&doc);
   9813                     ImGui::EndTabItem();
   9814                 }
   9815             }
   9816 
   9817             ImGui::EndTabBar();
   9818         }
   9819     }
   9820 
   9821     // Display renaming UI
   9822     if (app.RenamingDoc != NULL)
   9823     {
   9824         if (app.RenamingStarted)
   9825             ImGui::OpenPopup("Rename");
   9826         if (ImGui::BeginPopup("Rename"))
   9827         {
   9828             ImGui::SetNextItemWidth(ImGui::GetFontSize() * 30);
   9829             if (ImGui::InputText("###Name", app.RenamingDoc->Name, IM_ARRAYSIZE(app.RenamingDoc->Name), ImGuiInputTextFlags_EnterReturnsTrue))
   9830             {
   9831                 ImGui::CloseCurrentPopup();
   9832                 app.RenamingDoc = NULL;
   9833             }
   9834             if (app.RenamingStarted)
   9835                 ImGui::SetKeyboardFocusHere(-1);
   9836             ImGui::EndPopup();
   9837         }
   9838         else
   9839         {
   9840             app.RenamingDoc = NULL;
   9841         }
   9842         app.RenamingStarted = false;
   9843     }
   9844 
   9845     // Display closing confirmation UI
   9846     if (!app.CloseQueue.empty())
   9847     {
   9848         int close_queue_unsaved_documents = 0;
   9849         for (int n = 0; n < app.CloseQueue.Size; n++)
   9850             if (app.CloseQueue[n]->Dirty)
   9851                 close_queue_unsaved_documents++;
   9852 
   9853         if (close_queue_unsaved_documents == 0)
   9854         {
   9855             // Close documents when all are unsaved
   9856             for (int n = 0; n < app.CloseQueue.Size; n++)
   9857                 app.CloseQueue[n]->DoForceClose();
   9858             app.CloseQueue.clear();
   9859         }
   9860         else
   9861         {
   9862             if (!ImGui::IsPopupOpen("Save?"))
   9863                 ImGui::OpenPopup("Save?");
   9864             if (ImGui::BeginPopupModal("Save?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
   9865             {
   9866                 ImGui::Text("Save change to the following items?");
   9867                 float item_height = ImGui::GetTextLineHeightWithSpacing();
   9868                 if (ImGui::BeginChild(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height), ImGuiChildFlags_FrameStyle))
   9869                     for (MyDocument* doc : app.CloseQueue)
   9870                         if (doc->Dirty)
   9871                             ImGui::Text("%s", doc->Name);
   9872                 ImGui::EndChild();
   9873 
   9874                 ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
   9875                 if (ImGui::Button("Yes", button_size))
   9876                 {
   9877                     for (MyDocument* doc : app.CloseQueue)
   9878                     {
   9879                         if (doc->Dirty)
   9880                             doc->DoSave();
   9881                         doc->DoForceClose();
   9882                     }
   9883                     app.CloseQueue.clear();
   9884                     ImGui::CloseCurrentPopup();
   9885                 }
   9886                 ImGui::SameLine();
   9887                 if (ImGui::Button("No", button_size))
   9888                 {
   9889                     for (MyDocument* doc : app.CloseQueue)
   9890                         doc->DoForceClose();
   9891                     app.CloseQueue.clear();
   9892                     ImGui::CloseCurrentPopup();
   9893                 }
   9894                 ImGui::SameLine();
   9895                 if (ImGui::Button("Cancel", button_size))
   9896                 {
   9897                     app.CloseQueue.clear();
   9898                     ImGui::CloseCurrentPopup();
   9899                 }
   9900                 ImGui::EndPopup();
   9901             }
   9902         }
   9903     }
   9904 
   9905     ImGui::End();
   9906 }
   9907 
   9908 //-----------------------------------------------------------------------------
   9909 // [SECTION] Example App: Assets Browser / ShowExampleAppAssetsBrowser()
   9910 //-----------------------------------------------------------------------------
   9911 
   9912 //#include "imgui_internal.h" // NavMoveRequestTryWrapping()
   9913 
   9914 struct ExampleAsset
   9915 {
   9916     ImGuiID ID;
   9917     int     Type;
   9918 
   9919     ExampleAsset(ImGuiID id, int type) { ID = id; Type = type; }
   9920 
   9921     static const ImGuiTableSortSpecs* s_current_sort_specs;
   9922 
   9923     static void SortWithSortSpecs(ImGuiTableSortSpecs* sort_specs, ExampleAsset* items, int items_count)
   9924     {
   9925         s_current_sort_specs = sort_specs; // Store in variable accessible by the sort function.
   9926         if (items_count > 1)
   9927             qsort(items, (size_t)items_count, sizeof(items[0]), ExampleAsset::CompareWithSortSpecs);
   9928         s_current_sort_specs = NULL;
   9929     }
   9930 
   9931     // Compare function to be used by qsort()
   9932     static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs)
   9933     {
   9934         const ExampleAsset* a = (const ExampleAsset*)lhs;
   9935         const ExampleAsset* b = (const ExampleAsset*)rhs;
   9936         for (int n = 0; n < s_current_sort_specs->SpecsCount; n++)
   9937         {
   9938             const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n];
   9939             int delta = 0;
   9940             if (sort_spec->ColumnIndex == 0)
   9941                 delta = ((int)a->ID - (int)b->ID);
   9942             else if (sort_spec->ColumnIndex == 1)
   9943                 delta = (a->Type - b->Type);
   9944             if (delta > 0)
   9945                 return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1;
   9946             if (delta < 0)
   9947                 return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1;
   9948         }
   9949         return ((int)a->ID - (int)b->ID);
   9950     }
   9951 };
   9952 const ImGuiTableSortSpecs* ExampleAsset::s_current_sort_specs = NULL;
   9953 
   9954 struct ExampleAssetsBrowser
   9955 {
   9956     // Options
   9957     bool            ShowTypeOverlay = true;
   9958     bool            AllowSorting = true;
   9959     bool            AllowDragUnselected = false;
   9960     bool            AllowBoxSelect = true;
   9961     float           IconSize = 32.0f;
   9962     int             IconSpacing = 10;
   9963     int             IconHitSpacing = 4;         // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
   9964     bool            StretchSpacing = true;
   9965 
   9966     // State
   9967     ImVector<ExampleAsset> Items;               // Our items
   9968     ExampleSelectionWithDeletion Selection;     // Our selection (ImGuiSelectionBasicStorage + helper funcs to handle deletion)
   9969     ImGuiID         NextItemId = 0;             // Unique identifier when creating new items
   9970     bool            RequestDelete = false;      // Deferred deletion request
   9971     bool            RequestSort = false;        // Deferred sort request
   9972     float           ZoomWheelAccum = 0.0f;      // Mouse wheel accumulator to handle smooth wheels better
   9973 
   9974     // Calculated sizes for layout, output of UpdateLayoutSizes(). Could be locals but our code is simpler this way.
   9975     ImVec2          LayoutItemSize;
   9976     ImVec2          LayoutItemStep;             // == LayoutItemSize + LayoutItemSpacing
   9977     float           LayoutItemSpacing = 0.0f;
   9978     float           LayoutSelectableSpacing = 0.0f;
   9979     float           LayoutOuterPadding = 0.0f;
   9980     int             LayoutColumnCount = 0;
   9981     int             LayoutLineCount = 0;
   9982 
   9983     // Functions
   9984     ExampleAssetsBrowser()
   9985     {
   9986         AddItems(10000);
   9987     }
   9988     void AddItems(int count)
   9989     {
   9990         if (Items.Size == 0)
   9991             NextItemId = 0;
   9992         Items.reserve(Items.Size + count);
   9993         for (int n = 0; n < count; n++, NextItemId++)
   9994             Items.push_back(ExampleAsset(NextItemId, (NextItemId % 20) < 15 ? 0 : (NextItemId % 20) < 18 ? 1 : 2));
   9995         RequestSort = true;
   9996     }
   9997     void ClearItems()
   9998     {
   9999         Items.clear();
  10000         Selection.Clear();
  10001     }
  10002 
  10003     // Logic would be written in the main code BeginChild() and outputing to local variables.
  10004     // We extracted it into a function so we can call it easily from multiple places.
  10005     void UpdateLayoutSizes(float avail_width)
  10006     {
  10007         // Layout: when not stretching: allow extending into right-most spacing.
  10008         LayoutItemSpacing = (float)IconSpacing;
  10009         if (StretchSpacing == false)
  10010             avail_width += floorf(LayoutItemSpacing * 0.5f);
  10011 
  10012         // Layout: calculate number of icon per line and number of lines
  10013         LayoutItemSize = ImVec2(floorf(IconSize), floorf(IconSize));
  10014         LayoutColumnCount = IM_MAX((int)(avail_width / (LayoutItemSize.x + LayoutItemSpacing)), 1);
  10015         LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
  10016 
  10017         // Layout: when stretching: allocate remaining space to more spacing. Round before division, so item_spacing may be non-integer.
  10018         if (StretchSpacing && LayoutColumnCount > 1)
  10019             LayoutItemSpacing = floorf(avail_width - LayoutItemSize.x * LayoutColumnCount) / LayoutColumnCount;
  10020 
  10021         LayoutItemStep = ImVec2(LayoutItemSize.x + LayoutItemSpacing, LayoutItemSize.y + LayoutItemSpacing);
  10022         LayoutSelectableSpacing = IM_MAX(floorf(LayoutItemSpacing) - IconHitSpacing, 0.0f);
  10023         LayoutOuterPadding = floorf(LayoutItemSpacing * 0.5f);
  10024     }
  10025 
  10026     void Draw(const char* title, bool* p_open)
  10027     {
  10028         ImGui::SetNextWindowSize(ImVec2(IconSize * 25, IconSize * 15), ImGuiCond_FirstUseEver);
  10029         if (!ImGui::Begin(title, p_open, ImGuiWindowFlags_MenuBar))
  10030         {
  10031             ImGui::End();
  10032             return;
  10033         }
  10034 
  10035         // Menu bar
  10036         if (ImGui::BeginMenuBar())
  10037         {
  10038             if (ImGui::BeginMenu("File"))
  10039             {
  10040                 if (ImGui::MenuItem("Add 10000 items"))
  10041                     AddItems(10000);
  10042                 if (ImGui::MenuItem("Clear items"))
  10043                     ClearItems();
  10044                 ImGui::Separator();
  10045                 if (ImGui::MenuItem("Close", NULL, false, p_open != NULL))
  10046                     *p_open = false;
  10047                 ImGui::EndMenu();
  10048             }
  10049             if (ImGui::BeginMenu("Edit"))
  10050             {
  10051                 if (ImGui::MenuItem("Delete", "Del", false, Selection.Size > 0))
  10052                     RequestDelete = true;
  10053                 ImGui::EndMenu();
  10054             }
  10055             if (ImGui::BeginMenu("Options"))
  10056             {
  10057                 ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
  10058 
  10059                 ImGui::SeparatorText("Contents");
  10060                 ImGui::Checkbox("Show Type Overlay", &ShowTypeOverlay);
  10061                 ImGui::Checkbox("Allow Sorting", &AllowSorting);
  10062 
  10063                 ImGui::SeparatorText("Selection Behavior");
  10064                 ImGui::Checkbox("Allow dragging unselected item", &AllowDragUnselected);
  10065                 ImGui::Checkbox("Allow box-selection", &AllowBoxSelect);
  10066 
  10067                 ImGui::SeparatorText("Layout");
  10068                 ImGui::SliderFloat("Icon Size", &IconSize, 16.0f, 128.0f, "%.0f");
  10069                 ImGui::SameLine(); HelpMarker("Use CTRL+Wheel to zoom");
  10070                 ImGui::SliderInt("Icon Spacing", &IconSpacing, 0, 32);
  10071                 ImGui::SliderInt("Icon Hit Spacing", &IconHitSpacing, 0, 32);
  10072                 ImGui::Checkbox("Stretch Spacing", &StretchSpacing);
  10073                 ImGui::PopItemWidth();
  10074                 ImGui::EndMenu();
  10075             }
  10076             ImGui::EndMenuBar();
  10077         }
  10078 
  10079         // Show a table with ONLY one header row to showcase the idea/possibility of using this to provide a sorting UI
  10080         if (AllowSorting)
  10081         {
  10082             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
  10083             ImGuiTableFlags table_flags_for_sort_specs = ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Borders;
  10084             if (ImGui::BeginTable("for_sort_specs_only", 2, table_flags_for_sort_specs, ImVec2(0.0f, ImGui::GetFrameHeight())))
  10085             {
  10086                 ImGui::TableSetupColumn("Index");
  10087                 ImGui::TableSetupColumn("Type");
  10088                 ImGui::TableHeadersRow();
  10089                 if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs())
  10090                     if (sort_specs->SpecsDirty || RequestSort)
  10091                     {
  10092                         ExampleAsset::SortWithSortSpecs(sort_specs, Items.Data, Items.Size);
  10093                         sort_specs->SpecsDirty = RequestSort = false;
  10094                     }
  10095                 ImGui::EndTable();
  10096             }
  10097             ImGui::PopStyleVar();
  10098         }
  10099 
  10100         ImGuiIO& io = ImGui::GetIO();
  10101         ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.x + LayoutItemSpacing)));
  10102         if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Border, ImGuiWindowFlags_NoMove))
  10103         {
  10104             ImDrawList* draw_list = ImGui::GetWindowDrawList();
  10105 
  10106             const float avail_width = ImGui::GetContentRegionAvail().x;
  10107             UpdateLayoutSizes(avail_width);
  10108 
  10109             // Calculate and store start position.
  10110             ImVec2 start_pos = ImGui::GetCursorScreenPos();
  10111             start_pos = ImVec2(start_pos.x + LayoutOuterPadding, start_pos.y + LayoutOuterPadding);
  10112             ImGui::SetCursorScreenPos(start_pos);
  10113 
  10114             // Multi-select
  10115             ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_ClearOnClickVoid;
  10116 
  10117             // - Enable box-select (in 2D mode, so that changing box-select rectangle X1/X2 boundaries will affect clipped items)
  10118             if (AllowBoxSelect)
  10119                 ms_flags |= ImGuiMultiSelectFlags_BoxSelect2d;
  10120 
  10121             // - This feature allows dragging an unselected item without selecting it (rarely used)
  10122             if (AllowDragUnselected)
  10123                 ms_flags |= ImGuiMultiSelectFlags_SelectOnClickRelease;
  10124 
  10125             // - Enable keyboard wrapping on X axis
  10126             // (FIXME-MULTISELECT: We haven't designed/exposed a general nav wrapping api yet, so this flag is provided as a courtesy to avoid doing:
  10127             //    ImGui::NavMoveRequestTryWrapping(ImGui::GetCurrentWindow(), ImGuiNavMoveFlags_WrapX);
  10128             // When we finish implementing a more general API for this, we will obsolete this flag in favor of the new system)
  10129             ms_flags |= ImGuiMultiSelectFlags_NavWrapX;
  10130 
  10131             ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, Selection.Size, Items.Size);
  10132 
  10133             // Use custom selection adapter: store ID in selection (recommended)
  10134             Selection.UserData = this;
  10135             Selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self_, int idx) { ExampleAssetsBrowser* self = (ExampleAssetsBrowser*)self_->UserData; return self->Items[idx].ID; };
  10136             Selection.ApplyRequests(ms_io);
  10137 
  10138             const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (Selection.Size > 0)) || RequestDelete;
  10139             const int item_curr_idx_to_focus = want_delete ? Selection.ApplyDeletionPreLoop(ms_io, Items.Size) : -1;
  10140             RequestDelete = false;
  10141 
  10142             // Push LayoutSelectableSpacing (which is LayoutItemSpacing minus hit-spacing, if we decide to have hit gaps between items)
  10143             // Altering style ItemSpacing may seem unnecessary as we position every items using SetCursorScreenPos()...
  10144             // But it is necessary for two reasons:
  10145             // - Selectables uses it by default to visually fill the space between two items.
  10146             // - The vertical spacing would be measured by Clipper to calculate line height if we didn't provide it explicitly (here we do).
  10147             ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(LayoutSelectableSpacing, LayoutSelectableSpacing));
  10148 
  10149             // Rendering parameters
  10150             const ImU32 icon_type_overlay_colors[3] = { 0, IM_COL32(200, 70, 70, 255), IM_COL32(70, 170, 70, 255) };
  10151             const ImU32 icon_bg_color = ImGui::GetColorU32(ImGuiCol_MenuBarBg);
  10152             const ImVec2 icon_type_overlay_size = ImVec2(4.0f, 4.0f);
  10153             const bool display_label = (LayoutItemSize.x >= ImGui::CalcTextSize("999").x);
  10154 
  10155             const int column_count = LayoutColumnCount;
  10156             ImGuiListClipper clipper;
  10157             clipper.Begin(LayoutLineCount, LayoutItemStep.y);
  10158             if (item_curr_idx_to_focus != -1)
  10159                 clipper.IncludeItemByIndex(item_curr_idx_to_focus / column_count); // Ensure focused item line is not clipped.
  10160             if (ms_io->RangeSrcItem != -1)
  10161                 clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem / column_count); // Ensure RangeSrc item line is not clipped.
  10162             while (clipper.Step())
  10163             {
  10164                 for (int line_idx = clipper.DisplayStart; line_idx < clipper.DisplayEnd; line_idx++)
  10165                 {
  10166                     const int item_min_idx_for_current_line = line_idx * column_count;
  10167                     const int item_max_idx_for_current_line = IM_MIN((line_idx + 1) * column_count, Items.Size);
  10168                     for (int item_idx = item_min_idx_for_current_line; item_idx < item_max_idx_for_current_line; ++item_idx)
  10169                     {
  10170                         ExampleAsset* item_data = &Items[item_idx];
  10171                         ImGui::PushID((int)item_data->ID);
  10172 
  10173                         // Position item
  10174                         ImVec2 pos = ImVec2(start_pos.x + (item_idx % column_count) * LayoutItemStep.x, start_pos.y + line_idx * LayoutItemStep.y);
  10175                         ImGui::SetCursorScreenPos(pos);
  10176 
  10177                         ImGui::SetNextItemSelectionUserData(item_idx);
  10178                         bool item_is_selected = Selection.Contains((ImGuiID)item_data->ID);
  10179                         bool item_is_visible = ImGui::IsRectVisible(LayoutItemSize);
  10180                         ImGui::Selectable("", item_is_selected, ImGuiSelectableFlags_None, LayoutItemSize);
  10181 
  10182                         // Update our selection state immediately (without waiting for EndMultiSelect() requests)
  10183                         // because we use this to alter the color of our text/icon.
  10184                         if (ImGui::IsItemToggledSelection())
  10185                             item_is_selected = !item_is_selected;
  10186 
  10187                         // Focus (for after deletion)
  10188                         if (item_curr_idx_to_focus == item_idx)
  10189                             ImGui::SetKeyboardFocusHere(-1);
  10190 
  10191                         // Drag and drop
  10192                         if (ImGui::BeginDragDropSource())
  10193                         {
  10194                             // Create payload with full selection OR single unselected item.
  10195                             // (the later is only possible when using ImGuiMultiSelectFlags_SelectOnClickRelease)
  10196                             if (ImGui::GetDragDropPayload() == NULL)
  10197                             {
  10198                                 ImVector<ImGuiID> payload_items;
  10199                                 void* it = NULL;
  10200                                 ImGuiID id = 0;
  10201                                 if (!item_is_selected)
  10202                                     payload_items.push_back(item_data->ID);
  10203                                 else
  10204                                     while (Selection.GetNextSelectedItem(&it, &id))
  10205                                         payload_items.push_back(id);
  10206                                 ImGui::SetDragDropPayload("ASSETS_BROWSER_ITEMS", payload_items.Data, (size_t)payload_items.size_in_bytes());
  10207                             }
  10208 
  10209                             // Display payload content in tooltip, by extracting it from the payload data
  10210                             // (we could read from selection, but it is more correct and reusable to read from payload)
  10211                             const ImGuiPayload* payload = ImGui::GetDragDropPayload();
  10212                             const int payload_count = (int)payload->DataSize / (int)sizeof(ImGuiID);
  10213                             ImGui::Text("%d assets", payload_count);
  10214 
  10215                             ImGui::EndDragDropSource();
  10216                         }
  10217 
  10218                         // Render icon (a real app would likely display an image/thumbnail here)
  10219                         // Because we use ImGuiMultiSelectFlags_BoxSelect2d, clipping vertical may occasionally be larger, so we coarse-clip our rendering as well.
  10220                         if (item_is_visible)
  10221                         {
  10222                             ImVec2 box_min(pos.x - 1, pos.y - 1);
  10223                             ImVec2 box_max(box_min.x + LayoutItemSize.x + 2, box_min.y + LayoutItemSize.y + 2); // Dubious
  10224                             draw_list->AddRectFilled(box_min, box_max, icon_bg_color); // Background color
  10225                             if (ShowTypeOverlay && item_data->Type != 0)
  10226                             {
  10227                                 ImU32 type_col = icon_type_overlay_colors[item_data->Type % IM_ARRAYSIZE(icon_type_overlay_colors)];
  10228                                 draw_list->AddRectFilled(ImVec2(box_max.x - 2 - icon_type_overlay_size.x, box_min.y + 2), ImVec2(box_max.x - 2, box_min.y + 2 + icon_type_overlay_size.y), type_col);
  10229                             }
  10230                             if (display_label)
  10231                             {
  10232                                 ImU32 label_col = ImGui::GetColorU32(item_is_selected ? ImGuiCol_Text : ImGuiCol_TextDisabled);
  10233                                 char label[32];
  10234                                 sprintf(label, "%d", item_data->ID);
  10235                                 draw_list->AddText(ImVec2(box_min.x, box_max.y - ImGui::GetFontSize()), label_col, label);
  10236                             }
  10237                         }
  10238 
  10239                         ImGui::PopID();
  10240                     }
  10241                 }
  10242             }
  10243             clipper.End();
  10244             ImGui::PopStyleVar(); // ImGuiStyleVar_ItemSpacing
  10245 
  10246             // Context menu
  10247             if (ImGui::BeginPopupContextWindow())
  10248             {
  10249                 ImGui::Text("Selection: %d items", Selection.Size);
  10250                 ImGui::Separator();
  10251                 if (ImGui::MenuItem("Delete", "Del", false, Selection.Size > 0))
  10252                     RequestDelete = true;
  10253                 ImGui::EndPopup();
  10254             }
  10255 
  10256             ms_io = ImGui::EndMultiSelect();
  10257             Selection.ApplyRequests(ms_io);
  10258             if (want_delete)
  10259                 Selection.ApplyDeletionPostLoop(ms_io, Items, item_curr_idx_to_focus);
  10260 
  10261             // Zooming with CTRL+Wheel
  10262             if (ImGui::IsWindowAppearing())
  10263                 ZoomWheelAccum = 0.0f;
  10264             if (ImGui::IsWindowHovered() && io.MouseWheel != 0.0f && ImGui::IsKeyDown(ImGuiMod_Ctrl) && ImGui::IsAnyItemActive() == false)
  10265             {
  10266                 ZoomWheelAccum += io.MouseWheel;
  10267                 if (fabsf(ZoomWheelAccum) >= 1.0f)
  10268                 {
  10269                     // Calculate hovered item index from mouse location
  10270                     // FIXME: Locking aiming on 'hovered_item_idx' (with a cool-down timer) would ensure zoom keeps on it.
  10271                     const float hovered_item_nx = (io.MousePos.x - start_pos.x + LayoutItemSpacing * 0.5f) / LayoutItemStep.x;
  10272                     const float hovered_item_ny = (io.MousePos.y - start_pos.y + LayoutItemSpacing * 0.5f) / LayoutItemStep.y;
  10273                     const int hovered_item_idx = ((int)hovered_item_ny * LayoutColumnCount) + (int)hovered_item_nx;
  10274                     //ImGui::SetTooltip("%f,%f -> item %d", hovered_item_nx, hovered_item_ny, hovered_item_idx); // Move those 4 lines in block above for easy debugging
  10275 
  10276                     // Zoom
  10277                     IconSize *= powf(1.1f, (float)(int)ZoomWheelAccum);
  10278                     IconSize = IM_CLAMP(IconSize, 16.0f, 128.0f);
  10279                     ZoomWheelAccum -= (int)ZoomWheelAccum;
  10280                     UpdateLayoutSizes(avail_width);
  10281 
  10282                     // Manipulate scroll to that we will land at the same Y location of currently hovered item.
  10283                     // - Calculate next frame position of item under mouse
  10284                     // - Set new scroll position to be used in next ImGui::BeginChild() call.
  10285                     float hovered_item_rel_pos_y = ((float)(hovered_item_idx / LayoutColumnCount) + fmodf(hovered_item_ny, 1.0f)) * LayoutItemStep.y;
  10286                     hovered_item_rel_pos_y += ImGui::GetStyle().WindowPadding.y;
  10287                     float mouse_local_y = io.MousePos.y - ImGui::GetWindowPos().y;
  10288                     ImGui::SetScrollY(hovered_item_rel_pos_y - mouse_local_y);
  10289                 }
  10290             }
  10291         }
  10292         ImGui::EndChild();
  10293 
  10294         ImGui::Text("Selected: %d/%d items", Selection.Size, Items.Size);
  10295         ImGui::End();
  10296     }
  10297 };
  10298 
  10299 void ShowExampleAppAssetsBrowser(bool* p_open)
  10300 {
  10301     IMGUI_DEMO_MARKER("Examples/Assets Browser");
  10302     static ExampleAssetsBrowser assets_browser;
  10303     assets_browser.Draw("Example: Assets Browser", p_open);
  10304 }
  10305 
  10306 // End of Demo code
  10307 #else
  10308 
  10309 void ImGui::ShowAboutWindow(bool*) {}
  10310 void ImGui::ShowDemoWindow(bool*) {}
  10311 void ImGui::ShowUserGuide() {}
  10312 void ImGui::ShowStyleEditor(ImGuiStyle*) {}
  10313 
  10314 #endif
  10315 
  10316 #endif // #ifndef IMGUI_DISABLE