Changeset e66fd66 in opengl-game for IMGUI/imgui_demo.cpp


Ignore:
Timestamp:
Dec 5, 2020, 7:14:31 PM (4 years ago)
Author:
Dmitry Portnoy <dportnoy@…>
Branches:
feature/imgui-sdl, master
Children:
95c657f
Parents:
78c3045
Message:

In OpenGLReference, change all enums to enum classes and update IMGUI to the latest version

File:
1 edited

Legend:

Unmodified
Added
Removed
  • IMGUI/imgui_demo.cpp

    r78c3045 re66fd66  
    1 // dear imgui, v1.61 WIP
     1// dear imgui, v1.79
    22// (demo code)
    33
    4 // Message to the person tempted to delete this file when integrating ImGui into their code base:
    5 // Don't do it! Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to.
     4// Help:
     5// - Read FAQ at http://dearimgui.org/faq
     6// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
     7// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
     8// Read imgui.cpp for more details, documentation and comments.
     9// Get latest version at https://github.com/ocornut/imgui
     10
     11// Message to the person tempted to delete this file when integrating Dear ImGui into their code base:
     12// Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other
     13// coders will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available
     14// debug menu of your game/app! Removing this file from your project is hindering access to documentation for everyone
     15// in your team, likely leading you to poorer usage of the library.
    616// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
    7 // During development, you can call ImGui::ShowDemoWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu!
    8 // Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library.
    9 // Note that you can #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h for the same effect.
    10 // If you want to link core ImGui in your final builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty.
    11 // In other situation, when you have ImGui available you probably want this to be available for reference and execution.
     17// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
     18// linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
     19// In other situation, whenever you have Dear ImGui available you probably want this to be available for reference.
    1220// Thank you,
    13 // -Your beloved friend, imgui_demo.cpp (that you won't delete)
    14 
    15 // Message to beginner C/C++ programmers. About the meaning of 'static': in this demo code, we frequently we use 'static' variables inside functions.
    16 // We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code.
    17 // A static variable persist across calls, so it is essentially like a global variable but declared inside the scope of the function.
    18 // It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads.
    19 // This might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your function.
     21// -Your beloved friend, imgui_demo.cpp (which you won't delete)
     22
     23// Message to beginner C/C++ programmers about the meaning of the 'static' keyword:
     24// In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls,
     25// so it is essentially like a global variable but declared inside the scope of the function. We do this as a way to
     26// gather code and data in the same place, to make the demo source code faster to read, faster to write, and smaller
     27// in size. It also happens to be a convenient way of storing simple UI related information as long as your function
     28// doesn't need to be reentrant or used in multiple threads. This might be a pattern you will want to use in your code,
     29// but most of the real data you would be editing is likely going to be stored outside your functions.
     30
     31// The Demo code in this file is designed to be easy to copy-and-paste in into your application!
     32// Because of this:
     33// - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
     34// - We try to declare static variables in the local scope, as close as possible to the code using them.
     35// - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
     36// - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
     37//   by imgui_internal.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
     38//   and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
     39//   Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
     40
     41/*
     42
     43Index of this file:
     44
     45// [SECTION] Forward Declarations, Helpers
     46// [SECTION] Demo Window / ShowDemoWindow()
     47// [SECTION] About Window / ShowAboutWindow()
     48// [SECTION] Style Editor / ShowStyleEditor()
     49// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
     50// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
     51// [SECTION] Example App: Debug Log / ShowExampleAppLog()
     52// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
     53// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
     54// [SECTION] Example App: Long Text / ShowExampleAppLongText()
     55// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
     56// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
     57// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
     58// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
     59// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
     60// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
     61
     62*/
    2063
    2164#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
     
    2467
    2568#include "imgui.h"
    26 #include <ctype.h>          // toupper, isprint
     69#ifndef IMGUI_DISABLE
     70
     71#include <ctype.h>          // toupper
     72#include <limits.h>         // INT_MIN, INT_MAX
    2773#include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
    2874#include <stdio.h>          // vsnprintf, sscanf, printf
     
    3480#endif
    3581
     82// Visual Studio warnings
    3683#ifdef _MSC_VER
    3784#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
    38 #define snprintf _snprintf
    3985#endif
    40 #ifdef __clang__
    41 #pragma clang diagnostic ignored "-Wold-style-cast"             // warning : use of old-style cast                              // yes, they are more terse.
    42 #pragma clang diagnostic ignored "-Wdeprecated-declarations"    // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
    43 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"   // warning : cast to 'void *' from smaller integer type 'int'
    44 #pragma clang diagnostic ignored "-Wformat-security"            // warning : warning: format string is not a string literal
    45 #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.
    46 #if __has_warning("-Wreserved-id-macro")
    47 #pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                //
     86
     87// Clang/GCC warnings with -Weverything
     88#if defined(__clang__)
     89#if __has_warning("-Wunknown-warning-option")
     90#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!
    4891#endif
     92#pragma clang diagnostic ignored "-Wunknown-pragmas"                // warning: unknown warning group 'xxx'
     93#pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast                           // yes, they are more terse.
     94#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)
     95#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"       // warning: cast to 'void *' from smaller integer type
     96#pragma clang diagnostic ignored "-Wformat-security"                // warning: format string is not a string literal
     97#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.
     98#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.
     99#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant                   // some standard header variations use #define NULL 0
     100#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.
     101#pragma clang diagnostic ignored "-Wreserved-id-macro"              // warning: macro name is a reserved identifier
     102#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
    49103#elif defined(__GNUC__)
    50 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"          // warning: cast to pointer from integer of different size
    51 #pragma GCC diagnostic ignored "-Wformat-security"              // warning : format string is not a string literal (potentially insecure)
    52 #pragma GCC diagnostic ignored "-Wdouble-promotion"             // warning: implicit conversion from 'float' to 'double' when passing argument to function
    53 #pragma GCC diagnostic ignored "-Wconversion"                   // warning: conversion to 'xxxx' from 'xxxx' may alter its value
    54 #if (__GNUC__ >= 6)
    55 #pragma GCC diagnostic ignored "-Wmisleading-indentation"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
     104#pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
     105#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
     106#pragma GCC diagnostic ignored "-Wformat-security"          // warning: format string is not a string literal (potentially insecure)
     107#pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
     108#pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
     109#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.
    56110#endif
     111
     112// Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
     113#ifdef _WIN32
     114#define IM_NEWLINE  "\r\n"
     115#else
     116#define IM_NEWLINE  "\n"
    57117#endif
    58118
    59 // Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n.
    60 #ifdef _WIN32
    61 #define IM_NEWLINE "\r\n"
    62 #else
    63 #define IM_NEWLINE "\n"
     119// Helpers
     120#if defined(_MSC_VER) && !defined(snprintf)
     121#define snprintf    _snprintf
    64122#endif
    65 
    66 #define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))
     123#if defined(_MSC_VER) && !defined(vsnprintf)
     124#define vsnprintf   _vsnprintf
     125#endif
     126
     127// Helpers macros
     128// We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
     129// but making an exception here as those are largely simplifying code...
     130// In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo.
     131#define IM_MIN(A, B)            (((A) < (B)) ? (A) : (B))
     132#define IM_MAX(A, B)            (((A) >= (B)) ? (A) : (B))
     133#define IM_CLAMP(V, MN, MX)     ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
    67134
    68135//-----------------------------------------------------------------------------
    69 // DEMO CODE
     136// [SECTION] Forward Declarations, Helpers
    70137//-----------------------------------------------------------------------------
    71138
    72 #if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS)   // Obsolete name since 1.53, TEST->DEMO
    73 #define IMGUI_DISABLE_DEMO_WINDOWS
    74 #endif
    75 
    76139#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
    77140
     141// Forward Declarations
     142static void ShowExampleAppDocuments(bool* p_open);
     143static void ShowExampleAppMainMenuBar();
    78144static void ShowExampleAppConsole(bool* p_open);
    79145static void ShowExampleAppLog(bool* p_open);
     
    83149static void ShowExampleAppAutoResize(bool* p_open);
    84150static void ShowExampleAppConstrainedResize(bool* p_open);
    85 static void ShowExampleAppFixedOverlay(bool* p_open);
     151static void ShowExampleAppSimpleOverlay(bool* p_open);
    86152static void ShowExampleAppWindowTitles(bool* p_open);
    87153static void ShowExampleAppCustomRendering(bool* p_open);
    88 static void ShowExampleAppMainMenuBar();
    89154static void ShowExampleMenuFile();
    90155
    91 static void ShowHelpMarker(const char* desc)
     156// Helper to display a little (?) mark which shows a tooltip when hovered.
     157// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
     158static void HelpMarker(const char* desc)
    92159{
    93    ImGui::TextDisabled("(?)");
    94    if (ImGui::IsItemHovered())
    95    {
    96       ImGui::BeginTooltip();
    97       ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
    98       ImGui::TextUnformatted(desc);
    99       ImGui::PopTextWrapPos();
    100       ImGui::EndTooltip();
    101    }
     160    ImGui::TextDisabled("(?)");
     161    if (ImGui::IsItemHovered())
     162    {
     163        ImGui::BeginTooltip();
     164        ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
     165        ImGui::TextUnformatted(desc);
     166        ImGui::PopTextWrapPos();
     167        ImGui::EndTooltip();
     168    }
    102169}
    103170
     171// Helper to display basic user controls.
    104172void ImGui::ShowUserGuide()
    105173{
    106    ImGui::BulletText("Double-click on title bar to collapse window.");
    107    ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
    108    ImGui::BulletText("Click and drag on any empty space to move window.");
    109    ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
    110    ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
    111    if (ImGui::GetIO().FontAllowUserScaling)
    112       ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
    113    ImGui::BulletText("Mouse Wheel to scroll.");
    114    ImGui::BulletText("While editing text:\n");
    115    ImGui::Indent();
    116    ImGui::BulletText("Hold SHIFT or use mouse to select text.");
    117    ImGui::BulletText("CTRL+Left/Right to word jump.");
    118    ImGui::BulletText("CTRL+A or double-click to select all.");
    119    ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
    120    ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
    121    ImGui::BulletText("ESCAPE to revert.");
    122    ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
    123    ImGui::Unindent();
     174    ImGuiIO& io = ImGui::GetIO();
     175    ImGui::BulletText("Double-click on title bar to collapse window.");
     176    ImGui::BulletText(
     177        "Click and drag on lower corner to resize window\n"
     178        "(double-click to auto fit window to its contents).");
     179    ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
     180    ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
     181    if (io.FontAllowUserScaling)
     182        ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
     183    ImGui::BulletText("While inputing text:\n");
     184    ImGui::Indent();
     185    ImGui::BulletText("CTRL+Left/Right to word jump.");
     186    ImGui::BulletText("CTRL+A or double-click to select all.");
     187    ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
     188    ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
     189    ImGui::BulletText("ESCAPE to revert.");
     190    ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
     191    ImGui::Unindent();
     192    ImGui::BulletText("With keyboard navigation enabled:");
     193    ImGui::Indent();
     194    ImGui::BulletText("Arrow keys to navigate.");
     195    ImGui::BulletText("Space to activate a widget.");
     196    ImGui::BulletText("Return to input text into a widget.");
     197    ImGui::BulletText("Escape to deactivate a widget, close popup, exit child window.");
     198    ImGui::BulletText("Alt to jump to the menu layer of a window.");
     199    ImGui::BulletText("CTRL+Tab to select a window.");
     200    ImGui::Unindent();
    124201}
    125202
    126 // Demonstrate most ImGui features (big function!)
     203//-----------------------------------------------------------------------------
     204// [SECTION] Demo Window / ShowDemoWindow()
     205//-----------------------------------------------------------------------------
     206// - ShowDemoWindowWidgets()
     207// - ShowDemoWindowLayout()
     208// - ShowDemoWindowPopups()
     209// - ShowDemoWindowColumns()
     210// - ShowDemoWindowMisc()
     211//-----------------------------------------------------------------------------
     212
     213// We split the contents of the big ShowDemoWindow() function into smaller functions
     214// (because the link time of very large functions grow non-linearly)
     215static void ShowDemoWindowWidgets();
     216static void ShowDemoWindowLayout();
     217static void ShowDemoWindowPopups();
     218static void ShowDemoWindowColumns();
     219static void ShowDemoWindowMisc();
     220
     221// Demonstrate most Dear ImGui features (this is big function!)
     222// You may execute this function to experiment with the UI and understand what it does.
     223// You may then search for keywords in the code when you are interested by a specific feature.
    127224void ImGui::ShowDemoWindow(bool* p_open)
    128225{
    129    // Examples apps
    130    static bool show_app_main_menu_bar = false;
    131    static bool show_app_console = false;
    132    static bool show_app_log = false;
    133    static bool show_app_layout = false;
    134    static bool show_app_property_editor = false;
    135    static bool show_app_long_text = false;
    136    static bool show_app_auto_resize = false;
    137    static bool show_app_constrained_resize = false;
    138    static bool show_app_fixed_overlay = false;
    139    static bool show_app_window_titles = false;
    140    static bool show_app_custom_rendering = false;
    141    static bool show_app_style_editor = false;
    142 
    143    static bool show_app_metrics = false;
    144    static bool show_app_about = false;
    145 
    146    if (show_app_main_menu_bar)       ShowExampleAppMainMenuBar();
    147    if (show_app_console)             ShowExampleAppConsole(&show_app_console);
    148    if (show_app_log)                 ShowExampleAppLog(&show_app_log);
    149    if (show_app_layout)              ShowExampleAppLayout(&show_app_layout);
    150    if (show_app_property_editor)     ShowExampleAppPropertyEditor(&show_app_property_editor);
    151    if (show_app_long_text)           ShowExampleAppLongText(&show_app_long_text);
    152    if (show_app_auto_resize)         ShowExampleAppAutoResize(&show_app_auto_resize);
    153    if (show_app_constrained_resize)  ShowExampleAppConstrainedResize(&show_app_constrained_resize);
    154    if (show_app_fixed_overlay)       ShowExampleAppFixedOverlay(&show_app_fixed_overlay);
    155    if (show_app_window_titles)       ShowExampleAppWindowTitles(&show_app_window_titles);
    156    if (show_app_custom_rendering)    ShowExampleAppCustomRendering(&show_app_custom_rendering);
    157 
    158    if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); }
    159    if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
    160    if (show_app_about)
    161    {
    162       ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize);
    163       ImGui::Text("Dear ImGui, %s", ImGui::GetVersion());
    164       ImGui::Separator();
    165       ImGui::Text("By Omar Cornut and all dear imgui contributors.");
    166       ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
    167       ImGui::End();
    168    }
    169 
    170    static bool no_titlebar = false;
    171    static bool no_scrollbar = false;
    172    static bool no_menu = false;
    173    static bool no_move = false;
    174    static bool no_resize = false;
    175    static bool no_collapse = false;
    176    static bool no_close = false;
    177    static bool no_nav = false;
    178 
    179    // Demonstrate the various window flags. Typically you would just use the default.
    180    ImGuiWindowFlags window_flags = 0;
    181    if (no_titlebar)  window_flags |= ImGuiWindowFlags_NoTitleBar;
    182    if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
    183    if (!no_menu)     window_flags |= ImGuiWindowFlags_MenuBar;
    184    if (no_move)      window_flags |= ImGuiWindowFlags_NoMove;
    185    if (no_resize)    window_flags |= ImGuiWindowFlags_NoResize;
    186    if (no_collapse)  window_flags |= ImGuiWindowFlags_NoCollapse;
    187    if (no_nav)       window_flags |= ImGuiWindowFlags_NoNav;
    188    if (no_close)     p_open = NULL; // Don't pass our bool* to Begin
    189 
    190    ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
    191    if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
    192    {
    193       // Early out if the window is collapsed, as an optimization.
    194       ImGui::End();
    195       return;
    196    }
    197 
    198    //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);    // 2/3 of the space for widget and 1/3 for labels
    199    ImGui::PushItemWidth(-140);                                 // Right align, keep 140 pixels for labels
    200 
    201    ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
    202 
    203    // Menu
    204    if (ImGui::BeginMenuBar())
    205    {
    206       if (ImGui::BeginMenu("Menu"))
    207       {
    208          ShowExampleMenuFile();
    209          ImGui::EndMenu();
    210       }
    211       if (ImGui::BeginMenu("Examples"))
    212       {
    213          ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
    214          ImGui::MenuItem("Console", NULL, &show_app_console);
    215          ImGui::MenuItem("Log", NULL, &show_app_log);
    216          ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
    217          ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
    218          ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
    219          ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
    220          ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
    221          ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay);
    222          ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
    223          ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
    224          ImGui::EndMenu();
    225       }
    226       if (ImGui::BeginMenu("Help"))
    227       {
    228          ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
    229          ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
    230          ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
    231          ImGui::EndMenu();
    232       }
    233       ImGui::EndMenuBar();
    234    }
    235 
    236    ImGui::Spacing();
    237    if (ImGui::CollapsingHeader("Help"))
    238    {
    239       ImGui::TextWrapped("This window is being created by the ShowDemoWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n");
    240       ImGui::Text("USER GUIDE:");
    241       ImGui::ShowUserGuide();
    242    }
    243 
    244    if (ImGui::CollapsingHeader("Window options"))
    245    {
    246       ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
    247       ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
    248       ImGui::Checkbox("No menu", &no_menu);
    249       ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
    250       ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
    251       ImGui::Checkbox("No collapse", &no_collapse);
    252       ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150);
    253       ImGui::Checkbox("No nav", &no_nav);
    254 
    255       if (ImGui::TreeNode("Style"))
    256       {
    257          ImGui::ShowStyleEditor();
    258          ImGui::TreePop();
    259       }
    260 
    261       if (ImGui::TreeNode("Capture/Logging"))
    262       {
    263          ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output.");
    264          ImGui::LogButtons();
    265          ImGui::TreePop();
    266       }
    267    }
    268 
    269    if (ImGui::CollapsingHeader("Widgets"))
    270    {
    271       if (ImGui::TreeNode("Basic"))
    272       {
    273          static int clicked = 0;
    274          if (ImGui::Button("Button"))
     226    // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
     227    // Most ImGui functions would normally just crash if the context is missing.
     228    IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing dear imgui context. Refer to examples app!");
     229
     230    // Examples Apps (accessible from the "Examples" menu)
     231    static bool show_app_main_menu_bar = false;
     232    static bool show_app_documents = false;
     233    static bool show_app_console = false;
     234    static bool show_app_log = false;
     235    static bool show_app_layout = false;
     236    static bool show_app_property_editor = false;
     237    static bool show_app_long_text = false;
     238    static bool show_app_auto_resize = false;
     239    static bool show_app_constrained_resize = false;
     240    static bool show_app_simple_overlay = false;
     241    static bool show_app_window_titles = false;
     242    static bool show_app_custom_rendering = false;
     243
     244    if (show_app_main_menu_bar)       ShowExampleAppMainMenuBar();
     245    if (show_app_documents)           ShowExampleAppDocuments(&show_app_documents);
     246
     247    if (show_app_console)             ShowExampleAppConsole(&show_app_console);
     248    if (show_app_log)                 ShowExampleAppLog(&show_app_log);
     249    if (show_app_layout)              ShowExampleAppLayout(&show_app_layout);
     250    if (show_app_property_editor)     ShowExampleAppPropertyEditor(&show_app_property_editor);
     251    if (show_app_long_text)           ShowExampleAppLongText(&show_app_long_text);
     252    if (show_app_auto_resize)         ShowExampleAppAutoResize(&show_app_auto_resize);
     253    if (show_app_constrained_resize)  ShowExampleAppConstrainedResize(&show_app_constrained_resize);
     254    if (show_app_simple_overlay)      ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
     255    if (show_app_window_titles)       ShowExampleAppWindowTitles(&show_app_window_titles);
     256    if (show_app_custom_rendering)    ShowExampleAppCustomRendering(&show_app_custom_rendering);
     257
     258    // Dear ImGui Apps (accessible from the "Tools" menu)
     259    static bool show_app_metrics = false;
     260    static bool show_app_style_editor = false;
     261    static bool show_app_about = false;
     262
     263    if (show_app_metrics)       { ImGui::ShowMetricsWindow(&show_app_metrics); }
     264    if (show_app_about)         { ImGui::ShowAboutWindow(&show_app_about); }
     265    if (show_app_style_editor)
     266    {
     267        ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor);
     268        ImGui::ShowStyleEditor();
     269        ImGui::End();
     270    }
     271
     272    // Demonstrate the various window flags. Typically you would just use the default!
     273    static bool no_titlebar = false;
     274    static bool no_scrollbar = false;
     275    static bool no_menu = false;
     276    static bool no_move = false;
     277    static bool no_resize = false;
     278    static bool no_collapse = false;
     279    static bool no_close = false;
     280    static bool no_nav = false;
     281    static bool no_background = false;
     282    static bool no_bring_to_front = false;
     283
     284    ImGuiWindowFlags window_flags = 0;
     285    if (no_titlebar)        window_flags |= ImGuiWindowFlags_NoTitleBar;
     286    if (no_scrollbar)       window_flags |= ImGuiWindowFlags_NoScrollbar;
     287    if (!no_menu)           window_flags |= ImGuiWindowFlags_MenuBar;
     288    if (no_move)            window_flags |= ImGuiWindowFlags_NoMove;
     289    if (no_resize)          window_flags |= ImGuiWindowFlags_NoResize;
     290    if (no_collapse)        window_flags |= ImGuiWindowFlags_NoCollapse;
     291    if (no_nav)             window_flags |= ImGuiWindowFlags_NoNav;
     292    if (no_background)      window_flags |= ImGuiWindowFlags_NoBackground;
     293    if (no_bring_to_front)  window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
     294    if (no_close)           p_open = NULL; // Don't pass our bool* to Begin
     295
     296    // We specify a default position/size in case there's no data in the .ini file.
     297    // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
     298    ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver);
     299    ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
     300
     301    // Main body of the Demo window starts here.
     302    if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags))
     303    {
     304        // Early out if the window is collapsed, as an optimization.
     305        ImGui::End();
     306        return;
     307    }
     308
     309    // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
     310
     311    // e.g. Use 2/3 of the space for widgets and 1/3 for labels (default)
     312    //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);
     313
     314    // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
     315    ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
     316
     317    // Menu Bar
     318    if (ImGui::BeginMenuBar())
     319    {
     320        if (ImGui::BeginMenu("Menu"))
     321        {
     322            ShowExampleMenuFile();
     323            ImGui::EndMenu();
     324        }
     325        if (ImGui::BeginMenu("Examples"))
     326        {
     327            ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
     328            ImGui::MenuItem("Console", NULL, &show_app_console);
     329            ImGui::MenuItem("Log", NULL, &show_app_log);
     330            ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
     331            ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
     332            ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
     333            ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
     334            ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
     335            ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
     336            ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
     337            ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
     338            ImGui::MenuItem("Documents", NULL, &show_app_documents);
     339            ImGui::EndMenu();
     340        }
     341        if (ImGui::BeginMenu("Tools"))
     342        {
     343            ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
     344            ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
     345            ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
     346            ImGui::EndMenu();
     347        }
     348        ImGui::EndMenuBar();
     349    }
     350
     351    ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
     352    ImGui::Spacing();
     353
     354    if (ImGui::CollapsingHeader("Help"))
     355    {
     356        ImGui::Text("ABOUT THIS DEMO:");
     357        ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
     358        ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
     359        ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
     360                          "and Metrics (general purpose Dear ImGui debugging tool).");
     361        ImGui::Separator();
     362
     363        ImGui::Text("PROGRAMMER GUIDE:");
     364        ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
     365        ImGui::BulletText("See comments in imgui.cpp.");
     366        ImGui::BulletText("See example applications in the examples/ folder.");
     367        ImGui::BulletText("Read the FAQ at http://www.dearimgui.org/faq/");
     368        ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
     369        ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
     370        ImGui::Separator();
     371
     372        ImGui::Text("USER GUIDE:");
     373        ImGui::ShowUserGuide();
     374    }
     375
     376    if (ImGui::CollapsingHeader("Configuration"))
     377    {
     378        ImGuiIO& io = ImGui::GetIO();
     379
     380        if (ImGui::TreeNode("Configuration##2"))
     381        {
     382            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard",    (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
     383            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad",     (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
     384            ImGui::SameLine(); HelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
     385            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
     386            ImGui::SameLine(); HelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
     387            ImGui::CheckboxFlags("io.ConfigFlags: NoMouse",              (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
     388
     389            // The "NoMouse" option above can get us stuck with a disable mouse! Provide an alternative way to fix it:
     390            if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
     391            {
     392                if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
     393                {
     394                    ImGui::SameLine();
     395                    ImGui::Text("<<PRESS SPACE TO DISABLE>>");
     396                }
     397                if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
     398                    io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
     399            }
     400            ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int*)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
     401            ImGui::SameLine(); HelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
     402            ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
     403            ImGui::SameLine(); HelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
     404            ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
     405            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.");
     406            ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
     407            ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
     408            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).");
     409            ImGui::Text("Also see Style->Rendering for rendering options.");
     410            ImGui::TreePop();
     411            ImGui::Separator();
     412        }
     413
     414        if (ImGui::TreeNode("Backend Flags"))
     415        {
     416            HelpMarker(
     417                "Those flags are set by the back-ends (imgui_impl_xxx files) to specify their capabilities.\n"
     418                "Here we expose then as read-only fields to avoid breaking interactions with your back-end.");
     419
     420            // Make a local copy to avoid modifying actual back-end flags.
     421            ImGuiBackendFlags backend_flags = io.BackendFlags;
     422            ImGui::CheckboxFlags("io.BackendFlags: HasGamepad",           (unsigned int*)&backend_flags, ImGuiBackendFlags_HasGamepad);
     423            ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors",      (unsigned int*)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
     424            ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos",       (unsigned int*)&backend_flags, ImGuiBackendFlags_HasSetMousePos);
     425            ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset", (unsigned int*)&backend_flags, ImGuiBackendFlags_RendererHasVtxOffset);
     426            ImGui::TreePop();
     427            ImGui::Separator();
     428        }
     429
     430        if (ImGui::TreeNode("Style"))
     431        {
     432            HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
     433            ImGui::ShowStyleEditor();
     434            ImGui::TreePop();
     435            ImGui::Separator();
     436        }
     437
     438        if (ImGui::TreeNode("Capture/Logging"))
     439        {
     440            HelpMarker(
     441                "The logging API redirects all text output so you can easily capture the content of "
     442                "a window or a block. Tree nodes can be automatically expanded.\n"
     443                "Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
     444            ImGui::LogButtons();
     445
     446            HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output.");
     447            if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
     448            {
     449                ImGui::LogToClipboard();
     450                ImGui::LogText("Hello, world!");
     451                ImGui::LogFinish();
     452            }
     453            ImGui::TreePop();
     454        }
     455    }
     456
     457    if (ImGui::CollapsingHeader("Window options"))
     458    {
     459        ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
     460        ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
     461        ImGui::Checkbox("No menu", &no_menu);
     462        ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
     463        ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
     464        ImGui::Checkbox("No collapse", &no_collapse);
     465        ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150);
     466        ImGui::Checkbox("No nav", &no_nav); ImGui::SameLine(300);
     467        ImGui::Checkbox("No background", &no_background);
     468        ImGui::Checkbox("No bring to front", &no_bring_to_front);
     469    }
     470
     471    // All demo contents
     472    ShowDemoWindowWidgets();
     473    ShowDemoWindowLayout();
     474    ShowDemoWindowPopups();
     475    ShowDemoWindowColumns();
     476    ShowDemoWindowMisc();
     477
     478    // End of ShowDemoWindow()
     479    ImGui::End();
     480}
     481
     482static void ShowDemoWindowWidgets()
     483{
     484    if (!ImGui::CollapsingHeader("Widgets"))
     485        return;
     486
     487    if (ImGui::TreeNode("Basic"))
     488    {
     489        static int clicked = 0;
     490        if (ImGui::Button("Button"))
    275491            clicked++;
    276          if (clicked & 1)
    277          {
     492        if (clicked & 1)
     493        {
    278494            ImGui::SameLine();
    279495            ImGui::Text("Thanks for clicking me!");
    280          }
    281 
    282          static bool check = true;
    283          ImGui::Checkbox("checkbox", &check);
    284 
    285          static int e = 0;
    286          ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
    287          ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
    288          ImGui::RadioButton("radio c", &e, 2);
    289 
    290          // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
    291          for (int i = 0; i < 7; i++)
    292          {
    293             if (i > 0) ImGui::SameLine();
     496        }
     497
     498        static bool check = true;
     499        ImGui::Checkbox("checkbox", &check);
     500
     501        static int e = 0;
     502        ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
     503        ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
     504        ImGui::RadioButton("radio c", &e, 2);
     505
     506        // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
     507        for (int i = 0; i < 7; i++)
     508        {
     509            if (i > 0)
     510                ImGui::SameLine();
    294511            ImGui::PushID(i);
    295512            ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
     
    299516            ImGui::PopStyleColor(3);
    300517            ImGui::PopID();
    301          }
    302 
    303          // Arrow buttons
    304          float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
    305          if (ImGui::ArrowButton("##left", ImGuiDir_Left)) {}
    306          ImGui::SameLine(0.0f, spacing);
    307          if (ImGui::ArrowButton("##left", ImGuiDir_Right)) {}
    308 
    309          ImGui::Text("Hover over me");
    310          if (ImGui::IsItemHovered())
     518        }
     519
     520        // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
     521        // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
     522        // See 'Demo->Layout->Text Baseline Alignment' for details.
     523        ImGui::AlignTextToFramePadding();
     524        ImGui::Text("Hold to repeat:");
     525        ImGui::SameLine();
     526
     527        // Arrow buttons with Repeater
     528        static int counter = 0;
     529        float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
     530        ImGui::PushButtonRepeat(true);
     531        if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
     532        ImGui::SameLine(0.0f, spacing);
     533        if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
     534        ImGui::PopButtonRepeat();
     535        ImGui::SameLine();
     536        ImGui::Text("%d", counter);
     537
     538        ImGui::Text("Hover over me");
     539        if (ImGui::IsItemHovered())
    311540            ImGui::SetTooltip("I am a tooltip");
    312541
    313          ImGui::SameLine();
    314          ImGui::Text("- or me");
    315          if (ImGui::IsItemHovered())
    316          {
     542        ImGui::SameLine();
     543        ImGui::Text("- or me");
     544        if (ImGui::IsItemHovered())
     545        {
    317546            ImGui::BeginTooltip();
    318547            ImGui::Text("I am a fancy tooltip");
     
    320549            ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
    321550            ImGui::EndTooltip();
    322          }
    323 
    324          ImGui::Separator();
    325 
    326          ImGui::LabelText("label", "Value");
    327 
    328          {
     551        }
     552
     553        ImGui::Separator();
     554
     555        ImGui::LabelText("label", "Value");
     556
     557        {
    329558            // Using the _simplified_ one-liner Combo() api here
    330             const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
     559            // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
     560            const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
    331561            static int item_current = 0;
    332562            ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
    333             ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
    334          }
    335 
    336          {
     563            ImGui::SameLine(); HelpMarker(
     564                "Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, "
     565                "and demonstration of various flags.\n");
     566        }
     567
     568        {
     569            // To wire InputText() with std::string or any other custom string type,
     570            // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
    337571            static char str0[128] = "Hello, world!";
     572            ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
     573            ImGui::SameLine(); HelpMarker(
     574                "USER:\n"
     575                "Hold SHIFT or use mouse to select text.\n"
     576                "CTRL+Left/Right to word jump.\n"
     577                "CTRL+A or double-click to select all.\n"
     578                "CTRL+X,CTRL+C,CTRL+V clipboard.\n"
     579                "CTRL+Z,CTRL+Y undo/redo.\n"
     580                "ESCAPE to revert.\n\n"
     581                "PROGRAMMER:\n"
     582                "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
     583                "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
     584                "in imgui_demo.cpp).");
     585
     586            static char str1[128] = "";
     587            ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
     588
    338589            static int i0 = 123;
    339             ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
    340             ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n");
    341 
    342590            ImGui::InputInt("input int", &i0);
    343             ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n  e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
     591            ImGui::SameLine(); HelpMarker(
     592                "You can apply arithmetic operators +,*,/ on numerical values.\n"
     593                "  e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\n"
     594                "Use +- to subtract.");
    344595
    345596            static float f0 = 0.001f;
    346             ImGui::InputFloat("input float", &f0, 0.01f, 1.0f);
    347 
    348             static double d0 = 999999.000001;
    349             ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.6f");
     597            ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
     598
     599            static double d0 = 999999.00000001;
     600            ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
    350601
    351602            static float f1 = 1.e10f;
    352603            ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
    353             ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n  e.g. \"1e+8\" becomes \"100000000\".\n");
     604            ImGui::SameLine(); HelpMarker(
     605                "You can input value using the scientific notation,\n"
     606                "  e.g. \"1e+8\" becomes \"100000000\".");
    354607
    355608            static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
    356609            ImGui::InputFloat3("input float3", vec4a);
    357          }
    358 
    359          {
     610        }
     611
     612        {
    360613            static int i1 = 50, i2 = 42;
    361614            ImGui::DragInt("drag int", &i1, 1);
    362             ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
    363 
    364             ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%.0f%%");
     615            ImGui::SameLine(); HelpMarker(
     616                "Click and drag to edit value.\n"
     617                "Hold SHIFT/ALT for faster/slower edit.\n"
     618                "Double-click or CTRL+click to input value.");
     619
     620            ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
    365621
    366622            static float f1 = 1.00f, f2 = 0.0067f;
    367623            ImGui::DragFloat("drag float", &f1, 0.005f);
    368624            ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
    369          }
    370 
    371          {
     625        }
     626
     627        {
    372628            static int i1 = 0;
    373629            ImGui::SliderInt("slider int", &i1, -1, 3);
    374             ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
     630            ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
    375631
    376632            static float f1 = 0.123f, f2 = 0.0f;
    377633            ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
    378             ImGui::SliderFloat("slider log float", &f2, -10.0f, 10.0f, "%.4f", 3.0f);
     634            ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic);
     635
    379636            static float angle = 0.0f;
    380637            ImGui::SliderAngle("slider angle", &angle);
    381          }
    382 
    383          {
    384             static float col1[3] = { 1.0f,0.0f,0.2f };
    385             static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
     638
     639            // Using the format string to display a name instead of an integer.
     640            // Here we completely omit '%d' from the format string, so it'll only display a name.
     641            // This technique can also be used with DragInt().
     642            enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
     643            static int elem = Element_Fire;
     644            const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
     645            const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
     646            ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name);
     647            ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
     648        }
     649
     650        {
     651            static float col1[3] = { 1.0f, 0.0f, 0.2f };
     652            static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
    386653            ImGui::ColorEdit3("color 1", col1);
    387             ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
     654            ImGui::SameLine(); HelpMarker(
     655                "Click on the colored square to open a color picker.\n"
     656                "Click and hold to use drag and drop.\n"
     657                "Right-click on the colored square to show options.\n"
     658                "CTRL+click on individual component to input value.\n");
    388659
    389660            ImGui::ColorEdit4("color 2", col2);
    390          }
    391 
    392          {
     661        }
     662
     663        {
    393664            // List box
    394             const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
    395             static int listbox_item_current = 1;
    396             ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
     665            const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
     666            static int item_current = 1;
     667            ImGui::ListBox("listbox\n(single select)", &item_current, items, IM_ARRAYSIZE(items), 4);
    397668
    398669            //static int listbox_item_current2 = 2;
    399             //ImGui::PushItemWidth(-1);
     670            //ImGui::SetNextItemWidth(-1);
    400671            //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
    401             //ImGui::PopItemWidth();
    402          }
    403 
    404          ImGui::TreePop();
    405       }
    406 
    407       // Testing ImGuiOnceUponAFrame helper.
    408       //static ImGuiOnceUponAFrame once;
    409       //for (int i = 0; i < 5; i++)
    410       //    if (once)
    411       //        ImGui::Text("This will be displayed only once.");
    412 
    413       if (ImGui::TreeNode("Trees"))
    414       {
    415          if (ImGui::TreeNode("Basic trees"))
    416          {
     672        }
     673
     674        ImGui::TreePop();
     675    }
     676
     677    // Testing ImGuiOnceUponAFrame helper.
     678    //static ImGuiOnceUponAFrame once;
     679    //for (int i = 0; i < 5; i++)
     680    //    if (once)
     681    //        ImGui::Text("This will be displayed only once.");
     682
     683    if (ImGui::TreeNode("Trees"))
     684    {
     685        if (ImGui::TreeNode("Basic trees"))
     686        {
    417687            for (int i = 0; i < 5; i++)
    418                if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
    419                {
    420                   ImGui::Text("blah blah");
    421                   ImGui::SameLine();
    422                   if (ImGui::SmallButton("button")) {};
    423                   ImGui::TreePop();
    424                }
     688            {
     689                // Use SetNextItemOpen() so set the default state of a node to be open. We could
     690                // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
     691                if (i == 0)
     692                    ImGui::SetNextItemOpen(true, ImGuiCond_Once);
     693
     694                if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
     695                {
     696                    ImGui::Text("blah blah");
     697                    ImGui::SameLine();
     698                    if (ImGui::SmallButton("button")) {}
     699                    ImGui::TreePop();
     700                }
     701            }
    425702            ImGui::TreePop();
    426          }
    427 
    428          if (ImGui::TreeNode("Advanced, with Selectable nodes"))
    429          {
    430             ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
     703        }
     704
     705        if (ImGui::TreeNode("Advanced, with Selectable nodes"))
     706        {
     707            HelpMarker(
     708                "This is a more typical looking tree with selectable nodes.\n"
     709                "Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
     710            static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
    431711            static bool align_label_with_current_x_position = false;
    432             ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
     712            static bool test_drag_and_drop = false;
     713            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow",       (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
     714            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", (unsigned int*)&base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
     715            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth",    (unsigned int*)&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.");
     716            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth",     (unsigned int*)&base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
     717            ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
     718            ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
    433719            ImGui::Text("Hello!");
    434720            if (align_label_with_current_x_position)
    435                ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
    436 
    437             static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
    438             int node_clicked = -1;                // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
    439             ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize() * 3); // Increase spacing to differentiate leaves from expanded contents.
     721                ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
     722
     723            // 'selection_mask' is dumb representation of what may be user-side selection state.
     724            //  You may retain selection state inside or outside your objects in whatever format you see fit.
     725            // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
     726            /// of the loop. May be a pointer to your own node type, etc.
     727            static int selection_mask = (1 << 2);
     728            int node_clicked = -1;
    440729            for (int i = 0; i < 6; i++)
    441730            {
    442                // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
    443                ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
    444                if (i < 3)
    445                {
    446                   // Node
    447                   bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
    448                   if (ImGui::IsItemClicked())
    449                      node_clicked = i;
    450                   if (node_open)
    451                   {
    452                      ImGui::Text("Blah blah\nBlah Blah");
    453                      ImGui::TreePop();
    454                   }
    455                }
    456                else
    457                {
    458                   // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text().
    459                   node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
    460                   ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
    461                   if (ImGui::IsItemClicked())
    462                      node_clicked = i;
    463                }
     731                // Disable the default "open on single-click behavior" + set Selected flag according to our selection.
     732                ImGuiTreeNodeFlags node_flags = base_flags;
     733                const bool is_selected = (selection_mask & (1 << i)) != 0;
     734                if (is_selected)
     735                    node_flags |= ImGuiTreeNodeFlags_Selected;
     736                if (i < 3)
     737                {
     738                    // Items 0..2 are Tree Node
     739                    bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
     740                    if (ImGui::IsItemClicked())
     741                        node_clicked = i;
     742                    if (test_drag_and_drop && ImGui::BeginDragDropSource())
     743                    {
     744                        ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
     745                        ImGui::Text("This is a drag and drop source");
     746                        ImGui::EndDragDropSource();
     747                    }
     748                    if (node_open)
     749                    {
     750                        ImGui::BulletText("Blah blah\nBlah Blah");
     751                        ImGui::TreePop();
     752                    }
     753                }
     754                else
     755                {
     756                    // Items 3..5 are Tree Leaves
     757                    // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
     758                    // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
     759                    node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
     760                    ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
     761                    if (ImGui::IsItemClicked())
     762                        node_clicked = i;
     763                    if (test_drag_and_drop && ImGui::BeginDragDropSource())
     764                    {
     765                        ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
     766                        ImGui::Text("This is a drag and drop source");
     767                        ImGui::EndDragDropSource();
     768                    }
     769                }
    464770            }
    465771            if (node_clicked != -1)
    466772            {
    467                // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
    468                if (ImGui::GetIO().KeyCtrl)
    469                   selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
    470                else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
    471                   selection_mask = (1 << node_clicked);           // Click to single-select
    472             }
    473             ImGui::PopStyleVar();
     773                // Update selection state
     774                // (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
     775                if (ImGui::GetIO().KeyCtrl)
     776                    selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
     777                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
     778                    selection_mask = (1 << node_clicked);           // Click to single-select
     779            }
    474780            if (align_label_with_current_x_position)
    475                ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
     781                ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
    476782            ImGui::TreePop();
    477          }
    478          ImGui::TreePop();
    479       }
    480 
    481       if (ImGui::TreeNode("Collapsing Headers"))
    482       {
    483          static bool closable_group = true;
    484          ImGui::Checkbox("Enable extra group", &closable_group);
    485          if (ImGui::CollapsingHeader("Header"))
    486          {
    487             ImGui::Text("IsItemHovered: %d", IsItemHovered());
     783        }
     784        ImGui::TreePop();
     785    }
     786
     787    if (ImGui::TreeNode("Collapsing Headers"))
     788    {
     789        static bool closable_group = true;
     790        ImGui::Checkbox("Show 2nd header", &closable_group);
     791        if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None))
     792        {
     793            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
    488794            for (int i = 0; i < 5; i++)
    489                ImGui::Text("Some content %d", i);
    490          }
    491          if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
    492          {
    493             ImGui::Text("IsItemHovered: %d", IsItemHovered());
     795                ImGui::Text("Some content %d", i);
     796        }
     797        if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
     798        {
     799            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
    494800            for (int i = 0; i < 5; i++)
    495                ImGui::Text("More content %d", i);
    496          }
    497          ImGui::TreePop();
    498       }
    499 
    500       if (ImGui::TreeNode("Bullets"))
    501       {
    502          ImGui::BulletText("Bullet point 1");
    503          ImGui::BulletText("Bullet point 2\nOn multiple lines");
    504          ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
    505          ImGui::Bullet(); ImGui::SmallButton("Button");
    506          ImGui::TreePop();
    507       }
    508 
    509       if (ImGui::TreeNode("Text"))
    510       {
    511          if (ImGui::TreeNode("Colored Text"))
    512          {
     801                ImGui::Text("More content %d", i);
     802        }
     803        /*
     804        if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet))
     805            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
     806        */
     807        ImGui::TreePop();
     808    }
     809
     810    if (ImGui::TreeNode("Bullets"))
     811    {
     812        ImGui::BulletText("Bullet point 1");
     813        ImGui::BulletText("Bullet point 2\nOn multiple lines");
     814        if (ImGui::TreeNode("Tree node"))
     815        {
     816            ImGui::BulletText("Another bullet point");
     817            ImGui::TreePop();
     818        }
     819        ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
     820        ImGui::Bullet(); ImGui::SmallButton("Button");
     821        ImGui::TreePop();
     822    }
     823
     824    if (ImGui::TreeNode("Text"))
     825    {
     826        if (ImGui::TreeNode("Colored Text"))
     827        {
    513828            // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
    514829            ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
    515830            ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
    516831            ImGui::TextDisabled("Disabled");
    517             ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
     832            ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
    518833            ImGui::TreePop();
    519          }
    520 
    521          if (ImGui::TreeNode("Word Wrapping"))
    522          {
     834        }
     835
     836        if (ImGui::TreeNode("Word Wrapping"))
     837        {
    523838            // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
    524             ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages.");
     839            ImGui::TextWrapped(
     840                "This text should automatically wrap on the edge of the window. The current implementation "
     841                "for text wrapping follows simple rules suitable for English and possibly other languages.");
    525842            ImGui::Spacing();
    526843
     
    528845            ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
    529846
    530             ImGui::Text("Test paragraph 1:");
    531             ImVec2 pos = ImGui::GetCursorScreenPos();
    532             ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255, 0, 255, 255));
    533             ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
    534             ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
    535             ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
    536             ImGui::PopTextWrapPos();
    537 
    538             ImGui::Text("Test paragraph 2:");
    539             pos = ImGui::GetCursorScreenPos();
    540             ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255, 0, 255, 255));
    541             ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
    542             ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
    543             ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
    544             ImGui::PopTextWrapPos();
     847            ImDrawList* draw_list = ImGui::GetWindowDrawList();
     848            for (int n = 0; n < 2; n++)
     849            {
     850                ImGui::Text("Test paragraph %d:", n);
     851                ImVec2 pos = ImGui::GetCursorScreenPos();
     852                ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y);
     853                ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight());
     854                ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
     855                if (n == 0)
     856                    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);
     857                else
     858                    ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
     859
     860                // Draw actual text bounding box, following by marker of our expected limit (should not overlap!)
     861                draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
     862                draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255));
     863                ImGui::PopTextWrapPos();
     864            }
    545865
    546866            ImGui::TreePop();
    547          }
    548 
    549          if (ImGui::TreeNode("UTF-8 Text"))
    550          {
     867        }
     868
     869        if (ImGui::TreeNode("UTF-8 Text"))
     870        {
    551871            // UTF-8 test with Japanese characters
    552             // (needs a suitable font, try Arial Unicode or M+ fonts http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html)
     872            // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
    553873            // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
    554             // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. Visual Studio save your file as 'UTF-8 without signature')
    555             // - HOWEVER, FOR THIS DEMO FILE, BECAUSE WE WANT TO SUPPORT COMPILER, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.
    556             //   Instead we are encoding a few string with hexadecimal constants. Don't do this in your application!
    557             // Note that characters values are preserved even by InputText() if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
    558             ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->LoadFromFileTTF() manually to load extra character ranges.");
    559             ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
     874            // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
     875            //   can save your source files as 'UTF-8 without signature').
     876            // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8
     877            //   CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants.
     878            //   Don't do this in your application! Please use u8"text in any language" in your application!
     879            // Note that characters values are preserved even by InputText() if the font cannot be displayed,
     880            // so you can safely copy & paste garbled characters into another application.
     881            ImGui::TextWrapped(
     882                "CJK text will only appears if the font was loaded with the appropriate CJK character ranges. "
     883                "Call io.Font->AddFontFromFileTTF() manually to load extra character ranges. "
     884                "Read docs/FONTS.md for details.");
     885            ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
    560886            ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
    561             static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"; // "nihongo"
     887            static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
     888            //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
    562889            ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
    563890            ImGui::TreePop();
    564          }
    565          ImGui::TreePop();
    566       }
    567 
    568       if (ImGui::TreeNode("Images"))
    569       {
    570          ImGuiIO& io = ImGui::GetIO();
    571          ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!");
    572 
    573          // Here we are grabbing the font texture because that's the only one we have access to inside the demo code.
    574          // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure.
    575          // If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID.
    576          // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.)
    577          // If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc.
    578          // Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this.
    579          // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
    580          ImTextureID my_tex_id = io.Fonts->TexID;
    581          float my_tex_w = (float)io.Fonts->TexWidth;
    582          float my_tex_h = (float)io.Fonts->TexHeight;
    583 
    584          ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
    585          ImVec2 pos = ImGui::GetCursorScreenPos();
    586          ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
    587          if (ImGui::IsItemHovered())
    588          {
    589             ImGui::BeginTooltip();
    590             float region_sz = 32.0f;
    591             float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; if (region_x < 0.0f) region_x = 0.0f; else if (region_x > my_tex_w - region_sz) region_x = my_tex_w - region_sz;
    592             float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; if (region_y < 0.0f) region_y = 0.0f; else if (region_y > my_tex_h - region_sz) region_y = my_tex_h - region_sz;
    593             float zoom = 4.0f;
    594             ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
    595             ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
    596             ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
    597             ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
    598             ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
    599             ImGui::EndTooltip();
    600          }
    601          ImGui::TextWrapped("And now some textured buttons..");
    602          static int pressed_count = 0;
    603          for (int i = 0; i < 8; i++)
    604          {
     891        }
     892        ImGui::TreePop();
     893    }
     894
     895    if (ImGui::TreeNode("Images"))
     896    {
     897        ImGuiIO& io = ImGui::GetIO();
     898        ImGui::TextWrapped(
     899            "Below we are displaying the font texture (which is the only texture we have access to in this demo). "
     900            "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. "
     901            "Hover the texture for a zoomed view!");
     902
     903        // Below we are displaying the font texture because it is the only texture we have access to inside the demo!
     904        // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that
     905        // will be passed to the rendering back-end via the ImDrawCmd structure.
     906        // If you use one of the default imgui_impl_XXXX.cpp rendering back-end, they all have comments at the top
     907        // of their respective source file to specify what they expect to be stored in ImTextureID, for example:
     908        // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer
     909        // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc.
     910        // More:
     911        // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers
     912        //   to ImGui::Image(), and gather width/height through your own functions, etc.
     913        // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer,
     914        //   it will help you debug issues if you are confused about it.
     915        // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
     916        // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
     917        // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
     918        ImTextureID my_tex_id = io.Fonts->TexID;
     919        float my_tex_w = (float)io.Fonts->TexWidth;
     920        float my_tex_h = (float)io.Fonts->TexHeight;
     921        {
     922            ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
     923            ImVec2 pos = ImGui::GetCursorScreenPos();
     924            ImVec2 uv_min = ImVec2(0.0f, 0.0f);                 // Top-left
     925            ImVec2 uv_max = ImVec2(1.0f, 1.0f);                 // Lower-right
     926            ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);   // No tint
     927            ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f); // 50% opaque white
     928            ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
     929            if (ImGui::IsItemHovered())
     930            {
     931                ImGui::BeginTooltip();
     932                float region_sz = 32.0f;
     933                float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
     934                float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
     935                float zoom = 4.0f;
     936                if (region_x < 0.0f) { region_x = 0.0f; }
     937                else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
     938                if (region_y < 0.0f) { region_y = 0.0f; }
     939                else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
     940                ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
     941                ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
     942                ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
     943                ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
     944                ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col);
     945                ImGui::EndTooltip();
     946            }
     947        }
     948        ImGui::TextWrapped("And now some textured buttons..");
     949        static int pressed_count = 0;
     950        for (int i = 0; i < 8; i++)
     951        {
    605952            ImGui::PushID(i);
    606             int frame_padding = -1 + i;     // -1 = uses default padding
    607             if (ImGui::ImageButton(my_tex_id, ImVec2(32, 32), ImVec2(0, 0), ImVec2(32.0f / my_tex_w, 32 / my_tex_h), frame_padding, ImColor(0, 0, 0, 255)))
    608                pressed_count += 1;
     953            int frame_padding = -1 + i;                             // -1 == uses default padding (style.FramePadding)
     954            ImVec2 size = ImVec2(32.0f, 32.0f);                     // Size of the image we want to make visible
     955            ImVec2 uv0 = ImVec2(0.0f, 0.0f);                        // UV coordinates for lower-left
     956            ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h);// UV coordinates for (32,32) in our texture
     957            ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);         // Black background
     958            ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);       // No tint
     959            if (ImGui::ImageButton(my_tex_id, size, uv0, uv1, frame_padding, bg_col, tint_col))
     960                pressed_count += 1;
    609961            ImGui::PopID();
    610962            ImGui::SameLine();
    611          }
    612          ImGui::NewLine();
    613          ImGui::Text("Pressed %d times.", pressed_count);
    614          ImGui::TreePop();
    615       }
    616 
    617       if (ImGui::TreeNode("Combo"))
    618       {
    619          // Expose flags as checkbox for the demo
    620          static ImGuiComboFlags flags = 0;
    621          ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
    622          if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
     963        }
     964        ImGui::NewLine();
     965        ImGui::Text("Pressed %d times.", pressed_count);
     966        ImGui::TreePop();
     967    }
     968
     969    if (ImGui::TreeNode("Combo"))
     970    {
     971        // Expose flags as checkbox for the demo
     972        static ImGuiComboFlags flags = 0;
     973        ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
     974        ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
     975        if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
    623976            flags &= ~ImGuiComboFlags_NoPreview;     // Clear the other flag, as we cannot combine both
    624          if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
     977        if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
    625978            flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both
    626979
    627                                                      // General BeginCombo() API, you have full control over your selection data and display type.
    628                                                      // (your selection data could be an index, a pointer to the object, an id for the object, a flag stored in the object itself, etc.)
    629          const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
    630          static const char* item_current = items[0];            // Here our selection is a single pointer stored outside the object.
    631          if (ImGui::BeginCombo("combo 1", item_current, flags)) // The second parameter is the label previewed before opening the combo.
    632          {
     980        // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
     981        // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
     982        // stored in the object itself, etc.)
     983        const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
     984        static int item_current_idx = 0;                    // Here our selection data is an index.
     985        const char* combo_label = items[item_current_idx];  // Label to preview before opening the combo (technically it could be anything)
     986        if (ImGui::BeginCombo("combo 1", combo_label, flags))
     987        {
    633988            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
    634989            {
    635                bool is_selected = (item_current == items[n]);
    636                if (ImGui::Selectable(items[n], is_selected))
    637                   item_current = items[n];
    638                if (is_selected)
    639                   ImGui::SetItemDefaultFocus();   // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
     990                const bool is_selected = (item_current_idx == n);
     991                if (ImGui::Selectable(items[n], is_selected))
     992                    item_current_idx = n;
     993
     994                // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
     995                if (is_selected)
     996                    ImGui::SetItemDefaultFocus();
    640997            }
    641998            ImGui::EndCombo();
    642          }
    643 
    644          // Simplified one-liner Combo() API, using values packed in a single constant string
    645          static int item_current_2 = 0;
    646          ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
    647 
    648          // Simplified one-liner Combo() using an array of const char*
    649          static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
    650          ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
    651 
    652          // Simplified one-liner Combo() using an accessor function
    653          struct FuncHolder { static bool ItemGetter(void* data, int idx, const char** out_str) { *out_str = ((const char**)data)[idx]; return true; } };
    654          static int item_current_4 = 0;
    655          ImGui::Combo("combo 4 (function)", &item_current_4, &FuncHolder::ItemGetter, items, IM_ARRAYSIZE(items));
    656 
    657          ImGui::TreePop();
    658       }
    659 
    660       if (ImGui::TreeNode("Selectables"))
    661       {
    662          // Selectable() has 2 overloads:
    663          // - The one taking "bool selected" as a read-only selection information. When Selectable() has been clicked is returns true and you can alter selection state accordingly.
    664          // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
    665          // The earlier is more flexible, as in real application your selection may be stored in a different manner (in flags within objects, as an external list, etc).
    666          if (ImGui::TreeNode("Basic"))
    667          {
     999        }
     1000
     1001        // Simplified one-liner Combo() API, using values packed in a single constant string
     1002        static int item_current_2 = 0;
     1003        ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
     1004
     1005        // Simplified one-liner Combo() using an array of const char*
     1006        static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
     1007        ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
     1008
     1009        // Simplified one-liner Combo() using an accessor function
     1010        struct Funcs { static bool ItemGetter(void* data, int n, const char** out_str) { *out_str = ((const char**)data)[n]; return true; } };
     1011        static int item_current_4 = 0;
     1012        ImGui::Combo("combo 4 (function)", &item_current_4, &Funcs::ItemGetter, items, IM_ARRAYSIZE(items));
     1013
     1014        ImGui::TreePop();
     1015    }
     1016
     1017    if (ImGui::TreeNode("Selectables"))
     1018    {
     1019        // Selectable() has 2 overloads:
     1020        // - The one taking "bool selected" as a read-only selection information.
     1021        //   When Selectable() has been clicked it returns true and you can alter selection state accordingly.
     1022        // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
     1023        // The earlier is more flexible, as in real application your selection may be stored in many different ways
     1024        // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc).
     1025        if (ImGui::TreeNode("Basic"))
     1026        {
    6681027            static bool selection[5] = { false, true, false, false, false };
    6691028            ImGui::Selectable("1. I am selectable", &selection[0]);
     
    6721031            ImGui::Selectable("4. I am selectable", &selection[3]);
    6731032            if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
    674                if (ImGui::IsMouseDoubleClicked(0))
    675                   selection[4] = !selection[4];
     1033                if (ImGui::IsMouseDoubleClicked(0))
     1034                    selection[4] = !selection[4];
    6761035            ImGui::TreePop();
    677          }
    678          if (ImGui::TreeNode("Selection State: Single Selection"))
    679          {
     1036        }
     1037        if (ImGui::TreeNode("Selection State: Single Selection"))
     1038        {
    6801039            static int selected = -1;
    6811040            for (int n = 0; n < 5; n++)
    6821041            {
    683                char buf[32];
    684                sprintf(buf, "Object %d", n);
    685                if (ImGui::Selectable(buf, selected == n))
    686                   selected = n;
     1042                char buf[32];
     1043                sprintf(buf, "Object %d", n);
     1044                if (ImGui::Selectable(buf, selected == n))
     1045                    selected = n;
    6871046            }
    6881047            ImGui::TreePop();
    689          }
    690          if (ImGui::TreeNode("Selection State: Multiple Selection"))
    691          {
    692             ShowHelpMarker("Hold CTRL and click to select multiple items.");
     1048        }
     1049        if (ImGui::TreeNode("Selection State: Multiple Selection"))
     1050        {
     1051            HelpMarker("Hold CTRL and click to select multiple items.");
    6931052            static bool selection[5] = { false, false, false, false, false };
    6941053            for (int n = 0; n < 5; n++)
    6951054            {
    696                char buf[32];
    697                sprintf(buf, "Object %d", n);
    698                if (ImGui::Selectable(buf, selection[n]))
    699                {
    700                   if (!ImGui::GetIO().KeyCtrl)    // Clear selection when CTRL is not held
    701                      memset(selection, 0, sizeof(selection));
    702                   selection[n] ^= 1;
    703                }
     1055                char buf[32];
     1056                sprintf(buf, "Object %d", n);
     1057                if (ImGui::Selectable(buf, selection[n]))
     1058                {
     1059                    if (!ImGui::GetIO().KeyCtrl)    // Clear selection when CTRL is not held
     1060                        memset(selection, 0, sizeof(selection));
     1061                    selection[n] ^= 1;
     1062                }
    7041063            }
    7051064            ImGui::TreePop();
    706          }
    707          if (ImGui::TreeNode("Rendering more text into the same line"))
    708          {
    709             // Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically.
     1065        }
     1066        if (ImGui::TreeNode("Rendering more text into the same line"))
     1067        {
     1068            // Using the Selectable() override that takes "bool* p_selected" parameter,
     1069            // this function toggle your bool value automatically.
    7101070            static bool selected[3] = { false, false, false };
    711             ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
     1071            ImGui::Selectable("main.c",    &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
    7121072            ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
    713             ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
     1073            ImGui::Selectable("Hello.h",   &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
    7141074            ImGui::TreePop();
    715          }
    716          if (ImGui::TreeNode("In columns"))
    717          {
     1075        }
     1076        if (ImGui::TreeNode("In columns"))
     1077        {
    7181078            ImGui::Columns(3, NULL, false);
    719             static bool selected[16] = { 0 };
     1079            static bool selected[16] = {};
    7201080            for (int i = 0; i < 16; i++)
    7211081            {
    722                char label[32]; sprintf(label, "Item %d", i);
    723                if (ImGui::Selectable(label, &selected[i])) {}
    724                ImGui::NextColumn();
     1082                char label[32]; sprintf(label, "Item %d", i);
     1083                if (ImGui::Selectable(label, &selected[i])) {}
     1084                ImGui::NextColumn();
    7251085            }
    7261086            ImGui::Columns(1);
    7271087            ImGui::TreePop();
    728          }
    729          if (ImGui::TreeNode("Grid"))
    730          {
    731             static bool selected[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
    732             for (int i = 0; i < 16; i++)
    733             {
    734                ImGui::PushID(i);
    735                if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50, 50)))
    736                {
    737                   int x = i % 4, y = i / 4;
    738                   if (x > 0) selected[i - 1] ^= 1;
    739                   if (x < 3) selected[i + 1] ^= 1;
    740                   if (y > 0) selected[i - 4] ^= 1;
    741                   if (y < 3) selected[i + 4] ^= 1;
    742                }
    743                if ((i % 4) < 3) ImGui::SameLine();
    744                ImGui::PopID();
    745             }
     1088        }
     1089        if (ImGui::TreeNode("Grid"))
     1090        {
     1091            static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
     1092
     1093            // Add in a bit of silly fun...
     1094            const float time = (float)ImGui::GetTime();
     1095            const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected...
     1096            if (winning_state)
     1097                ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f)));
     1098
     1099            for (int y = 0; y < 4; y++)
     1100                for (int x = 0; x < 4; x++)
     1101                {
     1102                    if (x > 0)
     1103                        ImGui::SameLine();
     1104                    ImGui::PushID(y * 4 + x);
     1105                    if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50)))
     1106                    {
     1107                        // Toggle clicked cell + toggle neighbors
     1108                        selected[y][x] ^= 1;
     1109                        if (x > 0) { selected[y][x - 1] ^= 1; }
     1110                        if (x < 3) { selected[y][x + 1] ^= 1; }
     1111                        if (y > 0) { selected[y - 1][x] ^= 1; }
     1112                        if (y < 3) { selected[y + 1][x] ^= 1; }
     1113                    }
     1114                    ImGui::PopID();
     1115                }
     1116
     1117            if (winning_state)
     1118                ImGui::PopStyleVar();
    7461119            ImGui::TreePop();
    747          }
    748          ImGui::TreePop();
    749       }
    750 
    751       if (ImGui::TreeNode("Filtered Text Input"))
    752       {
    753          static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
    754          static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
    755          static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
    756          static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
    757          static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
    758          struct TextFilters { static int FilterImGuiLetters(ImGuiTextEditCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
    759          static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
    760 
    761          ImGui::Text("Password input");
    762          static char bufpass[64] = "password123";
    763          ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
    764          ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
    765          ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
    766 
    767          ImGui::TreePop();
    768       }
    769 
    770       if (ImGui::TreeNode("Multi-line Text Input"))
    771       {
    772          static bool read_only = false;
    773          static char text[1024 * 16] =
    774             "/*\n"
    775             " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
    776             " the hexadecimal encoding of one offending instruction,\n"
    777             " more formally, the invalid operand with locked CMPXCHG8B\n"
    778             " instruction bug, is a design flaw in the majority of\n"
    779             " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
    780             " processors (all in the P5 microarchitecture).\n"
    781             "*/\n\n"
    782             "label:\n"
    783             "\tlock cmpxchg8b eax\n";
    784 
    785          ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
    786          ImGui::Checkbox("Read-only", &read_only);
    787          ImGui::PopStyleVar();
    788          ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0));
    789          ImGui::TreePop();
    790       }
    791 
    792       if (ImGui::TreeNode("Plots widgets"))
    793       {
    794          static bool animate = true;
    795          ImGui::Checkbox("Animate", &animate);
    796 
    797          static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
    798          ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
    799 
    800          // Create a dummy array of contiguous float values to plot
    801          // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter.
    802          static float values[90] = { 0 };
    803          static int values_offset = 0;
    804          static float refresh_time = 0.0f;
    805          if (!animate || refresh_time == 0.0f)
     1120        }
     1121        if (ImGui::TreeNode("Alignment"))
     1122        {
     1123            HelpMarker(
     1124                "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item "
     1125                "basis using PushStyleVar(). You'll probably want to always keep your default situation to "
     1126                "left-align otherwise it becomes difficult to layout multiple items on a same line");
     1127            static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true };
     1128            for (int y = 0; y < 3; y++)
     1129            {
     1130                for (int x = 0; x < 3; x++)
     1131                {
     1132                    ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
     1133                    char name[32];
     1134                    sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
     1135                    if (x > 0) ImGui::SameLine();
     1136                    ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
     1137                    ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80));
     1138                    ImGui::PopStyleVar();
     1139                }
     1140            }
     1141            ImGui::TreePop();
     1142        }
     1143        ImGui::TreePop();
     1144    }
     1145
     1146    // To wire InputText() with std::string or any other custom string type,
     1147    // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
     1148    if (ImGui::TreeNode("Text Input"))
     1149    {
     1150        if (ImGui::TreeNode("Multi-line Text Input"))
     1151        {
     1152            // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
     1153            // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
     1154            static char text[1024 * 16] =
     1155                "/*\n"
     1156                " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
     1157                " the hexadecimal encoding of one offending instruction,\n"
     1158                " more formally, the invalid operand with locked CMPXCHG8B\n"
     1159                " instruction bug, is a design flaw in the majority of\n"
     1160                " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
     1161                " processors (all in the P5 microarchitecture).\n"
     1162                "*/\n\n"
     1163                "label:\n"
     1164                "\tlock cmpxchg8b eax\n";
     1165
     1166            static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
     1167            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)");
     1168            ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", (unsigned int*)&flags, ImGuiInputTextFlags_ReadOnly);
     1169            ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", (unsigned int*)&flags, ImGuiInputTextFlags_AllowTabInput);
     1170            ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", (unsigned int*)&flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
     1171            ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
     1172            ImGui::TreePop();
     1173        }
     1174
     1175        if (ImGui::TreeNode("Filtered Text Input"))
     1176        {
     1177            struct TextFilters
     1178            {
     1179                // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i'
     1180                static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
     1181                {
     1182                    if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
     1183                        return 0;
     1184                    return 1;
     1185                }
     1186            };
     1187
     1188            static char buf1[64] = ""; ImGui::InputText("default",     buf1, 64);
     1189            static char buf2[64] = ""; ImGui::InputText("decimal",     buf2, 64, ImGuiInputTextFlags_CharsDecimal);
     1190            static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
     1191            static char buf4[64] = ""; ImGui::InputText("uppercase",   buf4, 64, ImGuiInputTextFlags_CharsUppercase);
     1192            static char buf5[64] = ""; ImGui::InputText("no blank",    buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
     1193            static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
     1194            ImGui::TreePop();
     1195        }
     1196
     1197        if (ImGui::TreeNode("Password Input"))
     1198        {
     1199            static char password[64] = "password123";
     1200            ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
     1201            ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
     1202            ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
     1203            ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password));
     1204            ImGui::TreePop();
     1205        }
     1206
     1207        if (ImGui::TreeNode("Completion, History, Edit Callbacks"))
     1208        {
     1209            struct Funcs
     1210            {
     1211                static int MyCallback(ImGuiInputTextCallbackData* data)
     1212                {
     1213                    if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
     1214                    {
     1215                        data->InsertChars(data->CursorPos, "..");
     1216                    }
     1217                    else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
     1218                    {
     1219                        if (data->EventKey == ImGuiKey_UpArrow)
     1220                        {
     1221                            data->DeleteChars(0, data->BufTextLen);
     1222                            data->InsertChars(0, "Pressed Up!");
     1223                            data->SelectAll();
     1224                        }
     1225                        else if (data->EventKey == ImGuiKey_DownArrow)
     1226                        {
     1227                            data->DeleteChars(0, data->BufTextLen);
     1228                            data->InsertChars(0, "Pressed Down!");
     1229                            data->SelectAll();
     1230                        }
     1231                    }
     1232                    else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
     1233                    {
     1234                        // Toggle casing of first character
     1235                        char c = data->Buf[0];
     1236                        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32;
     1237                        data->BufDirty = true;
     1238
     1239                        // Increment a counter
     1240                        int* p_int = (int*)data->UserData;
     1241                        *p_int = *p_int + 1;
     1242                    }
     1243                    return 0;
     1244                }
     1245            };
     1246            static char buf1[64];
     1247            ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
     1248            ImGui::SameLine(); HelpMarker("Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
     1249
     1250            static char buf2[64];
     1251            ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
     1252            ImGui::SameLine(); HelpMarker("Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
     1253
     1254            static char buf3[64];
     1255            static int edit_count = 0;
     1256            ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
     1257            ImGui::SameLine(); HelpMarker("Here we toggle the casing of the first character on every edits + count edits.");
     1258            ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
     1259
     1260            ImGui::TreePop();
     1261        }
     1262
     1263        if (ImGui::TreeNode("Resize Callback"))
     1264        {
     1265            // To wire InputText() with std::string or any other custom string type,
     1266            // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper
     1267            // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string.
     1268            HelpMarker(
     1269                "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n"
     1270                "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string.");
     1271            struct Funcs
     1272            {
     1273                static int MyResizeCallback(ImGuiInputTextCallbackData* data)
     1274                {
     1275                    if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
     1276                    {
     1277                        ImVector<char>* my_str = (ImVector<char>*)data->UserData;
     1278                        IM_ASSERT(my_str->begin() == data->Buf);
     1279                        my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1
     1280                        data->Buf = my_str->begin();
     1281                    }
     1282                    return 0;
     1283                }
     1284
     1285                // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace.
     1286                // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)'
     1287                static bool MyInputTextMultiline(const char* label, ImVector<char>* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
     1288                {
     1289                    IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
     1290                    return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str);
     1291                }
     1292            };
     1293
     1294            // For this demo we are using ImVector as a string container.
     1295            // Note that because we need to store a terminating zero character, our size/capacity are 1 more
     1296            // than usually reported by a typical string class.
     1297            static ImVector<char> my_str;
     1298            if (my_str.empty())
     1299                my_str.push_back(0);
     1300            Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16));
     1301            ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity());
     1302            ImGui::TreePop();
     1303        }
     1304
     1305        ImGui::TreePop();
     1306    }
     1307
     1308    // Plot/Graph widgets are currently fairly limited.
     1309    // Consider writing your own plotting widget, or using a third-party one
     1310    // (for third-party Plot widgets, see 'Wiki->Useful Widgets' or https://github.com/ocornut/imgui/labels/plot%2Fgraph)
     1311    if (ImGui::TreeNode("Plots Widgets"))
     1312    {
     1313        static bool animate = true;
     1314        ImGui::Checkbox("Animate", &animate);
     1315
     1316        static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
     1317        ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
     1318
     1319        // Fill an array of contiguous float values to plot
     1320        // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
     1321        // and the sizeof() of your structure in the "stride" parameter.
     1322        static float values[90] = {};
     1323        static int values_offset = 0;
     1324        static double refresh_time = 0.0;
     1325        if (!animate || refresh_time == 0.0)
    8061326            refresh_time = ImGui::GetTime();
    807          while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo
    808          {
     1327        while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
     1328        {
    8091329            static float phase = 0.0f;
    8101330            values[values_offset] = cosf(phase);
    8111331            values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
    812             phase += 0.10f*values_offset;
     1332            phase += 0.10f * values_offset;
    8131333            refresh_time += 1.0f / 60.0f;
    814          }
    815          ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0, 80));
    816          ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80));
    817 
    818          // Use functions to generate output
    819          // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count.
    820          struct Funcs
    821          {
     1334        }
     1335
     1336        // Plots can display overlay texts
     1337        // (in this example, we will display an average value)
     1338        {
     1339            float average = 0.0f;
     1340            for (int n = 0; n < IM_ARRAYSIZE(values); n++)
     1341                average += values[n];
     1342            average /= (float)IM_ARRAYSIZE(values);
     1343            char overlay[32];
     1344            sprintf(overlay, "avg %f", average);
     1345            ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
     1346        }
     1347        ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
     1348
     1349        // Use functions to generate output
     1350        // FIXME: This is rather awkward because current plot API only pass in indices.
     1351        // We probably want an API passing floats and user provide sample rate/count.
     1352        struct Funcs
     1353        {
    8221354            static float Sin(void*, int i) { return sinf(i * 0.1f); }
    8231355            static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
    824          };
    825          static int func_type = 0, display_count = 70;
    826          ImGui::Separator();
    827          ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
    828          ImGui::SameLine();
    829          ImGui::SliderInt("Sample count", &display_count, 1, 400);
    830          float(*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
    831          ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
    832          ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
    833          ImGui::Separator();
    834 
    835          // Animate a simple progress bar
    836          static float progress = 0.0f, progress_dir = 1.0f;
    837          if (animate)
    838          {
     1356        };
     1357        static int func_type = 0, display_count = 70;
     1358        ImGui::Separator();
     1359        ImGui::SetNextItemWidth(100);
     1360        ImGui::Combo("func", &func_type, "Sin\0Saw\0");
     1361        ImGui::SameLine();
     1362        ImGui::SliderInt("Sample count", &display_count, 1, 400);
     1363        float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
     1364        ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
     1365        ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
     1366        ImGui::Separator();
     1367
     1368        // Animate a simple progress bar
     1369        static float progress = 0.0f, progress_dir = 1.0f;
     1370        if (animate)
     1371        {
    8391372            progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
    8401373            if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
    8411374            if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
    842          }
    843 
    844          // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
    845          ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
    846          ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
    847          ImGui::Text("Progress Bar");
    848 
    849          float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
    850          char buf[32];
    851          sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
    852          ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
    853          ImGui::TreePop();
    854       }
    855 
    856       if (ImGui::TreeNode("Color/Picker Widgets"))
    857       {
    858          static ImVec4 color = ImColor(114, 144, 154, 200);
    859 
    860          static bool alpha_preview = true;
    861          static bool alpha_half_preview = false;
    862          static bool options_menu = true;
    863          static bool hdr = false;
    864          ImGui::Checkbox("With Alpha Preview", &alpha_preview);
    865          ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
    866          ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
    867          ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
    868          int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions);
    869 
    870          ImGui::Text("Color widget:");
    871          ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
    872          ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
    873 
    874          ImGui::Text("Color widget HSV with Alpha:");
    875          ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
    876 
    877          ImGui::Text("Color widget with Float Display:");
    878          ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
    879 
    880          ImGui::Text("Color button with Picker:");
    881          ImGui::SameLine(); ShowHelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.");
    882          ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
    883 
    884          ImGui::Text("Color button with Custom Picker Popup:");
    885 
    886          // Generate a dummy palette
    887          static bool saved_palette_inited = false;
    888          static ImVec4 saved_palette[32];
    889          if (!saved_palette_inited)
     1375        }
     1376
     1377        // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
     1378        // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
     1379        ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
     1380        ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
     1381        ImGui::Text("Progress Bar");
     1382
     1383        float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
     1384        char buf[32];
     1385        sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
     1386        ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
     1387        ImGui::TreePop();
     1388    }
     1389
     1390    if (ImGui::TreeNode("Color/Picker Widgets"))
     1391    {
     1392        static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
     1393
     1394        static bool alpha_preview = true;
     1395        static bool alpha_half_preview = false;
     1396        static bool drag_and_drop = true;
     1397        static bool options_menu = true;
     1398        static bool hdr = false;
     1399        ImGui::Checkbox("With Alpha Preview", &alpha_preview);
     1400        ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
     1401        ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
     1402        ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
     1403        ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
     1404        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);
     1405
     1406        ImGui::Text("Color widget:");
     1407        ImGui::SameLine(); HelpMarker(
     1408            "Click on the colored square to open a color picker.\n"
     1409            "CTRL+click on individual component to input value.\n");
     1410        ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
     1411
     1412        ImGui::Text("Color widget HSV with Alpha:");
     1413        ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags);
     1414
     1415        ImGui::Text("Color widget with Float Display:");
     1416        ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
     1417
     1418        ImGui::Text("Color button with Picker:");
     1419        ImGui::SameLine(); HelpMarker(
     1420            "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n"
     1421            "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only "
     1422            "be used for the tooltip and picker popup.");
     1423        ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
     1424
     1425        ImGui::Text("Color button with Custom Picker Popup:");
     1426
     1427        // Generate a default palette. The palette will persist and can be edited.
     1428        static bool saved_palette_init = true;
     1429        static ImVec4 saved_palette[32] = {};
     1430        if (saved_palette_init)
     1431        {
    8901432            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
    8911433            {
    892                ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
    893                saved_palette[n].w = 1.0f; // Alpha
    894             }
    895          saved_palette_inited = true;
    896 
    897          static ImVec4 backup_color;
    898          bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
    899          ImGui::SameLine();
    900          open_popup |= ImGui::Button("Palette");
    901          if (open_popup)
    902          {
     1434                ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f,
     1435                    saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
     1436                saved_palette[n].w = 1.0f; // Alpha
     1437            }
     1438            saved_palette_init = false;
     1439        }
     1440
     1441        static ImVec4 backup_color;
     1442        bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
     1443        ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
     1444        open_popup |= ImGui::Button("Palette");
     1445        if (open_popup)
     1446        {
    9031447            ImGui::OpenPopup("mypicker");
    9041448            backup_color = color;
    905          }
    906          if (ImGui::BeginPopup("mypicker"))
    907          {
    908             // FIXME: Adding a drag and drop example here would be perfect!
     1449        }
     1450        if (ImGui::BeginPopup("mypicker"))
     1451        {
    9091452            ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
    9101453            ImGui::Separator();
    9111454            ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
    9121455            ImGui::SameLine();
    913             ImGui::BeginGroup();
     1456
     1457            ImGui::BeginGroup(); // Lock X position
    9141458            ImGui::Text("Current");
    9151459            ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
    9161460            ImGui::Text("Previous");
    9171461            if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
    918                color = backup_color;
     1462                color = backup_color;
    9191463            ImGui::Separator();
    9201464            ImGui::Text("Palette");
    9211465            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
    9221466            {
    923                ImGui::PushID(n);
    924                if ((n % 8) != 0)
    925                   ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
    926                if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20)))
    927                   color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
    928 
    929                if (ImGui::BeginDragDropTarget())
    930                {
    931                   if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
    932                      memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
    933                   if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
    934                      memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
    935                   EndDragDropTarget();
    936                }
    937 
    938                ImGui::PopID();
     1467                ImGui::PushID(n);
     1468                if ((n % 8) != 0)
     1469                    ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
     1470
     1471                ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
     1472                if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
     1473                    color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
     1474
     1475                // Allow user to drop colors into each palette entry. Note that ColorButton() is already a
     1476                // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag.
     1477                if (ImGui::BeginDragDropTarget())
     1478                {
     1479                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
     1480                        memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
     1481                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
     1482                        memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
     1483                    ImGui::EndDragDropTarget();
     1484                }
     1485
     1486                ImGui::PopID();
    9391487            }
    9401488            ImGui::EndGroup();
    9411489            ImGui::EndPopup();
    942          }
    943 
    944          ImGui::Text("Color button only:");
    945          ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80, 80));
    946 
    947          ImGui::Text("Color picker:");
    948          static bool alpha = true;
    949          static bool alpha_bar = true;
    950          static bool side_preview = true;
    951          static bool ref_color = false;
    952          static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
    953          static int inputs_mode = 2;
    954          static int picker_mode = 0;
    955          ImGui::Checkbox("With Alpha", &alpha);
    956          ImGui::Checkbox("With Alpha Bar", &alpha_bar);
    957          ImGui::Checkbox("With Side Preview", &side_preview);
    958          if (side_preview)
    959          {
     1490        }
     1491
     1492        ImGui::Text("Color button only:");
     1493        static bool no_border = false;
     1494        ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
     1495        ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
     1496
     1497        ImGui::Text("Color picker:");
     1498        static bool alpha = true;
     1499        static bool alpha_bar = true;
     1500        static bool side_preview = true;
     1501        static bool ref_color = false;
     1502        static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
     1503        static int display_mode = 0;
     1504        static int picker_mode = 0;
     1505        ImGui::Checkbox("With Alpha", &alpha);
     1506        ImGui::Checkbox("With Alpha Bar", &alpha_bar);
     1507        ImGui::Checkbox("With Side Preview", &side_preview);
     1508        if (side_preview)
     1509        {
    9601510            ImGui::SameLine();
    9611511            ImGui::Checkbox("With Ref Color", &ref_color);
    9621512            if (ref_color)
    9631513            {
    964                ImGui::SameLine();
    965                ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
    966             }
    967          }
    968          ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
    969          ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
    970          ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
    971          ImGuiColorEditFlags flags = misc_flags;
    972          if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
    973          if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
    974          if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
    975          if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
    976          if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
    977          if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;
    978          if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;
    979          if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;
    980          if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;
    981          ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
    982 
    983          ImGui::Text("Programmatically set defaults/options:");
    984          ImGui::SameLine(); ShowHelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.");
    985          if (ImGui::Button("Uint8 + HSV"))
    986             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV);
    987          ImGui::SameLine();
    988          if (ImGui::Button("Float + HDR"))
    989             ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_RGB);
    990 
    991          ImGui::TreePop();
    992       }
    993 
    994       if (ImGui::TreeNode("Range Widgets"))
    995       {
    996          static float begin = 10, end = 90;
    997          static int begin_i = 100, end_i = 1000;
    998          ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
    999          ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %.0f units", "Max: %.0f units");
    1000          ImGui::TreePop();
    1001       }
    1002 
    1003       if (ImGui::TreeNode("Multi-component Widgets"))
    1004       {
    1005          static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
    1006          static int vec4i[4] = { 1, 5, 100, 255 };
    1007 
    1008          ImGui::InputFloat2("input float2", vec4f);
    1009          ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
    1010          ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
    1011          ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
    1012          ImGui::InputInt2("input int2", vec4i);
    1013          ImGui::SliderInt2("slider int2", vec4i, 0, 255);
    1014          ImGui::Spacing();
    1015 
    1016          ImGui::InputFloat3("input float3", vec4f);
    1017          ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
    1018          ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
    1019          ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
    1020          ImGui::InputInt3("input int3", vec4i);
    1021          ImGui::SliderInt3("slider int3", vec4i, 0, 255);
    1022          ImGui::Spacing();
    1023 
    1024          ImGui::InputFloat4("input float4", vec4f);
    1025          ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
    1026          ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
    1027          ImGui::InputInt4("input int4", vec4i);
    1028          ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
    1029          ImGui::SliderInt4("slider int4", vec4i, 0, 255);
    1030 
    1031          ImGui::TreePop();
    1032       }
    1033 
    1034       if (ImGui::TreeNode("Vertical Sliders"))
    1035       {
    1036          const float spacing = 4;
    1037          ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
    1038 
    1039          static int int_value = 0;
    1040          ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
    1041          ImGui::SameLine();
    1042 
    1043          static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
    1044          ImGui::PushID("set1");
    1045          for (int i = 0; i < 7; i++)
    1046          {
     1514                ImGui::SameLine();
     1515                ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
     1516            }
     1517        }
     1518        ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
     1519        ImGui::SameLine(); HelpMarker(
     1520            "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
     1521            "but the user can change it with a right-click.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
     1522            "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
     1523        ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
     1524        ImGui::SameLine(); HelpMarker("User can right-click the picker to change mode.");
     1525        ImGuiColorEditFlags flags = misc_flags;
     1526        if (!alpha)            flags |= ImGuiColorEditFlags_NoAlpha;        // This is by default if you call ColorPicker3() instead of ColorPicker4()
     1527        if (alpha_bar)         flags |= ImGuiColorEditFlags_AlphaBar;
     1528        if (!side_preview)     flags |= ImGuiColorEditFlags_NoSidePreview;
     1529        if (picker_mode == 1)  flags |= ImGuiColorEditFlags_PickerHueBar;
     1530        if (picker_mode == 2)  flags |= ImGuiColorEditFlags_PickerHueWheel;
     1531        if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;       // Disable all RGB/HSV/Hex displays
     1532        if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB;     // Override display mode
     1533        if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
     1534        if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
     1535        ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
     1536
     1537        ImGui::Text("Set defaults in code:");
     1538        ImGui::SameLine(); HelpMarker(
     1539            "SetColorEditOptions() is designed to allow you to set boot-time default.\n"
     1540            "We don't have Push/Pop functions because you can force options on a per-widget basis if needed,"
     1541            "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid"
     1542            "encouraging you to persistently save values that aren't forward-compatible.");
     1543        if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
     1544            ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
     1545        if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
     1546            ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
     1547
     1548        // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
     1549        static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
     1550        ImGui::Spacing();
     1551        ImGui::Text("HSV encoded colors");
     1552        ImGui::SameLine(); HelpMarker(
     1553            "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV"
     1554            "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the"
     1555            "added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
     1556        ImGui::Text("Color widget with InputHSV:");
     1557        ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
     1558        ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
     1559        ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f);
     1560
     1561        ImGui::TreePop();
     1562    }
     1563
     1564    if (ImGui::TreeNode("Drag/Slider Flags"))
     1565    {
     1566        // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
     1567        static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
     1568        ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", (unsigned int*)&flags, ImGuiSliderFlags_AlwaysClamp);
     1569        ImGui::SameLine(); HelpMarker("Always clamp value to min/max bounds (if any) when input manually with CTRL+Click.");
     1570        ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", (unsigned int*)&flags, ImGuiSliderFlags_Logarithmic);
     1571        ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values).");
     1572        ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", (unsigned int*)&flags, ImGuiSliderFlags_NoRoundToFormat);
     1573        ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
     1574        ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", (unsigned int*)&flags, ImGuiSliderFlags_NoInput);
     1575        ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
     1576
     1577        // Drags
     1578        static float drag_f = 0.5f;
     1579        static int drag_i = 50;
     1580        ImGui::Text("Underlying float value: %f", drag_f);
     1581        ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags);
     1582        ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags);
     1583        ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags);
     1584        ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags);
     1585        ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
     1586
     1587        // Sliders
     1588        static float slider_f = 0.5f;
     1589        static int slider_i = 50;
     1590        ImGui::Text("Underlying float value: %f", slider_f);
     1591        ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags);
     1592        ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags);
     1593
     1594        ImGui::TreePop();
     1595    }
     1596
     1597    if (ImGui::TreeNode("Range Widgets"))
     1598    {
     1599        static float begin = 10, end = 90;
     1600        static int begin_i = 100, end_i = 1000;
     1601        ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp);
     1602        ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units");
     1603        ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
     1604        ImGui::TreePop();
     1605    }
     1606
     1607    if (ImGui::TreeNode("Data Types"))
     1608    {
     1609        // DragScalar/InputScalar/SliderScalar functions allow various data types
     1610        // - signed/unsigned
     1611        // - 8/16/32/64-bits
     1612        // - integer/float/double
     1613        // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum
     1614        // to pass the type, and passing all arguments by pointer.
     1615        // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
     1616        // In practice, if you frequently use a given type that is not covered by the normal API entry points,
     1617        // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*,
     1618        // and then pass their address to the generic function. For example:
     1619        //   bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
     1620        //   {
     1621        //      return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
     1622        //   }
     1623
     1624        // Setup limits (as helper variables so we can take their address, as explained above)
     1625        // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
     1626        #ifndef LLONG_MIN
     1627        ImS64 LLONG_MIN = -9223372036854775807LL - 1;
     1628        ImS64 LLONG_MAX = 9223372036854775807LL;
     1629        ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
     1630        #endif
     1631        const char    s8_zero  = 0,   s8_one  = 1,   s8_fifty  = 50, s8_min  = -128,        s8_max = 127;
     1632        const ImU8    u8_zero  = 0,   u8_one  = 1,   u8_fifty  = 50, u8_min  = 0,           u8_max = 255;
     1633        const short   s16_zero = 0,   s16_one = 1,   s16_fifty = 50, s16_min = -32768,      s16_max = 32767;
     1634        const ImU16   u16_zero = 0,   u16_one = 1,   u16_fifty = 50, u16_min = 0,           u16_max = 65535;
     1635        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;
     1636        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;
     1637        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;
     1638        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;
     1639        const float   f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
     1640        const double  f64_zero = 0.,  f64_one = 1.,  f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
     1641
     1642        // State
     1643        static char   s8_v  = 127;
     1644        static ImU8   u8_v  = 255;
     1645        static short  s16_v = 32767;
     1646        static ImU16  u16_v = 65535;
     1647        static ImS32  s32_v = -1;
     1648        static ImU32  u32_v = (ImU32)-1;
     1649        static ImS64  s64_v = -1;
     1650        static ImU64  u64_v = (ImU64)-1;
     1651        static float  f32_v = 0.123f;
     1652        static double f64_v = 90000.01234567890123456789;
     1653
     1654        const float drag_speed = 0.2f;
     1655        static bool drag_clamp = false;
     1656        ImGui::Text("Drags:");
     1657        ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
     1658        ImGui::SameLine(); HelpMarker(
     1659            "As with every widgets in dear imgui, we never modify values unless there is a user interaction.\n"
     1660            "You can override the clamping limits by using CTRL+Click to input a value.");
     1661        ImGui::DragScalar("drag s8",        ImGuiDataType_S8,     &s8_v,  drag_speed, drag_clamp ? &s8_zero  : NULL, drag_clamp ? &s8_fifty  : NULL);
     1662        ImGui::DragScalar("drag u8",        ImGuiDataType_U8,     &u8_v,  drag_speed, drag_clamp ? &u8_zero  : NULL, drag_clamp ? &u8_fifty  : NULL, "%u ms");
     1663        ImGui::DragScalar("drag s16",       ImGuiDataType_S16,    &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
     1664        ImGui::DragScalar("drag u16",       ImGuiDataType_U16,    &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
     1665        ImGui::DragScalar("drag s32",       ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
     1666        ImGui::DragScalar("drag u32",       ImGuiDataType_U32,    &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
     1667        ImGui::DragScalar("drag s64",       ImGuiDataType_S64,    &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
     1668        ImGui::DragScalar("drag u64",       ImGuiDataType_U64,    &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
     1669        ImGui::DragScalar("drag float",     ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f");
     1670        ImGui::DragScalar("drag float log", ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic);
     1671        ImGui::DragScalar("drag double",    ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL,     "%.10f grams");
     1672        ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic);
     1673
     1674        ImGui::Text("Sliders");
     1675        ImGui::SliderScalar("slider s8 full",       ImGuiDataType_S8,     &s8_v,  &s8_min,   &s8_max,   "%d");
     1676        ImGui::SliderScalar("slider u8 full",       ImGuiDataType_U8,     &u8_v,  &u8_min,   &u8_max,   "%u");
     1677        ImGui::SliderScalar("slider s16 full",      ImGuiDataType_S16,    &s16_v, &s16_min,  &s16_max,  "%d");
     1678        ImGui::SliderScalar("slider u16 full",      ImGuiDataType_U16,    &u16_v, &u16_min,  &u16_max,  "%u");
     1679        ImGui::SliderScalar("slider s32 low",       ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty,"%d");
     1680        ImGui::SliderScalar("slider s32 high",      ImGuiDataType_S32,    &s32_v, &s32_hi_a, &s32_hi_b, "%d");
     1681        ImGui::SliderScalar("slider s32 full",      ImGuiDataType_S32,    &s32_v, &s32_min,  &s32_max,  "%d");
     1682        ImGui::SliderScalar("slider u32 low",       ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u");
     1683        ImGui::SliderScalar("slider u32 high",      ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u");
     1684        ImGui::SliderScalar("slider u32 full",      ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u");
     1685        ImGui::SliderScalar("slider s64 low",       ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%I64d");
     1686        ImGui::SliderScalar("slider s64 high",      ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%I64d");
     1687        ImGui::SliderScalar("slider s64 full",      ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%I64d");
     1688        ImGui::SliderScalar("slider u64 low",       ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%I64u ms");
     1689        ImGui::SliderScalar("slider u64 high",      ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms");
     1690        ImGui::SliderScalar("slider u64 full",      ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%I64u ms");
     1691        ImGui::SliderScalar("slider float low",     ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one);
     1692        ImGui::SliderScalar("slider float low log", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
     1693        ImGui::SliderScalar("slider float high",    ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e");
     1694        ImGui::SliderScalar("slider double low",    ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f grams");
     1695        ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
     1696        ImGui::SliderScalar("slider double high",   ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
     1697
     1698        ImGui::Text("Sliders (reverse)");
     1699        ImGui::SliderScalar("slider s8 reverse",    ImGuiDataType_S8,   &s8_v,  &s8_max,    &s8_min, "%d");
     1700        ImGui::SliderScalar("slider u8 reverse",    ImGuiDataType_U8,   &u8_v,  &u8_max,    &u8_min, "%u");
     1701        ImGui::SliderScalar("slider s32 reverse",   ImGuiDataType_S32,  &s32_v, &s32_fifty, &s32_zero, "%d");
     1702        ImGui::SliderScalar("slider u32 reverse",   ImGuiDataType_U32,  &u32_v, &u32_fifty, &u32_zero, "%u");
     1703        ImGui::SliderScalar("slider s64 reverse",   ImGuiDataType_S64,  &s64_v, &s64_fifty, &s64_zero, "%I64d");
     1704        ImGui::SliderScalar("slider u64 reverse",   ImGuiDataType_U64,  &u64_v, &u64_fifty, &u64_zero, "%I64u ms");
     1705
     1706        static bool inputs_step = true;
     1707        ImGui::Text("Inputs");
     1708        ImGui::Checkbox("Show step buttons", &inputs_step);
     1709        ImGui::InputScalar("input s8",      ImGuiDataType_S8,     &s8_v,  inputs_step ? &s8_one  : NULL, NULL, "%d");
     1710        ImGui::InputScalar("input u8",      ImGuiDataType_U8,     &u8_v,  inputs_step ? &u8_one  : NULL, NULL, "%u");
     1711        ImGui::InputScalar("input s16",     ImGuiDataType_S16,    &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d");
     1712        ImGui::InputScalar("input u16",     ImGuiDataType_U16,    &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u");
     1713        ImGui::InputScalar("input s32",     ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
     1714        ImGui::InputScalar("input s32 hex", ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
     1715        ImGui::InputScalar("input u32",     ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
     1716        ImGui::InputScalar("input u32 hex", ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
     1717        ImGui::InputScalar("input s64",     ImGuiDataType_S64,    &s64_v, inputs_step ? &s64_one : NULL);
     1718        ImGui::InputScalar("input u64",     ImGuiDataType_U64,    &u64_v, inputs_step ? &u64_one : NULL);
     1719        ImGui::InputScalar("input float",   ImGuiDataType_Float,  &f32_v, inputs_step ? &f32_one : NULL);
     1720        ImGui::InputScalar("input double",  ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
     1721
     1722        ImGui::TreePop();
     1723    }
     1724
     1725    if (ImGui::TreeNode("Multi-component Widgets"))
     1726    {
     1727        static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
     1728        static int vec4i[4] = { 1, 5, 100, 255 };
     1729
     1730        ImGui::InputFloat2("input float2", vec4f);
     1731        ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
     1732        ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
     1733        ImGui::InputInt2("input int2", vec4i);
     1734        ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
     1735        ImGui::SliderInt2("slider int2", vec4i, 0, 255);
     1736        ImGui::Spacing();
     1737
     1738        ImGui::InputFloat3("input float3", vec4f);
     1739        ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
     1740        ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
     1741        ImGui::InputInt3("input int3", vec4i);
     1742        ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
     1743        ImGui::SliderInt3("slider int3", vec4i, 0, 255);
     1744        ImGui::Spacing();
     1745
     1746        ImGui::InputFloat4("input float4", vec4f);
     1747        ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
     1748        ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
     1749        ImGui::InputInt4("input int4", vec4i);
     1750        ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
     1751        ImGui::SliderInt4("slider int4", vec4i, 0, 255);
     1752
     1753        ImGui::TreePop();
     1754    }
     1755
     1756    if (ImGui::TreeNode("Vertical Sliders"))
     1757    {
     1758        const float spacing = 4;
     1759        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
     1760
     1761        static int int_value = 0;
     1762        ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
     1763        ImGui::SameLine();
     1764
     1765        static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
     1766        ImGui::PushID("set1");
     1767        for (int i = 0; i < 7; i++)
     1768        {
    10471769            if (i > 0) ImGui::SameLine();
    10481770            ImGui::PushID(i);
     
    10531775            ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
    10541776            if (ImGui::IsItemActive() || ImGui::IsItemHovered())
    1055                ImGui::SetTooltip("%.3f", values[i]);
     1777                ImGui::SetTooltip("%.3f", values[i]);
    10561778            ImGui::PopStyleColor(4);
    10571779            ImGui::PopID();
    1058          }
    1059          ImGui::PopID();
    1060 
    1061          ImGui::SameLine();
    1062          ImGui::PushID("set2");
    1063          static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
    1064          const int rows = 3;
    1065          const ImVec2 small_slider_size(18, (160.0f - (rows - 1)*spacing) / rows);
    1066          for (int nx = 0; nx < 4; nx++)
    1067          {
     1780        }
     1781        ImGui::PopID();
     1782
     1783        ImGui::SameLine();
     1784        ImGui::PushID("set2");
     1785        static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
     1786        const int rows = 3;
     1787        const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
     1788        for (int nx = 0; nx < 4; nx++)
     1789        {
    10681790            if (nx > 0) ImGui::SameLine();
    10691791            ImGui::BeginGroup();
    10701792            for (int ny = 0; ny < rows; ny++)
    10711793            {
    1072                ImGui::PushID(nx*rows + ny);
    1073                ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
    1074                if (ImGui::IsItemActive() || ImGui::IsItemHovered())
    1075                   ImGui::SetTooltip("%.3f", values2[nx]);
    1076                ImGui::PopID();
     1794                ImGui::PushID(nx * rows + ny);
     1795                ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
     1796                if (ImGui::IsItemActive() || ImGui::IsItemHovered())
     1797                    ImGui::SetTooltip("%.3f", values2[nx]);
     1798                ImGui::PopID();
    10771799            }
    10781800            ImGui::EndGroup();
    1079          }
    1080          ImGui::PopID();
    1081 
    1082          ImGui::SameLine();
    1083          ImGui::PushID("set3");
    1084          for (int i = 0; i < 4; i++)
    1085          {
     1801        }
     1802        ImGui::PopID();
     1803
     1804        ImGui::SameLine();
     1805        ImGui::PushID("set3");
     1806        for (int i = 0; i < 4; i++)
     1807        {
    10861808            if (i > 0) ImGui::SameLine();
    10871809            ImGui::PushID(i);
     
    10901812            ImGui::PopStyleVar();
    10911813            ImGui::PopID();
    1092          }
    1093          ImGui::PopID();
    1094          ImGui::PopStyleVar();
    1095          ImGui::TreePop();
    1096       }
    1097    }
    1098 
    1099    if (ImGui::CollapsingHeader("Layout"))
    1100    {
    1101       if (ImGui::TreeNode("Child regions"))
    1102       {
    1103          static bool disable_mouse_wheel = false;
    1104          static bool disable_menu = false;
    1105          ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
    1106          ImGui::Checkbox("Disable Menu", &disable_menu);
    1107 
    1108          static int line = 50;
    1109          bool goto_line = ImGui::Button("Goto");
    1110          ImGui::SameLine();
    1111          ImGui::PushItemWidth(100);
    1112          goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
    1113          ImGui::PopItemWidth();
    1114 
    1115          // Child 1: no border, enable horizontal scrollbar
    1116          {
    1117             ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0));
     1814        }
     1815        ImGui::PopID();
     1816        ImGui::PopStyleVar();
     1817        ImGui::TreePop();
     1818    }
     1819
     1820    if (ImGui::TreeNode("Drag and Drop"))
     1821    {
     1822        if (ImGui::TreeNode("Drag and drop in standard widgets"))
     1823        {
     1824            // ColorEdit widgets automatically act as drag source and drag target.
     1825            // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F
     1826            // to allow your own widgets to use colors in their drag and drop interaction.
     1827            // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo.
     1828            HelpMarker("You can drag from the colored squares.");
     1829            static float col1[3] = { 1.0f, 0.0f, 0.2f };
     1830            static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
     1831            ImGui::ColorEdit3("color 1", col1);
     1832            ImGui::ColorEdit4("color 2", col2);
     1833            ImGui::TreePop();
     1834        }
     1835
     1836        if (ImGui::TreeNode("Drag and drop to copy/swap items"))
     1837        {
     1838            enum Mode
     1839            {
     1840                Mode_Copy,
     1841                Mode_Move,
     1842                Mode_Swap
     1843            };
     1844            static int mode = 0;
     1845            if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
     1846            if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
     1847            if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
     1848            static const char* names[9] =
     1849            {
     1850                "Bobby", "Beatrice", "Betty",
     1851                "Brianna", "Barry", "Bernard",
     1852                "Bibi", "Blaine", "Bryn"
     1853            };
     1854            for (int n = 0; n < IM_ARRAYSIZE(names); n++)
     1855            {
     1856                ImGui::PushID(n);
     1857                if ((n % 3) != 0)
     1858                    ImGui::SameLine();
     1859                ImGui::Button(names[n], ImVec2(60, 60));
     1860
     1861                // Our buttons are both drag sources and drag targets here!
     1862                if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
     1863                {
     1864                    // Set payload to carry the index of our item (could be anything)
     1865                    ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));
     1866
     1867                    // Display preview (could be anything, e.g. when dragging an image we could decide to display
     1868                    // the filename and a small preview of the image, etc.)
     1869                    if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }
     1870                    if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
     1871                    if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
     1872                    ImGui::EndDragDropSource();
     1873                }
     1874                if (ImGui::BeginDragDropTarget())
     1875                {
     1876                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
     1877                    {
     1878                        IM_ASSERT(payload->DataSize == sizeof(int));
     1879                        int payload_n = *(const int*)payload->Data;
     1880                        if (mode == Mode_Copy)
     1881                        {
     1882                            names[n] = names[payload_n];
     1883                        }
     1884                        if (mode == Mode_Move)
     1885                        {
     1886                            names[n] = names[payload_n];
     1887                            names[payload_n] = "";
     1888                        }
     1889                        if (mode == Mode_Swap)
     1890                        {
     1891                            const char* tmp = names[n];
     1892                            names[n] = names[payload_n];
     1893                            names[payload_n] = tmp;
     1894                        }
     1895                    }
     1896                    ImGui::EndDragDropTarget();
     1897                }
     1898                ImGui::PopID();
     1899            }
     1900            ImGui::TreePop();
     1901        }
     1902
     1903        if (ImGui::TreeNode("Drag to reorder items (simple)"))
     1904        {
     1905            // Simple reordering
     1906            HelpMarker(
     1907                "We don't use the drag and drop api at all here! "
     1908                "Instead we query when the item is held but not hovered, and order items accordingly.");
     1909            static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
     1910            for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
     1911            {
     1912                const char* item = item_names[n];
     1913                ImGui::Selectable(item);
     1914
     1915                if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
     1916                {
     1917                    int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
     1918                    if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
     1919                    {
     1920                        item_names[n] = item_names[n_next];
     1921                        item_names[n_next] = item;
     1922                        ImGui::ResetMouseDragDelta();
     1923                    }
     1924                }
     1925            }
     1926            ImGui::TreePop();
     1927        }
     1928
     1929        ImGui::TreePop();
     1930    }
     1931
     1932    if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)"))
     1933    {
     1934        // Select an item type
     1935        const char* item_names[] =
     1936        {
     1937            "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat",
     1938            "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "ListBox"
     1939        };
     1940        static int item_type = 1;
     1941        ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
     1942        ImGui::SameLine();
     1943        HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions.");
     1944
     1945        // Submit selected item item so we can query their status in the code following it.
     1946        bool ret = false;
     1947        static bool b = false;
     1948        static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
     1949        static char str[16] = {};
     1950        if (item_type == 0) { ImGui::Text("ITEM: Text"); }                                              // Testing text items with no identifier/interaction
     1951        if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); }                                    // Testing button
     1952        if (item_type == 2) { ImGui::PushButtonRepeat(true); ret = ImGui::Button("ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater)
     1953        if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); }                            // Testing checkbox
     1954        if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
     1955        if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); }  // Testing input text (which handles tabbing)
     1956        if (item_type == 6) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); }               // Testing +/- buttons on scalar input
     1957        if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); }                   // Testing multi-component items (IsItemXXX flags are reported merged)
     1958        if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
     1959        if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); }                                // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
     1960        if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); }     // Testing tree node
     1961        if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
     1962        if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
     1963
     1964        // Display the values of IsItemHovered() and other common item state functions.
     1965        // Note that the ImGuiHoveredFlags_XXX flags can be combined.
     1966        // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
     1967        // we query every state in a single call to avoid storing them and to simplify the code.
     1968        ImGui::BulletText(
     1969            "Return value = %d\n"
     1970            "IsItemFocused() = %d\n"
     1971            "IsItemHovered() = %d\n"
     1972            "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
     1973            "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
     1974            "IsItemHovered(_AllowWhenOverlapped) = %d\n"
     1975            "IsItemHovered(_RectOnly) = %d\n"
     1976            "IsItemActive() = %d\n"
     1977            "IsItemEdited() = %d\n"
     1978            "IsItemActivated() = %d\n"
     1979            "IsItemDeactivated() = %d\n"
     1980            "IsItemDeactivatedAfterEdit() = %d\n"
     1981            "IsItemVisible() = %d\n"
     1982            "IsItemClicked() = %d\n"
     1983            "IsItemToggledOpen() = %d\n"
     1984            "GetItemRectMin() = (%.1f, %.1f)\n"
     1985            "GetItemRectMax() = (%.1f, %.1f)\n"
     1986            "GetItemRectSize() = (%.1f, %.1f)",
     1987            ret,
     1988            ImGui::IsItemFocused(),
     1989            ImGui::IsItemHovered(),
     1990            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
     1991            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
     1992            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
     1993            ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
     1994            ImGui::IsItemActive(),
     1995            ImGui::IsItemEdited(),
     1996            ImGui::IsItemActivated(),
     1997            ImGui::IsItemDeactivated(),
     1998            ImGui::IsItemDeactivatedAfterEdit(),
     1999            ImGui::IsItemVisible(),
     2000            ImGui::IsItemClicked(),
     2001            ImGui::IsItemToggledOpen(),
     2002            ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
     2003            ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
     2004            ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
     2005        );
     2006
     2007        static bool embed_all_inside_a_child_window = false;
     2008        ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
     2009        if (embed_all_inside_a_child_window)
     2010            ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), true);
     2011
     2012        // Testing IsWindowFocused() function with its various flags.
     2013        // Note that the ImGuiFocusedFlags_XXX flags can be combined.
     2014        ImGui::BulletText(
     2015            "IsWindowFocused() = %d\n"
     2016            "IsWindowFocused(_ChildWindows) = %d\n"
     2017            "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
     2018            "IsWindowFocused(_RootWindow) = %d\n"
     2019            "IsWindowFocused(_AnyWindow) = %d\n",
     2020            ImGui::IsWindowFocused(),
     2021            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
     2022            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
     2023            ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
     2024            ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
     2025
     2026        // Testing IsWindowHovered() function with its various flags.
     2027        // Note that the ImGuiHoveredFlags_XXX flags can be combined.
     2028        ImGui::BulletText(
     2029            "IsWindowHovered() = %d\n"
     2030            "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
     2031            "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
     2032            "IsWindowHovered(_ChildWindows) = %d\n"
     2033            "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
     2034            "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
     2035            "IsWindowHovered(_RootWindow) = %d\n"
     2036            "IsWindowHovered(_AnyWindow) = %d\n",
     2037            ImGui::IsWindowHovered(),
     2038            ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
     2039            ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
     2040            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
     2041            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
     2042            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
     2043            ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
     2044            ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
     2045
     2046        ImGui::BeginChild("child", ImVec2(0, 50), true);
     2047        ImGui::Text("This is another child window for testing the _ChildWindows flag.");
     2048        ImGui::EndChild();
     2049        if (embed_all_inside_a_child_window)
     2050            ImGui::EndChild();
     2051
     2052        static char unused_str[] = "This widget is only here to be able to tab-out of the widgets above.";
     2053        ImGui::InputText("unused", unused_str, IM_ARRAYSIZE(unused_str), ImGuiInputTextFlags_ReadOnly);
     2054
     2055        // Calling IsItemHovered() after begin returns the hovered status of the title bar.
     2056        // This is useful in particular if you want to create a context menu associated to the title bar of a window.
     2057        static bool test_window = false;
     2058        ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
     2059        if (test_window)
     2060        {
     2061            ImGui::Begin("Title bar Hovered/Active tests", &test_window);
     2062            if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
     2063            {
     2064                if (ImGui::MenuItem("Close")) { test_window = false; }
     2065                ImGui::EndPopup();
     2066            }
     2067            ImGui::Text(
     2068                "IsItemHovered() after begin = %d (== is title bar hovered)\n"
     2069                "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
     2070                ImGui::IsItemHovered(), ImGui::IsItemActive());
     2071            ImGui::End();
     2072        }
     2073
     2074        ImGui::TreePop();
     2075    }
     2076}
     2077
     2078static void ShowDemoWindowLayout()
     2079{
     2080    if (!ImGui::CollapsingHeader("Layout & Scrolling"))
     2081        return;
     2082
     2083    if (ImGui::TreeNode("Child windows"))
     2084    {
     2085        HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
     2086        static bool disable_mouse_wheel = false;
     2087        static bool disable_menu = false;
     2088        ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
     2089        ImGui::Checkbox("Disable Menu", &disable_menu);
     2090
     2091        // Child 1: no border, enable horizontal scrollbar
     2092        {
     2093            ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
     2094            if (disable_mouse_wheel)
     2095                window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
     2096            ImGui::BeginChild("ChildL", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags);
    11182097            for (int i = 0; i < 100; i++)
    1119             {
    1120                ImGui::Text("%04d: scrollable region", i);
    1121                if (goto_line && line == i)
    1122                   ImGui::SetScrollHere();
    1123             }
    1124             if (goto_line && line >= 100)
    1125                ImGui::SetScrollHere();
     2098                ImGui::Text("%04d: scrollable region", i);
    11262099            ImGui::EndChild();
    1127          }
    1128 
    1129          ImGui::SameLine();
    1130 
    1131          // Child 2: rounded border
    1132          {
     2100        }
     2101
     2102        ImGui::SameLine();
     2103
     2104        // Child 2: rounded border
     2105        {
     2106            ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
     2107            if (disable_mouse_wheel)
     2108                window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
     2109            if (!disable_menu)
     2110                window_flags |= ImGuiWindowFlags_MenuBar;
    11332111            ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
    1134             ImGui::BeginChild("Child2", ImVec2(0, 300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar));
     2112            ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags);
    11352113            if (!disable_menu && ImGui::BeginMenuBar())
    11362114            {
    1137                if (ImGui::BeginMenu("Menu"))
    1138                {
    1139                   ShowExampleMenuFile();
    1140                   ImGui::EndMenu();
    1141                }
    1142                ImGui::EndMenuBar();
     2115                if (ImGui::BeginMenu("Menu"))
     2116                {
     2117                    ShowExampleMenuFile();
     2118                    ImGui::EndMenu();
     2119                }
     2120                ImGui::EndMenuBar();
    11432121            }
    11442122            ImGui::Columns(2);
    11452123            for (int i = 0; i < 100; i++)
    11462124            {
    1147                if (i == 50)
    1148                   ImGui::NextColumn();
    1149                char buf[32];
    1150                sprintf(buf, "%08x", i * 5731);
    1151                ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
     2125                char buf[32];
     2126                sprintf(buf, "%03d", i);
     2127                ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
     2128                ImGui::NextColumn();
    11522129            }
    11532130            ImGui::EndChild();
    11542131            ImGui::PopStyleVar();
    1155          }
    1156 
    1157          ImGui::TreePop();
    1158       }
    1159 
    1160       if (ImGui::TreeNode("Widgets Width"))
    1161       {
    1162          static float f = 0.0f;
    1163          ImGui::Text("PushItemWidth(100)");
    1164          ImGui::SameLine(); ShowHelpMarker("Fixed width.");
    1165          ImGui::PushItemWidth(100);
    1166          ImGui::DragFloat("float##1", &f);
    1167          ImGui::PopItemWidth();
    1168 
    1169          ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
    1170          ImGui::SameLine(); ShowHelpMarker("Half of window width.");
    1171          ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
    1172          ImGui::DragFloat("float##2", &f);
    1173          ImGui::PopItemWidth();
    1174 
    1175          ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
    1176          ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
    1177          ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
    1178          ImGui::DragFloat("float##3", &f);
    1179          ImGui::PopItemWidth();
    1180 
    1181          ImGui::Text("PushItemWidth(-100)");
    1182          ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
    1183          ImGui::PushItemWidth(-100);
    1184          ImGui::DragFloat("float##4", &f);
    1185          ImGui::PopItemWidth();
    1186 
    1187          ImGui::Text("PushItemWidth(-1)");
    1188          ImGui::SameLine(); ShowHelpMarker("Align to right edge");
    1189          ImGui::PushItemWidth(-1);
    1190          ImGui::DragFloat("float##5", &f);
    1191          ImGui::PopItemWidth();
    1192 
    1193          ImGui::TreePop();
    1194       }
    1195 
    1196       if (ImGui::TreeNode("Basic Horizontal Layout"))
    1197       {
    1198          ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
    1199 
    1200          // Text
    1201          ImGui::Text("Two items: Hello"); ImGui::SameLine();
    1202          ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
    1203 
    1204          // Adjust spacing
    1205          ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
    1206          ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
    1207 
    1208          // Button
    1209          ImGui::AlignTextToFramePadding();
    1210          ImGui::Text("Normal buttons"); ImGui::SameLine();
    1211          ImGui::Button("Banana"); ImGui::SameLine();
    1212          ImGui::Button("Apple"); ImGui::SameLine();
    1213          ImGui::Button("Corniflower");
    1214 
    1215          // Button
    1216          ImGui::Text("Small buttons"); ImGui::SameLine();
    1217          ImGui::SmallButton("Like this one"); ImGui::SameLine();
    1218          ImGui::Text("can fit within a text block.");
    1219 
    1220          // Aligned to arbitrary position. Easy/cheap column.
    1221          ImGui::Text("Aligned");
    1222          ImGui::SameLine(150); ImGui::Text("x=150");
    1223          ImGui::SameLine(300); ImGui::Text("x=300");
    1224          ImGui::Text("Aligned");
    1225          ImGui::SameLine(150); ImGui::SmallButton("x=150");
    1226          ImGui::SameLine(300); ImGui::SmallButton("x=300");
    1227 
    1228          // Checkbox
    1229          static bool c1 = false, c2 = false, c3 = false, c4 = false;
    1230          ImGui::Checkbox("My", &c1); ImGui::SameLine();
    1231          ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
    1232          ImGui::Checkbox("Is", &c3); ImGui::SameLine();
    1233          ImGui::Checkbox("Rich", &c4);
    1234 
    1235          // Various
    1236          static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
    1237          ImGui::PushItemWidth(80);
    1238          const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
    1239          static int item = -1;
    1240          ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
    1241          ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
    1242          ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
    1243          ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
    1244          ImGui::PopItemWidth();
    1245 
    1246          ImGui::PushItemWidth(80);
    1247          ImGui::Text("Lists:");
    1248          static int selection[4] = { 0, 1, 2, 3 };
    1249          for (int i = 0; i < 4; i++)
    1250          {
     2132        }
     2133
     2134        ImGui::Separator();
     2135
     2136        // Demonstrate a few extra things
     2137        // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
     2138        // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window)
     2139        //   You can also call SetNextWindowPos() to position the child window. The parent window will effectively
     2140        //   layout from this position.
     2141        // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from
     2142        //   the POV of the parent window). See 'Demo->Querying Status (Active/Focused/Hovered etc.)' for details.
     2143        {
     2144            static int offset_x = 0;
     2145            ImGui::SetNextItemWidth(100);
     2146            ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
     2147
     2148            ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
     2149            ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
     2150            ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None);
     2151            for (int n = 0; n < 50; n++)
     2152                ImGui::Text("Some test %d", n);
     2153            ImGui::EndChild();
     2154            bool child_is_hovered = ImGui::IsItemHovered();
     2155            ImVec2 child_rect_min = ImGui::GetItemRectMin();
     2156            ImVec2 child_rect_max = ImGui::GetItemRectMax();
     2157            ImGui::PopStyleColor();
     2158            ImGui::Text("Hovered: %d", child_is_hovered);
     2159            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);
     2160        }
     2161
     2162        ImGui::TreePop();
     2163    }
     2164
     2165    if (ImGui::TreeNode("Widgets Width"))
     2166    {
     2167        // Use SetNextItemWidth() to set the width of a single upcoming item.
     2168        // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
     2169        // In real code use you'll probably want to choose width values that are proportional to your font size
     2170        // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
     2171
     2172        static float f = 0.0f;
     2173        ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
     2174        ImGui::SameLine(); HelpMarker("Fixed width.");
     2175        ImGui::SetNextItemWidth(100);
     2176        ImGui::DragFloat("float##1", &f);
     2177
     2178        ImGui::Text("SetNextItemWidth/PushItemWidth(GetWindowWidth() * 0.5f)");
     2179        ImGui::SameLine(); HelpMarker("Half of window width.");
     2180        ImGui::SetNextItemWidth(ImGui::GetWindowWidth() * 0.5f);
     2181        ImGui::DragFloat("float##2", &f);
     2182
     2183        ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
     2184        ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
     2185        ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
     2186        ImGui::DragFloat("float##3", &f);
     2187
     2188        ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
     2189        ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
     2190        ImGui::SetNextItemWidth(-100);
     2191        ImGui::DragFloat("float##4", &f);
     2192
     2193        // Demonstrate using PushItemWidth to surround three items.
     2194        // Calling SetNextItemWidth() before each of them would have the same effect.
     2195        ImGui::Text("SetNextItemWidth/PushItemWidth(-1)");
     2196        ImGui::SameLine(); HelpMarker("Align to right edge");
     2197        ImGui::PushItemWidth(-1);
     2198        ImGui::DragFloat("##float5a", &f);
     2199        ImGui::DragFloat("##float5b", &f);
     2200        ImGui::DragFloat("##float5c", &f);
     2201        ImGui::PopItemWidth();
     2202
     2203        ImGui::TreePop();
     2204    }
     2205
     2206    if (ImGui::TreeNode("Basic Horizontal Layout"))
     2207    {
     2208        ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
     2209
     2210        // Text
     2211        ImGui::Text("Two items: Hello"); ImGui::SameLine();
     2212        ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
     2213
     2214        // Adjust spacing
     2215        ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
     2216        ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
     2217
     2218        // Button
     2219        ImGui::AlignTextToFramePadding();
     2220        ImGui::Text("Normal buttons"); ImGui::SameLine();
     2221        ImGui::Button("Banana"); ImGui::SameLine();
     2222        ImGui::Button("Apple"); ImGui::SameLine();
     2223        ImGui::Button("Corniflower");
     2224
     2225        // Button
     2226        ImGui::Text("Small buttons"); ImGui::SameLine();
     2227        ImGui::SmallButton("Like this one"); ImGui::SameLine();
     2228        ImGui::Text("can fit within a text block.");
     2229
     2230        // Aligned to arbitrary position. Easy/cheap column.
     2231        ImGui::Text("Aligned");
     2232        ImGui::SameLine(150); ImGui::Text("x=150");
     2233        ImGui::SameLine(300); ImGui::Text("x=300");
     2234        ImGui::Text("Aligned");
     2235        ImGui::SameLine(150); ImGui::SmallButton("x=150");
     2236        ImGui::SameLine(300); ImGui::SmallButton("x=300");
     2237
     2238        // Checkbox
     2239        static bool c1 = false, c2 = false, c3 = false, c4 = false;
     2240        ImGui::Checkbox("My", &c1); ImGui::SameLine();
     2241        ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
     2242        ImGui::Checkbox("Is", &c3); ImGui::SameLine();
     2243        ImGui::Checkbox("Rich", &c4);
     2244
     2245        // Various
     2246        static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
     2247        ImGui::PushItemWidth(80);
     2248        const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
     2249        static int item = -1;
     2250        ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
     2251        ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
     2252        ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
     2253        ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
     2254        ImGui::PopItemWidth();
     2255
     2256        ImGui::PushItemWidth(80);
     2257        ImGui::Text("Lists:");
     2258        static int selection[4] = { 0, 1, 2, 3 };
     2259        for (int i = 0; i < 4; i++)
     2260        {
    12512261            if (i > 0) ImGui::SameLine();
    12522262            ImGui::PushID(i);
     
    12542264            ImGui::PopID();
    12552265            //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
    1256          }
    1257          ImGui::PopItemWidth();
    1258 
    1259          // Dummy
    1260          ImVec2 sz(30, 30);
    1261          ImGui::Button("A", sz); ImGui::SameLine();
    1262          ImGui::Dummy(sz); ImGui::SameLine();
    1263          ImGui::Button("B", sz);
    1264 
    1265          ImGui::TreePop();
    1266       }
    1267 
    1268       if (ImGui::TreeNode("Groups"))
    1269       {
    1270          ImGui::TextWrapped("(Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.)");
    1271          ImGui::BeginGroup();
    1272          {
     2266        }
     2267        ImGui::PopItemWidth();
     2268
     2269        // Dummy
     2270        ImVec2 button_sz(40, 40);
     2271        ImGui::Button("A", button_sz); ImGui::SameLine();
     2272        ImGui::Dummy(button_sz); ImGui::SameLine();
     2273        ImGui::Button("B", button_sz);
     2274
     2275        // Manually wrapping
     2276        // (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
     2277        ImGui::Text("Manually wrapping:");
     2278        ImGuiStyle& style = ImGui::GetStyle();
     2279        int buttons_count = 20;
     2280        float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
     2281        for (int n = 0; n < buttons_count; n++)
     2282        {
     2283            ImGui::PushID(n);
     2284            ImGui::Button("Box", button_sz);
     2285            float last_button_x2 = ImGui::GetItemRectMax().x;
     2286            float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
     2287            if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
     2288                ImGui::SameLine();
     2289            ImGui::PopID();
     2290        }
     2291
     2292        ImGui::TreePop();
     2293    }
     2294
     2295    if (ImGui::TreeNode("Tabs"))
     2296    {
     2297        if (ImGui::TreeNode("Basic"))
     2298        {
     2299            ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
     2300            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
     2301            {
     2302                if (ImGui::BeginTabItem("Avocado"))
     2303                {
     2304                    ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
     2305                    ImGui::EndTabItem();
     2306                }
     2307                if (ImGui::BeginTabItem("Broccoli"))
     2308                {
     2309                    ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
     2310                    ImGui::EndTabItem();
     2311                }
     2312                if (ImGui::BeginTabItem("Cucumber"))
     2313                {
     2314                    ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
     2315                    ImGui::EndTabItem();
     2316                }
     2317                ImGui::EndTabBar();
     2318            }
     2319            ImGui::Separator();
     2320            ImGui::TreePop();
     2321        }
     2322
     2323        if (ImGui::TreeNode("Advanced & Close Button"))
     2324        {
     2325            // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
     2326            static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
     2327            ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_Reorderable);
     2328            ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
     2329            ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
     2330            ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
     2331            if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
     2332                tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
     2333            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
     2334                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
     2335            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
     2336                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
     2337
     2338            // Tab Bar
     2339            const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
     2340            static bool opened[4] = { true, true, true, true }; // Persistent user state
     2341            for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
     2342            {
     2343                if (n > 0) { ImGui::SameLine(); }
     2344                ImGui::Checkbox(names[n], &opened[n]);
     2345            }
     2346
     2347            // Passing a bool* to BeginTabItem() is similar to passing one to Begin():
     2348            // the underlying bool will be set to false when the tab is closed.
     2349            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
     2350            {
     2351                for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
     2352                    if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
     2353                    {
     2354                        ImGui::Text("This is the %s tab!", names[n]);
     2355                        if (n & 1)
     2356                            ImGui::Text("I am an odd tab.");
     2357                        ImGui::EndTabItem();
     2358                    }
     2359                ImGui::EndTabBar();
     2360            }
     2361            ImGui::Separator();
     2362            ImGui::TreePop();
     2363        }
     2364
     2365        if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags"))
     2366        {
     2367            static ImVector<int> active_tabs;
     2368            static int next_tab_id = 0;
     2369            if (next_tab_id == 0) // Initialize with some default tabs
     2370                for (int i = 0; i < 3; i++)
     2371                    active_tabs.push_back(next_tab_id++);
     2372
     2373            // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together.
     2374            // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags...
     2375            // but they tend to make more sense together)
     2376            static bool show_leading_button = true;
     2377            static bool show_trailing_button = true;
     2378            ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
     2379            ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
     2380
     2381            // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
     2382            static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown;
     2383            ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
     2384            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
     2385                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
     2386            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
     2387                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
     2388
     2389            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
     2390            {
     2391                // Demo a Leading TabItemButton(): click the "?" button to open a menu
     2392                if (show_leading_button)
     2393                    if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip))
     2394                        ImGui::OpenPopup("MyHelpMenu");
     2395                if (ImGui::BeginPopup("MyHelpMenu"))
     2396                {
     2397                    ImGui::Selectable("Hello!");
     2398                    ImGui::EndPopup();
     2399                }
     2400
     2401                // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+")
     2402                // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
     2403                if (show_trailing_button)
     2404                    if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
     2405                        active_tabs.push_back(next_tab_id++); // Add new tab
     2406
     2407                // Submit our regular tabs
     2408                for (int n = 0; n < active_tabs.Size; )
     2409                {
     2410                    bool open = true;
     2411                    char name[16];
     2412                    snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);
     2413                    if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
     2414                    {
     2415                        ImGui::Text("This is the %s tab!", name);
     2416                        ImGui::EndTabItem();
     2417                    }
     2418
     2419                    if (!open)
     2420                        active_tabs.erase(active_tabs.Data + n);
     2421                    else
     2422                        n++;
     2423                }
     2424
     2425                ImGui::EndTabBar();
     2426            }
     2427            ImGui::Separator();
     2428            ImGui::TreePop();
     2429        }
     2430        ImGui::TreePop();
     2431    }
     2432
     2433    if (ImGui::TreeNode("Groups"))
     2434    {
     2435        HelpMarker(
     2436            "BeginGroup() basically locks the horizontal position for new line. "
     2437            "EndGroup() bundles the whole group so that you can use \"item\" functions such as "
     2438            "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group.");
     2439        ImGui::BeginGroup();
     2440        {
    12732441            ImGui::BeginGroup();
    12742442            ImGui::Button("AAA");
     
    12842452            ImGui::EndGroup();
    12852453            if (ImGui::IsItemHovered())
    1286                ImGui::SetTooltip("First group hovered");
    1287          }
    1288          // Capture the group size and create widgets using the same size
    1289          ImVec2 size = ImGui::GetItemRectSize();
    1290          const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
    1291          ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
    1292 
    1293          ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
    1294          ImGui::SameLine();
    1295          ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
    1296          ImGui::EndGroup();
    1297          ImGui::SameLine();
    1298 
    1299          ImGui::Button("LEVERAGE\nBUZZWORD", size);
    1300          ImGui::SameLine();
    1301 
    1302          if (ImGui::ListBoxHeader("List", size))
    1303          {
     2454                ImGui::SetTooltip("First group hovered");
     2455        }
     2456        // Capture the group size and create widgets using the same size
     2457        ImVec2 size = ImGui::GetItemRectSize();
     2458        const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
     2459        ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
     2460
     2461        ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
     2462        ImGui::SameLine();
     2463        ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
     2464        ImGui::EndGroup();
     2465        ImGui::SameLine();
     2466
     2467        ImGui::Button("LEVERAGE\nBUZZWORD", size);
     2468        ImGui::SameLine();
     2469
     2470        if (ImGui::ListBoxHeader("List", size))
     2471        {
    13042472            ImGui::Selectable("Selected", true);
    13052473            ImGui::Selectable("Not Selected", false);
    13062474            ImGui::ListBoxFooter();
    1307          }
    1308 
    1309          ImGui::TreePop();
    1310       }
    1311 
    1312       if (ImGui::TreeNode("Text Baseline Alignment"))
    1313       {
    1314          ImGui::TextWrapped("(This is testing the vertical alignment that occurs on text to keep it at the same baseline as widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets)");
    1315 
    1316          ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
    1317          ImGui::Text("Hello\nWorld"); ImGui::SameLine();
    1318          ImGui::Text("Banana");
    1319 
    1320          ImGui::Text("Banana"); ImGui::SameLine();
    1321          ImGui::Text("Hello\nWorld"); ImGui::SameLine();
    1322          ImGui::Text("One\nTwo\nThree");
    1323 
    1324          ImGui::Button("HOP##1"); ImGui::SameLine();
    1325          ImGui::Text("Banana"); ImGui::SameLine();
    1326          ImGui::Text("Hello\nWorld"); ImGui::SameLine();
    1327          ImGui::Text("Banana");
    1328 
    1329          ImGui::Button("HOP##2"); ImGui::SameLine();
    1330          ImGui::Text("Hello\nWorld"); ImGui::SameLine();
    1331          ImGui::Text("Banana");
    1332 
    1333          ImGui::Button("TEST##1"); ImGui::SameLine();
    1334          ImGui::Text("TEST"); ImGui::SameLine();
    1335          ImGui::SmallButton("TEST##2");
    1336 
    1337          ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets.
    1338          ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
    1339          ImGui::Button("Widget##1"); ImGui::SameLine();
    1340          ImGui::Text("Widget"); ImGui::SameLine();
    1341          ImGui::SmallButton("Widget##2"); ImGui::SameLine();
    1342          ImGui::Button("Widget##3");
    1343 
    1344          // Tree
    1345          const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
    1346          ImGui::Button("Button##1");
    1347          ImGui::SameLine(0.0f, spacing);
    1348          if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }    // Dummy tree data
    1349 
    1350          ImGui::AlignTextToFramePadding();         // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
    1351          bool node_open = ImGui::TreeNode("Node##2");  // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.
    1352          ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
    1353          if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }   // Dummy tree data
    1354 
    1355                                                                                                                // Bullet
    1356          ImGui::Button("Button##3");
    1357          ImGui::SameLine(0.0f, spacing);
    1358          ImGui::BulletText("Bullet text");
    1359 
    1360          ImGui::AlignTextToFramePadding();
    1361          ImGui::BulletText("Node");
    1362          ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
    1363 
    1364          ImGui::TreePop();
    1365       }
    1366 
    1367       if (ImGui::TreeNode("Scrolling"))
    1368       {
    1369          ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)");
    1370          static bool track = true;
    1371          static int track_line = 50, scroll_to_px = 200;
    1372          ImGui::Checkbox("Track", &track);
    1373          ImGui::PushItemWidth(100);
    1374          ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %.0f");
    1375          bool scroll_to = ImGui::Button("Scroll To Pos");
    1376          ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %.0f px");
    1377          ImGui::PopItemWidth();
    1378          if (scroll_to) track = false;
    1379 
    1380          for (int i = 0; i < 5; i++)
    1381          {
     2475        }
     2476
     2477        ImGui::TreePop();
     2478    }
     2479
     2480    if (ImGui::TreeNode("Text Baseline Alignment"))
     2481    {
     2482        {
     2483            ImGui::BulletText("Text baseline:");
     2484            ImGui::SameLine(); HelpMarker(
     2485                "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. "
     2486                "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets.");
     2487            ImGui::Indent();
     2488
     2489            ImGui::Text("KO Blahblah"); ImGui::SameLine();
     2490            ImGui::Button("Some framed item"); ImGui::SameLine();
     2491            HelpMarker("Baseline of button will look misaligned with text..");
     2492
     2493            // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
     2494            // (because we don't know what's coming after the Text() statement, we need to move the text baseline
     2495            // down by FramePadding.y ahead of time)
     2496            ImGui::AlignTextToFramePadding();
     2497            ImGui::Text("OK Blahblah"); ImGui::SameLine();
     2498            ImGui::Button("Some framed item"); ImGui::SameLine();
     2499            HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
     2500
     2501            // SmallButton() uses the same vertical padding as Text
     2502            ImGui::Button("TEST##1"); ImGui::SameLine();
     2503            ImGui::Text("TEST"); ImGui::SameLine();
     2504            ImGui::SmallButton("TEST##2");
     2505
     2506            // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
     2507            ImGui::AlignTextToFramePadding();
     2508            ImGui::Text("Text aligned to framed item"); ImGui::SameLine();
     2509            ImGui::Button("Item##1"); ImGui::SameLine();
     2510            ImGui::Text("Item"); ImGui::SameLine();
     2511            ImGui::SmallButton("Item##2"); ImGui::SameLine();
     2512            ImGui::Button("Item##3");
     2513
     2514            ImGui::Unindent();
     2515        }
     2516
     2517        ImGui::Spacing();
     2518
     2519        {
     2520            ImGui::BulletText("Multi-line text:");
     2521            ImGui::Indent();
     2522            ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
     2523            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
     2524            ImGui::Text("Banana");
     2525
     2526            ImGui::Text("Banana"); ImGui::SameLine();
     2527            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
     2528            ImGui::Text("One\nTwo\nThree");
     2529
     2530            ImGui::Button("HOP##1"); ImGui::SameLine();
     2531            ImGui::Text("Banana"); ImGui::SameLine();
     2532            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
     2533            ImGui::Text("Banana");
     2534
     2535            ImGui::Button("HOP##2"); ImGui::SameLine();
     2536            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
     2537            ImGui::Text("Banana");
     2538            ImGui::Unindent();
     2539        }
     2540
     2541        ImGui::Spacing();
     2542
     2543        {
     2544            ImGui::BulletText("Misc items:");
     2545            ImGui::Indent();
     2546
     2547            // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button.
     2548            ImGui::Button("80x80", ImVec2(80, 80));
     2549            ImGui::SameLine();
     2550            ImGui::Button("50x50", ImVec2(50, 50));
     2551            ImGui::SameLine();
     2552            ImGui::Button("Button()");
     2553            ImGui::SameLine();
     2554            ImGui::SmallButton("SmallButton()");
     2555
     2556            // Tree
     2557            const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
     2558            ImGui::Button("Button##1");
     2559            ImGui::SameLine(0.0f, spacing);
     2560            if (ImGui::TreeNode("Node##1"))
     2561            {
     2562                // Placeholder tree data
     2563                for (int i = 0; i < 6; i++)
     2564                    ImGui::BulletText("Item %d..", i);
     2565                ImGui::TreePop();
     2566            }
     2567
     2568            // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget.
     2569            // Otherwise you can use SmallButton() (smaller fit).
     2570            ImGui::AlignTextToFramePadding();
     2571
     2572            // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add
     2573            // other contents below the node.
     2574            bool node_open = ImGui::TreeNode("Node##2");
     2575            ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
     2576            if (node_open)
     2577            {
     2578                // Placeholder tree data
     2579                for (int i = 0; i < 6; i++)
     2580                    ImGui::BulletText("Item %d..", i);
     2581                ImGui::TreePop();
     2582            }
     2583
     2584            // Bullet
     2585            ImGui::Button("Button##3");
     2586            ImGui::SameLine(0.0f, spacing);
     2587            ImGui::BulletText("Bullet text");
     2588
     2589            ImGui::AlignTextToFramePadding();
     2590            ImGui::BulletText("Node");
     2591            ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
     2592            ImGui::Unindent();
     2593        }
     2594
     2595        ImGui::TreePop();
     2596    }
     2597
     2598    if (ImGui::TreeNode("Scrolling"))
     2599    {
     2600        // Vertical scroll functions
     2601        HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
     2602
     2603        static int track_item = 50;
     2604        static bool enable_track = true;
     2605        static bool enable_extra_decorations = false;
     2606        static float scroll_to_off_px = 0.0f;
     2607        static float scroll_to_pos_px = 200.0f;
     2608
     2609        ImGui::Checkbox("Decoration", &enable_extra_decorations);
     2610
     2611        ImGui::Checkbox("Track", &enable_track);
     2612        ImGui::PushItemWidth(100);
     2613        ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
     2614
     2615        bool scroll_to_off = ImGui::Button("Scroll Offset");
     2616        ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
     2617
     2618        bool scroll_to_pos = ImGui::Button("Scroll To Pos");
     2619        ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
     2620        ImGui::PopItemWidth();
     2621
     2622        if (scroll_to_off || scroll_to_pos)
     2623            enable_track = false;
     2624
     2625        ImGuiStyle& style = ImGui::GetStyle();
     2626        float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
     2627        if (child_w < 1.0f)
     2628            child_w = 1.0f;
     2629        ImGui::PushID("##VerticalScrolling");
     2630        for (int i = 0; i < 5; i++)
     2631        {
    13822632            if (i > 0) ImGui::SameLine();
    13832633            ImGui::BeginGroup();
    1384             ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
    1385             ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
    1386             if (scroll_to)
    1387                ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
    1388             for (int line = 0; line < 100; line++)
    1389             {
    1390                if (track && line == track_line)
    1391                {
    1392                   ImGui::TextColored(ImColor(255, 255, 0), "Line %d", line);
    1393                   ImGui::SetScrollHere(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
    1394                }
    1395                else
    1396                {
    1397                   ImGui::Text("Line %d", line);
    1398                }
    1399             }
    1400             float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
     2634            const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
     2635            ImGui::TextUnformatted(names[i]);
     2636
     2637            const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
     2638            const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
     2639            const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), true, child_flags);
     2640            if (ImGui::BeginMenuBar())
     2641            {
     2642                ImGui::TextUnformatted("abc");
     2643                ImGui::EndMenuBar();
     2644            }
     2645            if (scroll_to_off)
     2646                ImGui::SetScrollY(scroll_to_off_px);
     2647            if (scroll_to_pos)
     2648                ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
     2649            if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
     2650            {
     2651                for (int item = 0; item < 100; item++)
     2652                {
     2653                    if (enable_track && item == track_item)
     2654                    {
     2655                        ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
     2656                        ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
     2657                    }
     2658                    else
     2659                    {
     2660                        ImGui::Text("Item %d", item);
     2661                    }
     2662                }
     2663            }
     2664            float scroll_y = ImGui::GetScrollY();
     2665            float scroll_max_y = ImGui::GetScrollMaxY();
    14012666            ImGui::EndChild();
    1402             ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
     2667            ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
    14032668            ImGui::EndGroup();
    1404          }
    1405          ImGui::TreePop();
    1406       }
    1407 
    1408       if (ImGui::TreeNode("Horizontal Scrolling"))
    1409       {
    1410          ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
    1411          ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
    1412          static int lines = 7;
    1413          ImGui::SliderInt("Lines", &lines, 1, 15);
    1414          ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
    1415          ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
    1416          ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
    1417          for (int line = 0; line < lines; line++)
    1418          {
    1419             // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off
    1420             // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API)
     2669        }
     2670        ImGui::PopID();
     2671
     2672        // Horizontal scroll functions
     2673        ImGui::Spacing();
     2674        HelpMarker(
     2675            "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n"
     2676            "Because the clipping rectangle of most window hides half worth of WindowPadding on the "
     2677            "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the "
     2678            "equivalent SetScrollFromPosY(+1) wouldn't.");
     2679        ImGui::PushID("##HorizontalScrolling");
     2680        for (int i = 0; i < 5; i++)
     2681        {
     2682            float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
     2683            ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
     2684            ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
     2685            bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), true, child_flags);
     2686            if (scroll_to_off)
     2687                ImGui::SetScrollX(scroll_to_off_px);
     2688            if (scroll_to_pos)
     2689                ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
     2690            if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
     2691            {
     2692                for (int item = 0; item < 100; item++)
     2693                {
     2694                    if (enable_track && item == track_item)
     2695                    {
     2696                        ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
     2697                        ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
     2698                    }
     2699                    else
     2700                    {
     2701                        ImGui::Text("Item %d", item);
     2702                    }
     2703                    ImGui::SameLine();
     2704                }
     2705            }
     2706            float scroll_x = ImGui::GetScrollX();
     2707            float scroll_max_x = ImGui::GetScrollMaxX();
     2708            ImGui::EndChild();
     2709            ImGui::SameLine();
     2710            const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
     2711            ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
     2712            ImGui::Spacing();
     2713        }
     2714        ImGui::PopID();
     2715
     2716        // Miscellaneous Horizontal Scrolling Demo
     2717        HelpMarker(
     2718            "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n"
     2719            "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin().");
     2720        static int lines = 7;
     2721        ImGui::SliderInt("Lines", &lines, 1, 15);
     2722        ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
     2723        ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
     2724        ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
     2725        ImGui::BeginChild("scrolling", scrolling_child_size, true, ImGuiWindowFlags_HorizontalScrollbar);
     2726        for (int line = 0; line < lines; line++)
     2727        {
     2728            // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
     2729            // If you want to create your own time line for a real application you may be better off manipulating
     2730            // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
     2731            // yourself. You may also want to use the lower-level ImDrawList API.
    14212732            int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
    14222733            for (int n = 0; n < num_buttons; n++)
    14232734            {
    1424                if (n > 0) ImGui::SameLine();
    1425                ImGui::PushID(n + line * 1000);
    1426                char num_buf[16];
    1427                sprintf(num_buf, "%d", n);
    1428                const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
    1429                float hue = n * 0.05f;
    1430                ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
    1431                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
    1432                ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
    1433                ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
    1434                ImGui::PopStyleColor(3);
    1435                ImGui::PopID();
    1436             }
    1437          }
    1438          float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
    1439          ImGui::EndChild();
    1440          ImGui::PopStyleVar(2);
    1441          float scroll_x_delta = 0.0f;
    1442          ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
    1443          ImGui::Text("Scroll from code"); ImGui::SameLine();
    1444          ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; ImGui::SameLine();
    1445          ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
    1446          if (scroll_x_delta != 0.0f)
    1447          {
    1448             ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window)
     2735                if (n > 0) ImGui::SameLine();
     2736                ImGui::PushID(n + line * 1000);
     2737                char num_buf[16];
     2738                sprintf(num_buf, "%d", n);
     2739                const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
     2740                float hue = n * 0.05f;
     2741                ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
     2742                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
     2743                ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
     2744                ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
     2745                ImGui::PopStyleColor(3);
     2746                ImGui::PopID();
     2747            }
     2748        }
     2749        float scroll_x = ImGui::GetScrollX();
     2750        float scroll_max_x = ImGui::GetScrollMaxX();
     2751        ImGui::EndChild();
     2752        ImGui::PopStyleVar(2);
     2753        float scroll_x_delta = 0.0f;
     2754        ImGui::SmallButton("<<");
     2755        if (ImGui::IsItemActive())
     2756            scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
     2757        ImGui::SameLine();
     2758        ImGui::Text("Scroll from code"); ImGui::SameLine();
     2759        ImGui::SmallButton(">>");
     2760        if (ImGui::IsItemActive())
     2761            scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
     2762        ImGui::SameLine();
     2763        ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
     2764        if (scroll_x_delta != 0.0f)
     2765        {
     2766            // Demonstrate a trick: you can use Begin to set yourself in the context of another window
     2767            // (here we are already out of your child window)
     2768            ImGui::BeginChild("scrolling");
    14492769            ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
     2770            ImGui::EndChild();
     2771        }
     2772        ImGui::Spacing();
     2773
     2774        static bool show_horizontal_contents_size_demo_window = false;
     2775        ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
     2776
     2777        if (show_horizontal_contents_size_demo_window)
     2778        {
     2779            static bool show_h_scrollbar = true;
     2780            static bool show_button = true;
     2781            static bool show_tree_nodes = true;
     2782            static bool show_text_wrapped = false;
     2783            static bool show_columns = true;
     2784            static bool show_tab_bar = true;
     2785            static bool show_child = false;
     2786            static bool explicit_content_size = false;
     2787            static float contents_size_x = 300.0f;
     2788            if (explicit_content_size)
     2789                ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
     2790            ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
     2791            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
     2792            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
     2793            HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
     2794            ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
     2795            ImGui::Checkbox("Button", &show_button);            // Will grow contents size (unless explicitly overwritten)
     2796            ImGui::Checkbox("Tree nodes", &show_tree_nodes);    // Will grow contents size and display highlight over full width
     2797            ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
     2798            ImGui::Checkbox("Columns", &show_columns);          // Will use contents size
     2799            ImGui::Checkbox("Tab bar", &show_tab_bar);          // Will use contents size
     2800            ImGui::Checkbox("Child", &show_child);              // Will grow and use contents size
     2801            ImGui::Checkbox("Explicit content size", &explicit_content_size);
     2802            ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
     2803            if (explicit_content_size)
     2804            {
     2805                ImGui::SameLine();
     2806                ImGui::SetNextItemWidth(100);
     2807                ImGui::DragFloat("##csx", &contents_size_x);
     2808                ImVec2 p = ImGui::GetCursorScreenPos();
     2809                ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
     2810                ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
     2811                ImGui::Dummy(ImVec2(0, 10));
     2812            }
     2813            ImGui::PopStyleVar(2);
     2814            ImGui::Separator();
     2815            if (show_button)
     2816            {
     2817                ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
     2818            }
     2819            if (show_tree_nodes)
     2820            {
     2821                bool open = true;
     2822                if (ImGui::TreeNode("this is a tree node"))
     2823                {
     2824                    if (ImGui::TreeNode("another one of those tree node..."))
     2825                    {
     2826                        ImGui::Text("Some tree contents");
     2827                        ImGui::TreePop();
     2828                    }
     2829                    ImGui::TreePop();
     2830                }
     2831                ImGui::CollapsingHeader("CollapsingHeader", &open);
     2832            }
     2833            if (show_text_wrapped)
     2834            {
     2835                ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
     2836            }
     2837            if (show_columns)
     2838            {
     2839                ImGui::Columns(4);
     2840                for (int n = 0; n < 4; n++)
     2841                {
     2842                    ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
     2843                    ImGui::NextColumn();
     2844                }
     2845                ImGui::Columns(1);
     2846            }
     2847            if (show_tab_bar && ImGui::BeginTabBar("Hello"))
     2848            {
     2849                if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
     2850                if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
     2851                if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
     2852                if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
     2853                ImGui::EndTabBar();
     2854            }
     2855            if (show_child)
     2856            {
     2857                ImGui::BeginChild("child", ImVec2(0, 0), true);
     2858                ImGui::EndChild();
     2859            }
    14502860            ImGui::End();
    1451          }
    1452          ImGui::TreePop();
    1453       }
    1454 
    1455       if (ImGui::TreeNode("Clipping"))
    1456       {
    1457          static ImVec2 size(100, 100), offset(50, 20);
    1458          ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
    1459          ImGui::DragFloat2("size", (float*)&size, 0.5f, 0.0f, 200.0f, "%.0f");
    1460          ImGui::TextWrapped("(Click and drag)");
    1461          ImVec2 pos = ImGui::GetCursorScreenPos();
    1462          ImVec4 clip_rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y);
    1463          ImGui::InvisibleButton("##dummy", size);
    1464          if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
    1465          ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(90, 90, 120, 255));
    1466          ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x + offset.x, pos.y + offset.y), IM_COL32(255, 255, 255, 255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
    1467          ImGui::TreePop();
    1468       }
    1469    }
    1470 
    1471    if (ImGui::CollapsingHeader("Popups & Modal windows"))
    1472    {
    1473       if (ImGui::TreeNode("Popups"))
    1474       {
    1475          ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
    1476 
    1477          static int selected_fish = -1;
    1478          const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
    1479          static bool toggles[] = { true, false, false, false, false };
    1480 
    1481          // Simple selection popup
    1482          // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
    1483          if (ImGui::Button("Select.."))
    1484             ImGui::OpenPopup("select");
    1485          ImGui::SameLine();
    1486          ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
    1487          if (ImGui::BeginPopup("select"))
    1488          {
     2861        }
     2862
     2863        ImGui::TreePop();
     2864    }
     2865
     2866    if (ImGui::TreeNode("Clipping"))
     2867    {
     2868        static ImVec2 size(100.0f, 100.0f);
     2869        static ImVec2 offset(30.0f, 30.0f);
     2870        ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
     2871        ImGui::TextWrapped("(Click and drag to scroll)");
     2872
     2873        for (int n = 0; n < 3; n++)
     2874        {
     2875            if (n > 0)
     2876                ImGui::SameLine();
     2877            ImGui::PushID(n);
     2878            ImGui::BeginGroup(); // Lock X position
     2879
     2880            ImGui::InvisibleButton("##empty", size);
     2881            if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
     2882            {
     2883                offset.x += ImGui::GetIO().MouseDelta.x;
     2884                offset.y += ImGui::GetIO().MouseDelta.y;
     2885            }
     2886            const ImVec2 p0 = ImGui::GetItemRectMin();
     2887            const ImVec2 p1 = ImGui::GetItemRectMax();
     2888            const char* text_str = "Line 1 hello\nLine 2 clip me!";
     2889            const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y);
     2890            ImDrawList* draw_list = ImGui::GetWindowDrawList();
     2891
     2892            switch (n)
     2893            {
     2894            case 0:
     2895                HelpMarker(
     2896                    "Using ImGui::PushClipRect():\n"
     2897                    "Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
     2898                    "(use this if you want your clipping rectangle to affect interactions)");
     2899                ImGui::PushClipRect(p0, p1, true);
     2900                draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
     2901                draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
     2902                ImGui::PopClipRect();
     2903                break;
     2904            case 1:
     2905                HelpMarker(
     2906                    "Using ImDrawList::PushClipRect():\n"
     2907                    "Will alter ImDrawList rendering only.\n"
     2908                    "(use this as a shortcut if you are only using ImDrawList calls)");
     2909                draw_list->PushClipRect(p0, p1, true);
     2910                draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
     2911                draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
     2912                draw_list->PopClipRect();
     2913                break;
     2914            case 2:
     2915                HelpMarker(
     2916                    "Using ImDrawList::AddText() with a fine ClipRect:\n"
     2917                    "Will alter only this specific ImDrawList::AddText() rendering.\n"
     2918                    "(this is often used internally to avoid altering the clipping rectangle and minimize draw calls)");
     2919                ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert.
     2920                draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
     2921                draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect);
     2922                break;
     2923            }
     2924            ImGui::EndGroup();
     2925            ImGui::PopID();
     2926        }
     2927
     2928        ImGui::TreePop();
     2929    }
     2930}
     2931
     2932static void ShowDemoWindowPopups()
     2933{
     2934    if (!ImGui::CollapsingHeader("Popups & Modal windows"))
     2935        return;
     2936
     2937    // The properties of popups windows are:
     2938    // - They block normal mouse hovering detection outside them. (*)
     2939    // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
     2940    // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as
     2941    //   we are used to with regular Begin() calls. User can manipulate the visibility state by calling OpenPopup().
     2942    // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even
     2943    //     when normally blocked by a popup.
     2944    // Those three properties are connected. The library needs to hold their visibility state BECAUSE it can close
     2945    // popups at any time.
     2946
     2947    // Typical use for regular windows:
     2948    //   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();
     2949    // Typical use for popups:
     2950    //   if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
     2951
     2952    // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
     2953    // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
     2954
     2955    if (ImGui::TreeNode("Popups"))
     2956    {
     2957        ImGui::TextWrapped(
     2958            "When a popup is active, it inhibits interacting with windows that are behind the popup. "
     2959            "Clicking outside the popup closes it.");
     2960
     2961        static int selected_fish = -1;
     2962        const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
     2963        static bool toggles[] = { true, false, false, false, false };
     2964
     2965        // Simple selection popup (if you want to show the current selection inside the Button itself,
     2966        // you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
     2967        if (ImGui::Button("Select.."))
     2968            ImGui::OpenPopup("my_select_popup");
     2969        ImGui::SameLine();
     2970        ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
     2971        if (ImGui::BeginPopup("my_select_popup"))
     2972        {
    14892973            ImGui::Text("Aquarium");
    14902974            ImGui::Separator();
    14912975            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
    1492                if (ImGui::Selectable(names[i]))
    1493                   selected_fish = i;
     2976                if (ImGui::Selectable(names[i]))
     2977                    selected_fish = i;
    14942978            ImGui::EndPopup();
    1495          }
    1496 
    1497          // Showing a menu with toggles
    1498          if (ImGui::Button("Toggle.."))
    1499             ImGui::OpenPopup("toggle");
    1500          if (ImGui::BeginPopup("toggle"))
    1501          {
     2979        }
     2980
     2981        // Showing a menu with toggles
     2982        if (ImGui::Button("Toggle.."))
     2983            ImGui::OpenPopup("my_toggle_popup");
     2984        if (ImGui::BeginPopup("my_toggle_popup"))
     2985        {
    15022986            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
    1503                ImGui::MenuItem(names[i], "", &toggles[i]);
     2987                ImGui::MenuItem(names[i], "", &toggles[i]);
    15042988            if (ImGui::BeginMenu("Sub-menu"))
    15052989            {
    1506                ImGui::MenuItem("Click me");
    1507                ImGui::EndMenu();
     2990                ImGui::MenuItem("Click me");
     2991                ImGui::EndMenu();
    15082992            }
    15092993
     
    15112995            ImGui::Text("Tooltip here");
    15122996            if (ImGui::IsItemHovered())
    1513                ImGui::SetTooltip("I am a tooltip over a popup");
     2997                ImGui::SetTooltip("I am a tooltip over a popup");
    15142998
    15152999            if (ImGui::Button("Stacked Popup"))
    1516                ImGui::OpenPopup("another popup");
     3000                ImGui::OpenPopup("another popup");
    15173001            if (ImGui::BeginPopup("another popup"))
    15183002            {
    1519                for (int i = 0; i < IM_ARRAYSIZE(names); i++)
    1520                   ImGui::MenuItem(names[i], "", &toggles[i]);
    1521                if (ImGui::BeginMenu("Sub-menu"))
    1522                {
    1523                   ImGui::MenuItem("Click me");
    1524                   ImGui::EndMenu();
    1525                }
    1526                ImGui::EndPopup();
     3003                for (int i = 0; i < IM_ARRAYSIZE(names); i++)
     3004                    ImGui::MenuItem(names[i], "", &toggles[i]);
     3005                if (ImGui::BeginMenu("Sub-menu"))
     3006                {
     3007                    ImGui::MenuItem("Click me");
     3008                    if (ImGui::Button("Stacked Popup"))
     3009                        ImGui::OpenPopup("another popup");
     3010                    if (ImGui::BeginPopup("another popup"))
     3011                    {
     3012                        ImGui::Text("I am the last one here.");
     3013                        ImGui::EndPopup();
     3014                    }
     3015                    ImGui::EndMenu();
     3016                }
     3017                ImGui::EndPopup();
    15273018            }
    15283019            ImGui::EndPopup();
    1529          }
    1530 
    1531          if (ImGui::Button("Popup Menu.."))
    1532             ImGui::OpenPopup("FilePopup");
    1533          if (ImGui::BeginPopup("FilePopup"))
    1534          {
     3020        }
     3021
     3022        // Call the more complete ShowExampleMenuFile which we use in various places of this demo
     3023        if (ImGui::Button("File Menu.."))
     3024            ImGui::OpenPopup("my_file_popup");
     3025        if (ImGui::BeginPopup("my_file_popup"))
     3026        {
    15353027            ShowExampleMenuFile();
    15363028            ImGui::EndPopup();
    1537          }
    1538 
    1539          ImGui::TreePop();
    1540       }
    1541 
    1542       if (ImGui::TreeNode("Context menus"))
    1543       {
    1544          // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
    1545          //    if (IsItemHovered() && IsMouseClicked(0))
    1546          //       OpenPopup(id);
    1547          //    return BeginPopup(id);
    1548          // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
    1549          static float value = 0.5f;
    1550          ImGui::Text("Value = %.3f (<-- right-click here)", value);
    1551          if (ImGui::BeginPopupContextItem("item context menu"))
    1552          {
     3029        }
     3030
     3031        ImGui::TreePop();
     3032    }
     3033
     3034    if (ImGui::TreeNode("Context menus"))
     3035    {
     3036        // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
     3037        //    if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
     3038        //       OpenPopup(id);
     3039        //    return BeginPopup(id);
     3040        // For more advanced uses you may want to replicate and customize this code.
     3041        // See details in BeginPopupContextItem().
     3042        static float value = 0.5f;
     3043        ImGui::Text("Value = %.3f (<-- right-click here)", value);
     3044        if (ImGui::BeginPopupContextItem("item context menu"))
     3045        {
    15533046            if (ImGui::Selectable("Set to zero")) value = 0.0f;
    15543047            if (ImGui::Selectable("Set to PI")) value = 3.1415f;
    1555             ImGui::PushItemWidth(-1);
     3048            ImGui::SetNextItemWidth(-1);
    15563049            ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
    1557             ImGui::PopItemWidth();
    15583050            ImGui::EndPopup();
    1559          }
    1560 
    1561          static char name[32] = "Label1";
    1562          char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
    1563          ImGui::Button(buf);
    1564          if (ImGui::BeginPopupContextItem()) // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
    1565          {
     3051        }
     3052
     3053        // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the
     3054        // Begin() call. So here we will make it that clicking on the text field with the right mouse button (1)
     3055        // will toggle the visibility of the popup above.
     3056        ImGui::Text("(You can also right-click me to open the same popup as above.)");
     3057        ImGui::OpenPopupOnItemClick("item context menu", 1);
     3058
     3059        // When used after an item that has an ID (e.g.Button), we can skip providing an ID to BeginPopupContextItem().
     3060        // BeginPopupContextItem() will use the last item ID as the popup ID.
     3061        // In addition here, we want to include your editable label inside the button label.
     3062        // We use the ### operator to override the ID (read FAQ about ID for details)
     3063        static char name[32] = "Label1";
     3064        char buf[64];
     3065        sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
     3066        ImGui::Button(buf);
     3067        if (ImGui::BeginPopupContextItem())
     3068        {
    15663069            ImGui::Text("Edit name:");
    15673070            ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
    15683071            if (ImGui::Button("Close"))
    1569                ImGui::CloseCurrentPopup();
     3072                ImGui::CloseCurrentPopup();
    15703073            ImGui::EndPopup();
    1571          }
    1572          ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
    1573 
    1574          ImGui::TreePop();
    1575       }
    1576 
    1577       if (ImGui::TreeNode("Modals"))
    1578       {
    1579          ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
    1580 
    1581          if (ImGui::Button("Delete.."))
     3074        }
     3075        ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
     3076
     3077        ImGui::TreePop();
     3078    }
     3079
     3080    if (ImGui::TreeNode("Modals"))
     3081    {
     3082        ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside.");
     3083
     3084        if (ImGui::Button("Delete.."))
    15823085            ImGui::OpenPopup("Delete?");
    1583          if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
    1584          {
     3086
     3087        // Always center this window when appearing
     3088        ImVec2 center(ImGui::GetIO().DisplaySize.x * 0.5f, ImGui::GetIO().DisplaySize.y * 0.5f);
     3089        ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
     3090
     3091        if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
     3092        {
    15853093            ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
    15863094            ImGui::Separator();
    15873095
    1588             //static int dummy_i = 0;
    1589             //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
     3096            //static int unused_i = 0;
     3097            //ImGui::Combo("Combo", &unused_i, "Delete\0Delete harder\0");
    15903098
    15913099            static bool dont_ask_me_next_time = false;
     
    15993107            if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
    16003108            ImGui::EndPopup();
    1601          }
    1602 
    1603          if (ImGui::Button("Stacked modals.."))
     3109        }
     3110
     3111        if (ImGui::Button("Stacked modals.."))
    16043112            ImGui::OpenPopup("Stacked 1");
    1605          if (ImGui::BeginPopupModal("Stacked 1"))
    1606          {
    1607             ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDarkening] for darkening.");
     3113        if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
     3114        {
     3115            if (ImGui::BeginMenuBar())
     3116            {
     3117                if (ImGui::BeginMenu("File"))
     3118                {
     3119                    if (ImGui::MenuItem("Some menu item")) {}
     3120                    ImGui::EndMenu();
     3121                }
     3122                ImGui::EndMenuBar();
     3123            }
     3124            ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
     3125
     3126            // Testing behavior of widgets stacking their own regular popups over the modal.
    16083127            static int item = 1;
     3128            static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
    16093129            ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
    1610             static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
    1611             ImGui::ColorEdit4("color", color);  // This is to test behavior of stacked regular popups over a modal
     3130            ImGui::ColorEdit4("color", color);
    16123131
    16133132            if (ImGui::Button("Add another modal.."))
    1614                ImGui::OpenPopup("Stacked 2");
    1615             if (ImGui::BeginPopupModal("Stacked 2"))
    1616             {
    1617                ImGui::Text("Hello from Stacked The Second!");
    1618                if (ImGui::Button("Close"))
    1619                   ImGui::CloseCurrentPopup();
    1620                ImGui::EndPopup();
     3133                ImGui::OpenPopup("Stacked 2");
     3134
     3135            // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which
     3136            // will close the popup. Note that the visibility state of popups is owned by imgui, so the input value
     3137            // of the bool actually doesn't matter here.
     3138            bool unused_open = true;
     3139            if (ImGui::BeginPopupModal("Stacked 2", &unused_open))
     3140            {
     3141                ImGui::Text("Hello from Stacked The Second!");
     3142                if (ImGui::Button("Close"))
     3143                    ImGui::CloseCurrentPopup();
     3144                ImGui::EndPopup();
    16213145            }
    16223146
    16233147            if (ImGui::Button("Close"))
    1624                ImGui::CloseCurrentPopup();
     3148                ImGui::CloseCurrentPopup();
    16253149            ImGui::EndPopup();
    1626          }
    1627 
    1628          ImGui::TreePop();
    1629       }
    1630 
    1631       if (ImGui::TreeNode("Menus inside a regular window"))
    1632       {
    1633          ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
    1634          ImGui::Separator();
    1635          // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above.
    1636          // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here
    1637          // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus.
    1638          ImGui::PushID("foo");
    1639          ImGui::MenuItem("Menu item", "CTRL+M");
    1640          if (ImGui::BeginMenu("Menu inside a regular window"))
    1641          {
     3150        }
     3151
     3152        ImGui::TreePop();
     3153    }
     3154
     3155    if (ImGui::TreeNode("Menus inside a regular window"))
     3156    {
     3157        ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
     3158        ImGui::Separator();
     3159
     3160        // Note: As a quirk in this very specific example, we want to differentiate the parent of this menu from the
     3161        // parent of the various popup menus above. To do so we are encloding the items in a PushID()/PopID() block
     3162        // to make them two different menusets. If we don't, opening any popup above and hovering our menu here would
     3163        // open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it,
     3164        // which is the desired behavior for regular menus.
     3165        ImGui::PushID("foo");
     3166        ImGui::MenuItem("Menu item", "CTRL+M");
     3167        if (ImGui::BeginMenu("Menu inside a regular window"))
     3168        {
    16423169            ShowExampleMenuFile();
    16433170            ImGui::EndMenu();
    1644          }
    1645          ImGui::PopID();
    1646          ImGui::Separator();
    1647          ImGui::TreePop();
    1648       }
    1649    }
    1650 
    1651    if (ImGui::CollapsingHeader("Columns"))
    1652    {
    1653       ImGui::PushID("Columns");
    1654 
    1655       // Basic columns
    1656       if (ImGui::TreeNode("Basic"))
    1657       {
    1658          ImGui::Text("Without border:");
    1659          ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
    1660          ImGui::Separator();
    1661          for (int n = 0; n < 14; n++)
    1662          {
     3171        }
     3172        ImGui::PopID();
     3173        ImGui::Separator();
     3174        ImGui::TreePop();
     3175    }
     3176}
     3177
     3178static void ShowDemoWindowColumns()
     3179{
     3180    if (!ImGui::CollapsingHeader("Columns"))
     3181        return;
     3182
     3183    ImGui::PushID("Columns");
     3184
     3185    static bool disable_indent = false;
     3186    ImGui::Checkbox("Disable tree indentation", &disable_indent);
     3187    ImGui::SameLine();
     3188    HelpMarker("Disable the indenting of tree nodes so demo columns can use the full window width.");
     3189    if (disable_indent)
     3190        ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
     3191
     3192    // Basic columns
     3193    if (ImGui::TreeNode("Basic"))
     3194    {
     3195        ImGui::Text("Without border:");
     3196        ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
     3197        ImGui::Separator();
     3198        for (int n = 0; n < 14; n++)
     3199        {
    16633200            char label[32];
    16643201            sprintf(label, "Item %d", n);
    16653202            if (ImGui::Selectable(label)) {}
    1666             //if (ImGui::Button(label, ImVec2(-1,0))) {}
     3203            //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {}
    16673204            ImGui::NextColumn();
    1668          }
    1669          ImGui::Columns(1);
    1670          ImGui::Separator();
    1671 
    1672          ImGui::Text("With border:");
    1673          ImGui::Columns(4, "mycolumns"); // 4-ways, with border
    1674          ImGui::Separator();
    1675          ImGui::Text("ID"); ImGui::NextColumn();
    1676          ImGui::Text("Name"); ImGui::NextColumn();
    1677          ImGui::Text("Path"); ImGui::NextColumn();
    1678          ImGui::Text("Hovered"); ImGui::NextColumn();
    1679          ImGui::Separator();
    1680          const char* names[3] = { "One", "Two", "Three" };
    1681          const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
    1682          static int selected = -1;
    1683          for (int i = 0; i < 3; i++)
    1684          {
     3205        }
     3206        ImGui::Columns(1);
     3207        ImGui::Separator();
     3208
     3209        ImGui::Text("With border:");
     3210        ImGui::Columns(4, "mycolumns"); // 4-ways, with border
     3211        ImGui::Separator();
     3212        ImGui::Text("ID"); ImGui::NextColumn();
     3213        ImGui::Text("Name"); ImGui::NextColumn();
     3214        ImGui::Text("Path"); ImGui::NextColumn();
     3215        ImGui::Text("Hovered"); ImGui::NextColumn();
     3216        ImGui::Separator();
     3217        const char* names[3] = { "One", "Two", "Three" };
     3218        const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
     3219        static int selected = -1;
     3220        for (int i = 0; i < 3; i++)
     3221        {
    16853222            char label[32];
    16863223            sprintf(label, "%04d", i);
    16873224            if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
    1688                selected = i;
     3225                selected = i;
    16893226            bool hovered = ImGui::IsItemHovered();
    16903227            ImGui::NextColumn();
     
    16923229            ImGui::Text(paths[i]); ImGui::NextColumn();
    16933230            ImGui::Text("%d", hovered); ImGui::NextColumn();
    1694          }
    1695          ImGui::Columns(1);
    1696          ImGui::Separator();
    1697          ImGui::TreePop();
    1698       }
    1699 
    1700       // Create multiple items in a same cell before switching to next column
    1701       if (ImGui::TreeNode("Mixed items"))
    1702       {
    1703          ImGui::Columns(3, "mixed");
    1704          ImGui::Separator();
    1705 
    1706          ImGui::Text("Hello");
    1707          ImGui::Button("Banana");
    1708          ImGui::NextColumn();
    1709 
    1710          ImGui::Text("ImGui");
    1711          ImGui::Button("Apple");
    1712          static float foo = 1.0f;
    1713          ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
    1714          ImGui::Text("An extra line here.");
    1715          ImGui::NextColumn();
    1716 
    1717          ImGui::Text("Sailor");
    1718          ImGui::Button("Corniflower");
    1719          static float bar = 1.0f;
    1720          ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
    1721          ImGui::NextColumn();
    1722 
    1723          if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
    1724          if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
    1725          if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
    1726          ImGui::Columns(1);
    1727          ImGui::Separator();
    1728          ImGui::TreePop();
    1729       }
    1730 
    1731       // Word wrapping
    1732       if (ImGui::TreeNode("Word-wrapping"))
    1733       {
    1734          ImGui::Columns(2, "word-wrapping");
    1735          ImGui::Separator();
    1736          ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
    1737          ImGui::TextWrapped("Hello Left");
    1738          ImGui::NextColumn();
    1739          ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
    1740          ImGui::TextWrapped("Hello Right");
    1741          ImGui::Columns(1);
    1742          ImGui::Separator();
    1743          ImGui::TreePop();
    1744       }
    1745 
    1746       if (ImGui::TreeNode("Borders"))
    1747       {
    1748          // NB: Future columns API should allow automatic horizontal borders.
    1749          static bool h_borders = true;
    1750          static bool v_borders = true;
    1751          ImGui::Checkbox("horizontal", &h_borders);
    1752          ImGui::SameLine();
    1753          ImGui::Checkbox("vertical", &v_borders);
    1754          ImGui::Columns(4, NULL, v_borders);
    1755          for (int i = 0; i < 4 * 3; i++)
    1756          {
     3231        }
     3232        ImGui::Columns(1);
     3233        ImGui::Separator();
     3234        ImGui::TreePop();
     3235    }
     3236
     3237    if (ImGui::TreeNode("Borders"))
     3238    {
     3239        // NB: Future columns API should allow automatic horizontal borders.
     3240        static bool h_borders = true;
     3241        static bool v_borders = true;
     3242        static int columns_count = 4;
     3243        const int lines_count = 3;
     3244        ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
     3245        ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns");
     3246        if (columns_count < 2)
     3247            columns_count = 2;
     3248        ImGui::SameLine();
     3249        ImGui::Checkbox("horizontal", &h_borders);
     3250        ImGui::SameLine();
     3251        ImGui::Checkbox("vertical", &v_borders);
     3252        ImGui::Columns(columns_count, NULL, v_borders);
     3253        for (int i = 0; i < columns_count * lines_count; i++)
     3254        {
    17573255            if (h_borders && ImGui::GetColumnIndex() == 0)
    1758                ImGui::Separator();
     3256                ImGui::Separator();
    17593257            ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
    1760             ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
     3258            ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
     3259            ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
     3260            ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
     3261            ImGui::Text("Long text that is likely to clip");
     3262            ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f));
    17613263            ImGui::NextColumn();
    1762          }
    1763          ImGui::Columns(1);
    1764          if (h_borders)
     3264        }
     3265        ImGui::Columns(1);
     3266        if (h_borders)
    17653267            ImGui::Separator();
    1766          ImGui::TreePop();
    1767       }
    1768 
    1769       // Scrolling columns
    1770       /*
    1771       if (ImGui::TreeNode("Vertical Scrolling"))
    1772       {
    1773       ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
    1774       ImGui::Columns(3);
    1775       ImGui::Text("ID"); ImGui::NextColumn();
    1776       ImGui::Text("Name"); ImGui::NextColumn();
    1777       ImGui::Text("Path"); ImGui::NextColumn();
    1778       ImGui::Columns(1);
    1779       ImGui::Separator();
    1780       ImGui::EndChild();
    1781       ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
    1782       ImGui::Columns(3);
    1783       for (int i = 0; i < 10; i++)
    1784       {
    1785       ImGui::Text("%04d", i); ImGui::NextColumn();
    1786       ImGui::Text("Foobar"); ImGui::NextColumn();
    1787       ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
    1788       }
    1789       ImGui::Columns(1);
    1790       ImGui::EndChild();
    1791       ImGui::TreePop();
    1792       }
    1793       */
    1794 
    1795       if (ImGui::TreeNode("Horizontal Scrolling"))
    1796       {
    1797          ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
    1798          ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
    1799          ImGui::Columns(10);
    1800          int ITEMS_COUNT = 2000;
    1801          ImGuiListClipper clipper(ITEMS_COUNT);  // Also demonstrate using the clipper for large list
    1802          while (clipper.Step())
    1803          {
     3268        ImGui::TreePop();
     3269    }
     3270
     3271    // Create multiple items in a same cell before switching to next column
     3272    if (ImGui::TreeNode("Mixed items"))
     3273    {
     3274        ImGui::Columns(3, "mixed");
     3275        ImGui::Separator();
     3276
     3277        ImGui::Text("Hello");
     3278        ImGui::Button("Banana");
     3279        ImGui::NextColumn();
     3280
     3281        ImGui::Text("ImGui");
     3282        ImGui::Button("Apple");
     3283        static float foo = 1.0f;
     3284        ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
     3285        ImGui::Text("An extra line here.");
     3286        ImGui::NextColumn();
     3287
     3288        ImGui::Text("Sailor");
     3289        ImGui::Button("Corniflower");
     3290        static float bar = 1.0f;
     3291        ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
     3292        ImGui::NextColumn();
     3293
     3294        if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
     3295        if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
     3296        if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
     3297        ImGui::Columns(1);
     3298        ImGui::Separator();
     3299        ImGui::TreePop();
     3300    }
     3301
     3302    // Word wrapping
     3303    if (ImGui::TreeNode("Word-wrapping"))
     3304    {
     3305        ImGui::Columns(2, "word-wrapping");
     3306        ImGui::Separator();
     3307        ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
     3308        ImGui::TextWrapped("Hello Left");
     3309        ImGui::NextColumn();
     3310        ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
     3311        ImGui::TextWrapped("Hello Right");
     3312        ImGui::Columns(1);
     3313        ImGui::Separator();
     3314        ImGui::TreePop();
     3315    }
     3316
     3317    // Scrolling columns
     3318    /*
     3319    if (ImGui::TreeNode("Vertical Scrolling"))
     3320    {
     3321        ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
     3322        ImGui::Columns(3);
     3323        ImGui::Text("ID"); ImGui::NextColumn();
     3324        ImGui::Text("Name"); ImGui::NextColumn();
     3325        ImGui::Text("Path"); ImGui::NextColumn();
     3326        ImGui::Columns(1);
     3327        ImGui::Separator();
     3328        ImGui::EndChild();
     3329        ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
     3330        ImGui::Columns(3);
     3331        for (int i = 0; i < 10; i++)
     3332        {
     3333            ImGui::Text("%04d", i); ImGui::NextColumn();
     3334            ImGui::Text("Foobar"); ImGui::NextColumn();
     3335            ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
     3336        }
     3337        ImGui::Columns(1);
     3338        ImGui::EndChild();
     3339        ImGui::TreePop();
     3340    }
     3341    */
     3342
     3343    if (ImGui::TreeNode("Horizontal Scrolling"))
     3344    {
     3345        ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
     3346        ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f);
     3347        ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar);
     3348        ImGui::Columns(10);
     3349        int ITEMS_COUNT = 2000;
     3350        ImGuiListClipper clipper; // Also demonstrate using the clipper for large list
     3351        clipper.Begin(ITEMS_COUNT);
     3352        while (clipper.Step())
     3353        {
    18043354            for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
    1805                for (int j = 0; j < 10; j++)
    1806                {
    1807                   ImGui::Text("Line %d Column %d...", i, j);
    1808                   ImGui::NextColumn();
    1809                }
    1810          }
    1811          ImGui::Columns(1);
    1812          ImGui::EndChild();
    1813          ImGui::TreePop();
    1814       }
    1815 
    1816       bool node_open = ImGui::TreeNode("Tree within single cell");
    1817       ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
    1818       if (node_open)
    1819       {
    1820          ImGui::Columns(2, "tree items");
    1821          ImGui::Separator();
    1822          if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
    1823          if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
    1824          ImGui::Columns(1);
    1825          ImGui::Separator();
    1826          ImGui::TreePop();
    1827       }
    1828       ImGui::PopID();
    1829    }
    1830 
    1831    if (ImGui::CollapsingHeader("Filtering"))
    1832    {
    1833       static ImGuiTextFilter filter;
    1834       ImGui::Text("Filter usage:\n"
    1835          "  \"\"         display all lines\n"
    1836          "  \"xxx\"      display lines containing \"xxx\"\n"
    1837          "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
    1838          "  \"-xxx\"     hide lines containing \"xxx\"");
    1839       filter.Draw();
    1840       const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
    1841       for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
    1842          if (filter.PassFilter(lines[i]))
    1843             ImGui::BulletText("%s", lines[i]);
    1844    }
    1845 
    1846    if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
    1847    {
    1848       ImGuiIO& io = ImGui::GetIO();
    1849 
    1850       ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
    1851       ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
    1852       ImGui::Text("WantTextInput: %d", io.WantTextInput);
    1853       ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
    1854       ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
    1855 
    1856       ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
    1857       ImGui::SameLine(); ShowHelpMarker("Instruct ImGui to render a mouse cursor for you in software. 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).");
    1858 
    1859       ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
    1860       ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
    1861       ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
    1862       ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
    1863       ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
    1864       ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
    1865 
    1866       if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
    1867       {
    1868          if (ImGui::IsMousePosValid())
    1869             ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
    1870          else
    1871             ImGui::Text("Mouse pos: <INVALID>");
    1872          ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
    1873          ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
    1874          ImGui::Text("Mouse clicked:");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
    1875          ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
    1876          ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
    1877          ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
    1878 
    1879          ImGui::Text("Keys down:");      for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }
    1880          ImGui::Text("Keys pressed:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
    1881          ImGui::Text("Keys release:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
    1882          ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
    1883 
    1884          ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); }
    1885          ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
    1886          ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); }
    1887 
    1888          ImGui::Button("Hovering me sets the\nkeyboard capture flag");
    1889          if (ImGui::IsItemHovered())
    1890             ImGui::CaptureKeyboardFromApp(true);
    1891          ImGui::SameLine();
    1892          ImGui::Button("Holding me clears the\nthe keyboard capture flag");
    1893          if (ImGui::IsItemActive())
    1894             ImGui::CaptureKeyboardFromApp(false);
    1895 
    1896          ImGui::TreePop();
    1897       }
    1898 
    1899       if (ImGui::TreeNode("Tabbing"))
    1900       {
    1901          ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
    1902          static char buf[32] = "dummy";
    1903          ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
    1904          ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
    1905          ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
    1906          ImGui::PushAllowKeyboardFocus(false);
    1907          ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
    1908          //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
    1909          ImGui::PopAllowKeyboardFocus();
    1910          ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
    1911          ImGui::TreePop();
    1912       }
    1913 
    1914       if (ImGui::TreeNode("Focus from code"))
    1915       {
    1916          bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
    1917          bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
    1918          bool focus_3 = ImGui::Button("Focus on 3");
    1919          int has_focus = 0;
    1920          static char buf[128] = "click on a button to set focus";
    1921 
    1922          if (focus_1) ImGui::SetKeyboardFocusHere();
    1923          ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
    1924          if (ImGui::IsItemActive()) has_focus = 1;
    1925 
    1926          if (focus_2) ImGui::SetKeyboardFocusHere();
    1927          ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
    1928          if (ImGui::IsItemActive()) has_focus = 2;
    1929 
    1930          ImGui::PushAllowKeyboardFocus(false);
    1931          if (focus_3) ImGui::SetKeyboardFocusHere();
    1932          ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
    1933          if (ImGui::IsItemActive()) has_focus = 3;
    1934          ImGui::PopAllowKeyboardFocus();
    1935 
    1936          if (has_focus)
    1937             ImGui::Text("Item with focus: %d", has_focus);
    1938          else
    1939             ImGui::Text("Item with focus: <none>");
    1940 
    1941          // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
    1942          static float f3[3] = { 0.0f, 0.0f, 0.0f };
    1943          int focus_ahead = -1;
    1944          if (ImGui::Button("Focus on X")) focus_ahead = 0; ImGui::SameLine();
    1945          if (ImGui::Button("Focus on Y")) focus_ahead = 1; ImGui::SameLine();
    1946          if (ImGui::Button("Focus on Z")) focus_ahead = 2;
    1947          if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
    1948          ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
    1949 
    1950          ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
    1951          ImGui::TreePop();
    1952       }
    1953 
    1954       if (ImGui::TreeNode("Focused & Hovered Test"))
    1955       {
    1956          static bool embed_all_inside_a_child_window = false;
    1957          ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
    1958          if (embed_all_inside_a_child_window)
    1959             ImGui::BeginChild("embeddingchild", ImVec2(0, ImGui::GetFontSize() * 25), true);
    1960 
    1961          // Testing IsWindowFocused() function with its various flags (note that the flags can be combined)
    1962          ImGui::BulletText(
    1963             "IsWindowFocused() = %d\n"
    1964             "IsWindowFocused(_ChildWindows) = %d\n"
    1965             "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
    1966             "IsWindowFocused(_RootWindow) = %d\n"
    1967             "IsWindowFocused(_AnyWindow) = %d\n",
    1968             ImGui::IsWindowFocused(),
    1969             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
    1970             ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
    1971             ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
    1972             ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
    1973 
    1974          // Testing IsWindowHovered() function with its various flags (note that the flags can be combined)
    1975          ImGui::BulletText(
    1976             "IsWindowHovered() = %d\n"
    1977             "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
    1978             "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
    1979             "IsWindowHovered(_ChildWindows) = %d\n"
    1980             "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
    1981             "IsWindowHovered(_RootWindow) = %d\n"
    1982             "IsWindowHovered(_AnyWindow) = %d\n",
    1983             ImGui::IsWindowHovered(),
    1984             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
    1985             ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
    1986             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
    1987             ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
    1988             ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
    1989             ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
    1990 
    1991          // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code)
    1992          ImGui::Button("ITEM");
    1993          ImGui::BulletText(
    1994             "IsItemHovered() = %d\n"
    1995             "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
    1996             "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
    1997             "IsItemHovered(_AllowWhenOverlapped) = %d\n"
    1998             "IsItemhovered(_RectOnly) = %d\n",
    1999             ImGui::IsItemHovered(),
    2000             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
    2001             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
    2002             ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
    2003             ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly));
    2004 
    2005          ImGui::BeginChild("child", ImVec2(0, 50), true);
    2006          ImGui::Text("This is another child window for testing IsWindowHovered() flags.");
    2007          ImGui::EndChild();
    2008 
    2009          if (embed_all_inside_a_child_window)
    2010             EndChild();
    2011 
    2012          ImGui::TreePop();
    2013       }
    2014 
    2015       if (ImGui::TreeNode("Dragging"))
    2016       {
    2017          ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
    2018          for (int button = 0; button < 3; button++)
    2019             ImGui::Text("IsMouseDragging(%d):\n  w/ default threshold: %d,\n  w/ zero threshold: %d\n  w/ large threshold: %d",
    2020                button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
    2021          ImGui::Button("Drag Me");
    2022          if (ImGui::IsItemActive())
    2023          {
    2024             // Draw a line between the button and the mouse cursor
    2025             ImDrawList* draw_list = ImGui::GetWindowDrawList();
    2026             draw_list->PushClipRectFullScreen();
    2027             draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f);
    2028             draw_list->PopClipRect();
    2029 
    2030             // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
    2031             // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
     3355                for (int j = 0; j < 10; j++)
     3356                {
     3357                    ImGui::Text("Line %d Column %d...", i, j);
     3358                    ImGui::NextColumn();
     3359                }
     3360        }
     3361        ImGui::Columns(1);
     3362        ImGui::EndChild();
     3363        ImGui::TreePop();
     3364    }
     3365
     3366    if (ImGui::TreeNode("Tree"))
     3367    {
     3368        ImGui::Columns(2, "tree", true);
     3369        for (int x = 0; x < 3; x++)
     3370        {
     3371            bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x);
     3372            ImGui::NextColumn();
     3373            ImGui::Text("Node contents");
     3374            ImGui::NextColumn();
     3375            if (open1)
     3376            {
     3377                for (int y = 0; y < 3; y++)
     3378                {
     3379                    bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y);
     3380                    ImGui::NextColumn();
     3381                    ImGui::Text("Node contents");
     3382                    if (open2)
     3383                    {
     3384                        ImGui::Text("Even more contents");
     3385                        if (ImGui::TreeNode("Tree in column"))
     3386                        {
     3387                            ImGui::Text("The quick brown fox jumps over the lazy dog");
     3388                            ImGui::TreePop();
     3389                        }
     3390                    }
     3391                    ImGui::NextColumn();
     3392                    if (open2)
     3393                        ImGui::TreePop();
     3394                }
     3395                ImGui::TreePop();
     3396            }
     3397        }
     3398        ImGui::Columns(1);
     3399        ImGui::TreePop();
     3400    }
     3401
     3402    if (disable_indent)
     3403        ImGui::PopStyleVar();
     3404    ImGui::PopID();
     3405}
     3406
     3407static void ShowDemoWindowMisc()
     3408{
     3409    if (ImGui::CollapsingHeader("Filtering"))
     3410    {
     3411        // Helper class to easy setup a text filter.
     3412        // You may want to implement a more feature-full filtering scheme in your own application.
     3413        static ImGuiTextFilter filter;
     3414        ImGui::Text("Filter usage:\n"
     3415                    "  \"\"         display all lines\n"
     3416                    "  \"xxx\"      display lines containing \"xxx\"\n"
     3417                    "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
     3418                    "  \"-xxx\"     hide lines containing \"xxx\"");
     3419        filter.Draw();
     3420        const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
     3421        for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
     3422            if (filter.PassFilter(lines[i]))
     3423                ImGui::BulletText("%s", lines[i]);
     3424    }
     3425
     3426    if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
     3427    {
     3428        ImGuiIO& io = ImGui::GetIO();
     3429
     3430        // Display ImGuiIO output flags
     3431        ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
     3432        ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
     3433        ImGui::Text("WantTextInput: %d", io.WantTextInput);
     3434        ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
     3435        ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
     3436
     3437        // Display Keyboard/Mouse state
     3438        if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
     3439        {
     3440            if (ImGui::IsMousePosValid())
     3441                ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
     3442            else
     3443                ImGui::Text("Mouse pos: <INVALID>");
     3444            ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
     3445            ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
     3446            ImGui::Text("Mouse clicked:");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i))          { ImGui::SameLine(); ImGui::Text("b%d", i); }
     3447            ImGui::Text("Mouse dblclick:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i))    { ImGui::SameLine(); ImGui::Text("b%d", i); }
     3448            ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i))         { ImGui::SameLine(); ImGui::Text("b%d", i); }
     3449            ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
     3450
     3451            ImGui::Text("Keys down:");      for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f)     { ImGui::SameLine(); ImGui::Text("%d (0x%X) (%.02f secs)", i, i, io.KeysDownDuration[i]); }
     3452            ImGui::Text("Keys pressed:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i))             { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
     3453            ImGui::Text("Keys release:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i))            { ImGui::SameLine(); ImGui::Text("%d (0x%X)", i, i); }
     3454            ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
     3455            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.
     3456
     3457            ImGui::Text("NavInputs down:");     for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f)              { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); }
     3458            ImGui::Text("NavInputs pressed:");  for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); }
     3459            ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); }
     3460
     3461            ImGui::Button("Hovering me sets the\nkeyboard capture flag");
     3462            if (ImGui::IsItemHovered())
     3463                ImGui::CaptureKeyboardFromApp(true);
     3464            ImGui::SameLine();
     3465            ImGui::Button("Holding me clears the\nthe keyboard capture flag");
     3466            if (ImGui::IsItemActive())
     3467                ImGui::CaptureKeyboardFromApp(false);
     3468
     3469            ImGui::TreePop();
     3470        }
     3471
     3472        if (ImGui::TreeNode("Tabbing"))
     3473        {
     3474            ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
     3475            static char buf[32] = "hello";
     3476            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
     3477            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
     3478            ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
     3479            ImGui::PushAllowKeyboardFocus(false);
     3480            ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
     3481            //ImGui::SameLine(); HelpMarker("Use ImGui::PushAllowKeyboardFocus(bool) to disable tabbing through certain widgets.");
     3482            ImGui::PopAllowKeyboardFocus();
     3483            ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
     3484            ImGui::TreePop();
     3485        }
     3486
     3487        if (ImGui::TreeNode("Focus from code"))
     3488        {
     3489            bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
     3490            bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
     3491            bool focus_3 = ImGui::Button("Focus on 3");
     3492            int has_focus = 0;
     3493            static char buf[128] = "click on a button to set focus";
     3494
     3495            if (focus_1) ImGui::SetKeyboardFocusHere();
     3496            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
     3497            if (ImGui::IsItemActive()) has_focus = 1;
     3498
     3499            if (focus_2) ImGui::SetKeyboardFocusHere();
     3500            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
     3501            if (ImGui::IsItemActive()) has_focus = 2;
     3502
     3503            ImGui::PushAllowKeyboardFocus(false);
     3504            if (focus_3) ImGui::SetKeyboardFocusHere();
     3505            ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
     3506            if (ImGui::IsItemActive()) has_focus = 3;
     3507            ImGui::PopAllowKeyboardFocus();
     3508
     3509            if (has_focus)
     3510                ImGui::Text("Item with focus: %d", has_focus);
     3511            else
     3512                ImGui::Text("Item with focus: <none>");
     3513
     3514            // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
     3515            static float f3[3] = { 0.0f, 0.0f, 0.0f };
     3516            int focus_ahead = -1;
     3517            if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
     3518            if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
     3519            if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
     3520            if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
     3521            ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
     3522
     3523            ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
     3524            ImGui::TreePop();
     3525        }
     3526
     3527        if (ImGui::TreeNode("Dragging"))
     3528        {
     3529            ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
     3530            for (int button = 0; button < 3; button++)
     3531            {
     3532                ImGui::Text("IsMouseDragging(%d):", button);
     3533                ImGui::Text("  w/ default threshold: %d,", ImGui::IsMouseDragging(button));
     3534                ImGui::Text("  w/ zero threshold: %d,", ImGui::IsMouseDragging(button, 0.0f));
     3535                ImGui::Text("  w/ large threshold: %d,", ImGui::IsMouseDragging(button, 20.0f));
     3536            }
     3537
     3538            ImGui::Button("Drag Me");
     3539            if (ImGui::IsItemActive())
     3540                ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor
     3541
     3542            // Drag operations gets "unlocked" when the mouse has moved past a certain threshold
     3543            // (the default threshold is stored in io.MouseDragThreshold). You can request a lower or higher
     3544            // threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta().
    20323545            ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
    20333546            ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
    20343547            ImVec2 mouse_delta = io.MouseDelta;
    2035             ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y);
    2036          }
    2037          ImGui::TreePop();
    2038       }
    2039 
    2040       if (ImGui::TreeNode("Mouse cursors"))
    2041       {
    2042          const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE" };
    2043          IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
    2044 
    2045          ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
    2046          ImGui::Text("Hover to see mouse cursors:");
    2047          ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
    2048          for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
    2049          {
    2050             char label[32];
    2051             sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
    2052             ImGui::Bullet(); ImGui::Selectable(label, false);
    2053             if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
    2054                ImGui::SetMouseCursor(i);
    2055          }
    2056          ImGui::TreePop();
    2057       }
    2058    }
    2059 
    2060    ImGui::End();
     3548            ImGui::Text("GetMouseDragDelta(0):");
     3549            ImGui::Text("  w/ default threshold: (%.1f, %.1f)", value_with_lock_threshold.x, value_with_lock_threshold.y);
     3550            ImGui::Text("  w/ zero threshold: (%.1f, %.1f)", value_raw.x, value_raw.y);
     3551            ImGui::Text("io.MouseDelta: (%.1f, %.1f)", mouse_delta.x, mouse_delta.y);
     3552            ImGui::TreePop();
     3553        }
     3554
     3555        if (ImGui::TreeNode("Mouse cursors"))
     3556        {
     3557            const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" };
     3558            IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
     3559
     3560            ImGuiMouseCursor current = ImGui::GetMouseCursor();
     3561            ImGui::Text("Current mouse cursor = %d: %s", current, mouse_cursors_names[current]);
     3562            ImGui::Text("Hover to see mouse cursors:");
     3563            ImGui::SameLine(); HelpMarker(
     3564                "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. "
     3565                "If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, "
     3566                "otherwise your backend needs to handle it.");
     3567            for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
     3568            {
     3569                char label[32];
     3570                sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
     3571                ImGui::Bullet(); ImGui::Selectable(label, false);
     3572                if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
     3573                    ImGui::SetMouseCursor(i);
     3574            }
     3575            ImGui::TreePop();
     3576        }
     3577    }
    20613578}
    20623579
     3580//-----------------------------------------------------------------------------
     3581// [SECTION] About Window / ShowAboutWindow()
     3582// Access from Dear ImGui Demo -> Tools -> About
     3583//-----------------------------------------------------------------------------
     3584
     3585void ImGui::ShowAboutWindow(bool* p_open)
     3586{
     3587    if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
     3588    {
     3589        ImGui::End();
     3590        return;
     3591    }
     3592    ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
     3593    ImGui::Separator();
     3594    ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
     3595    ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
     3596
     3597    static bool show_config_info = false;
     3598    ImGui::Checkbox("Config/Build Information", &show_config_info);
     3599    if (show_config_info)
     3600    {
     3601        ImGuiIO& io = ImGui::GetIO();
     3602        ImGuiStyle& style = ImGui::GetStyle();
     3603
     3604        bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
     3605        ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18);
     3606        ImGui::BeginChildFrame(ImGui::GetID("cfg_infos"), child_size, ImGuiWindowFlags_NoMove);
     3607        if (copy_to_clipboard)
     3608        {
     3609            ImGui::LogToClipboard();
     3610            ImGui::LogText("```\n"); // Back quotes will make text appears without formatting when pasting on GitHub
     3611        }
     3612
     3613        ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
     3614        ImGui::Separator();
     3615        ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
     3616        ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
     3617#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
     3618        ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
     3619#endif
     3620#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
     3621        ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
     3622#endif
     3623#ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
     3624        ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
     3625#endif
     3626#ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
     3627        ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
     3628#endif
     3629#ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
     3630        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS");
     3631#endif
     3632#ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
     3633        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS");
     3634#endif
     3635#ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
     3636        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS");
     3637#endif
     3638#ifdef IMGUI_DISABLE_FILE_FUNCTIONS
     3639        ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS");
     3640#endif
     3641#ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
     3642        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
     3643#endif
     3644#ifdef IMGUI_USE_BGRA_PACKED_COLOR
     3645        ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
     3646#endif
     3647#ifdef _WIN32
     3648        ImGui::Text("define: _WIN32");
     3649#endif
     3650#ifdef _WIN64
     3651        ImGui::Text("define: _WIN64");
     3652#endif
     3653#ifdef __linux__
     3654        ImGui::Text("define: __linux__");
     3655#endif
     3656#ifdef __APPLE__
     3657        ImGui::Text("define: __APPLE__");
     3658#endif
     3659#ifdef _MSC_VER
     3660        ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
     3661#endif
     3662#ifdef __MINGW32__
     3663        ImGui::Text("define: __MINGW32__");
     3664#endif
     3665#ifdef __MINGW64__
     3666        ImGui::Text("define: __MINGW64__");
     3667#endif
     3668#ifdef __GNUC__
     3669        ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
     3670#endif
     3671#ifdef __clang_version__
     3672        ImGui::Text("define: __clang_version__=%s", __clang_version__);
     3673#endif
     3674        ImGui::Separator();
     3675        ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
     3676        ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
     3677        ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
     3678        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)        ImGui::Text(" NavEnableKeyboard");
     3679        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
     3680        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)     ImGui::Text(" NavEnableSetMousePos");
     3681        if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)     ImGui::Text(" NavNoCaptureKeyboard");
     3682        if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
     3683        if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
     3684        if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
     3685        if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
     3686        if (io.ConfigInputTextCursorBlink)                              ImGui::Text("io.ConfigInputTextCursorBlink");
     3687        if (io.ConfigWindowsResizeFromEdges)                            ImGui::Text("io.ConfigWindowsResizeFromEdges");
     3688        if (io.ConfigWindowsMoveFromTitleBarOnly)                       ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
     3689        if (io.ConfigWindowsMemoryCompactTimer >= 0.0f)                 ImGui::Text("io.ConfigWindowsMemoryCompactTimer = %.1ff", io.ConfigWindowsMemoryCompactTimer);
     3690        ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
     3691        if (io.BackendFlags & ImGuiBackendFlags_HasGamepad)             ImGui::Text(" HasGamepad");
     3692        if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)        ImGui::Text(" HasMouseCursors");
     3693        if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)         ImGui::Text(" HasSetMousePos");
     3694        if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)   ImGui::Text(" RendererHasVtxOffset");
     3695        ImGui::Separator();
     3696        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);
     3697        ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
     3698        ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
     3699        ImGui::Separator();
     3700        ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
     3701        ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
     3702        ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
     3703        ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
     3704        ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
     3705        ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
     3706        ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
     3707
     3708        if (copy_to_clipboard)
     3709        {
     3710            ImGui::LogText("\n```\n");
     3711            ImGui::LogFinish();
     3712        }
     3713        ImGui::EndChildFrame();
     3714    }
     3715    ImGui::End();
     3716}
     3717
     3718//-----------------------------------------------------------------------------
     3719// [SECTION] Style Editor / ShowStyleEditor()
     3720//-----------------------------------------------------------------------------
     3721// - ShowStyleSelector()
     3722// - ShowFontSelector()
     3723// - ShowStyleEditor()
     3724//-----------------------------------------------------------------------------
     3725
    20633726// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
    2064 // Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally.
     3727// Here we use the simplified Combo() api that packs items into a single literal string.
     3728// Useful for quick combo boxes where the choices are known locally.
    20653729bool ImGui::ShowStyleSelector(const char* label)
    20663730{
    2067    static int style_idx = -1;
    2068    if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
    2069    {
    2070       switch (style_idx)
    2071       {
    2072       case 0: ImGui::StyleColorsClassic(); break;
    2073       case 1: ImGui::StyleColorsDark(); break;
    2074       case 2: ImGui::StyleColorsLight(); break;
    2075       }
    2076       return true;
    2077    }
    2078    return false;
     3731    static int style_idx = -1;
     3732    if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
     3733    {
     3734        switch (style_idx)
     3735        {
     3736        case 0: ImGui::StyleColorsClassic(); break;
     3737        case 1: ImGui::StyleColorsDark(); break;
     3738        case 2: ImGui::StyleColorsLight(); break;
     3739        }
     3740        return true;
     3741    }
     3742    return false;
    20793743}
    20803744
     
    20833747void ImGui::ShowFontSelector(const char* label)
    20843748{
    2085    ImGuiIO& io = ImGui::GetIO();
    2086    ImFont* font_current = ImGui::GetFont();
    2087    if (ImGui::BeginCombo(label, font_current->GetDebugName()))
    2088    {
    2089       for (int n = 0; n < io.Fonts->Fonts.Size; n++)
    2090          if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current))
    2091             io.FontDefault = io.Fonts->Fonts[n];
    2092       ImGui::EndCombo();
    2093    }
    2094    ImGui::SameLine();
    2095    ShowHelpMarker(
    2096       "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
    2097       "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
    2098       "- Read FAQ and documentation in misc/fonts/ for more details.\n"
    2099       "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
     3749    ImGuiIO& io = ImGui::GetIO();
     3750    ImFont* font_current = ImGui::GetFont();
     3751    if (ImGui::BeginCombo(label, font_current->GetDebugName()))
     3752    {
     3753        for (int n = 0; n < io.Fonts->Fonts.Size; n++)
     3754        {
     3755            ImFont* font = io.Fonts->Fonts[n];
     3756            ImGui::PushID((void*)font);
     3757            if (ImGui::Selectable(font->GetDebugName(), font == font_current))
     3758                io.FontDefault = font;
     3759            ImGui::PopID();
     3760        }
     3761        ImGui::EndCombo();
     3762    }
     3763    ImGui::SameLine();
     3764    HelpMarker(
     3765        "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
     3766        "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
     3767        "- Read FAQ and docs/FONTS.md for more details.\n"
     3768        "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
     3769}
     3770
     3771// [Internal] Display details for a single font, called by ShowStyleEditor().
     3772static void NodeFont(ImFont* font)
     3773{
     3774    ImGuiIO& io = ImGui::GetIO();
     3775    ImGuiStyle& style = ImGui::GetStyle();
     3776    bool font_details_opened = ImGui::TreeNode(font, "Font: \"%s\"\n%.2f px, %d glyphs, %d file(s)",
     3777        font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
     3778    ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { io.FontDefault = font; }
     3779    if (!font_details_opened)
     3780        return;
     3781
     3782    ImGui::PushFont(font);
     3783    ImGui::Text("The quick brown fox jumps over the lazy dog");
     3784    ImGui::PopFont();
     3785    ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");   // Scale only this font
     3786    ImGui::SameLine(); HelpMarker(
     3787        "Note than the default embedded font is NOT meant to be scaled.\n\n"
     3788        "Font are currently rendered into bitmaps at a given size at the time of building the atlas. "
     3789        "You may oversample them to get some flexibility with scaling. "
     3790        "You can also render at multiple sizes and select which one to use at runtime.\n\n"
     3791        "(Glimmer of hope: the atlas system will be rewritten in the future to make scaling more flexible.)");
     3792    ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
     3793    ImGui::Text("Fallback character: '%c' (U+%04X)", font->FallbackChar, font->FallbackChar);
     3794    ImGui::Text("Ellipsis character: '%c' (U+%04X)", font->EllipsisChar, font->EllipsisChar);
     3795    const int surface_sqrt = (int)sqrtf((float)font->MetricsTotalSurface);
     3796    ImGui::Text("Texture Area: about %d px ~%dx%d px", font->MetricsTotalSurface, surface_sqrt, surface_sqrt);
     3797    for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
     3798        if (font->ConfigData)
     3799            if (const ImFontConfig* cfg = &font->ConfigData[config_i])
     3800                ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
     3801                    config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
     3802    if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
     3803    {
     3804        // Display all glyphs of the fonts in separate pages of 256 characters
     3805        const ImU32 glyph_col = ImGui::GetColorU32(ImGuiCol_Text);
     3806        for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
     3807        {
     3808            // Skip ahead if a large bunch of glyphs are not present in the font (test in chunks of 4k)
     3809            // This is only a small optimization to reduce the number of iterations when IM_UNICODE_MAX_CODEPOINT
     3810            // is large // (if ImWchar==ImWchar32 we will do at least about 272 queries here)
     3811            if (!(base & 4095) && font->IsGlyphRangeUnused(base, base + 4095))
     3812            {
     3813                base += 4096 - 256;
     3814                continue;
     3815            }
     3816
     3817            int count = 0;
     3818            for (unsigned int n = 0; n < 256; n++)
     3819                if (font->FindGlyphNoFallback((ImWchar)(base + n)))
     3820                    count++;
     3821            if (count <= 0)
     3822                continue;
     3823            if (!ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
     3824                continue;
     3825            float cell_size = font->FontSize * 1;
     3826            float cell_spacing = style.ItemSpacing.y;
     3827            ImVec2 base_pos = ImGui::GetCursorScreenPos();
     3828            ImDrawList* draw_list = ImGui::GetWindowDrawList();
     3829            for (unsigned int n = 0; n < 256; n++)
     3830            {
     3831                // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions
     3832                // available here and thus cannot easily generate a zero-terminated UTF-8 encoded string.
     3833                ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
     3834                ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
     3835                const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
     3836                draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
     3837                if (glyph)
     3838                    font->RenderChar(draw_list, cell_size, cell_p1, glyph_col, (ImWchar)(base + n));
     3839                if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
     3840                {
     3841                    ImGui::BeginTooltip();
     3842                    ImGui::Text("Codepoint: U+%04X", base + n);
     3843                    ImGui::Separator();
     3844                    ImGui::Text("Visible: %d", glyph->Visible);
     3845                    ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
     3846                    ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
     3847                    ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
     3848                    ImGui::EndTooltip();
     3849                }
     3850            }
     3851            ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
     3852            ImGui::TreePop();
     3853        }
     3854        ImGui::TreePop();
     3855    }
     3856    ImGui::TreePop();
    21003857}
    21013858
    21023859void ImGui::ShowStyleEditor(ImGuiStyle* ref)
    21033860{
    2104    // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
    2105    ImGuiStyle& style = ImGui::GetStyle();
    2106    static ImGuiStyle ref_saved_style;
    2107 
    2108    // Default to using internal storage as reference
    2109    static bool init = true;
    2110    if (init && ref == NULL)
    2111       ref_saved_style = style;
    2112    init = false;
    2113    if (ref == NULL)
    2114       ref = &ref_saved_style;
    2115 
    2116    ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
    2117 
    2118    if (ImGui::ShowStyleSelector("Colors##Selector"))
    2119       ref_saved_style = style;
    2120    ImGui::ShowFontSelector("Fonts##Selector");
    2121 
    2122    // Simplified Settings
    2123    if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
    2124       style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
    2125    { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
    2126    ImGui::SameLine();
    2127    { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
    2128    ImGui::SameLine();
    2129    { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
    2130 
    2131    // Save/Revert button
    2132    if (ImGui::Button("Save Ref"))
    2133       *ref = ref_saved_style = style;
    2134    ImGui::SameLine();
    2135    if (ImGui::Button("Revert Ref"))
    2136       style = *ref;
    2137    ImGui::SameLine();
    2138    ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
    2139 
    2140    if (ImGui::TreeNode("Rendering"))
    2141    {
    2142       ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
    2143       ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
    2144       ImGui::PushItemWidth(100);
    2145       ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);
    2146       if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;
    2147       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.
    2148       ImGui::PopItemWidth();
    2149       ImGui::TreePop();
    2150    }
    2151 
    2152    if (ImGui::TreeNode("Settings"))
    2153    {
    2154       ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
    2155       ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 16.0f, "%.0f");
    2156       ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
    2157       ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
    2158       ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
    2159       ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
    2160       ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
    2161       ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
    2162       ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
    2163       ImGui::Text("BorderSize");
    2164       ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
    2165       ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
    2166       ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
    2167       ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
    2168       ImGui::Text("Rounding");
    2169       ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 14.0f, "%.0f");
    2170       ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 16.0f, "%.0f");
    2171       ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
    2172       ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
    2173       ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
    2174       ImGui::Text("Alignment");
    2175       ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
    2176       ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
    2177       ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
    2178       ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
    2179       ImGui::TreePop();
    2180    }
    2181 
    2182    if (ImGui::TreeNode("Colors"))
    2183    {
    2184       static int output_dest = 0;
    2185       static bool output_only_modified = true;
    2186       if (ImGui::Button("Export Unsaved"))
    2187       {
    2188          if (output_dest == 0)
    2189             ImGui::LogToClipboard();
    2190          else
    2191             ImGui::LogToTTY();
    2192          ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
    2193          for (int i = 0; i < ImGuiCol_COUNT; i++)
    2194          {
    2195             const ImVec4& col = style.Colors[i];
    2196             const char* name = ImGui::GetStyleColorName(i);
    2197             if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
    2198                ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
    2199          }
    2200          ImGui::LogFinish();
    2201       }
    2202       ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
    2203       ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
    2204 
    2205       ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");
    2206 
    2207       static ImGuiTextFilter filter;
    2208       filter.Draw("Filter colors", 200);
    2209 
    2210       static ImGuiColorEditFlags alpha_flags = 0;
    2211       ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
    2212       ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
    2213       ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf);
    2214 
    2215       ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
    2216       ImGui::PushItemWidth(-160);
    2217       for (int i = 0; i < ImGuiCol_COUNT; i++)
    2218       {
    2219          const char* name = ImGui::GetStyleColorName(i);
    2220          if (!filter.PassFilter(name))
    2221             continue;
    2222          ImGui::PushID(i);
    2223          ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
    2224          if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
    2225          {
    2226             // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons.
    2227             // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
    2228             ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
    2229             ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
    2230          }
    2231          ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
    2232          ImGui::TextUnformatted(name);
    2233          ImGui::PopID();
    2234       }
    2235       ImGui::PopItemWidth();
    2236       ImGui::EndChild();
    2237 
    2238       ImGui::TreePop();
    2239    }
    2240 
    2241    bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size);
    2242    if (fonts_opened)
    2243    {
    2244       ImFontAtlas* atlas = ImGui::GetIO().Fonts;
    2245       if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
    2246       {
    2247          ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
    2248          ImGui::TreePop();
    2249       }
    2250       ImGui::PushItemWidth(100);
    2251       for (int i = 0; i < atlas->Fonts.Size; i++)
    2252       {
    2253          ImFont* font = atlas->Fonts[i];
    2254          ImGui::PushID(font);
    2255          bool font_details_opened = ImGui::TreeNode(font, "Font %d: \'%s\', %.2f px, %d glyphs", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size);
    2256          ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault = font;
    2257          if (font_details_opened)
    2258          {
    2259             ImGui::PushFont(font);
    2260             ImGui::Text("The quick brown fox jumps over the lazy dog");
    2261             ImGui::PopFont();
    2262             ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");   // Scale only this font
    2263             ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, 0);
    2264             ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
    2265             ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
    2266             ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
    2267             ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface));
    2268             for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
    2269                if (ImFontConfig* cfg = &font->ConfigData[config_i])
    2270                   ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
    2271             if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
    2272             {
    2273                // Display all glyphs of the fonts in separate pages of 256 characters
    2274                for (int base = 0; base < 0x10000; base += 256)
    2275                {
    2276                   int count = 0;
    2277                   for (int n = 0; n < 256; n++)
    2278                      count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0;
    2279                   if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
    2280                   {
    2281                      float cell_size = font->FontSize * 1;
    2282                      float cell_spacing = style.ItemSpacing.y;
    2283                      ImVec2 base_pos = ImGui::GetCursorScreenPos();
    2284                      ImDrawList* draw_list = ImGui::GetWindowDrawList();
    2285                      for (int n = 0; n < 256; n++)
    2286                      {
    2287                         ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
    2288                         ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
    2289                         const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
    2290                         draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
    2291                         font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base + n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string.
    2292                         if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
    2293                         {
    2294                            ImGui::BeginTooltip();
    2295                            ImGui::Text("Codepoint: U+%04X", base + n);
    2296                            ImGui::Separator();
    2297                            ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
    2298                            ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
    2299                            ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
    2300                            ImGui::EndTooltip();
    2301                         }
    2302                      }
    2303                      ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
    2304                      ImGui::TreePop();
    2305                   }
    2306                }
    2307                ImGui::TreePop();
    2308             }
    2309             ImGui::TreePop();
    2310          }
    2311          ImGui::PopID();
    2312       }
    2313       static float window_scale = 1.0f;
    2314       ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.1f");              // scale only this window
    2315       ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.1f"); // scale everything
    2316       ImGui::PopItemWidth();
    2317       ImGui::SetWindowFontScale(window_scale);
    2318       ImGui::TreePop();
    2319    }
    2320 
    2321    ImGui::PopItemWidth();
     3861    // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
     3862    // (without a reference style pointer, we will use one compared locally as a reference)
     3863    ImGuiStyle& style = ImGui::GetStyle();
     3864    static ImGuiStyle ref_saved_style;
     3865
     3866    // Default to using internal storage as reference
     3867    static bool init = true;
     3868    if (init && ref == NULL)
     3869        ref_saved_style = style;
     3870    init = false;
     3871    if (ref == NULL)
     3872        ref = &ref_saved_style;
     3873
     3874    ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
     3875
     3876    if (ImGui::ShowStyleSelector("Colors##Selector"))
     3877        ref_saved_style = style;
     3878    ImGui::ShowFontSelector("Fonts##Selector");
     3879
     3880    // Simplified Settings (expose floating-pointer border sizes as boolean representing 0.0f or 1.0f)
     3881    if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
     3882        style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
     3883    { bool border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &border)) { style.WindowBorderSize = border ? 1.0f : 0.0f; } }
     3884    ImGui::SameLine();
     3885    { bool border = (style.FrameBorderSize > 0.0f);  if (ImGui::Checkbox("FrameBorder",  &border)) { style.FrameBorderSize  = border ? 1.0f : 0.0f; } }
     3886    ImGui::SameLine();
     3887    { bool border = (style.PopupBorderSize > 0.0f);  if (ImGui::Checkbox("PopupBorder",  &border)) { style.PopupBorderSize  = border ? 1.0f : 0.0f; } }
     3888
     3889    // Save/Revert button
     3890    if (ImGui::Button("Save Ref"))
     3891        *ref = ref_saved_style = style;
     3892    ImGui::SameLine();
     3893    if (ImGui::Button("Revert Ref"))
     3894        style = *ref;
     3895    ImGui::SameLine();
     3896    HelpMarker(
     3897        "Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
     3898        "Use \"Export\" below to save them somewhere.");
     3899
     3900    ImGui::Separator();
     3901
     3902    if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
     3903    {
     3904        if (ImGui::BeginTabItem("Sizes"))
     3905        {
     3906            ImGui::Text("Main");
     3907            ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
     3908            ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
     3909            ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
     3910            ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
     3911            ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
     3912            ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
     3913            ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
     3914            ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
     3915            ImGui::Text("Borders");
     3916            ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
     3917            ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
     3918            ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
     3919            ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
     3920            ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
     3921            ImGui::Text("Rounding");
     3922            ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
     3923            ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
     3924            ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
     3925            ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
     3926            ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
     3927            ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
     3928            ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
     3929            ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
     3930            ImGui::Text("Alignment");
     3931            ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
     3932            int window_menu_button_position = style.WindowMenuButtonPosition + 1;
     3933            if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
     3934                style.WindowMenuButtonPosition = window_menu_button_position - 1;
     3935            ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
     3936            ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
     3937            ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
     3938            ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
     3939            ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
     3940            ImGui::Text("Safe Area Padding");
     3941            ImGui::SameLine(); HelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
     3942            ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
     3943            ImGui::EndTabItem();
     3944        }
     3945
     3946        if (ImGui::BeginTabItem("Colors"))
     3947        {
     3948            static int output_dest = 0;
     3949            static bool output_only_modified = true;
     3950            if (ImGui::Button("Export"))
     3951            {
     3952                if (output_dest == 0)
     3953                    ImGui::LogToClipboard();
     3954                else
     3955                    ImGui::LogToTTY();
     3956                ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
     3957                for (int i = 0; i < ImGuiCol_COUNT; i++)
     3958                {
     3959                    const ImVec4& col = style.Colors[i];
     3960                    const char* name = ImGui::GetStyleColorName(i);
     3961                    if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
     3962                        ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE,
     3963                            name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
     3964                }
     3965                ImGui::LogFinish();
     3966            }
     3967            ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
     3968            ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
     3969
     3970            static ImGuiTextFilter filter;
     3971            filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
     3972
     3973            static ImGuiColorEditFlags alpha_flags = 0;
     3974            if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None))             { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();
     3975            if (ImGui::RadioButton("Alpha",  alpha_flags == ImGuiColorEditFlags_AlphaPreview))     { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
     3976            if (ImGui::RadioButton("Both",   alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
     3977            HelpMarker(
     3978                "In the color list:\n"
     3979                "Left-click on colored square to open color picker,\n"
     3980                "Right-click to open edit options menu.");
     3981
     3982            ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
     3983            ImGui::PushItemWidth(-160);
     3984            for (int i = 0; i < ImGuiCol_COUNT; i++)
     3985            {
     3986                const char* name = ImGui::GetStyleColorName(i);
     3987                if (!filter.PassFilter(name))
     3988                    continue;
     3989                ImGui::PushID(i);
     3990                ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
     3991                if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
     3992                {
     3993                    // Tips: in a real user application, you may want to merge and use an icon font into the main font,
     3994                    // so instead of "Save"/"Revert" you'd use icons!
     3995                    // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
     3996                    ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
     3997                    ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
     3998                }
     3999                ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
     4000                ImGui::TextUnformatted(name);
     4001                ImGui::PopID();
     4002            }
     4003            ImGui::PopItemWidth();
     4004            ImGui::EndChild();
     4005
     4006            ImGui::EndTabItem();
     4007        }
     4008
     4009        if (ImGui::BeginTabItem("Fonts"))
     4010        {
     4011            ImGuiIO& io = ImGui::GetIO();
     4012            ImFontAtlas* atlas = io.Fonts;
     4013            HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
     4014            ImGui::PushItemWidth(120);
     4015            for (int i = 0; i < atlas->Fonts.Size; i++)
     4016            {
     4017                ImFont* font = atlas->Fonts[i];
     4018                ImGui::PushID(font);
     4019                NodeFont(font);
     4020                ImGui::PopID();
     4021            }
     4022            if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
     4023            {
     4024                ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
     4025                ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
     4026                ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), tint_col, border_col);
     4027                ImGui::TreePop();
     4028            }
     4029
     4030            // Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
     4031            // (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
     4032            const float MIN_SCALE = 0.3f;
     4033            const float MAX_SCALE = 2.0f;
     4034            HelpMarker(
     4035                "Those are old settings provided for convenience.\n"
     4036                "However, the _correct_ way of scaling your UI is currently to reload your font at the designed size, "
     4037                "rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n"
     4038                "Using those settings here will give you poor quality results.");
     4039            static float window_scale = 1.0f;
     4040            if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
     4041                ImGui::SetWindowFontScale(window_scale);
     4042            ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything
     4043            ImGui::PopItemWidth();
     4044
     4045            ImGui::EndTabItem();
     4046        }
     4047
     4048        if (ImGui::BeginTabItem("Rendering"))
     4049        {
     4050            ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
     4051            ImGui::SameLine();
     4052            HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
     4053
     4054            ImGui::Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex);
     4055            ImGui::SameLine();
     4056            HelpMarker("Faster lines using texture data. Require back-end to render with bilinear filtering (not point/nearest filtering).");
     4057
     4058            ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
     4059            ImGui::PushItemWidth(100);
     4060            ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
     4061            if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
     4062
     4063            // When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
     4064            ImGui::DragFloat("Circle Segment Max Error", &style.CircleSegmentMaxError, 0.01f, 0.10f, 10.0f, "%.2f");
     4065            if (ImGui::IsItemActive())
     4066            {
     4067                ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
     4068                ImGui::BeginTooltip();
     4069                ImVec2 p = ImGui::GetCursorScreenPos();
     4070                ImDrawList* draw_list = ImGui::GetWindowDrawList();
     4071                float RAD_MIN = 10.0f, RAD_MAX = 80.0f;
     4072                float off_x = 10.0f;
     4073                for (int n = 0; n < 7; n++)
     4074                {
     4075                    const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (7.0f - 1.0f);
     4076                    draw_list->AddCircle(ImVec2(p.x + off_x + rad, p.y + RAD_MAX), rad, ImGui::GetColorU32(ImGuiCol_Text), 0);
     4077                    off_x += 10.0f + rad * 2.0f;
     4078                }
     4079                ImGui::Dummy(ImVec2(off_x, RAD_MAX * 2.0f));
     4080                ImGui::EndTooltip();
     4081            }
     4082            ImGui::SameLine();
     4083            HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically.");
     4084
     4085            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.
     4086            ImGui::PopItemWidth();
     4087
     4088            ImGui::EndTabItem();
     4089        }
     4090
     4091        ImGui::EndTabBar();
     4092    }
     4093
     4094    ImGui::PopItemWidth();
    23224095}
    23234096
    2324 // Demonstrate creating a fullscreen menu bar and populating it.
     4097//-----------------------------------------------------------------------------
     4098// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
     4099//-----------------------------------------------------------------------------
     4100// - ShowExampleAppMainMenuBar()
     4101// - ShowExampleMenuFile()
     4102//-----------------------------------------------------------------------------
     4103
     4104// Demonstrate creating a "main" fullscreen menu bar and populating it.
     4105// Note the difference between BeginMainMenuBar() and BeginMenuBar():
     4106// - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!)
     4107// - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it.
    23254108static void ShowExampleAppMainMenuBar()
    23264109{
    2327    if (ImGui::BeginMainMenuBar())
    2328    {
    2329       if (ImGui::BeginMenu("File"))
    2330       {
    2331          ShowExampleMenuFile();
    2332          ImGui::EndMenu();
    2333       }
    2334       if (ImGui::BeginMenu("Edit"))
    2335       {
    2336          if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
    2337          if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
    2338          ImGui::Separator();
    2339          if (ImGui::MenuItem("Cut", "CTRL+X")) {}
    2340          if (ImGui::MenuItem("Copy", "CTRL+C")) {}
    2341          if (ImGui::MenuItem("Paste", "CTRL+V")) {}
    2342          ImGui::EndMenu();
    2343       }
    2344       ImGui::EndMainMenuBar();
    2345    }
     4110    if (ImGui::BeginMainMenuBar())
     4111    {
     4112        if (ImGui::BeginMenu("File"))
     4113        {
     4114            ShowExampleMenuFile();
     4115            ImGui::EndMenu();
     4116        }
     4117        if (ImGui::BeginMenu("Edit"))
     4118        {
     4119            if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
     4120            if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
     4121            ImGui::Separator();
     4122            if (ImGui::MenuItem("Cut", "CTRL+X")) {}
     4123            if (ImGui::MenuItem("Copy", "CTRL+C")) {}
     4124            if (ImGui::MenuItem("Paste", "CTRL+V")) {}
     4125            ImGui::EndMenu();
     4126        }
     4127        ImGui::EndMainMenuBar();
     4128    }
    23464129}
    23474130
     4131// Note that shortcuts are currently provided for display only
     4132// (future version will add explicit flags to BeginMenu() to request processing shortcuts)
    23484133static void ShowExampleMenuFile()
    23494134{
    2350    ImGui::MenuItem("(dummy menu)", NULL, false, false);
    2351    if (ImGui::MenuItem("New")) {}
    2352    if (ImGui::MenuItem("Open", "Ctrl+O")) {}
    2353    if (ImGui::BeginMenu("Open Recent"))
    2354    {
    2355       ImGui::MenuItem("fish_hat.c");
    2356       ImGui::MenuItem("fish_hat.inl");
    2357       ImGui::MenuItem("fish_hat.h");
    2358       if (ImGui::BeginMenu("More.."))
    2359       {
    2360          ImGui::MenuItem("Hello");
    2361          ImGui::MenuItem("Sailor");
    2362          if (ImGui::BeginMenu("Recurse.."))
    2363          {
    2364             ShowExampleMenuFile();
     4135    ImGui::MenuItem("(demo menu)", NULL, false, false);
     4136    if (ImGui::MenuItem("New")) {}
     4137    if (ImGui::MenuItem("Open", "Ctrl+O")) {}
     4138    if (ImGui::BeginMenu("Open Recent"))
     4139    {
     4140        ImGui::MenuItem("fish_hat.c");
     4141        ImGui::MenuItem("fish_hat.inl");
     4142        ImGui::MenuItem("fish_hat.h");
     4143        if (ImGui::BeginMenu("More.."))
     4144        {
     4145            ImGui::MenuItem("Hello");
     4146            ImGui::MenuItem("Sailor");
     4147            if (ImGui::BeginMenu("Recurse.."))
     4148            {
     4149                ShowExampleMenuFile();
     4150                ImGui::EndMenu();
     4151            }
    23654152            ImGui::EndMenu();
    2366          }
    2367          ImGui::EndMenu();
    2368       }
    2369       ImGui::EndMenu();
    2370    }
    2371    if (ImGui::MenuItem("Save", "Ctrl+S")) {}
    2372    if (ImGui::MenuItem("Save As..")) {}
    2373    ImGui::Separator();
    2374    if (ImGui::BeginMenu("Options"))
    2375    {
    2376       static bool enabled = true;
    2377       ImGui::MenuItem("Enabled", "", &enabled);
    2378       ImGui::BeginChild("child", ImVec2(0, 60), true);
    2379       for (int i = 0; i < 10; i++)
    2380          ImGui::Text("Scrolling Text %d", i);
    2381       ImGui::EndChild();
    2382       static float f = 0.5f;
    2383       static int n = 0;
    2384       static bool b = true;
    2385       ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
    2386       ImGui::InputFloat("Input", &f, 0.1f);
    2387       ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
    2388       ImGui::Checkbox("Check", &b);
    2389       ImGui::EndMenu();
    2390    }
    2391    if (ImGui::BeginMenu("Colors"))
    2392    {
    2393       float sz = ImGui::GetTextLineHeight();
    2394       for (int i = 0; i < ImGuiCol_COUNT; i++)
    2395       {
    2396          const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
    2397          ImVec2 p = ImGui::GetCursorScreenPos();
    2398          ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
    2399          ImGui::Dummy(ImVec2(sz, sz));
    2400          ImGui::SameLine();
    2401          ImGui::MenuItem(name);
    2402       }
    2403       ImGui::EndMenu();
    2404    }
    2405    if (ImGui::BeginMenu("Disabled", false)) // Disabled
    2406    {
    2407       IM_ASSERT(0);
    2408    }
    2409    if (ImGui::MenuItem("Checked", NULL, true)) {}
    2410    if (ImGui::MenuItem("Quit", "Alt+F4")) {}
     4153        }
     4154        ImGui::EndMenu();
     4155    }
     4156    if (ImGui::MenuItem("Save", "Ctrl+S")) {}
     4157    if (ImGui::MenuItem("Save As..")) {}
     4158
     4159    ImGui::Separator();
     4160    if (ImGui::BeginMenu("Options"))
     4161    {
     4162        static bool enabled = true;
     4163        ImGui::MenuItem("Enabled", "", &enabled);
     4164        ImGui::BeginChild("child", ImVec2(0, 60), true);
     4165        for (int i = 0; i < 10; i++)
     4166            ImGui::Text("Scrolling Text %d", i);
     4167        ImGui::EndChild();
     4168        static float f = 0.5f;
     4169        static int n = 0;
     4170        ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
     4171        ImGui::InputFloat("Input", &f, 0.1f);
     4172        ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
     4173        ImGui::EndMenu();
     4174    }
     4175
     4176    if (ImGui::BeginMenu("Colors"))
     4177    {
     4178        float sz = ImGui::GetTextLineHeight();
     4179        for (int i = 0; i < ImGuiCol_COUNT; i++)
     4180        {
     4181            const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
     4182            ImVec2 p = ImGui::GetCursorScreenPos();
     4183            ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
     4184            ImGui::Dummy(ImVec2(sz, sz));
     4185            ImGui::SameLine();
     4186            ImGui::MenuItem(name);
     4187        }
     4188        ImGui::EndMenu();
     4189    }
     4190
     4191    // Here we demonstrate appending again to the "Options" menu (which we already created above)
     4192    // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice.
     4193    // In a real code-base using it would make senses to use this feature from very different code locations.
     4194    if (ImGui::BeginMenu("Options")) // <-- Append!
     4195    {
     4196        static bool b = true;
     4197        ImGui::Checkbox("SomeOption", &b);
     4198        ImGui::EndMenu();
     4199    }
     4200
     4201    if (ImGui::BeginMenu("Disabled", false)) // Disabled
     4202    {
     4203        IM_ASSERT(0);
     4204    }
     4205    if (ImGui::MenuItem("Checked", NULL, true)) {}
     4206    if (ImGui::MenuItem("Quit", "Alt+F4")) {}
    24114207}
    24124208
    2413 // Demonstrate creating a window which gets auto-resized according to its content.
    2414 static void ShowExampleAppAutoResize(bool* p_open)
    2415 {
    2416    if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
    2417    {
    2418       ImGui::End();
    2419       return;
    2420    }
    2421 
    2422    static int lines = 10;
    2423    ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop.");
    2424    ImGui::SliderInt("Number of lines", &lines, 1, 20);
    2425    for (int i = 0; i < lines; i++)
    2426       ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
    2427    ImGui::End();
    2428 }
    2429 
    2430 // Demonstrate creating a window with custom resize constraints.
    2431 static void ShowExampleAppConstrainedResize(bool* p_open)
    2432 {
    2433    struct CustomConstraints // Helper functions to demonstrate programmatic constraints
    2434    {
    2435       static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
    2436       static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
    2437    };
    2438 
    2439    static bool auto_resize = false;
    2440    static int type = 0;
    2441    static int display_lines = 10;
    2442    if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX));      // Vertical only
    2443    if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX, -1));      // Horizontal only
    2444    if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
    2445    if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1));          // Width 400-500
    2446    if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500));          // Height 400-500
    2447    if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);          // Always Square
    2448    if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)100);// Fixed Step
    2449 
    2450    ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
    2451    if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
    2452    {
    2453       const char* desc[] =
    2454       {
    2455          "Resize vertical only",
    2456          "Resize horizontal only",
    2457          "Width > 100, Height > 100",
    2458          "Width 400-500",
    2459          "Height 400-500",
    2460          "Custom: Always Square",
    2461          "Custom: Fixed Steps (100)",
    2462       };
    2463       if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
    2464       if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
    2465       if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
    2466       ImGui::PushItemWidth(200);
    2467       ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
    2468       ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
    2469       ImGui::PopItemWidth();
    2470       ImGui::Checkbox("Auto-resize", &auto_resize);
    2471       for (int i = 0; i < display_lines; i++)
    2472          ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
    2473    }
    2474    ImGui::End();
    2475 }
    2476 
    2477 // Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
    2478 static void ShowExampleAppFixedOverlay(bool* p_open)
    2479 {
    2480    const float DISTANCE = 10.0f;
    2481    static int corner = 0;
    2482    ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE);
    2483    ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
    2484    if (corner != -1)
    2485       ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
    2486    ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background
    2487    if (ImGui::Begin("Example: Fixed Overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
    2488    {
    2489       ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
    2490       ImGui::Separator();
    2491       if (ImGui::IsMousePosValid())
    2492          ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos.x, ImGui::GetIO().MousePos.y);
    2493       else
    2494          ImGui::Text("Mouse Position: <invalid>");
    2495       if (ImGui::BeginPopupContextWindow())
    2496       {
    2497          if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1;
    2498          if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
    2499          if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
    2500          if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
    2501          if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
    2502          if (p_open && ImGui::MenuItem("Close")) *p_open = false;
    2503          ImGui::EndPopup();
    2504       }
    2505       ImGui::End();
    2506    }
    2507 }
    2508 
    2509 // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
    2510 // This apply to regular items as well. Read FAQ section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." for details.
    2511 static void ShowExampleAppWindowTitles(bool*)
    2512 {
    2513    // By default, Windows are uniquely identified by their title.
    2514    // You can use the "##" and "###" markers to manipulate the display/ID.
    2515 
    2516    // Using "##" to display same title but have unique identifier.
    2517    ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
    2518    ImGui::Begin("Same title as another window##1");
    2519    ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
    2520    ImGui::End();
    2521 
    2522    ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
    2523    ImGui::Begin("Same title as another window##2");
    2524    ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
    2525    ImGui::End();
    2526 
    2527    // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
    2528    char buf[128];
    2529    sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
    2530    ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
    2531    ImGui::Begin(buf);
    2532    ImGui::Text("This window has a changing title.");
    2533    ImGui::End();
    2534 }
    2535 
    2536 // Demonstrate using the low-level ImDrawList to draw custom shapes.
    2537 static void ShowExampleAppCustomRendering(bool* p_open)
    2538 {
    2539    ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver);
    2540    if (!ImGui::Begin("Example: Custom rendering", p_open))
    2541    {
    2542       ImGui::End();
    2543       return;
    2544    }
    2545 
    2546    // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
    2547    // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
    2548    // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
    2549    // In this example we are not using the maths operators!
    2550    ImDrawList* draw_list = ImGui::GetWindowDrawList();
    2551 
    2552    // Primitives
    2553    ImGui::Text("Primitives");
    2554    static float sz = 36.0f;
    2555    static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
    2556    ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
    2557    ImGui::ColorEdit3("Color", &col.x);
    2558    {
    2559       const ImVec2 p = ImGui::GetCursorScreenPos();
    2560       const ImU32 col32 = ImColor(col);
    2561       float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
    2562       for (int n = 0; n < 2; n++)
    2563       {
    2564          float thickness = (n == 0) ? 1.0f : 4.0f;
    2565          draw_list->AddCircle(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col32, 20, thickness); x += sz + spacing;
    2566          draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 0.0f, ImDrawCornerFlags_All, thickness); x += sz + spacing;
    2567          draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f, ImDrawCornerFlags_All, thickness); x += sz + spacing;
    2568          draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f, ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight, thickness); x += sz + spacing;
    2569          draw_list->AddTriangle(ImVec2(x + sz * 0.5f, y), ImVec2(x + sz, y + sz - 0.5f), ImVec2(x, y + sz - 0.5f), col32, thickness); x += sz + spacing;
    2570          draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col32, thickness); x += sz + spacing;
    2571          draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, thickness); x += sz + spacing;
    2572          draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col32, thickness); x += spacing;
    2573          draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x + sz * 1.3f, y + sz * 0.3f), ImVec2(x + sz - sz * 1.3f, y + sz - sz * 0.3f), ImVec2(x + sz, y + sz), col32, thickness);
    2574          x = p.x + 4;
    2575          y += sz + spacing;
    2576       }
    2577       draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col32, 32); x += sz + spacing;
    2578       draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32); x += sz + spacing;
    2579       draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f); x += sz + spacing;
    2580       draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col32, 10.0f, ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight); x += sz + spacing;
    2581       draw_list->AddTriangleFilled(ImVec2(x + sz * 0.5f, y), ImVec2(x + sz, y + sz - 0.5f), ImVec2(x, y + sz - 0.5f), col32); x += sz + spacing;
    2582       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));
    2583       ImGui::Dummy(ImVec2((sz + spacing) * 8, (sz + spacing) * 3));
    2584    }
    2585    ImGui::Separator();
    2586    {
    2587       static ImVector<ImVec2> points;
    2588       static bool adding_line = false;
    2589       ImGui::Text("Canvas example");
    2590       if (ImGui::Button("Clear")) points.clear();
    2591       if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
    2592       ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
    2593 
    2594       // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
    2595       // However you can draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
    2596       // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
    2597       ImVec2 canvas_pos = ImGui::GetCursorScreenPos();            // ImDrawList API uses screen coordinates!
    2598       ImVec2 canvas_size = ImGui::GetContentRegionAvail();        // Resize canvas to what's available
    2599       if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
    2600       if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
    2601       draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50, 50, 50, 255), IM_COL32(50, 50, 60, 255), IM_COL32(60, 60, 70, 255), IM_COL32(50, 50, 60, 255));
    2602       draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255));
    2603 
    2604       bool adding_preview = false;
    2605       ImGui::InvisibleButton("canvas", canvas_size);
    2606       ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
    2607       if (adding_line)
    2608       {
    2609          adding_preview = true;
    2610          points.push_back(mouse_pos_in_canvas);
    2611          if (!ImGui::IsMouseDown(0))
    2612             adding_line = adding_preview = false;
    2613       }
    2614       if (ImGui::IsItemHovered())
    2615       {
    2616          if (!adding_line && ImGui::IsMouseClicked(0))
    2617          {
    2618             points.push_back(mouse_pos_in_canvas);
    2619             adding_line = true;
    2620          }
    2621          if (ImGui::IsMouseClicked(1) && !points.empty())
    2622          {
    2623             adding_line = adding_preview = false;
    2624             points.pop_back();
    2625             points.pop_back();
    2626          }
    2627       }
    2628       draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), true);      // clip lines within the canvas (if we resize it, etc.)
    2629       for (int i = 0; i < points.Size - 1; i += 2)
    2630          draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i + 1].x, canvas_pos.y + points[i + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
    2631       draw_list->PopClipRect();
    2632       if (adding_preview)
    2633          points.pop_back();
    2634    }
    2635    ImGui::End();
    2636 }
    2637 
    2638 // Demonstrating creating a simple console window, with scrolling, filtering, completion and history.
    2639 // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
     4209//-----------------------------------------------------------------------------
     4210// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
     4211//-----------------------------------------------------------------------------
     4212
     4213// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
     4214// For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
    26404215struct ExampleAppConsole
    26414216{
    2642    char                  InputBuf[256];
    2643    ImVector<char*>       Items;
    2644    bool                  ScrollToBottom;
    2645    ImVector<char*>       History;
    2646    int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
    2647    ImVector<const char*> Commands;
    2648 
    2649    ExampleAppConsole()
    2650    {
    2651       ClearLog();
    2652       memset(InputBuf, 0, sizeof(InputBuf));
    2653       HistoryPos = -1;
    2654       Commands.push_back("HELP");
    2655       Commands.push_back("HISTORY");
    2656       Commands.push_back("CLEAR");
    2657       Commands.push_back("CLASSIFY");  // "classify" is here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
    2658       AddLog("Welcome to ImGui!");
    2659    }
    2660    ~ExampleAppConsole()
    2661    {
    2662       ClearLog();
    2663       for (int i = 0; i < History.Size; i++)
    2664          free(History[i]);
    2665    }
    2666 
    2667    // Portable helpers
    2668    static int   Stricmp(const char* str1, const char* str2) { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
    2669    static int   Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; }
    2670    static char* Strdup(const char *str) { size_t len = strlen(str) + 1; void* buff = malloc(len); return (char*)memcpy(buff, (const void*)str, len); }
    2671 
    2672    void    ClearLog()
    2673    {
    2674       for (int i = 0; i < Items.Size; i++)
    2675          free(Items[i]);
    2676       Items.clear();
    2677       ScrollToBottom = true;
    2678    }
    2679 
    2680    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
    2681    {
    2682       // FIXME-OPT
    2683       char buf[1024];
    2684       va_list args;
    2685       va_start(args, fmt);
    2686       vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
    2687       buf[IM_ARRAYSIZE(buf) - 1] = 0;
    2688       va_end(args);
    2689       Items.push_back(Strdup(buf));
    2690       ScrollToBottom = true;
    2691    }
    2692 
    2693    void    Draw(const char* title, bool* p_open)
    2694    {
    2695       ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
    2696       if (!ImGui::Begin(title, p_open))
    2697       {
    2698          ImGui::End();
    2699          return;
    2700       }
    2701 
    2702       // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
    2703       // Here we create a context menu only available from the title bar.
    2704       if (ImGui::BeginPopupContextItem())
    2705       {
    2706          if (ImGui::MenuItem("Close"))
    2707             *p_open = false;
    2708          ImGui::EndPopup();
    2709       }
    2710 
    2711       ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
    2712       ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
    2713 
    2714       // TODO: display items starting from the bottom
    2715 
    2716       if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
    2717       if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
    2718       if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
    2719       bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine();
    2720       if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
    2721       //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
    2722 
    2723       ImGui::Separator();
    2724 
    2725       ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
    2726       static ImGuiTextFilter filter;
    2727       filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
    2728       ImGui::PopStyleVar();
    2729       ImGui::Separator();
    2730 
    2731       const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
    2732       ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText
    2733       if (ImGui::BeginPopupContextWindow())
    2734       {
    2735          if (ImGui::Selectable("Clear")) ClearLog();
    2736          ImGui::EndPopup();
    2737       }
    2738 
    2739       // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
    2740       // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
    2741       // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements.
    2742       // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
    2743       //     ImGuiListClipper clipper(Items.Size);
    2744       //     while (clipper.Step())
    2745       //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
    2746       // However take note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list.
    2747       // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter,
    2748       // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code!
    2749       // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list.
    2750       ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
    2751       if (copy_to_clipboard)
    2752          ImGui::LogToClipboard();
    2753       ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text);
    2754       for (int i = 0; i < Items.Size; i++)
    2755       {
    2756          const char* item = Items[i];
    2757          if (!filter.PassFilter(item))
    2758             continue;
    2759          ImVec4 col = col_default_text;
    2760          if (strstr(item, "[error]")) col = ImColor(1.0f, 0.4f, 0.4f, 1.0f);
    2761          else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f, 0.78f, 0.58f, 1.0f);
    2762          ImGui::PushStyleColor(ImGuiCol_Text, col);
    2763          ImGui::TextUnformatted(item);
    2764          ImGui::PopStyleColor();
    2765       }
    2766       if (copy_to_clipboard)
    2767          ImGui::LogFinish();
    2768       if (ScrollToBottom)
    2769          ImGui::SetScrollHere();
    2770       ScrollToBottom = false;
    2771       ImGui::PopStyleVar();
    2772       ImGui::EndChild();
    2773       ImGui::Separator();
    2774 
    2775       // Command-line
    2776       bool reclaim_focus = false;
    2777       if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
    2778       {
    2779          char* input_end = InputBuf + strlen(InputBuf);
    2780          while (input_end > InputBuf && input_end[-1] == ' ') { input_end--; } *input_end = 0;
    2781          if (InputBuf[0])
    2782             ExecCommand(InputBuf);
    2783          strcpy(InputBuf, "");
    2784          reclaim_focus = true;
    2785       }
    2786 
    2787       // Demonstrate keeping focus on the input box
    2788       ImGui::SetItemDefaultFocus();
    2789       if (reclaim_focus)
    2790          ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
    2791 
    2792       ImGui::End();
    2793    }
    2794 
    2795    void    ExecCommand(const char* command_line)
    2796    {
    2797       AddLog("# %s\n", command_line);
    2798 
    2799       // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.
    2800       HistoryPos = -1;
    2801       for (int i = History.Size - 1; i >= 0; i--)
    2802          if (Stricmp(History[i], command_line) == 0)
    2803          {
     4217    char                  InputBuf[256];
     4218    ImVector<char*>       Items;
     4219    ImVector<const char*> Commands;
     4220    ImVector<char*>       History;
     4221    int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
     4222    ImGuiTextFilter       Filter;
     4223    bool                  AutoScroll;
     4224    bool                  ScrollToBottom;
     4225
     4226    ExampleAppConsole()
     4227    {
     4228        ClearLog();
     4229        memset(InputBuf, 0, sizeof(InputBuf));
     4230        HistoryPos = -1;
     4231
     4232        // "CLASSIFY" is here to provide the test case where "C"+[tab] completes to "CL" and display multiple matches.
     4233        Commands.push_back("HELP");
     4234        Commands.push_back("HISTORY");
     4235        Commands.push_back("CLEAR");
     4236        Commands.push_back("CLASSIFY");
     4237        AutoScroll = true;
     4238        ScrollToBottom = false;
     4239        AddLog("Welcome to Dear ImGui!");
     4240    }
     4241    ~ExampleAppConsole()
     4242    {
     4243        ClearLog();
     4244        for (int i = 0; i < History.Size; i++)
    28044245            free(History[i]);
    2805             History.erase(History.begin() + i);
    2806             break;
    2807          }
    2808       History.push_back(Strdup(command_line));
    2809 
    2810       // Process command
    2811       if (Stricmp(command_line, "CLEAR") == 0)
    2812       {
    2813          ClearLog();
    2814       }
    2815       else if (Stricmp(command_line, "HELP") == 0)
    2816       {
    2817          AddLog("Commands:");
    2818          for (int i = 0; i < Commands.Size; i++)
    2819             AddLog("- %s", Commands[i]);
    2820       }
    2821       else if (Stricmp(command_line, "HISTORY") == 0)
    2822       {
    2823          int first = History.Size - 10;
    2824          for (int i = first > 0 ? first : 0; i < History.Size; i++)
    2825             AddLog("%3d: %s\n", i, History[i]);
    2826       }
    2827       else
    2828       {
    2829          AddLog("Unknown command: '%s'\n", command_line);
    2830       }
    2831    }
    2832 
    2833    static int TextEditCallbackStub(ImGuiTextEditCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
    2834    {
    2835       ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
    2836       return console->TextEditCallback(data);
    2837    }
    2838 
    2839    int     TextEditCallback(ImGuiTextEditCallbackData* data)
    2840    {
    2841       //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
    2842       switch (data->EventFlag)
    2843       {
    2844       case ImGuiInputTextFlags_CallbackCompletion:
    2845       {
    2846          // Example of TEXT COMPLETION
    2847 
    2848          // Locate beginning of current word
    2849          const char* word_end = data->Buf + data->CursorPos;
    2850          const char* word_start = word_end;
    2851          while (word_start > data->Buf)
    2852          {
    2853             const char c = word_start[-1];
    2854             if (c == ' ' || c == '\t' || c == ',' || c == ';')
    2855                break;
    2856             word_start--;
    2857          }
    2858 
    2859          // Build a list of candidates
    2860          ImVector<const char*> candidates;
    2861          for (int i = 0; i < Commands.Size; i++)
    2862             if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
    2863                candidates.push_back(Commands[i]);
    2864 
    2865          if (candidates.Size == 0)
    2866          {
    2867             // No match
    2868             AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
    2869          }
    2870          else if (candidates.Size == 1)
    2871          {
    2872             // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
    2873             data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
    2874             data->InsertChars(data->CursorPos, candidates[0]);
    2875             data->InsertChars(data->CursorPos, " ");
    2876          }
    2877          else
    2878          {
    2879             // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
    2880             int match_len = (int)(word_end - word_start);
    2881             for (;;)
    2882             {
    2883                int c = 0;
    2884                bool all_candidates_matches = true;
    2885                for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
    2886                   if (i == 0)
    2887                      c = toupper(candidates[i][match_len]);
    2888                   else if (c == 0 || c != toupper(candidates[i][match_len]))
    2889                      all_candidates_matches = false;
    2890                if (!all_candidates_matches)
    2891                   break;
    2892                match_len++;
    2893             }
    2894 
    2895             if (match_len > 0)
    2896             {
    2897                data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
    2898                data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
    2899             }
    2900 
    2901             // List matches
    2902             AddLog("Possible matches:\n");
    2903             for (int i = 0; i < candidates.Size; i++)
    2904                AddLog("- %s\n", candidates[i]);
    2905          }
    2906 
    2907          break;
    2908       }
    2909       case ImGuiInputTextFlags_CallbackHistory:
    2910       {
    2911          // Example of HISTORY
    2912          const int prev_history_pos = HistoryPos;
    2913          if (data->EventKey == ImGuiKey_UpArrow)
    2914          {
    2915             if (HistoryPos == -1)
    2916                HistoryPos = History.Size - 1;
    2917             else if (HistoryPos > 0)
    2918                HistoryPos--;
    2919          }
    2920          else if (data->EventKey == ImGuiKey_DownArrow)
    2921          {
    2922             if (HistoryPos != -1)
    2923                if (++HistoryPos >= History.Size)
    2924                   HistoryPos = -1;
    2925          }
    2926 
    2927          // A better implementation would preserve the data on the current input line along with cursor position.
    2928          if (prev_history_pos != HistoryPos)
    2929          {
    2930             data->CursorPos = data->SelectionStart = data->SelectionEnd = data->BufTextLen = (int)snprintf(data->Buf, (size_t)data->BufSize, "%s", (HistoryPos >= 0) ? History[HistoryPos] : "");
    2931             data->BufDirty = true;
    2932          }
    2933       }
    2934       }
    2935       return 0;
    2936    }
     4246    }
     4247
     4248    // Portable helpers
     4249    static int   Stricmp(const char* s1, const char* s2)         { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
     4250    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; }
     4251    static char* Strdup(const char* s)                           { size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
     4252    static void  Strtrim(char* s)                                { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
     4253
     4254    void    ClearLog()
     4255    {
     4256        for (int i = 0; i < Items.Size; i++)
     4257            free(Items[i]);
     4258        Items.clear();
     4259    }
     4260
     4261    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
     4262    {
     4263        // FIXME-OPT
     4264        char buf[1024];
     4265        va_list args;
     4266        va_start(args, fmt);
     4267        vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
     4268        buf[IM_ARRAYSIZE(buf)-1] = 0;
     4269        va_end(args);
     4270        Items.push_back(Strdup(buf));
     4271    }
     4272
     4273    void    Draw(const char* title, bool* p_open)
     4274    {
     4275        ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
     4276        if (!ImGui::Begin(title, p_open))
     4277        {
     4278            ImGui::End();
     4279            return;
     4280        }
     4281
     4282        // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar.
     4283        // So e.g. IsItemHovered() will return true when hovering the title bar.
     4284        // Here we create a context menu only available from the title bar.
     4285        if (ImGui::BeginPopupContextItem())
     4286        {
     4287            if (ImGui::MenuItem("Close Console"))
     4288                *p_open = false;
     4289            ImGui::EndPopup();
     4290        }
     4291
     4292        ImGui::TextWrapped(
     4293            "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate "
     4294            "implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
     4295        ImGui::TextWrapped("Enter 'HELP' for help.");
     4296
     4297        // TODO: display items starting from the bottom
     4298
     4299        if (ImGui::SmallButton("Add Debug Text"))  { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); }
     4300        ImGui::SameLine();
     4301        if (ImGui::SmallButton("Add Debug Error")) { AddLog("[error] something went wrong"); }
     4302        ImGui::SameLine();
     4303        if (ImGui::SmallButton("Clear"))           { ClearLog(); }
     4304        ImGui::SameLine();
     4305        bool copy_to_clipboard = ImGui::SmallButton("Copy");
     4306        //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
     4307
     4308        ImGui::Separator();
     4309
     4310        // Options menu
     4311        if (ImGui::BeginPopup("Options"))
     4312        {
     4313            ImGui::Checkbox("Auto-scroll", &AutoScroll);
     4314            ImGui::EndPopup();
     4315        }
     4316
     4317        // Options, Filter
     4318        if (ImGui::Button("Options"))
     4319            ImGui::OpenPopup("Options");
     4320        ImGui::SameLine();
     4321        Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
     4322        ImGui::Separator();
     4323
     4324        // Reserve enough left-over height for 1 separator + 1 input text
     4325        const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
     4326        ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar);
     4327        if (ImGui::BeginPopupContextWindow())
     4328        {
     4329            if (ImGui::Selectable("Clear")) ClearLog();
     4330            ImGui::EndPopup();
     4331        }
     4332
     4333        // Display every line as a separate entry so we can change their color or add custom widgets.
     4334        // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
     4335        // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
     4336        // to only process visible items. The clipper will automatically measure the height of your first item and then
     4337        // "seek" to display only items in the visible area.
     4338        // To use the clipper we can replace your standard loop:
     4339        //      for (int i = 0; i < Items.Size; i++)
     4340        //   With:
     4341        //      ImGuiListClipper clipper;
     4342        //      clipper.Begin(Items.Size);
     4343        //      while (clipper.Step())
     4344        //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
     4345        // - That your items are evenly spaced (same height)
     4346        // - That you have cheap random access to your elements (you can access them given their index,
     4347        //   without processing all the ones before)
     4348        // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
     4349        // We would need random-access on the post-filtered list.
     4350        // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
     4351        // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
     4352        // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
     4353        // to improve this example code!
     4354        // If your items are of variable height:
     4355        // - Split them into same height items would be simpler and facilitate random-seeking into your list.
     4356        // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
     4357        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
     4358        if (copy_to_clipboard)
     4359            ImGui::LogToClipboard();
     4360        for (int i = 0; i < Items.Size; i++)
     4361        {
     4362            const char* item = Items[i];
     4363            if (!Filter.PassFilter(item))
     4364                continue;
     4365
     4366            // Normally you would store more information in your item than just a string.
     4367            // (e.g. make Items[] an array of structure, store color/type etc.)
     4368            ImVec4 color;
     4369            bool has_color = false;
     4370            if (strstr(item, "[error]"))          { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
     4371            else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
     4372            if (has_color)
     4373                ImGui::PushStyleColor(ImGuiCol_Text, color);
     4374            ImGui::TextUnformatted(item);
     4375            if (has_color)
     4376                ImGui::PopStyleColor();
     4377        }
     4378        if (copy_to_clipboard)
     4379            ImGui::LogFinish();
     4380
     4381        if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
     4382            ImGui::SetScrollHereY(1.0f);
     4383        ScrollToBottom = false;
     4384
     4385        ImGui::PopStyleVar();
     4386        ImGui::EndChild();
     4387        ImGui::Separator();
     4388
     4389        // Command-line
     4390        bool reclaim_focus = false;
     4391        ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
     4392        if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
     4393        {
     4394            char* s = InputBuf;
     4395            Strtrim(s);
     4396            if (s[0])
     4397                ExecCommand(s);
     4398            strcpy(s, "");
     4399            reclaim_focus = true;
     4400        }
     4401
     4402        // Auto-focus on window apparition
     4403        ImGui::SetItemDefaultFocus();
     4404        if (reclaim_focus)
     4405            ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
     4406
     4407        ImGui::End();
     4408    }
     4409
     4410    void    ExecCommand(const char* command_line)
     4411    {
     4412        AddLog("# %s\n", command_line);
     4413
     4414        // Insert into history. First find match and delete it so it can be pushed to the back.
     4415        // This isn't trying to be smart or optimal.
     4416        HistoryPos = -1;
     4417        for (int i = History.Size - 1; i >= 0; i--)
     4418            if (Stricmp(History[i], command_line) == 0)
     4419            {
     4420                free(History[i]);
     4421                History.erase(History.begin() + i);
     4422                break;
     4423            }
     4424        History.push_back(Strdup(command_line));
     4425
     4426        // Process command
     4427        if (Stricmp(command_line, "CLEAR") == 0)
     4428        {
     4429            ClearLog();
     4430        }
     4431        else if (Stricmp(command_line, "HELP") == 0)
     4432        {
     4433            AddLog("Commands:");
     4434            for (int i = 0; i < Commands.Size; i++)
     4435                AddLog("- %s", Commands[i]);
     4436        }
     4437        else if (Stricmp(command_line, "HISTORY") == 0)
     4438        {
     4439            int first = History.Size - 10;
     4440            for (int i = first > 0 ? first : 0; i < History.Size; i++)
     4441                AddLog("%3d: %s\n", i, History[i]);
     4442        }
     4443        else
     4444        {
     4445            AddLog("Unknown command: '%s'\n", command_line);
     4446        }
     4447
     4448        // On command input, we scroll to bottom even if AutoScroll==false
     4449        ScrollToBottom = true;
     4450    }
     4451
     4452    // In C++11 you'd be better off using lambdas for this sort of forwarding callbacks
     4453    static int TextEditCallbackStub(ImGuiInputTextCallbackData* data)
     4454    {
     4455        ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
     4456        return console->TextEditCallback(data);
     4457    }
     4458
     4459    int     TextEditCallback(ImGuiInputTextCallbackData* data)
     4460    {
     4461        //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
     4462        switch (data->EventFlag)
     4463        {
     4464        case ImGuiInputTextFlags_CallbackCompletion:
     4465            {
     4466                // Example of TEXT COMPLETION
     4467
     4468                // Locate beginning of current word
     4469                const char* word_end = data->Buf + data->CursorPos;
     4470                const char* word_start = word_end;
     4471                while (word_start > data->Buf)
     4472                {
     4473                    const char c = word_start[-1];
     4474                    if (c == ' ' || c == '\t' || c == ',' || c == ';')
     4475                        break;
     4476                    word_start--;
     4477                }
     4478
     4479                // Build a list of candidates
     4480                ImVector<const char*> candidates;
     4481                for (int i = 0; i < Commands.Size; i++)
     4482                    if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
     4483                        candidates.push_back(Commands[i]);
     4484
     4485                if (candidates.Size == 0)
     4486                {
     4487                    // No match
     4488                    AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
     4489                }
     4490                else if (candidates.Size == 1)
     4491                {
     4492                    // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing.
     4493                    data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
     4494                    data->InsertChars(data->CursorPos, candidates[0]);
     4495                    data->InsertChars(data->CursorPos, " ");
     4496                }
     4497                else
     4498                {
     4499                    // Multiple matches. Complete as much as we can..
     4500                    // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches.
     4501                    int match_len = (int)(word_end - word_start);
     4502                    for (;;)
     4503                    {
     4504                        int c = 0;
     4505                        bool all_candidates_matches = true;
     4506                        for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
     4507                            if (i == 0)
     4508                                c = toupper(candidates[i][match_len]);
     4509                            else if (c == 0 || c != toupper(candidates[i][match_len]))
     4510                                all_candidates_matches = false;
     4511                        if (!all_candidates_matches)
     4512                            break;
     4513                        match_len++;
     4514                    }
     4515
     4516                    if (match_len > 0)
     4517                    {
     4518                        data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
     4519                        data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
     4520                    }
     4521
     4522                    // List matches
     4523                    AddLog("Possible matches:\n");
     4524                    for (int i = 0; i < candidates.Size; i++)
     4525                        AddLog("- %s\n", candidates[i]);
     4526                }
     4527
     4528                break;
     4529            }
     4530        case ImGuiInputTextFlags_CallbackHistory:
     4531            {
     4532                // Example of HISTORY
     4533                const int prev_history_pos = HistoryPos;
     4534                if (data->EventKey == ImGuiKey_UpArrow)
     4535                {
     4536                    if (HistoryPos == -1)
     4537                        HistoryPos = History.Size - 1;
     4538                    else if (HistoryPos > 0)
     4539                        HistoryPos--;
     4540                }
     4541                else if (data->EventKey == ImGuiKey_DownArrow)
     4542                {
     4543                    if (HistoryPos != -1)
     4544                        if (++HistoryPos >= History.Size)
     4545                            HistoryPos = -1;
     4546                }
     4547
     4548                // A better implementation would preserve the data on the current input line along with cursor position.
     4549                if (prev_history_pos != HistoryPos)
     4550                {
     4551                    const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
     4552                    data->DeleteChars(0, data->BufTextLen);
     4553                    data->InsertChars(0, history_str);
     4554                }
     4555            }
     4556        }
     4557        return 0;
     4558    }
    29374559};
    29384560
    29394561static void ShowExampleAppConsole(bool* p_open)
    29404562{
    2941    static ExampleAppConsole console;
    2942    console.Draw("Example: Console", p_open);
     4563    static ExampleAppConsole console;
     4564    console.Draw("Example: Console", p_open);
    29434565}
     4566
     4567//-----------------------------------------------------------------------------
     4568// [SECTION] Example App: Debug Log / ShowExampleAppLog()
     4569//-----------------------------------------------------------------------------
    29444570
    29454571// Usage:
     
    29494575struct ExampleAppLog
    29504576{
    2951    ImGuiTextBuffer     Buf;
    2952    ImGuiTextFilter     Filter;
    2953    ImVector<int>       LineOffsets;        // Index to lines offset
    2954    bool                ScrollToBottom;
    2955 
    2956    void    Clear() { Buf.clear(); LineOffsets.clear(); }
    2957 
    2958    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
    2959    {
    2960       int old_size = Buf.size();
    2961       va_list args;
    2962       va_start(args, fmt);
    2963       Buf.appendfv(fmt, args);
    2964       va_end(args);
    2965       for (int new_size = Buf.size(); old_size < new_size; old_size++)
    2966          if (Buf[old_size] == '\n')
    2967             LineOffsets.push_back(old_size);
    2968       ScrollToBottom = true;
    2969    }
    2970 
    2971    void    Draw(const char* title, bool* p_open = NULL)
    2972    {
    2973       ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
    2974       ImGui::Begin(title, p_open);
    2975       if (ImGui::Button("Clear")) Clear();
    2976       ImGui::SameLine();
    2977       bool copy = ImGui::Button("Copy");
    2978       ImGui::SameLine();
    2979       Filter.Draw("Filter", -100.0f);
    2980       ImGui::Separator();
    2981       ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
    2982       if (copy) ImGui::LogToClipboard();
    2983 
    2984       if (Filter.IsActive())
    2985       {
    2986          const char* buf_begin = Buf.begin();
    2987          const char* line = buf_begin;
    2988          for (int line_no = 0; line != NULL; line_no++)
    2989          {
    2990             const char* line_end = (line_no < LineOffsets.Size) ? buf_begin + LineOffsets[line_no] : NULL;
    2991             if (Filter.PassFilter(line, line_end))
    2992                ImGui::TextUnformatted(line, line_end);
    2993             line = line_end && line_end[1] ? line_end + 1 : NULL;
    2994          }
    2995       }
    2996       else
    2997       {
    2998          ImGui::TextUnformatted(Buf.begin());
    2999       }
    3000 
    3001       if (ScrollToBottom)
    3002          ImGui::SetScrollHere(1.0f);
    3003       ScrollToBottom = false;
    3004       ImGui::EndChild();
    3005       ImGui::End();
    3006    }
     4577    ImGuiTextBuffer     Buf;
     4578    ImGuiTextFilter     Filter;
     4579    ImVector<int>       LineOffsets; // Index to lines offset. We maintain this with AddLog() calls.
     4580    bool                AutoScroll;  // Keep scrolling if already at the bottom.
     4581
     4582    ExampleAppLog()
     4583    {
     4584        AutoScroll = true;
     4585        Clear();
     4586    }
     4587
     4588    void    Clear()
     4589    {
     4590        Buf.clear();
     4591        LineOffsets.clear();
     4592        LineOffsets.push_back(0);
     4593    }
     4594
     4595    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
     4596    {
     4597        int old_size = Buf.size();
     4598        va_list args;
     4599        va_start(args, fmt);
     4600        Buf.appendfv(fmt, args);
     4601        va_end(args);
     4602        for (int new_size = Buf.size(); old_size < new_size; old_size++)
     4603            if (Buf[old_size] == '\n')
     4604                LineOffsets.push_back(old_size + 1);
     4605    }
     4606
     4607    void    Draw(const char* title, bool* p_open = NULL)
     4608    {
     4609        if (!ImGui::Begin(title, p_open))
     4610        {
     4611            ImGui::End();
     4612            return;
     4613        }
     4614
     4615        // Options menu
     4616        if (ImGui::BeginPopup("Options"))
     4617        {
     4618            ImGui::Checkbox("Auto-scroll", &AutoScroll);
     4619            ImGui::EndPopup();
     4620        }
     4621
     4622        // Main window
     4623        if (ImGui::Button("Options"))
     4624            ImGui::OpenPopup("Options");
     4625        ImGui::SameLine();
     4626        bool clear = ImGui::Button("Clear");
     4627        ImGui::SameLine();
     4628        bool copy = ImGui::Button("Copy");
     4629        ImGui::SameLine();
     4630        Filter.Draw("Filter", -100.0f);
     4631
     4632        ImGui::Separator();
     4633        ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
     4634
     4635        if (clear)
     4636            Clear();
     4637        if (copy)
     4638            ImGui::LogToClipboard();
     4639
     4640        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
     4641        const char* buf = Buf.begin();
     4642        const char* buf_end = Buf.end();
     4643        if (Filter.IsActive())
     4644        {
     4645            // In this example we don't use the clipper when Filter is enabled.
     4646            // This is because we don't have a random access on the result on our filter.
     4647            // A real application processing logs with ten of thousands of entries may want to store the result of
     4648            // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
     4649            for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
     4650            {
     4651                const char* line_start = buf + LineOffsets[line_no];
     4652                const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
     4653                if (Filter.PassFilter(line_start, line_end))
     4654                    ImGui::TextUnformatted(line_start, line_end);
     4655            }
     4656        }
     4657        else
     4658        {
     4659            // The simplest and easy way to display the entire buffer:
     4660            //   ImGui::TextUnformatted(buf_begin, buf_end);
     4661            // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
     4662            // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
     4663            // within the visible area.
     4664            // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
     4665            // on your side is recommended. Using ImGuiListClipper requires
     4666            // - A) random access into your data
     4667            // - B) items all being the  same height,
     4668            // both of which we can handle since we an array pointing to the beginning of each line of text.
     4669            // When using the filter (in the block of code above) we don't have random access into the data to display
     4670            // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
     4671            // it possible (and would be recommended if you want to search through tens of thousands of entries).
     4672            ImGuiListClipper clipper;
     4673            clipper.Begin(LineOffsets.Size);
     4674            while (clipper.Step())
     4675            {
     4676                for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
     4677                {
     4678                    const char* line_start = buf + LineOffsets[line_no];
     4679                    const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
     4680                    ImGui::TextUnformatted(line_start, line_end);
     4681                }
     4682            }
     4683            clipper.End();
     4684        }
     4685        ImGui::PopStyleVar();
     4686
     4687        if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
     4688            ImGui::SetScrollHereY(1.0f);
     4689
     4690        ImGui::EndChild();
     4691        ImGui::End();
     4692    }
    30074693};
    30084694
     
    30104696static void ShowExampleAppLog(bool* p_open)
    30114697{
    3012    static ExampleAppLog log;
    3013 
    3014    // Demo: add random items (unless Ctrl is held)
    3015    static float last_time = -1.0f;
    3016    float time = ImGui::GetTime();
    3017    if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl)
    3018    {
    3019       const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
    3020       log.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, ImGui::GetFrameCount());
    3021       last_time = time;
    3022    }
    3023 
    3024    log.Draw("Example: Log", p_open);
     4698    static ExampleAppLog log;
     4699
     4700    // For the demo: add a debug button _BEFORE_ the normal log window contents
     4701    // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
     4702    // Most of the contents of the window will be added by the log.Draw() call.
     4703    ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
     4704    ImGui::Begin("Example: Log", p_open);
     4705    if (ImGui::SmallButton("[Debug] Add 5 entries"))
     4706    {
     4707        static int counter = 0;
     4708        const char* categories[3] = { "info", "warn", "error" };
     4709        const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
     4710        for (int n = 0; n < 5; n++)
     4711        {
     4712            const char* category = categories[counter % IM_ARRAYSIZE(categories)];
     4713            const char* word = words[counter % IM_ARRAYSIZE(words)];
     4714            log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
     4715                ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
     4716            counter++;
     4717        }
     4718    }
     4719    ImGui::End();
     4720
     4721    // Actually call in the regular Log helper (which will Begin() into the same window as we just did)
     4722    log.Draw("Example: Log", p_open);
    30254723}
     4724
     4725//-----------------------------------------------------------------------------
     4726// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
     4727//-----------------------------------------------------------------------------
    30264728
    30274729// Demonstrate create a window with multiple child windows.
    30284730static void ShowExampleAppLayout(bool* p_open)
    30294731{
    3030    ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
    3031    if (ImGui::Begin("Example: Layout", p_open, ImGuiWindowFlags_MenuBar))
    3032    {
    3033       if (ImGui::BeginMenuBar())
    3034       {
    3035          if (ImGui::BeginMenu("File"))
    3036          {
    3037             if (ImGui::MenuItem("Close")) *p_open = false;
    3038             ImGui::EndMenu();
    3039          }
    3040          ImGui::EndMenuBar();
    3041       }
    3042 
    3043       // left
    3044       static int selected = 0;
    3045       ImGui::BeginChild("left pane", ImVec2(150, 0), true);
    3046       for (int i = 0; i < 100; i++)
    3047       {
    3048          char label[128];
    3049          sprintf(label, "MyObject %d", i);
    3050          if (ImGui::Selectable(label, selected == i))
    3051             selected = i;
    3052       }
    3053       ImGui::EndChild();
    3054       ImGui::SameLine();
    3055 
    3056       // right
    3057       ImGui::BeginGroup();
    3058       ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
    3059       ImGui::Text("MyObject: %d", selected);
    3060       ImGui::Separator();
    3061       ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
    3062       ImGui::EndChild();
    3063       if (ImGui::Button("Revert")) {}
    3064       ImGui::SameLine();
    3065       if (ImGui::Button("Save")) {}
    3066       ImGui::EndGroup();
    3067    }
    3068    ImGui::End();
     4732    ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
     4733    if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
     4734    {
     4735        if (ImGui::BeginMenuBar())
     4736        {
     4737            if (ImGui::BeginMenu("File"))
     4738            {
     4739                if (ImGui::MenuItem("Close")) *p_open = false;
     4740                ImGui::EndMenu();
     4741            }
     4742            ImGui::EndMenuBar();
     4743        }
     4744
     4745        // Left
     4746        static int selected = 0;
     4747        {
     4748            ImGui::BeginChild("left pane", ImVec2(150, 0), true);
     4749            for (int i = 0; i < 100; i++)
     4750            {
     4751                char label[128];
     4752                sprintf(label, "MyObject %d", i);
     4753                if (ImGui::Selectable(label, selected == i))
     4754                    selected = i;
     4755            }
     4756            ImGui::EndChild();
     4757        }
     4758        ImGui::SameLine();
     4759
     4760        // Right
     4761        {
     4762            ImGui::BeginGroup();
     4763            ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
     4764            ImGui::Text("MyObject: %d", selected);
     4765            ImGui::Separator();
     4766            if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
     4767            {
     4768                if (ImGui::BeginTabItem("Description"))
     4769                {
     4770                    ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
     4771                    ImGui::EndTabItem();
     4772                }
     4773                if (ImGui::BeginTabItem("Details"))
     4774                {
     4775                    ImGui::Text("ID: 0123456789");
     4776                    ImGui::EndTabItem();
     4777                }
     4778                ImGui::EndTabBar();
     4779            }
     4780            ImGui::EndChild();
     4781            if (ImGui::Button("Revert")) {}
     4782            ImGui::SameLine();
     4783            if (ImGui::Button("Save")) {}
     4784            ImGui::EndGroup();
     4785        }
     4786    }
     4787    ImGui::End();
     4788}
     4789
     4790//-----------------------------------------------------------------------------
     4791// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
     4792//-----------------------------------------------------------------------------
     4793
     4794static void ShowPlaceholderObject(const char* prefix, int uid)
     4795{
     4796    // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
     4797    ImGui::PushID(uid);
     4798
     4799    // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high.
     4800    ImGui::AlignTextToFramePadding();
     4801    bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
     4802    ImGui::NextColumn();
     4803    ImGui::AlignTextToFramePadding();
     4804    ImGui::Text("my sailor is rich");
     4805    ImGui::NextColumn();
     4806    if (node_open)
     4807    {
     4808        static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f };
     4809        for (int i = 0; i < 8; i++)
     4810        {
     4811            ImGui::PushID(i); // Use field index as identifier.
     4812            if (i < 2)
     4813            {
     4814                ShowPlaceholderObject("Child", 424242);
     4815            }
     4816            else
     4817            {
     4818                // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
     4819                ImGui::AlignTextToFramePadding();
     4820                ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet;
     4821                ImGui::TreeNodeEx("Field", flags, "Field_%d", i);
     4822                ImGui::NextColumn();
     4823                ImGui::SetNextItemWidth(-1);
     4824                if (i >= 5)
     4825                    ImGui::InputFloat("##value", &placeholder_members[i], 1.0f);
     4826                else
     4827                    ImGui::DragFloat("##value", &placeholder_members[i], 0.01f);
     4828                ImGui::NextColumn();
     4829            }
     4830            ImGui::PopID();
     4831        }
     4832        ImGui::TreePop();
     4833    }
     4834    ImGui::PopID();
    30694835}
    30704836
     
    30724838static void ShowExampleAppPropertyEditor(bool* p_open)
    30734839{
    3074    ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
    3075    if (!ImGui::Begin("Example: Property editor", p_open))
    3076    {
    3077       ImGui::End();
    3078       return;
    3079    }
    3080 
    3081    ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");
    3082 
    3083    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
    3084    ImGui::Columns(2);
    3085    ImGui::Separator();
    3086 
    3087    struct funcs
    3088    {
    3089       static void ShowDummyObject(const char* prefix, int uid)
    3090       {
    3091          ImGui::PushID(uid);                      // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
    3092          ImGui::AlignTextToFramePadding();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
    3093          bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
    3094          ImGui::NextColumn();
    3095          ImGui::AlignTextToFramePadding();
    3096          ImGui::Text("my sailor is rich");
    3097          ImGui::NextColumn();
    3098          if (node_open)
    3099          {
    3100             static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
    3101             for (int i = 0; i < 8; i++)
    3102             {
    3103                ImGui::PushID(i); // Use field index as identifier.
    3104                if (i < 2)
    3105                {
    3106                   ShowDummyObject("Child", 424242);
    3107                }
    3108                else
    3109                {
    3110                   ImGui::AlignTextToFramePadding();
    3111                   // Here we use a Selectable (instead of Text) to highlight on hover
    3112                   //ImGui::Text("Field_%d", i);
    3113                   char label[32];
    3114                   sprintf(label, "Field_%d", i);
    3115                   ImGui::Bullet();
    3116                   ImGui::Selectable(label);
    3117                   ImGui::NextColumn();
    3118                   ImGui::PushItemWidth(-1);
    3119                   if (i >= 5)
    3120                      ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
    3121                   else
    3122                      ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
    3123                   ImGui::PopItemWidth();
    3124                   ImGui::NextColumn();
    3125                }
    3126                ImGui::PopID();
    3127             }
    3128             ImGui::TreePop();
    3129          }
    3130          ImGui::PopID();
    3131       }
    3132    };
    3133 
    3134    // Iterate dummy objects with dummy members (all the same data)
    3135    for (int obj_i = 0; obj_i < 3; obj_i++)
    3136       funcs::ShowDummyObject("Object", obj_i);
    3137 
    3138    ImGui::Columns(1);
    3139    ImGui::Separator();
    3140    ImGui::PopStyleVar();
    3141    ImGui::End();
     4840    ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
     4841    if (!ImGui::Begin("Example: Property editor", p_open))
     4842    {
     4843        ImGui::End();
     4844        return;
     4845    }
     4846
     4847    HelpMarker(
     4848        "This example shows how you may implement a property editor using two columns.\n"
     4849        "All objects/fields data are dummies here.\n"
     4850        "Remember that in many simple cases, you can use ImGui::SameLine(xxx) to position\n"
     4851        "your cursor horizontally instead of using the Columns() API.");
     4852
     4853    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
     4854    ImGui::Columns(2);
     4855    ImGui::Separator();
     4856
     4857    // Iterate placeholder objects (all the same data)
     4858    for (int obj_i = 0; obj_i < 3; obj_i++)
     4859        ShowPlaceholderObject("Object", obj_i);
     4860
     4861    ImGui::Columns(1);
     4862    ImGui::Separator();
     4863    ImGui::PopStyleVar();
     4864    ImGui::End();
    31424865}
     4866
     4867//-----------------------------------------------------------------------------
     4868// [SECTION] Example App: Long Text / ShowExampleAppLongText()
     4869//-----------------------------------------------------------------------------
    31434870
    31444871// Demonstrate/test rendering huge amount of text, and the incidence of clipping.
    31454872static void ShowExampleAppLongText(bool* p_open)
    31464873{
    3147    ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
    3148    if (!ImGui::Begin("Example: Long text display", p_open))
    3149    {
    3150       ImGui::End();
    3151       return;
    3152    }
    3153 
    3154    static int test_type = 0;
    3155    static ImGuiTextBuffer log;
    3156    static int lines = 0;
    3157    ImGui::Text("Printing unusually long amount of text.");
    3158    ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
    3159    ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
    3160    if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
    3161    ImGui::SameLine();
    3162    if (ImGui::Button("Add 1000 lines"))
    3163    {
    3164       for (int i = 0; i < 1000; i++)
    3165          log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
    3166       lines += 1000;
    3167    }
    3168    ImGui::BeginChild("Log");
    3169    switch (test_type)
    3170    {
    3171    case 0:
    3172       // Single call to TextUnformatted() with a big buffer
    3173       ImGui::TextUnformatted(log.begin(), log.end());
    3174       break;
    3175    case 1:
    3176    {
    3177       // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
    3178       ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
    3179       ImGuiListClipper clipper(lines);
    3180       while (clipper.Step())
    3181          for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
     4874    ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
     4875    if (!ImGui::Begin("Example: Long text display", p_open))
     4876    {
     4877        ImGui::End();
     4878        return;
     4879    }
     4880
     4881    static int test_type = 0;
     4882    static ImGuiTextBuffer log;
     4883    static int lines = 0;
     4884    ImGui::Text("Printing unusually long amount of text.");
     4885    ImGui::Combo("Test type", &test_type,
     4886        "Single call to TextUnformatted()\0"
     4887        "Multiple calls to Text(), clipped\0"
     4888        "Multiple calls to Text(), not clipped (slow)\0");
     4889    ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
     4890    if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
     4891    ImGui::SameLine();
     4892    if (ImGui::Button("Add 1000 lines"))
     4893    {
     4894        for (int i = 0; i < 1000; i++)
     4895            log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
     4896        lines += 1000;
     4897    }
     4898    ImGui::BeginChild("Log");
     4899    switch (test_type)
     4900    {
     4901    case 0:
     4902        // Single call to TextUnformatted() with a big buffer
     4903        ImGui::TextUnformatted(log.begin(), log.end());
     4904        break;
     4905    case 1:
     4906        {
     4907            // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
     4908            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
     4909            ImGuiListClipper clipper;
     4910            clipper.Begin(lines);
     4911            while (clipper.Step())
     4912                for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
     4913                    ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
     4914            ImGui::PopStyleVar();
     4915            break;
     4916        }
     4917    case 2:
     4918        // Multiple calls to Text(), not clipped (slow)
     4919        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
     4920        for (int i = 0; i < lines; i++)
    31824921            ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
    3183       ImGui::PopStyleVar();
    3184       break;
    3185    }
    3186    case 2:
    3187       // Multiple calls to Text(), not clipped (slow)
    3188       ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
    3189       for (int i = 0; i < lines; i++)
    3190          ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
    3191       ImGui::PopStyleVar();
    3192       break;
    3193    }
    3194    ImGui::EndChild();
    3195    ImGui::End();
     4922        ImGui::PopStyleVar();
     4923        break;
     4924    }
     4925    ImGui::EndChild();
     4926    ImGui::End();
     4927}
     4928
     4929//-----------------------------------------------------------------------------
     4930// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
     4931//-----------------------------------------------------------------------------
     4932
     4933// Demonstrate creating a window which gets auto-resized according to its content.
     4934static void ShowExampleAppAutoResize(bool* p_open)
     4935{
     4936    if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
     4937    {
     4938        ImGui::End();
     4939        return;
     4940    }
     4941
     4942    static int lines = 10;
     4943    ImGui::TextUnformatted(
     4944        "Window will resize every-frame to the size of its content.\n"
     4945        "Note that you probably don't want to query the window size to\n"
     4946        "output your content because that would create a feedback loop.");
     4947    ImGui::SliderInt("Number of lines", &lines, 1, 20);
     4948    for (int i = 0; i < lines; i++)
     4949        ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
     4950    ImGui::End();
     4951}
     4952
     4953//-----------------------------------------------------------------------------
     4954// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
     4955//-----------------------------------------------------------------------------
     4956
     4957// Demonstrate creating a window with custom resize constraints.
     4958static void ShowExampleAppConstrainedResize(bool* p_open)
     4959{
     4960    struct CustomConstraints
     4961    {
     4962        // Helper functions to demonstrate programmatic constraints
     4963        static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y); }
     4964        static void Step(ImGuiSizeCallbackData* data)   { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
     4965    };
     4966
     4967    const char* test_desc[] =
     4968    {
     4969        "Resize vertical only",
     4970        "Resize horizontal only",
     4971        "Width > 100, Height > 100",
     4972        "Width 400-500",
     4973        "Height 400-500",
     4974        "Custom: Always Square",
     4975        "Custom: Fixed Steps (100)",
     4976    };
     4977
     4978    static bool auto_resize = false;
     4979    static int type = 0;
     4980    static int display_lines = 10;
     4981    if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Vertical only
     4982    if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Horizontal only
     4983    if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
     4984    if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width 400-500
     4985    if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, 500));          // Height 400-500
     4986    if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);                     // Always Square
     4987    if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
     4988
     4989    ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
     4990    if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
     4991    {
     4992        if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
     4993        if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
     4994        if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
     4995        ImGui::SetNextItemWidth(200);
     4996        ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
     4997        ImGui::SetNextItemWidth(200);
     4998        ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
     4999        ImGui::Checkbox("Auto-resize", &auto_resize);
     5000        for (int i = 0; i < display_lines; i++)
     5001            ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
     5002    }
     5003    ImGui::End();
     5004}
     5005
     5006//-----------------------------------------------------------------------------
     5007// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
     5008//-----------------------------------------------------------------------------
     5009
     5010// Demonstrate creating a simple static window with no decoration
     5011// + a context-menu to choose which corner of the screen to use.
     5012static void ShowExampleAppSimpleOverlay(bool* p_open)
     5013{
     5014    const float DISTANCE = 10.0f;
     5015    static int corner = 0;
     5016    ImGuiIO& io = ImGui::GetIO();
     5017    ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
     5018    if (corner != -1)
     5019    {
     5020        window_flags |= ImGuiWindowFlags_NoMove;
     5021        ImVec2 window_pos = ImVec2((corner & 1) ? io.DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? io.DisplaySize.y - DISTANCE : DISTANCE);
     5022        ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
     5023        ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
     5024    }
     5025    ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
     5026    if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
     5027    {
     5028        ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
     5029        ImGui::Separator();
     5030        if (ImGui::IsMousePosValid())
     5031            ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
     5032        else
     5033            ImGui::Text("Mouse Position: <invalid>");
     5034        if (ImGui::BeginPopupContextWindow())
     5035        {
     5036            if (ImGui::MenuItem("Custom",       NULL, corner == -1)) corner = -1;
     5037            if (ImGui::MenuItem("Top-left",     NULL, corner == 0)) corner = 0;
     5038            if (ImGui::MenuItem("Top-right",    NULL, corner == 1)) corner = 1;
     5039            if (ImGui::MenuItem("Bottom-left",  NULL, corner == 2)) corner = 2;
     5040            if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
     5041            if (p_open && ImGui::MenuItem("Close")) *p_open = false;
     5042            ImGui::EndPopup();
     5043        }
     5044    }
     5045    ImGui::End();
     5046}
     5047
     5048//-----------------------------------------------------------------------------
     5049// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
     5050//-----------------------------------------------------------------------------
     5051
     5052// Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
     5053// This apply to all regular items as well.
     5054// Read FAQ section "How can I have multiple widgets with the same label?" for details.
     5055static void ShowExampleAppWindowTitles(bool*)
     5056{
     5057    // By default, Windows are uniquely identified by their title.
     5058    // You can use the "##" and "###" markers to manipulate the display/ID.
     5059
     5060    // Using "##" to display same title but have unique identifier.
     5061    ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
     5062    ImGui::Begin("Same title as another window##1");
     5063    ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
     5064    ImGui::End();
     5065
     5066    ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
     5067    ImGui::Begin("Same title as another window##2");
     5068    ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
     5069    ImGui::End();
     5070
     5071    // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
     5072    char buf[128];
     5073    sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
     5074    ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
     5075    ImGui::Begin(buf);
     5076    ImGui::Text("This window has a changing title.");
     5077    ImGui::End();
     5078}
     5079
     5080//-----------------------------------------------------------------------------
     5081// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
     5082//-----------------------------------------------------------------------------
     5083
     5084// Demonstrate using the low-level ImDrawList to draw custom shapes.
     5085static void ShowExampleAppCustomRendering(bool* p_open)
     5086{
     5087    if (!ImGui::Begin("Example: Custom rendering", p_open))
     5088    {
     5089        ImGui::End();
     5090        return;
     5091    }
     5092
     5093    // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of
     5094    // overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your
     5095    // types and ImVec2/ImVec4. Dear ImGui defines overloaded operators but they are internal to imgui.cpp and not
     5096    // exposed outside (to avoid messing with your types) In this example we are not using the maths operators!
     5097
     5098    if (ImGui::BeginTabBar("##TabBar"))
     5099    {
     5100        if (ImGui::BeginTabItem("Primitives"))
     5101        {
     5102            ImGui::PushItemWidth(-ImGui::GetFontSize() * 10);
     5103            ImDrawList* draw_list = ImGui::GetWindowDrawList();
     5104
     5105            // Draw gradients
     5106            // (note that those are currently exacerbating our sRGB/Linear issues)
     5107            // Calling ImGui::GetColorU32() multiplies the given colors by the current Style Alpha, but you may pass the IM_COL32() directly as well..
     5108            ImGui::Text("Gradients");
     5109            ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight());
     5110            {
     5111                ImVec2 p0 = ImGui::GetCursorScreenPos();
     5112                ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
     5113                ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255));
     5114                ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255));
     5115                draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
     5116                ImGui::InvisibleButton("##gradient1", gradient_size);
     5117            }
     5118            {
     5119                ImVec2 p0 = ImGui::GetCursorScreenPos();
     5120                ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
     5121                ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255));
     5122                ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255));
     5123                draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
     5124                ImGui::InvisibleButton("##gradient2", gradient_size);
     5125            }
     5126
     5127            // Draw a bunch of primitives
     5128            ImGui::Text("All primitives");
     5129            static float sz = 36.0f;
     5130            static float thickness = 3.0f;
     5131            static int ngon_sides = 6;
     5132            static bool circle_segments_override = false;
     5133            static int circle_segments_override_v = 12;
     5134            static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
     5135            ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
     5136            ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
     5137            ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
     5138            ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
     5139            ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
     5140            if (ImGui::SliderInt("Circle segments", &circle_segments_override_v, 3, 40))
     5141                circle_segments_override = true;
     5142            ImGui::ColorEdit4("Color", &colf.x);
     5143
     5144            const ImVec2 p = ImGui::GetCursorScreenPos();
     5145            const ImU32 col = ImColor(colf);
     5146            const float spacing = 10.0f;
     5147            const ImDrawCornerFlags corners_none = 0;
     5148            const ImDrawCornerFlags corners_all = ImDrawCornerFlags_All;
     5149            const ImDrawCornerFlags corners_tl_br = ImDrawCornerFlags_TopLeft | ImDrawCornerFlags_BotRight;
     5150            const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
     5151            float x = p.x + 4.0f;
     5152            float y = p.y + 4.0f;
     5153            for (int n = 0; n < 2; n++)
     5154            {
     5155                // First line uses a thickness of 1.0f, second line uses the configurable thickness
     5156                float th = (n == 0) ? 1.0f : thickness;
     5157                draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th);                 x += sz + spacing;  // N-gon
     5158                draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th);          x += sz + spacing;  // Circle
     5159                draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f,  corners_none, th);             x += sz + spacing;  // Square
     5160                draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_all, th);              x += sz + spacing;  // Square with all rounded corners
     5161                draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f, corners_tl_br, th);            x += sz + spacing;  // Square with two rounded corners
     5162                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
     5163                //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
     5164                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!)
     5165                draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th);                                       x += spacing;       // Vertical line (note: drawing a filled rectangle will be faster!)
     5166                draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th);                                  x += sz + spacing;  // Diagonal line
     5167                draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x + sz*1.3f, y + sz*0.3f), ImVec2(x + sz - sz*1.3f, y + sz - sz*0.3f), ImVec2(x + sz, y + sz), col, th);
     5168                x = p.x + 4;
     5169                y += sz + spacing;
     5170            }
     5171            draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz*0.5f, col, ngon_sides);               x += sz + spacing;  // N-gon
     5172            draw_list->AddCircleFilled(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments);            x += sz + spacing;  // Circle
     5173            draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col);                                    x += sz + spacing;  // Square
     5174            draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f);                             x += sz + spacing;  // Square with all rounded corners
     5175            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
     5176            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
     5177            //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
     5178            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)
     5179            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)
     5180            draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col);                                      x += sz;            // Pixel (faster than AddLine)
     5181            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));
     5182
     5183            ImGui::Dummy(ImVec2((sz + spacing) * 8.8f, (sz + spacing) * 3.0f));
     5184            ImGui::PopItemWidth();
     5185            ImGui::EndTabItem();
     5186        }
     5187
     5188        if (ImGui::BeginTabItem("Canvas"))
     5189        {
     5190            static ImVector<ImVec2> points;
     5191            static ImVec2 scrolling(0.0f, 0.0f);
     5192            static bool opt_enable_grid = true;
     5193            static bool opt_enable_context_menu = true;
     5194            static bool adding_line = false;
     5195
     5196            ImGui::Checkbox("Enable grid", &opt_enable_grid);
     5197            ImGui::Checkbox("Enable context menu", &opt_enable_context_menu);
     5198            ImGui::Text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.");
     5199
     5200            // Typically you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling.
     5201            // Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls.
     5202            // To use a child window instead we could use, e.g:
     5203            //      ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));      // Disable padding
     5204            //      ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255));  // Set a background color
     5205            //      ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), true, ImGuiWindowFlags_NoMove);
     5206            //      ImGui::PopStyleColor();
     5207            //      ImGui::PopStyleVar();
     5208            //      [...]
     5209            //      ImGui::EndChild();
     5210
     5211            // Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive()
     5212            ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();      // ImDrawList API uses screen coordinates!
     5213            ImVec2 canvas_sz = ImGui::GetContentRegionAvail();   // Resize canvas to what's available
     5214            if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
     5215            if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f;
     5216            ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
     5217
     5218            // Draw border and background color
     5219            ImGuiIO& io = ImGui::GetIO();
     5220            ImDrawList* draw_list = ImGui::GetWindowDrawList();
     5221            draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
     5222            draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
     5223
     5224            // This will catch our interactions
     5225            ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
     5226            const bool is_hovered = ImGui::IsItemHovered(); // Hovered
     5227            const bool is_active = ImGui::IsItemActive();   // Held
     5228            const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y); // Lock scrolled origin
     5229            const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
     5230
     5231            // Add first and second point
     5232            if (is_hovered && !adding_line && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
     5233            {
     5234                points.push_back(mouse_pos_in_canvas);
     5235                points.push_back(mouse_pos_in_canvas);
     5236                adding_line = true;
     5237            }
     5238            if (adding_line)
     5239            {
     5240                points.back() = mouse_pos_in_canvas;
     5241                if (!ImGui::IsMouseDown(ImGuiMouseButton_Left))
     5242                    adding_line = false;
     5243            }
     5244
     5245            // Pan (we use a zero mouse threshold when there's no context menu)
     5246            // You may decide to make that threshold dynamic based on whether the mouse is hovering something etc.
     5247            const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
     5248            if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan))
     5249            {
     5250                scrolling.x += io.MouseDelta.x;
     5251                scrolling.y += io.MouseDelta.y;
     5252            }
     5253
     5254            // Context menu (under default mouse threshold)
     5255            ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
     5256            if (opt_enable_context_menu && ImGui::IsMouseReleased(ImGuiMouseButton_Right) && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
     5257                ImGui::OpenPopupOnItemClick("context");
     5258            if (ImGui::BeginPopup("context"))
     5259            {
     5260                if (adding_line)
     5261                    points.resize(points.size() - 2);
     5262                adding_line = false;
     5263                if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) { points.resize(points.size() - 2); }
     5264                if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) { points.clear(); }
     5265                ImGui::EndPopup();
     5266            }
     5267
     5268            // Draw grid + all lines in the canvas
     5269            draw_list->PushClipRect(canvas_p0, canvas_p1, true);
     5270            if (opt_enable_grid)
     5271            {
     5272                const float GRID_STEP = 64.0f;
     5273                for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
     5274                    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));
     5275                for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
     5276                    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));
     5277            }
     5278            for (int n = 0; n < points.Size; n += 2)
     5279                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);
     5280            draw_list->PopClipRect();
     5281
     5282            ImGui::EndTabItem();
     5283        }
     5284
     5285        if (ImGui::BeginTabItem("BG/FG draw lists"))
     5286        {
     5287            static bool draw_bg = true;
     5288            static bool draw_fg = true;
     5289            ImGui::Checkbox("Draw in Background draw list", &draw_bg);
     5290            ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows.");
     5291            ImGui::Checkbox("Draw in Foreground draw list", &draw_fg);
     5292            ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows.");
     5293            ImVec2 window_pos = ImGui::GetWindowPos();
     5294            ImVec2 window_size = ImGui::GetWindowSize();
     5295            ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
     5296            if (draw_bg)
     5297                ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4);
     5298            if (draw_fg)
     5299                ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10);
     5300            ImGui::EndTabItem();
     5301        }
     5302
     5303        ImGui::EndTabBar();
     5304    }
     5305
     5306    ImGui::End();
     5307}
     5308
     5309//-----------------------------------------------------------------------------
     5310// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
     5311//-----------------------------------------------------------------------------
     5312
     5313// Simplified structure to mimic a Document model
     5314struct MyDocument
     5315{
     5316    const char* Name;       // Document title
     5317    bool        Open;       // Set when open (we keep an array of all available documents to simplify demo code!)
     5318    bool        OpenPrev;   // Copy of Open from last update.
     5319    bool        Dirty;      // Set when the document has been modified
     5320    bool        WantClose;  // Set when the document
     5321    ImVec4      Color;      // An arbitrary variable associated to the document
     5322
     5323    MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
     5324    {
     5325        Name = name;
     5326        Open = OpenPrev = open;
     5327        Dirty = false;
     5328        WantClose = false;
     5329        Color = color;
     5330    }
     5331    void DoOpen()       { Open = true; }
     5332    void DoQueueClose() { WantClose = true; }
     5333    void DoForceClose() { Open = false; Dirty = false; }
     5334    void DoSave()       { Dirty = false; }
     5335
     5336    // Display placeholder contents for the Document
     5337    static void DisplayContents(MyDocument* doc)
     5338    {
     5339        ImGui::PushID(doc);
     5340        ImGui::Text("Document \"%s\"", doc->Name);
     5341        ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
     5342        ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
     5343        ImGui::PopStyleColor();
     5344        if (ImGui::Button("Modify", ImVec2(100, 0)))
     5345            doc->Dirty = true;
     5346        ImGui::SameLine();
     5347        if (ImGui::Button("Save", ImVec2(100, 0)))
     5348            doc->DoSave();
     5349        ImGui::ColorEdit3("color", &doc->Color.x);  // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
     5350        ImGui::PopID();
     5351    }
     5352
     5353    // Display context menu for the Document
     5354    static void DisplayContextMenu(MyDocument* doc)
     5355    {
     5356        if (!ImGui::BeginPopupContextItem())
     5357            return;
     5358
     5359        char buf[256];
     5360        sprintf(buf, "Save %s", doc->Name);
     5361        if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
     5362            doc->DoSave();
     5363        if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
     5364            doc->DoQueueClose();
     5365        ImGui::EndPopup();
     5366    }
     5367};
     5368
     5369struct ExampleAppDocuments
     5370{
     5371    ImVector<MyDocument> Documents;
     5372
     5373    ExampleAppDocuments()
     5374    {
     5375        Documents.push_back(MyDocument("Lettuce",             true,  ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
     5376        Documents.push_back(MyDocument("Eggplant",            true,  ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
     5377        Documents.push_back(MyDocument("Carrot",              true,  ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
     5378        Documents.push_back(MyDocument("Tomato",              false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
     5379        Documents.push_back(MyDocument("A Rather Long Title", false));
     5380        Documents.push_back(MyDocument("Some Document",       false));
     5381    }
     5382};
     5383
     5384// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
     5385// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
     5386// as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
     5387// 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
     5388// disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
     5389// give the impression of a flicker for one frame.
     5390// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
     5391// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
     5392static void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
     5393{
     5394    for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
     5395    {
     5396        MyDocument* doc = &app.Documents[doc_n];
     5397        if (!doc->Open && doc->OpenPrev)
     5398            ImGui::SetTabItemClosed(doc->Name);
     5399        doc->OpenPrev = doc->Open;
     5400    }
     5401}
     5402
     5403void ShowExampleAppDocuments(bool* p_open)
     5404{
     5405    static ExampleAppDocuments app;
     5406
     5407    // Options
     5408    static bool opt_reorderable = true;
     5409    static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
     5410
     5411    bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
     5412    if (!window_contents_visible)
     5413    {
     5414        ImGui::End();
     5415        return;
     5416    }
     5417
     5418    // Menu
     5419    if (ImGui::BeginMenuBar())
     5420    {
     5421        if (ImGui::BeginMenu("File"))
     5422        {
     5423            int open_count = 0;
     5424            for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
     5425                open_count += app.Documents[doc_n].Open ? 1 : 0;
     5426
     5427            if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
     5428            {
     5429                for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
     5430                {
     5431                    MyDocument* doc = &app.Documents[doc_n];
     5432                    if (!doc->Open)
     5433                        if (ImGui::MenuItem(doc->Name))
     5434                            doc->DoOpen();
     5435                }
     5436                ImGui::EndMenu();
     5437            }
     5438            if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
     5439                for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
     5440                    app.Documents[doc_n].DoQueueClose();
     5441            if (ImGui::MenuItem("Exit", "Alt+F4")) {}
     5442            ImGui::EndMenu();
     5443        }
     5444        ImGui::EndMenuBar();
     5445    }
     5446
     5447    // [Debug] List documents with one checkbox for each
     5448    for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
     5449    {
     5450        MyDocument* doc = &app.Documents[doc_n];
     5451        if (doc_n > 0)
     5452            ImGui::SameLine();
     5453        ImGui::PushID(doc);
     5454        if (ImGui::Checkbox(doc->Name, &doc->Open))
     5455            if (!doc->Open)
     5456                doc->DoForceClose();
     5457        ImGui::PopID();
     5458    }
     5459
     5460    ImGui::Separator();
     5461
     5462    // Submit Tab Bar and Tabs
     5463    {
     5464        ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
     5465        if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
     5466        {
     5467            if (opt_reorderable)
     5468                NotifyOfDocumentsClosedElsewhere(app);
     5469
     5470            // [DEBUG] Stress tests
     5471            //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1;            // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
     5472            //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name);  // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
     5473
     5474            // Submit Tabs
     5475            for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
     5476            {
     5477                MyDocument* doc = &app.Documents[doc_n];
     5478                if (!doc->Open)
     5479                    continue;
     5480
     5481                ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
     5482                bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
     5483
     5484                // Cancel attempt to close when unsaved add to save queue so we can display a popup.
     5485                if (!doc->Open && doc->Dirty)
     5486                {
     5487                    doc->Open = true;
     5488                    doc->DoQueueClose();
     5489                }
     5490
     5491                MyDocument::DisplayContextMenu(doc);
     5492                if (visible)
     5493                {
     5494                    MyDocument::DisplayContents(doc);
     5495                    ImGui::EndTabItem();
     5496                }
     5497            }
     5498
     5499            ImGui::EndTabBar();
     5500        }
     5501    }
     5502
     5503    // Update closing queue
     5504    static ImVector<MyDocument*> close_queue;
     5505    if (close_queue.empty())
     5506    {
     5507        // Close queue is locked once we started a popup
     5508        for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
     5509        {
     5510            MyDocument* doc = &app.Documents[doc_n];
     5511            if (doc->WantClose)
     5512            {
     5513                doc->WantClose = false;
     5514                close_queue.push_back(doc);
     5515            }
     5516        }
     5517    }
     5518
     5519    // Display closing confirmation UI
     5520    if (!close_queue.empty())
     5521    {
     5522        int close_queue_unsaved_documents = 0;
     5523        for (int n = 0; n < close_queue.Size; n++)
     5524            if (close_queue[n]->Dirty)
     5525                close_queue_unsaved_documents++;
     5526
     5527        if (close_queue_unsaved_documents == 0)
     5528        {
     5529            // Close documents when all are unsaved
     5530            for (int n = 0; n < close_queue.Size; n++)
     5531                close_queue[n]->DoForceClose();
     5532            close_queue.clear();
     5533        }
     5534        else
     5535        {
     5536            if (!ImGui::IsPopupOpen("Save?"))
     5537                ImGui::OpenPopup("Save?");
     5538            if (ImGui::BeginPopupModal("Save?"))
     5539            {
     5540                ImGui::Text("Save change to the following items?");
     5541                ImGui::SetNextItemWidth(-1.0f);
     5542                if (ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6))
     5543                {
     5544                    for (int n = 0; n < close_queue.Size; n++)
     5545                        if (close_queue[n]->Dirty)
     5546                            ImGui::Text("%s", close_queue[n]->Name);
     5547                    ImGui::ListBoxFooter();
     5548                }
     5549
     5550                if (ImGui::Button("Yes", ImVec2(80, 0)))
     5551                {
     5552                    for (int n = 0; n < close_queue.Size; n++)
     5553                    {
     5554                        if (close_queue[n]->Dirty)
     5555                            close_queue[n]->DoSave();
     5556                        close_queue[n]->DoForceClose();
     5557                    }
     5558                    close_queue.clear();
     5559                    ImGui::CloseCurrentPopup();
     5560                }
     5561                ImGui::SameLine();
     5562                if (ImGui::Button("No", ImVec2(80, 0)))
     5563                {
     5564                    for (int n = 0; n < close_queue.Size; n++)
     5565                        close_queue[n]->DoForceClose();
     5566                    close_queue.clear();
     5567                    ImGui::CloseCurrentPopup();
     5568                }
     5569                ImGui::SameLine();
     5570                if (ImGui::Button("Cancel", ImVec2(80, 0)))
     5571                {
     5572                    close_queue.clear();
     5573                    ImGui::CloseCurrentPopup();
     5574                }
     5575                ImGui::EndPopup();
     5576            }
     5577        }
     5578    }
     5579
     5580    ImGui::End();
    31965581}
    31975582
     
    31995584#else
    32005585
     5586void ImGui::ShowAboutWindow(bool*) {}
    32015587void ImGui::ShowDemoWindow(bool*) {}
    32025588void ImGui::ShowUserGuide() {}
     
    32045590
    32055591#endif
     5592
     5593#endif // #ifndef IMGUI_DISABLE
Note: See TracChangeset for help on using the changeset viewer.