git repos / blockattack-game

blame: source/code/Libs/imgui/imgui_demo.cpp

normal view · raw

1193b4be Poul Sander 2025-02-03 21:28 1
// dear imgui, v1.91.4
1193b4be Poul Sander 2025-02-03 21:28 2
// (demo code)
1193b4be Poul Sander 2025-02-03 21:28 3
1193b4be Poul Sander 2025-02-03 21:28 4
// Help:
1193b4be Poul Sander 2025-02-03 21:28 5
// - Read FAQ at http://dearimgui.com/faq
1193b4be Poul Sander 2025-02-03 21:28 6
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
1193b4be Poul Sander 2025-02-03 21:28 7
// - Need help integrating Dear ImGui in your codebase?
1193b4be Poul Sander 2025-02-03 21:28 8
//   - Read Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started
1193b4be Poul Sander 2025-02-03 21:28 9
//   - Read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
1193b4be Poul Sander 2025-02-03 21:28 10
// Read top of imgui.cpp and imgui.h for many details, documentation, comments, links.
1193b4be Poul Sander 2025-02-03 21:28 11
// Get the latest version at https://github.com/ocornut/imgui
1193b4be Poul Sander 2025-02-03 21:28 12
1193b4be Poul Sander 2025-02-03 21:28 13
// How to easily locate code?
1193b4be Poul Sander 2025-02-03 21:28 14
// - Use Tools->Item Picker to debug break in code by clicking any widgets: https://github.com/ocornut/imgui/wiki/Debug-Tools
1193b4be Poul Sander 2025-02-03 21:28 15
// - Browse an online version the demo with code linked to hovered widgets: https://pthom.github.io/imgui_manual_online/manual/imgui_manual.html
1193b4be Poul Sander 2025-02-03 21:28 16
// - Find a visible string and search for it in the code!
1193b4be Poul Sander 2025-02-03 21:28 17
1193b4be Poul Sander 2025-02-03 21:28 18
//---------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 19
// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
1193b4be Poul Sander 2025-02-03 21:28 20
//---------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 21
// Message to the person tempted to delete this file when integrating Dear ImGui into their codebase:
1193b4be Poul Sander 2025-02-03 21:28 22
// Think again! It is the most useful reference code that you and other coders will want to refer to and call.
1193b4be Poul Sander 2025-02-03 21:28 23
// Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of your game/app!
1193b4be Poul Sander 2025-02-03 21:28 24
// Also include Metrics! ItemPicker! DebugLog! and other debug features.
1193b4be Poul Sander 2025-02-03 21:28 25
// Removing this file from your project is hindering access to documentation for everyone in your team,
1193b4be Poul Sander 2025-02-03 21:28 26
// likely leading you to poorer usage of the library.
1193b4be Poul Sander 2025-02-03 21:28 27
// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
1193b4be Poul Sander 2025-02-03 21:28 28
// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
1193b4be Poul Sander 2025-02-03 21:28 29
// linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
1193b4be Poul Sander 2025-02-03 21:28 30
// In another situation, whenever you have Dear ImGui available you probably want this to be available for reference.
1193b4be Poul Sander 2025-02-03 21:28 31
// Thank you,
1193b4be Poul Sander 2025-02-03 21:28 32
// -Your beloved friend, imgui_demo.cpp (which you won't delete)
1193b4be Poul Sander 2025-02-03 21:28 33
1193b4be Poul Sander 2025-02-03 21:28 34
//--------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 35
// ABOUT THE MEANING OF THE 'static' KEYWORD:
1193b4be Poul Sander 2025-02-03 21:28 36
//--------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 37
// In this demo code, we frequently use 'static' variables inside functions.
1193b4be Poul Sander 2025-02-03 21:28 38
// A static variable persists across calls. It is essentially a global variable but declared inside the scope of the function.
1193b4be Poul Sander 2025-02-03 21:28 39
// Think of "static int n = 0;" as "global int n = 0;" !
1193b4be Poul Sander 2025-02-03 21:28 40
// We do this IN THE DEMO because we want:
1193b4be Poul Sander 2025-02-03 21:28 41
// - to gather code and data in the same place.
1193b4be Poul Sander 2025-02-03 21:28 42
// - to make the demo source code faster to read, faster to change, smaller in size.
1193b4be Poul Sander 2025-02-03 21:28 43
// - it is also a convenient way of storing simple UI related information as long as your function
1193b4be Poul Sander 2025-02-03 21:28 44
//   doesn't need to be reentrant or used in multiple threads.
1193b4be Poul Sander 2025-02-03 21:28 45
// This might be a pattern you will want to use in your code, but most of the data you would be working
1193b4be Poul Sander 2025-02-03 21:28 46
// with in a complex codebase is likely going to be stored outside your functions.
1193b4be Poul Sander 2025-02-03 21:28 47
1193b4be Poul Sander 2025-02-03 21:28 48
//-----------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 49
// ABOUT THE CODING STYLE OF OUR DEMO CODE
1193b4be Poul Sander 2025-02-03 21:28 50
//-----------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 51
// The Demo code in this file is designed to be easy to copy-and-paste into your application!
1193b4be Poul Sander 2025-02-03 21:28 52
// Because of this:
1193b4be Poul Sander 2025-02-03 21:28 53
// - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
1193b4be Poul Sander 2025-02-03 21:28 54
// - We try to declare static variables in the local scope, as close as possible to the code using them.
1193b4be Poul Sander 2025-02-03 21:28 55
// - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
1193b4be Poul Sander 2025-02-03 21:28 56
// - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
1193b4be Poul Sander 2025-02-03 21:28 57
//   by imgui.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
1193b4be Poul Sander 2025-02-03 21:28 58
//   and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
1193b4be Poul Sander 2025-02-03 21:28 59
//   Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
1193b4be Poul Sander 2025-02-03 21:28 60
1193b4be Poul Sander 2025-02-03 21:28 61
// Navigating this file:
1193b4be Poul Sander 2025-02-03 21:28 62
// - In Visual Studio: CTRL+comma ("Edit.GoToAll") can follow symbols inside comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
1193b4be Poul Sander 2025-02-03 21:28 63
// - In Visual Studio w/ Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols inside comments.
1193b4be Poul Sander 2025-02-03 21:28 64
// - In VS Code, CLion, etc.: CTRL+click can follow symbols inside comments.
1193b4be Poul Sander 2025-02-03 21:28 65
// - You can search/grep for all sections listed in the index to find the section.
1193b4be Poul Sander 2025-02-03 21:28 66
1193b4be Poul Sander 2025-02-03 21:28 67
/*
1193b4be Poul Sander 2025-02-03 21:28 68
1193b4be Poul Sander 2025-02-03 21:28 69
Index of this file:
1193b4be Poul Sander 2025-02-03 21:28 70
1193b4be Poul Sander 2025-02-03 21:28 71
// [SECTION] Forward Declarations
1193b4be Poul Sander 2025-02-03 21:28 72
// [SECTION] Helpers
1193b4be Poul Sander 2025-02-03 21:28 73
// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos)
1193b4be Poul Sander 2025-02-03 21:28 74
// [SECTION] Demo Window / ShowDemoWindow()
1193b4be Poul Sander 2025-02-03 21:28 75
// [SECTION] ShowDemoWindowMenuBar()
1193b4be Poul Sander 2025-02-03 21:28 76
// [SECTION] ShowDemoWindowWidgets()
1193b4be Poul Sander 2025-02-03 21:28 77
// [SECTION] ShowDemoWindowMultiSelect()
1193b4be Poul Sander 2025-02-03 21:28 78
// [SECTION] ShowDemoWindowLayout()
1193b4be Poul Sander 2025-02-03 21:28 79
// [SECTION] ShowDemoWindowPopups()
1193b4be Poul Sander 2025-02-03 21:28 80
// [SECTION] ShowDemoWindowTables()
1193b4be Poul Sander 2025-02-03 21:28 81
// [SECTION] ShowDemoWindowInputs()
1193b4be Poul Sander 2025-02-03 21:28 82
// [SECTION] About Window / ShowAboutWindow()
1193b4be Poul Sander 2025-02-03 21:28 83
// [SECTION] Style Editor / ShowStyleEditor()
1193b4be Poul Sander 2025-02-03 21:28 84
// [SECTION] User Guide / ShowUserGuide()
1193b4be Poul Sander 2025-02-03 21:28 85
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
1193b4be Poul Sander 2025-02-03 21:28 86
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
1193b4be Poul Sander 2025-02-03 21:28 87
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
1193b4be Poul Sander 2025-02-03 21:28 88
// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
1193b4be Poul Sander 2025-02-03 21:28 89
// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
1193b4be Poul Sander 2025-02-03 21:28 90
// [SECTION] Example App: Long Text / ShowExampleAppLongText()
1193b4be Poul Sander 2025-02-03 21:28 91
// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
1193b4be Poul Sander 2025-02-03 21:28 92
// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
1193b4be Poul Sander 2025-02-03 21:28 93
// [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
1193b4be Poul Sander 2025-02-03 21:28 94
// [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
1193b4be Poul Sander 2025-02-03 21:28 95
// [SECTION] Example App: Manipulating window titles / ShowExampleAppWindowTitles()
1193b4be Poul Sander 2025-02-03 21:28 96
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
1193b4be Poul Sander 2025-02-03 21:28 97
// [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace()
1193b4be Poul Sander 2025-02-03 21:28 98
// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
1193b4be Poul Sander 2025-02-03 21:28 99
// [SECTION] Example App: Assets Browser / ShowExampleAppAssetsBrowser()
1193b4be Poul Sander 2025-02-03 21:28 100
1193b4be Poul Sander 2025-02-03 21:28 101
*/
1193b4be Poul Sander 2025-02-03 21:28 102
1193b4be Poul Sander 2025-02-03 21:28 103
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
1193b4be Poul Sander 2025-02-03 21:28 104
#define _CRT_SECURE_NO_WARNINGS
1193b4be Poul Sander 2025-02-03 21:28 105
#endif
1193b4be Poul Sander 2025-02-03 21:28 106
1193b4be Poul Sander 2025-02-03 21:28 107
#include "imgui.h"
1193b4be Poul Sander 2025-02-03 21:28 108
#ifndef IMGUI_DISABLE
1193b4be Poul Sander 2025-02-03 21:28 109
1193b4be Poul Sander 2025-02-03 21:28 110
// System includes
1193b4be Poul Sander 2025-02-03 21:28 111
#include <ctype.h>          // toupper
1193b4be Poul Sander 2025-02-03 21:28 112
#include <limits.h>         // INT_MIN, INT_MAX
1193b4be Poul Sander 2025-02-03 21:28 113
#include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
1193b4be Poul Sander 2025-02-03 21:28 114
#include <stdio.h>          // vsnprintf, sscanf, printf
1193b4be Poul Sander 2025-02-03 21:28 115
#include <stdlib.h>         // NULL, malloc, free, atoi
1193b4be Poul Sander 2025-02-03 21:28 116
#include <stdint.h>         // intptr_t
1193b4be Poul Sander 2025-02-03 21:28 117
#if !defined(_MSC_VER) || _MSC_VER >= 1800
1193b4be Poul Sander 2025-02-03 21:28 118
#include <inttypes.h>       // PRId64/PRIu64, not avail in some MinGW headers.
1193b4be Poul Sander 2025-02-03 21:28 119
#endif
1193b4be Poul Sander 2025-02-03 21:28 120
#ifdef __EMSCRIPTEN__
1193b4be Poul Sander 2025-02-03 21:28 121
#include <emscripten/version.h>     // __EMSCRIPTEN_major__ etc.
1193b4be Poul Sander 2025-02-03 21:28 122
#endif
1193b4be Poul Sander 2025-02-03 21:28 123
1193b4be Poul Sander 2025-02-03 21:28 124
// Visual Studio warnings
1193b4be Poul Sander 2025-02-03 21:28 125
#ifdef _MSC_VER
1193b4be Poul Sander 2025-02-03 21:28 126
#pragma warning (disable: 4127)     // condition expression is constant
1193b4be Poul Sander 2025-02-03 21:28 127
#pragma warning (disable: 4996)     // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
1193b4be Poul Sander 2025-02-03 21:28 128
#pragma warning (disable: 26451)    // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to an 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
1193b4be Poul Sander 2025-02-03 21:28 129
#endif
1193b4be Poul Sander 2025-02-03 21:28 130
1193b4be Poul Sander 2025-02-03 21:28 131
// Clang/GCC warnings with -Weverything
1193b4be Poul Sander 2025-02-03 21:28 132
#if defined(__clang__)
1193b4be Poul Sander 2025-02-03 21:28 133
#if __has_warning("-Wunknown-warning-option")
1193b4be Poul Sander 2025-02-03 21:28 134
#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!
1193b4be Poul Sander 2025-02-03 21:28 135
#endif
1193b4be Poul Sander 2025-02-03 21:28 136
#pragma clang diagnostic ignored "-Wunknown-pragmas"                // warning: unknown warning group 'xxx'
1193b4be Poul Sander 2025-02-03 21:28 137
#pragma clang diagnostic ignored "-Wold-style-cast"                 // warning: use of old-style cast                           // yes, they are more terse.
1193b4be Poul Sander 2025-02-03 21:28 138
#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)
1193b4be Poul Sander 2025-02-03 21:28 139
#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"       // warning: cast to 'void *' from smaller integer type
1193b4be Poul Sander 2025-02-03 21:28 140
#pragma clang diagnostic ignored "-Wformat-security"                // warning: format string is not a string literal
1193b4be Poul Sander 2025-02-03 21:28 141
#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.
1193b4be Poul Sander 2025-02-03 21:28 142
#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.
1193b4be Poul Sander 2025-02-03 21:28 143
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning: zero as null pointer constant                   // some standard header variations use #define NULL 0
1193b4be Poul Sander 2025-02-03 21:28 144
#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.
1193b4be Poul Sander 2025-02-03 21:28 145
#pragma clang diagnostic ignored "-Wreserved-id-macro"              // warning: macro name is a reserved identifier
1193b4be Poul Sander 2025-02-03 21:28 146
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion"  // warning: implicit conversion from 'xxx' to 'float' may lose precision
1193b4be Poul Sander 2025-02-03 21:28 147
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"            // warning: 'xxx' is an unsafe pointer used for buffer access
1193b4be Poul Sander 2025-02-03 21:28 148
#elif defined(__GNUC__)
1193b4be Poul Sander 2025-02-03 21:28 149
#pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
1193b4be Poul Sander 2025-02-03 21:28 150
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"      // warning: cast to pointer from integer of different size
1193b4be Poul Sander 2025-02-03 21:28 151
#pragma GCC diagnostic ignored "-Wformat-security"          // warning: format string is not a string literal (potentially insecure)
1193b4be Poul Sander 2025-02-03 21:28 152
#pragma GCC diagnostic ignored "-Wdouble-promotion"         // warning: implicit conversion from 'float' to 'double' when passing argument to function
1193b4be Poul Sander 2025-02-03 21:28 153
#pragma GCC diagnostic ignored "-Wconversion"               // warning: conversion to 'xxxx' from 'xxxx' may alter its value
1193b4be Poul Sander 2025-02-03 21:28 154
#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.
1193b4be Poul Sander 2025-02-03 21:28 155
#endif
1193b4be Poul Sander 2025-02-03 21:28 156
1193b4be Poul Sander 2025-02-03 21:28 157
// Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
1193b4be Poul Sander 2025-02-03 21:28 158
#ifdef _WIN32
1193b4be Poul Sander 2025-02-03 21:28 159
#define IM_NEWLINE  "\r\n"
1193b4be Poul Sander 2025-02-03 21:28 160
#else
1193b4be Poul Sander 2025-02-03 21:28 161
#define IM_NEWLINE  "\n"
1193b4be Poul Sander 2025-02-03 21:28 162
#endif
1193b4be Poul Sander 2025-02-03 21:28 163
1193b4be Poul Sander 2025-02-03 21:28 164
// Helpers
1193b4be Poul Sander 2025-02-03 21:28 165
#if defined(_MSC_VER) && !defined(snprintf)
1193b4be Poul Sander 2025-02-03 21:28 166
#define snprintf    _snprintf
1193b4be Poul Sander 2025-02-03 21:28 167
#endif
1193b4be Poul Sander 2025-02-03 21:28 168
#if defined(_MSC_VER) && !defined(vsnprintf)
1193b4be Poul Sander 2025-02-03 21:28 169
#define vsnprintf   _vsnprintf
1193b4be Poul Sander 2025-02-03 21:28 170
#endif
1193b4be Poul Sander 2025-02-03 21:28 171
1193b4be Poul Sander 2025-02-03 21:28 172
// Format specifiers for 64-bit values (hasn't been decently standardized before VS2013)
1193b4be Poul Sander 2025-02-03 21:28 173
#if !defined(PRId64) && defined(_MSC_VER)
1193b4be Poul Sander 2025-02-03 21:28 174
#define PRId64 "I64d"
1193b4be Poul Sander 2025-02-03 21:28 175
#define PRIu64 "I64u"
1193b4be Poul Sander 2025-02-03 21:28 176
#elif !defined(PRId64)
1193b4be Poul Sander 2025-02-03 21:28 177
#define PRId64 "lld"
1193b4be Poul Sander 2025-02-03 21:28 178
#define PRIu64 "llu"
1193b4be Poul Sander 2025-02-03 21:28 179
#endif
1193b4be Poul Sander 2025-02-03 21:28 180
1193b4be Poul Sander 2025-02-03 21:28 181
// Helpers macros
1193b4be Poul Sander 2025-02-03 21:28 182
// We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
1193b4be Poul Sander 2025-02-03 21:28 183
// but making an exception here as those are largely simplifying code...
1193b4be Poul Sander 2025-02-03 21:28 184
// In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo.
1193b4be Poul Sander 2025-02-03 21:28 185
#define IM_MIN(A, B)            (((A) < (B)) ? (A) : (B))
1193b4be Poul Sander 2025-02-03 21:28 186
#define IM_MAX(A, B)            (((A) >= (B)) ? (A) : (B))
1193b4be Poul Sander 2025-02-03 21:28 187
#define IM_CLAMP(V, MN, MX)     ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
1193b4be Poul Sander 2025-02-03 21:28 188
1193b4be Poul Sander 2025-02-03 21:28 189
// Enforce cdecl calling convention for functions called by the standard library,
1193b4be Poul Sander 2025-02-03 21:28 190
// in case compilation settings changed the default to e.g. __vectorcall
1193b4be Poul Sander 2025-02-03 21:28 191
#ifndef IMGUI_CDECL
1193b4be Poul Sander 2025-02-03 21:28 192
#ifdef _MSC_VER
1193b4be Poul Sander 2025-02-03 21:28 193
#define IMGUI_CDECL __cdecl
1193b4be Poul Sander 2025-02-03 21:28 194
#else
1193b4be Poul Sander 2025-02-03 21:28 195
#define IMGUI_CDECL
1193b4be Poul Sander 2025-02-03 21:28 196
#endif
1193b4be Poul Sander 2025-02-03 21:28 197
#endif
1193b4be Poul Sander 2025-02-03 21:28 198
1193b4be Poul Sander 2025-02-03 21:28 199
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 200
// [SECTION] Forward Declarations
1193b4be Poul Sander 2025-02-03 21:28 201
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 202
1193b4be Poul Sander 2025-02-03 21:28 203
#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
1193b4be Poul Sander 2025-02-03 21:28 204
1193b4be Poul Sander 2025-02-03 21:28 205
// Forward Declarations
1193b4be Poul Sander 2025-02-03 21:28 206
struct ImGuiDemoWindowData;
1193b4be Poul Sander 2025-02-03 21:28 207
static void ShowExampleAppMainMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 208
static void ShowExampleAppAssetsBrowser(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 209
static void ShowExampleAppConsole(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 210
static void ShowExampleAppCustomRendering(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 211
static void ShowExampleAppDockSpace(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 212
static void ShowExampleAppDocuments(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 213
static void ShowExampleAppLog(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 214
static void ShowExampleAppLayout(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 215
static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data);
1193b4be Poul Sander 2025-02-03 21:28 216
static void ShowExampleAppSimpleOverlay(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 217
static void ShowExampleAppAutoResize(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 218
static void ShowExampleAppConstrainedResize(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 219
static void ShowExampleAppFullscreen(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 220
static void ShowExampleAppLongText(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 221
static void ShowExampleAppWindowTitles(bool* p_open);
1193b4be Poul Sander 2025-02-03 21:28 222
static void ShowExampleMenuFile();
1193b4be Poul Sander 2025-02-03 21:28 223
1193b4be Poul Sander 2025-02-03 21:28 224
// We split the contents of the big ShowDemoWindow() function into smaller functions
1193b4be Poul Sander 2025-02-03 21:28 225
// (because the link time of very large functions tends to grow non-linearly)
1193b4be Poul Sander 2025-02-03 21:28 226
static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data);
1193b4be Poul Sander 2025-02-03 21:28 227
static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data);
1193b4be Poul Sander 2025-02-03 21:28 228
static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data);
1193b4be Poul Sander 2025-02-03 21:28 229
static void ShowDemoWindowLayout();
1193b4be Poul Sander 2025-02-03 21:28 230
static void ShowDemoWindowPopups();
1193b4be Poul Sander 2025-02-03 21:28 231
static void ShowDemoWindowTables();
1193b4be Poul Sander 2025-02-03 21:28 232
static void ShowDemoWindowColumns();
1193b4be Poul Sander 2025-02-03 21:28 233
static void ShowDemoWindowInputs();
1193b4be Poul Sander 2025-02-03 21:28 234
1193b4be Poul Sander 2025-02-03 21:28 235
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 236
// [SECTION] Helpers
1193b4be Poul Sander 2025-02-03 21:28 237
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 238
1193b4be Poul Sander 2025-02-03 21:28 239
// Helper to display a little (?) mark which shows a tooltip when hovered.
1193b4be Poul Sander 2025-02-03 21:28 240
// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
1193b4be Poul Sander 2025-02-03 21:28 241
static void HelpMarker(const char* desc)
1193b4be Poul Sander 2025-02-03 21:28 242
{
1193b4be Poul Sander 2025-02-03 21:28 243
    ImGui::TextDisabled("(?)");
1193b4be Poul Sander 2025-02-03 21:28 244
    if (ImGui::BeginItemTooltip())
1193b4be Poul Sander 2025-02-03 21:28 245
    {
1193b4be Poul Sander 2025-02-03 21:28 246
        ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
1193b4be Poul Sander 2025-02-03 21:28 247
        ImGui::TextUnformatted(desc);
1193b4be Poul Sander 2025-02-03 21:28 248
        ImGui::PopTextWrapPos();
1193b4be Poul Sander 2025-02-03 21:28 249
        ImGui::EndTooltip();
1193b4be Poul Sander 2025-02-03 21:28 250
    }
1193b4be Poul Sander 2025-02-03 21:28 251
}
1193b4be Poul Sander 2025-02-03 21:28 252
1193b4be Poul Sander 2025-02-03 21:28 253
static void ShowDockingDisabledMessage()
1193b4be Poul Sander 2025-02-03 21:28 254
{
1193b4be Poul Sander 2025-02-03 21:28 255
    ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 256
    ImGui::Text("ERROR: Docking is not enabled! See Demo > Configuration.");
1193b4be Poul Sander 2025-02-03 21:28 257
    ImGui::Text("Set io.ConfigFlags |= ImGuiConfigFlags_DockingEnable in your code, or ");
1193b4be Poul Sander 2025-02-03 21:28 258
    ImGui::SameLine(0.0f, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 259
    if (ImGui::SmallButton("click here"))
1193b4be Poul Sander 2025-02-03 21:28 260
        io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
1193b4be Poul Sander 2025-02-03 21:28 261
}
1193b4be Poul Sander 2025-02-03 21:28 262
1193b4be Poul Sander 2025-02-03 21:28 263
// Helper to wire demo markers located in code to an interactive browser
1193b4be Poul Sander 2025-02-03 21:28 264
typedef void (*ImGuiDemoMarkerCallback)(const char* file, int line, const char* section, void* user_data);
1193b4be Poul Sander 2025-02-03 21:28 265
extern ImGuiDemoMarkerCallback      GImGuiDemoMarkerCallback;
1193b4be Poul Sander 2025-02-03 21:28 266
extern void*                        GImGuiDemoMarkerCallbackUserData;
1193b4be Poul Sander 2025-02-03 21:28 267
ImGuiDemoMarkerCallback             GImGuiDemoMarkerCallback = NULL;
1193b4be Poul Sander 2025-02-03 21:28 268
void*                               GImGuiDemoMarkerCallbackUserData = NULL;
1193b4be Poul Sander 2025-02-03 21:28 269
#define IMGUI_DEMO_MARKER(section)  do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback(__FILE__, __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0)
1193b4be Poul Sander 2025-02-03 21:28 270
1193b4be Poul Sander 2025-02-03 21:28 271
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 272
// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor etc.)
1193b4be Poul Sander 2025-02-03 21:28 273
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 274
1193b4be Poul Sander 2025-02-03 21:28 275
// Simple representation for a tree
1193b4be Poul Sander 2025-02-03 21:28 276
// (this is designed to be simple to understand for our demos, not to be fancy or efficient etc.)
1193b4be Poul Sander 2025-02-03 21:28 277
struct ExampleTreeNode
1193b4be Poul Sander 2025-02-03 21:28 278
{
1193b4be Poul Sander 2025-02-03 21:28 279
    // Tree structure
1193b4be Poul Sander 2025-02-03 21:28 280
    char                        Name[28] = "";
1193b4be Poul Sander 2025-02-03 21:28 281
    int                         UID = 0;
1193b4be Poul Sander 2025-02-03 21:28 282
    ExampleTreeNode*            Parent = NULL;
1193b4be Poul Sander 2025-02-03 21:28 283
    ImVector<ExampleTreeNode*>  Childs;
1193b4be Poul Sander 2025-02-03 21:28 284
    unsigned short              IndexInParent = 0;  // Maintaining this allows us to implement linear traversal more easily
1193b4be Poul Sander 2025-02-03 21:28 285
1193b4be Poul Sander 2025-02-03 21:28 286
    // Leaf Data
1193b4be Poul Sander 2025-02-03 21:28 287
    bool                        HasData = false;    // All leaves have data
1193b4be Poul Sander 2025-02-03 21:28 288
    bool                        DataMyBool = true;
1193b4be Poul Sander 2025-02-03 21:28 289
    int                         DataMyInt = 128;
1193b4be Poul Sander 2025-02-03 21:28 290
    ImVec2                      DataMyVec2 = ImVec2(0.0f, 3.141592f);
1193b4be Poul Sander 2025-02-03 21:28 291
};
1193b4be Poul Sander 2025-02-03 21:28 292
1193b4be Poul Sander 2025-02-03 21:28 293
// Simple representation of struct metadata/serialization data.
1193b4be Poul Sander 2025-02-03 21:28 294
// (this is a minimal version of what a typical advanced application may provide)
1193b4be Poul Sander 2025-02-03 21:28 295
struct ExampleMemberInfo
1193b4be Poul Sander 2025-02-03 21:28 296
{
1193b4be Poul Sander 2025-02-03 21:28 297
    const char*     Name;       // Member name
1193b4be Poul Sander 2025-02-03 21:28 298
    ImGuiDataType   DataType;   // Member type
1193b4be Poul Sander 2025-02-03 21:28 299
    int             DataCount;  // Member count (1 when scalar)
1193b4be Poul Sander 2025-02-03 21:28 300
    int             Offset;     // Offset inside parent structure
1193b4be Poul Sander 2025-02-03 21:28 301
};
1193b4be Poul Sander 2025-02-03 21:28 302
1193b4be Poul Sander 2025-02-03 21:28 303
// Metadata description of ExampleTreeNode struct.
1193b4be Poul Sander 2025-02-03 21:28 304
static const ExampleMemberInfo ExampleTreeNodeMemberInfos[]
1193b4be Poul Sander 2025-02-03 21:28 305
{
1193b4be Poul Sander 2025-02-03 21:28 306
    { "MyBool",     ImGuiDataType_Bool,    1, offsetof(ExampleTreeNode, DataMyBool) },
1193b4be Poul Sander 2025-02-03 21:28 307
    { "MyInt",      ImGuiDataType_S32,     1, offsetof(ExampleTreeNode, DataMyInt) },
1193b4be Poul Sander 2025-02-03 21:28 308
    { "MyVec2",     ImGuiDataType_Float,   2, offsetof(ExampleTreeNode, DataMyVec2) },
1193b4be Poul Sander 2025-02-03 21:28 309
};
1193b4be Poul Sander 2025-02-03 21:28 310
1193b4be Poul Sander 2025-02-03 21:28 311
static ExampleTreeNode* ExampleTree_CreateNode(const char* name, int uid, ExampleTreeNode* parent)
1193b4be Poul Sander 2025-02-03 21:28 312
{
1193b4be Poul Sander 2025-02-03 21:28 313
    ExampleTreeNode* node = IM_NEW(ExampleTreeNode);
1193b4be Poul Sander 2025-02-03 21:28 314
    snprintf(node->Name, IM_ARRAYSIZE(node->Name), "%s", name);
1193b4be Poul Sander 2025-02-03 21:28 315
    node->UID = uid;
1193b4be Poul Sander 2025-02-03 21:28 316
    node->Parent = parent;
1193b4be Poul Sander 2025-02-03 21:28 317
    node->IndexInParent = parent ? (unsigned short)parent->Childs.Size : 0;
1193b4be Poul Sander 2025-02-03 21:28 318
    if (parent)
1193b4be Poul Sander 2025-02-03 21:28 319
        parent->Childs.push_back(node);
1193b4be Poul Sander 2025-02-03 21:28 320
    return node;
1193b4be Poul Sander 2025-02-03 21:28 321
}
1193b4be Poul Sander 2025-02-03 21:28 322
1193b4be Poul Sander 2025-02-03 21:28 323
// Create example tree data
1193b4be Poul Sander 2025-02-03 21:28 324
// (this allocates _many_ more times than most other code in either Dear ImGui or others demo)
1193b4be Poul Sander 2025-02-03 21:28 325
static ExampleTreeNode* ExampleTree_CreateDemoTree()
1193b4be Poul Sander 2025-02-03 21:28 326
{
1193b4be Poul Sander 2025-02-03 21:28 327
    static const char* root_names[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pear", "Pineapple", "Strawberry", "Watermelon" };
1193b4be Poul Sander 2025-02-03 21:28 328
    const size_t NAME_MAX_LEN = sizeof(ExampleTreeNode::Name);
1193b4be Poul Sander 2025-02-03 21:28 329
    char name_buf[NAME_MAX_LEN];
1193b4be Poul Sander 2025-02-03 21:28 330
    int uid = 0;
1193b4be Poul Sander 2025-02-03 21:28 331
    ExampleTreeNode* node_L0 = ExampleTree_CreateNode("<ROOT>", ++uid, NULL);
1193b4be Poul Sander 2025-02-03 21:28 332
    const int root_items_multiplier = 2;
1193b4be Poul Sander 2025-02-03 21:28 333
    for (int idx_L0 = 0; idx_L0 < IM_ARRAYSIZE(root_names) * root_items_multiplier; idx_L0++)
1193b4be Poul Sander 2025-02-03 21:28 334
    {
1193b4be Poul Sander 2025-02-03 21:28 335
        snprintf(name_buf, IM_ARRAYSIZE(name_buf), "%s %d", root_names[idx_L0 / root_items_multiplier], idx_L0 % root_items_multiplier);
1193b4be Poul Sander 2025-02-03 21:28 336
        ExampleTreeNode* node_L1 = ExampleTree_CreateNode(name_buf, ++uid, node_L0);
1193b4be Poul Sander 2025-02-03 21:28 337
        const int number_of_childs = (int)strlen(node_L1->Name);
1193b4be Poul Sander 2025-02-03 21:28 338
        for (int idx_L1 = 0; idx_L1 < number_of_childs; idx_L1++)
1193b4be Poul Sander 2025-02-03 21:28 339
        {
1193b4be Poul Sander 2025-02-03 21:28 340
            snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Child %d", idx_L1);
1193b4be Poul Sander 2025-02-03 21:28 341
            ExampleTreeNode* node_L2 = ExampleTree_CreateNode(name_buf, ++uid, node_L1);
1193b4be Poul Sander 2025-02-03 21:28 342
            node_L2->HasData = true;
1193b4be Poul Sander 2025-02-03 21:28 343
            if (idx_L1 == 0)
1193b4be Poul Sander 2025-02-03 21:28 344
            {
1193b4be Poul Sander 2025-02-03 21:28 345
                snprintf(name_buf, IM_ARRAYSIZE(name_buf), "Sub-child %d", 0);
1193b4be Poul Sander 2025-02-03 21:28 346
                ExampleTreeNode* node_L3 = ExampleTree_CreateNode(name_buf, ++uid, node_L2);
1193b4be Poul Sander 2025-02-03 21:28 347
                node_L3->HasData = true;
1193b4be Poul Sander 2025-02-03 21:28 348
            }
1193b4be Poul Sander 2025-02-03 21:28 349
        }
1193b4be Poul Sander 2025-02-03 21:28 350
    }
1193b4be Poul Sander 2025-02-03 21:28 351
    return node_L0;
1193b4be Poul Sander 2025-02-03 21:28 352
}
1193b4be Poul Sander 2025-02-03 21:28 353
1193b4be Poul Sander 2025-02-03 21:28 354
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 355
// [SECTION] Demo Window / ShowDemoWindow()
1193b4be Poul Sander 2025-02-03 21:28 356
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 357
1193b4be Poul Sander 2025-02-03 21:28 358
// Data to be shared accross different functions of the demo.
1193b4be Poul Sander 2025-02-03 21:28 359
struct ImGuiDemoWindowData
1193b4be Poul Sander 2025-02-03 21:28 360
{
1193b4be Poul Sander 2025-02-03 21:28 361
    // Examples Apps (accessible from the "Examples" menu)
1193b4be Poul Sander 2025-02-03 21:28 362
    bool ShowMainMenuBar = false;
1193b4be Poul Sander 2025-02-03 21:28 363
    bool ShowAppAssetsBrowser = false;
1193b4be Poul Sander 2025-02-03 21:28 364
    bool ShowAppConsole = false;
1193b4be Poul Sander 2025-02-03 21:28 365
    bool ShowAppCustomRendering = false;
1193b4be Poul Sander 2025-02-03 21:28 366
    bool ShowAppDocuments = false;
1193b4be Poul Sander 2025-02-03 21:28 367
    bool ShowAppDockSpace = false;
1193b4be Poul Sander 2025-02-03 21:28 368
    bool ShowAppLog = false;
1193b4be Poul Sander 2025-02-03 21:28 369
    bool ShowAppLayout = false;
1193b4be Poul Sander 2025-02-03 21:28 370
    bool ShowAppPropertyEditor = false;
1193b4be Poul Sander 2025-02-03 21:28 371
    bool ShowAppSimpleOverlay = false;
1193b4be Poul Sander 2025-02-03 21:28 372
    bool ShowAppAutoResize = false;
1193b4be Poul Sander 2025-02-03 21:28 373
    bool ShowAppConstrainedResize = false;
1193b4be Poul Sander 2025-02-03 21:28 374
    bool ShowAppFullscreen = false;
1193b4be Poul Sander 2025-02-03 21:28 375
    bool ShowAppLongText = false;
1193b4be Poul Sander 2025-02-03 21:28 376
    bool ShowAppWindowTitles = false;
1193b4be Poul Sander 2025-02-03 21:28 377
1193b4be Poul Sander 2025-02-03 21:28 378
    // Dear ImGui Tools (accessible from the "Tools" menu)
1193b4be Poul Sander 2025-02-03 21:28 379
    bool ShowMetrics = false;
1193b4be Poul Sander 2025-02-03 21:28 380
    bool ShowDebugLog = false;
1193b4be Poul Sander 2025-02-03 21:28 381
    bool ShowIDStackTool = false;
1193b4be Poul Sander 2025-02-03 21:28 382
    bool ShowStyleEditor = false;
1193b4be Poul Sander 2025-02-03 21:28 383
    bool ShowAbout = false;
1193b4be Poul Sander 2025-02-03 21:28 384
1193b4be Poul Sander 2025-02-03 21:28 385
    // Other data
1193b4be Poul Sander 2025-02-03 21:28 386
    ExampleTreeNode* DemoTree = NULL;
1193b4be Poul Sander 2025-02-03 21:28 387
};
1193b4be Poul Sander 2025-02-03 21:28 388
1193b4be Poul Sander 2025-02-03 21:28 389
// Demonstrate most Dear ImGui features (this is big function!)
1193b4be Poul Sander 2025-02-03 21:28 390
// You may execute this function to experiment with the UI and understand what it does.
1193b4be Poul Sander 2025-02-03 21:28 391
// You may then search for keywords in the code when you are interested by a specific feature.
1193b4be Poul Sander 2025-02-03 21:28 392
void ImGui::ShowDemoWindow(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 393
{
1193b4be Poul Sander 2025-02-03 21:28 394
    // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
1193b4be Poul Sander 2025-02-03 21:28 395
    // Most functions would normally just assert/crash if the context is missing.
1193b4be Poul Sander 2025-02-03 21:28 396
    IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!");
1193b4be Poul Sander 2025-02-03 21:28 397
1193b4be Poul Sander 2025-02-03 21:28 398
    // Verify ABI compatibility between caller code and compiled version of Dear ImGui. This helps detects some build issues.
1193b4be Poul Sander 2025-02-03 21:28 399
    IMGUI_CHECKVERSION();
1193b4be Poul Sander 2025-02-03 21:28 400
1193b4be Poul Sander 2025-02-03 21:28 401
    // Stored data
1193b4be Poul Sander 2025-02-03 21:28 402
    static ImGuiDemoWindowData demo_data;
1193b4be Poul Sander 2025-02-03 21:28 403
1193b4be Poul Sander 2025-02-03 21:28 404
    // Examples Apps (accessible from the "Examples" menu)
1193b4be Poul Sander 2025-02-03 21:28 405
    if (demo_data.ShowMainMenuBar)          { ShowExampleAppMainMenuBar(); }
1193b4be Poul Sander 2025-02-03 21:28 406
    if (demo_data.ShowAppDockSpace)         { ShowExampleAppDockSpace(&demo_data.ShowAppDockSpace); } // Important: Process the Docking app first, as explicit DockSpace() nodes needs to be submitted early (read comments near the DockSpace function)
1193b4be Poul Sander 2025-02-03 21:28 407
    if (demo_data.ShowAppDocuments)         { ShowExampleAppDocuments(&demo_data.ShowAppDocuments); } // ...process the Document app next, as it may also use a DockSpace()
1193b4be Poul Sander 2025-02-03 21:28 408
    if (demo_data.ShowAppAssetsBrowser)     { ShowExampleAppAssetsBrowser(&demo_data.ShowAppAssetsBrowser); }
1193b4be Poul Sander 2025-02-03 21:28 409
    if (demo_data.ShowAppConsole)           { ShowExampleAppConsole(&demo_data.ShowAppConsole); }
1193b4be Poul Sander 2025-02-03 21:28 410
    if (demo_data.ShowAppCustomRendering)   { ShowExampleAppCustomRendering(&demo_data.ShowAppCustomRendering); }
1193b4be Poul Sander 2025-02-03 21:28 411
    if (demo_data.ShowAppLog)               { ShowExampleAppLog(&demo_data.ShowAppLog); }
1193b4be Poul Sander 2025-02-03 21:28 412
    if (demo_data.ShowAppLayout)            { ShowExampleAppLayout(&demo_data.ShowAppLayout); }
1193b4be Poul Sander 2025-02-03 21:28 413
    if (demo_data.ShowAppPropertyEditor)    { ShowExampleAppPropertyEditor(&demo_data.ShowAppPropertyEditor, &demo_data); }
1193b4be Poul Sander 2025-02-03 21:28 414
    if (demo_data.ShowAppSimpleOverlay)     { ShowExampleAppSimpleOverlay(&demo_data.ShowAppSimpleOverlay); }
1193b4be Poul Sander 2025-02-03 21:28 415
    if (demo_data.ShowAppAutoResize)        { ShowExampleAppAutoResize(&demo_data.ShowAppAutoResize); }
1193b4be Poul Sander 2025-02-03 21:28 416
    if (demo_data.ShowAppConstrainedResize) { ShowExampleAppConstrainedResize(&demo_data.ShowAppConstrainedResize); }
1193b4be Poul Sander 2025-02-03 21:28 417
    if (demo_data.ShowAppFullscreen)        { ShowExampleAppFullscreen(&demo_data.ShowAppFullscreen); }
1193b4be Poul Sander 2025-02-03 21:28 418
    if (demo_data.ShowAppLongText)          { ShowExampleAppLongText(&demo_data.ShowAppLongText); }
1193b4be Poul Sander 2025-02-03 21:28 419
    if (demo_data.ShowAppWindowTitles)      { ShowExampleAppWindowTitles(&demo_data.ShowAppWindowTitles); }
1193b4be Poul Sander 2025-02-03 21:28 420
1193b4be Poul Sander 2025-02-03 21:28 421
    // Dear ImGui Tools (accessible from the "Tools" menu)
1193b4be Poul Sander 2025-02-03 21:28 422
    if (demo_data.ShowMetrics)              { ImGui::ShowMetricsWindow(&demo_data.ShowMetrics); }
1193b4be Poul Sander 2025-02-03 21:28 423
    if (demo_data.ShowDebugLog)             { ImGui::ShowDebugLogWindow(&demo_data.ShowDebugLog); }
1193b4be Poul Sander 2025-02-03 21:28 424
    if (demo_data.ShowIDStackTool)          { ImGui::ShowIDStackToolWindow(&demo_data.ShowIDStackTool); }
1193b4be Poul Sander 2025-02-03 21:28 425
    if (demo_data.ShowAbout)                { ImGui::ShowAboutWindow(&demo_data.ShowAbout); }
1193b4be Poul Sander 2025-02-03 21:28 426
    if (demo_data.ShowStyleEditor)
1193b4be Poul Sander 2025-02-03 21:28 427
    {
1193b4be Poul Sander 2025-02-03 21:28 428
        ImGui::Begin("Dear ImGui Style Editor", &demo_data.ShowStyleEditor);
1193b4be Poul Sander 2025-02-03 21:28 429
        ImGui::ShowStyleEditor();
1193b4be Poul Sander 2025-02-03 21:28 430
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 431
    }
1193b4be Poul Sander 2025-02-03 21:28 432
1193b4be Poul Sander 2025-02-03 21:28 433
    // Demonstrate the various window flags. Typically you would just use the default!
1193b4be Poul Sander 2025-02-03 21:28 434
    static bool no_titlebar = false;
1193b4be Poul Sander 2025-02-03 21:28 435
    static bool no_scrollbar = false;
1193b4be Poul Sander 2025-02-03 21:28 436
    static bool no_menu = false;
1193b4be Poul Sander 2025-02-03 21:28 437
    static bool no_move = false;
1193b4be Poul Sander 2025-02-03 21:28 438
    static bool no_resize = false;
1193b4be Poul Sander 2025-02-03 21:28 439
    static bool no_collapse = false;
1193b4be Poul Sander 2025-02-03 21:28 440
    static bool no_close = false;
1193b4be Poul Sander 2025-02-03 21:28 441
    static bool no_nav = false;
1193b4be Poul Sander 2025-02-03 21:28 442
    static bool no_background = false;
1193b4be Poul Sander 2025-02-03 21:28 443
    static bool no_bring_to_front = false;
1193b4be Poul Sander 2025-02-03 21:28 444
    static bool no_docking = false;
1193b4be Poul Sander 2025-02-03 21:28 445
    static bool unsaved_document = false;
1193b4be Poul Sander 2025-02-03 21:28 446
1193b4be Poul Sander 2025-02-03 21:28 447
    ImGuiWindowFlags window_flags = 0;
1193b4be Poul Sander 2025-02-03 21:28 448
    if (no_titlebar)        window_flags |= ImGuiWindowFlags_NoTitleBar;
1193b4be Poul Sander 2025-02-03 21:28 449
    if (no_scrollbar)       window_flags |= ImGuiWindowFlags_NoScrollbar;
1193b4be Poul Sander 2025-02-03 21:28 450
    if (!no_menu)           window_flags |= ImGuiWindowFlags_MenuBar;
1193b4be Poul Sander 2025-02-03 21:28 451
    if (no_move)            window_flags |= ImGuiWindowFlags_NoMove;
1193b4be Poul Sander 2025-02-03 21:28 452
    if (no_resize)          window_flags |= ImGuiWindowFlags_NoResize;
1193b4be Poul Sander 2025-02-03 21:28 453
    if (no_collapse)        window_flags |= ImGuiWindowFlags_NoCollapse;
1193b4be Poul Sander 2025-02-03 21:28 454
    if (no_nav)             window_flags |= ImGuiWindowFlags_NoNav;
1193b4be Poul Sander 2025-02-03 21:28 455
    if (no_background)      window_flags |= ImGuiWindowFlags_NoBackground;
1193b4be Poul Sander 2025-02-03 21:28 456
    if (no_bring_to_front)  window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
1193b4be Poul Sander 2025-02-03 21:28 457
    if (no_docking)         window_flags |= ImGuiWindowFlags_NoDocking;
1193b4be Poul Sander 2025-02-03 21:28 458
    if (unsaved_document)   window_flags |= ImGuiWindowFlags_UnsavedDocument;
1193b4be Poul Sander 2025-02-03 21:28 459
    if (no_close)           p_open = NULL; // Don't pass our bool* to Begin
1193b4be Poul Sander 2025-02-03 21:28 460
1193b4be Poul Sander 2025-02-03 21:28 461
    // We specify a default position/size in case there's no data in the .ini file.
1193b4be Poul Sander 2025-02-03 21:28 462
    // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
1193b4be Poul Sander 2025-02-03 21:28 463
    const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
1193b4be Poul Sander 2025-02-03 21:28 464
    ImGui::SetNextWindowPos(ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 465
    ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 466
1193b4be Poul Sander 2025-02-03 21:28 467
    // Main body of the Demo window starts here.
1193b4be Poul Sander 2025-02-03 21:28 468
    if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags))
1193b4be Poul Sander 2025-02-03 21:28 469
    {
1193b4be Poul Sander 2025-02-03 21:28 470
        // Early out if the window is collapsed, as an optimization.
1193b4be Poul Sander 2025-02-03 21:28 471
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 472
        return;
1193b4be Poul Sander 2025-02-03 21:28 473
    }
1193b4be Poul Sander 2025-02-03 21:28 474
1193b4be Poul Sander 2025-02-03 21:28 475
    // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
1193b4be Poul Sander 2025-02-03 21:28 476
    ImGui::PushItemWidth(ImGui::GetFontSize() * -12);           // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
1193b4be Poul Sander 2025-02-03 21:28 477
    //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f);   // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align)
1193b4be Poul Sander 2025-02-03 21:28 478
1193b4be Poul Sander 2025-02-03 21:28 479
    // Menu Bar
1193b4be Poul Sander 2025-02-03 21:28 480
    ShowDemoWindowMenuBar(&demo_data);
1193b4be Poul Sander 2025-02-03 21:28 481
1193b4be Poul Sander 2025-02-03 21:28 482
    ImGui::Text("dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
1193b4be Poul Sander 2025-02-03 21:28 483
    ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 484
1193b4be Poul Sander 2025-02-03 21:28 485
    IMGUI_DEMO_MARKER("Help");
1193b4be Poul Sander 2025-02-03 21:28 486
    if (ImGui::CollapsingHeader("Help"))
1193b4be Poul Sander 2025-02-03 21:28 487
    {
1193b4be Poul Sander 2025-02-03 21:28 488
        ImGui::SeparatorText("ABOUT THIS DEMO:");
1193b4be Poul Sander 2025-02-03 21:28 489
        ImGui::BulletText("Sections below are demonstrating many aspects of the library.");
1193b4be Poul Sander 2025-02-03 21:28 490
        ImGui::BulletText("The \"Examples\" menu above leads to more demo contents.");
1193b4be Poul Sander 2025-02-03 21:28 491
        ImGui::BulletText("The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
1193b4be Poul Sander 2025-02-03 21:28 492
                          "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
1193b4be Poul Sander 2025-02-03 21:28 493
1193b4be Poul Sander 2025-02-03 21:28 494
        ImGui::SeparatorText("PROGRAMMER GUIDE:");
1193b4be Poul Sander 2025-02-03 21:28 495
        ImGui::BulletText("See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
1193b4be Poul Sander 2025-02-03 21:28 496
        ImGui::BulletText("See comments in imgui.cpp.");
1193b4be Poul Sander 2025-02-03 21:28 497
        ImGui::BulletText("See example applications in the examples/ folder.");
1193b4be Poul Sander 2025-02-03 21:28 498
        ImGui::BulletText("Read the FAQ at ");
1193b4be Poul Sander 2025-02-03 21:28 499
        ImGui::SameLine(0, 0);
1193b4be Poul Sander 2025-02-03 21:28 500
        ImGui::TextLinkOpenURL("https://www.dearimgui.com/faq/");
1193b4be Poul Sander 2025-02-03 21:28 501
        ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
1193b4be Poul Sander 2025-02-03 21:28 502
        ImGui::BulletText("Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
1193b4be Poul Sander 2025-02-03 21:28 503
1193b4be Poul Sander 2025-02-03 21:28 504
        ImGui::SeparatorText("USER GUIDE:");
1193b4be Poul Sander 2025-02-03 21:28 505
        ImGui::ShowUserGuide();
1193b4be Poul Sander 2025-02-03 21:28 506
    }
1193b4be Poul Sander 2025-02-03 21:28 507
1193b4be Poul Sander 2025-02-03 21:28 508
    IMGUI_DEMO_MARKER("Configuration");
1193b4be Poul Sander 2025-02-03 21:28 509
    if (ImGui::CollapsingHeader("Configuration"))
1193b4be Poul Sander 2025-02-03 21:28 510
    {
1193b4be Poul Sander 2025-02-03 21:28 511
        ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 512
1193b4be Poul Sander 2025-02-03 21:28 513
        if (ImGui::TreeNode("Configuration##2"))
1193b4be Poul Sander 2025-02-03 21:28 514
        {
1193b4be Poul Sander 2025-02-03 21:28 515
            ImGui::SeparatorText("General");
1193b4be Poul Sander 2025-02-03 21:28 516
            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard",    &io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
1193b4be Poul Sander 2025-02-03 21:28 517
            ImGui::SameLine(); HelpMarker("Enable keyboard controls.");
1193b4be Poul Sander 2025-02-03 21:28 518
            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad",     &io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
1193b4be Poul Sander 2025-02-03 21:28 519
            ImGui::SameLine(); HelpMarker("Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
1193b4be Poul Sander 2025-02-03 21:28 520
            ImGui::CheckboxFlags("io.ConfigFlags: NoMouse",              &io.ConfigFlags, ImGuiConfigFlags_NoMouse);
1193b4be Poul Sander 2025-02-03 21:28 521
            ImGui::SameLine(); HelpMarker("Instruct dear imgui to disable mouse inputs and interactions.");
1193b4be Poul Sander 2025-02-03 21:28 522
1193b4be Poul Sander 2025-02-03 21:28 523
            // The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it:
1193b4be Poul Sander 2025-02-03 21:28 524
            if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
1193b4be Poul Sander 2025-02-03 21:28 525
            {
1193b4be Poul Sander 2025-02-03 21:28 526
                if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
1193b4be Poul Sander 2025-02-03 21:28 527
                {
1193b4be Poul Sander 2025-02-03 21:28 528
                    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 529
                    ImGui::Text("<<PRESS SPACE TO DISABLE>>");
1193b4be Poul Sander 2025-02-03 21:28 530
                }
1193b4be Poul Sander 2025-02-03 21:28 531
                // Prevent both being checked
1193b4be Poul Sander 2025-02-03 21:28 532
                if (ImGui::IsKeyPressed(ImGuiKey_Space) || (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard))
1193b4be Poul Sander 2025-02-03 21:28 533
                    io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
1193b4be Poul Sander 2025-02-03 21:28 534
            }
1193b4be Poul Sander 2025-02-03 21:28 535
1193b4be Poul Sander 2025-02-03 21:28 536
            ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange",  &io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
1193b4be Poul Sander 2025-02-03 21:28 537
            ImGui::SameLine(); HelpMarker("Instruct backend to not alter mouse cursor shape and visibility.");
1193b4be Poul Sander 2025-02-03 21:28 538
            ImGui::CheckboxFlags("io.ConfigFlags: NoKeyboard", &io.ConfigFlags, ImGuiConfigFlags_NoKeyboard);
1193b4be Poul Sander 2025-02-03 21:28 539
            ImGui::SameLine(); HelpMarker("Instruct dear imgui to disable keyboard inputs and interactions.");
1193b4be Poul Sander 2025-02-03 21:28 540
1193b4be Poul Sander 2025-02-03 21:28 541
            ImGui::Checkbox("io.ConfigInputTrickleEventQueue", &io.ConfigInputTrickleEventQueue);
1193b4be Poul Sander 2025-02-03 21:28 542
            ImGui::SameLine(); HelpMarker("Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.");
1193b4be Poul Sander 2025-02-03 21:28 543
            ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
1193b4be Poul Sander 2025-02-03 21:28 544
            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).");
1193b4be Poul Sander 2025-02-03 21:28 545
1193b4be Poul Sander 2025-02-03 21:28 546
            ImGui::SeparatorText("Keyboard/Gamepad Navigation");
1193b4be Poul Sander 2025-02-03 21:28 547
            ImGui::Checkbox("io.ConfigNavSwapGamepadButtons", &io.ConfigNavSwapGamepadButtons);
1193b4be Poul Sander 2025-02-03 21:28 548
            ImGui::Checkbox("io.ConfigNavMoveSetMousePos", &io.ConfigNavMoveSetMousePos);
1193b4be Poul Sander 2025-02-03 21:28 549
            ImGui::SameLine(); HelpMarker("Directional/tabbing navigation teleports the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is difficult");
1193b4be Poul Sander 2025-02-03 21:28 550
            ImGui::Checkbox("io.ConfigNavCaptureKeyboard", &io.ConfigNavCaptureKeyboard);
1193b4be Poul Sander 2025-02-03 21:28 551
            ImGui::Checkbox("io.ConfigNavEscapeClearFocusItem", &io.ConfigNavEscapeClearFocusItem);
1193b4be Poul Sander 2025-02-03 21:28 552
            ImGui::SameLine(); HelpMarker("Pressing Escape clears focused item.");
1193b4be Poul Sander 2025-02-03 21:28 553
            ImGui::Checkbox("io.ConfigNavEscapeClearFocusWindow", &io.ConfigNavEscapeClearFocusWindow);
1193b4be Poul Sander 2025-02-03 21:28 554
            ImGui::SameLine(); HelpMarker("Pressing Escape clears focused window.");
1193b4be Poul Sander 2025-02-03 21:28 555
            ImGui::Checkbox("io.ConfigNavCursorVisibleAuto", &io.ConfigNavCursorVisibleAuto);
1193b4be Poul Sander 2025-02-03 21:28 556
            ImGui::SameLine(); HelpMarker("Using directional navigation key makes the cursor visible. Mouse click hides the cursor.");
1193b4be Poul Sander 2025-02-03 21:28 557
            ImGui::Checkbox("io.ConfigNavCursorVisibleAlways", &io.ConfigNavCursorVisibleAlways);
1193b4be Poul Sander 2025-02-03 21:28 558
            ImGui::SameLine(); HelpMarker("Navigation cursor is always visible.");
1193b4be Poul Sander 2025-02-03 21:28 559
1193b4be Poul Sander 2025-02-03 21:28 560
            ImGui::SeparatorText("Docking");
1193b4be Poul Sander 2025-02-03 21:28 561
            ImGui::CheckboxFlags("io.ConfigFlags: DockingEnable", &io.ConfigFlags, ImGuiConfigFlags_DockingEnable);
1193b4be Poul Sander 2025-02-03 21:28 562
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 563
            if (io.ConfigDockingWithShift)
1193b4be Poul Sander 2025-02-03 21:28 564
                HelpMarker("Drag from window title bar or their tab to dock/undock. Hold SHIFT to enable docking.\n\nDrag from window menu button (upper-left button) to undock an entire node (all windows).");
1193b4be Poul Sander 2025-02-03 21:28 565
            else
1193b4be Poul Sander 2025-02-03 21:28 566
                HelpMarker("Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.\n\nDrag from window menu button (upper-left button) to undock an entire node (all windows).");
1193b4be Poul Sander 2025-02-03 21:28 567
            if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
1193b4be Poul Sander 2025-02-03 21:28 568
            {
1193b4be Poul Sander 2025-02-03 21:28 569
                ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 570
                ImGui::Checkbox("io.ConfigDockingNoSplit", &io.ConfigDockingNoSplit);
1193b4be Poul Sander 2025-02-03 21:28 571
                ImGui::SameLine(); HelpMarker("Simplified docking mode: disable window splitting, so docking is limited to merging multiple windows together into tab-bars.");
1193b4be Poul Sander 2025-02-03 21:28 572
                ImGui::Checkbox("io.ConfigDockingWithShift", &io.ConfigDockingWithShift);
1193b4be Poul Sander 2025-02-03 21:28 573
                ImGui::SameLine(); HelpMarker("Enable docking when holding Shift only (allow to drop in wider space, reduce visual noise)");
1193b4be Poul Sander 2025-02-03 21:28 574
                ImGui::Checkbox("io.ConfigDockingAlwaysTabBar", &io.ConfigDockingAlwaysTabBar);
1193b4be Poul Sander 2025-02-03 21:28 575
                ImGui::SameLine(); HelpMarker("Create a docking node and tab-bar on single floating windows.");
1193b4be Poul Sander 2025-02-03 21:28 576
                ImGui::Checkbox("io.ConfigDockingTransparentPayload", &io.ConfigDockingTransparentPayload);
1193b4be Poul Sander 2025-02-03 21:28 577
                ImGui::SameLine(); HelpMarker("Make window or viewport transparent when docking and only display docking boxes on the target viewport. Useful if rendering of multiple viewport cannot be synced. Best used with ConfigViewportsNoAutoMerge.");
1193b4be Poul Sander 2025-02-03 21:28 578
                ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 579
            }
1193b4be Poul Sander 2025-02-03 21:28 580
1193b4be Poul Sander 2025-02-03 21:28 581
            ImGui::SeparatorText("Multi-viewports");
1193b4be Poul Sander 2025-02-03 21:28 582
            ImGui::CheckboxFlags("io.ConfigFlags: ViewportsEnable", &io.ConfigFlags, ImGuiConfigFlags_ViewportsEnable);
1193b4be Poul Sander 2025-02-03 21:28 583
            ImGui::SameLine(); HelpMarker("[beta] Enable beta multi-viewports support. See ImGuiPlatformIO for details.");
1193b4be Poul Sander 2025-02-03 21:28 584
            if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
1193b4be Poul Sander 2025-02-03 21:28 585
            {
1193b4be Poul Sander 2025-02-03 21:28 586
                ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 587
                ImGui::Checkbox("io.ConfigViewportsNoAutoMerge", &io.ConfigViewportsNoAutoMerge);
1193b4be Poul Sander 2025-02-03 21:28 588
                ImGui::SameLine(); HelpMarker("Set to make all floating imgui windows always create their own viewport. Otherwise, they are merged into the main host viewports when overlapping it.");
1193b4be Poul Sander 2025-02-03 21:28 589
                ImGui::Checkbox("io.ConfigViewportsNoTaskBarIcon", &io.ConfigViewportsNoTaskBarIcon);
1193b4be Poul Sander 2025-02-03 21:28 590
                ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the task bar icon state right away).");
1193b4be Poul Sander 2025-02-03 21:28 591
                ImGui::Checkbox("io.ConfigViewportsNoDecoration", &io.ConfigViewportsNoDecoration);
1193b4be Poul Sander 2025-02-03 21:28 592
                ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the decoration right away).");
1193b4be Poul Sander 2025-02-03 21:28 593
                ImGui::Checkbox("io.ConfigViewportsNoDefaultParent", &io.ConfigViewportsNoDefaultParent);
1193b4be Poul Sander 2025-02-03 21:28 594
                ImGui::SameLine(); HelpMarker("Toggling this at runtime is normally unsupported (most platform backends won't refresh the parenting right away).");
1193b4be Poul Sander 2025-02-03 21:28 595
                ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 596
            }
1193b4be Poul Sander 2025-02-03 21:28 597
1193b4be Poul Sander 2025-02-03 21:28 598
            ImGui::SeparatorText("Widgets");
1193b4be Poul Sander 2025-02-03 21:28 599
            ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
1193b4be Poul Sander 2025-02-03 21:28 600
            ImGui::SameLine(); HelpMarker("Enable blinking cursor (optional as some users consider it to be distracting).");
1193b4be Poul Sander 2025-02-03 21:28 601
            ImGui::Checkbox("io.ConfigInputTextEnterKeepActive", &io.ConfigInputTextEnterKeepActive);
1193b4be Poul Sander 2025-02-03 21:28 602
            ImGui::SameLine(); HelpMarker("Pressing Enter will keep item active and select contents (single-line only).");
1193b4be Poul Sander 2025-02-03 21:28 603
            ImGui::Checkbox("io.ConfigDragClickToInputText", &io.ConfigDragClickToInputText);
1193b4be Poul Sander 2025-02-03 21:28 604
            ImGui::SameLine(); HelpMarker("Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
1193b4be Poul Sander 2025-02-03 21:28 605
            ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
1193b4be Poul Sander 2025-02-03 21:28 606
            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.");
1193b4be Poul Sander 2025-02-03 21:28 607
            ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
1193b4be Poul Sander 2025-02-03 21:28 608
            ImGui::Checkbox("io.ConfigScrollbarScrollByPage", &io.ConfigScrollbarScrollByPage);
1193b4be Poul Sander 2025-02-03 21:28 609
            ImGui::SameLine(); HelpMarker("Enable scrolling page by page when clicking outside the scrollbar grab.\nWhen disabled, always scroll to clicked location.\nWhen enabled, Shift+Click scrolls to clicked location.");
1193b4be Poul Sander 2025-02-03 21:28 610
            ImGui::Checkbox("io.ConfigMacOSXBehaviors", &io.ConfigMacOSXBehaviors);
1193b4be Poul Sander 2025-02-03 21:28 611
            ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
1193b4be Poul Sander 2025-02-03 21:28 612
            ImGui::Text("Also see Style->Rendering for rendering options.");
1193b4be Poul Sander 2025-02-03 21:28 613
1193b4be Poul Sander 2025-02-03 21:28 614
            // Also read: https://github.com/ocornut/imgui/wiki/Error-Handling
1193b4be Poul Sander 2025-02-03 21:28 615
            ImGui::SeparatorText("Error Handling");
1193b4be Poul Sander 2025-02-03 21:28 616
1193b4be Poul Sander 2025-02-03 21:28 617
            ImGui::Checkbox("io.ConfigErrorRecovery", &io.ConfigErrorRecovery);
1193b4be Poul Sander 2025-02-03 21:28 618
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 619
                "Options to configure how we handle recoverable errors.\n"
1193b4be Poul Sander 2025-02-03 21:28 620
                "- Error recovery is not perfect nor guaranteed! It is a feature to ease development.\n"
1193b4be Poul Sander 2025-02-03 21:28 621
                "- You not are not supposed to rely on it in the course of a normal application run.\n"
1193b4be Poul Sander 2025-02-03 21:28 622
                "- Possible usage: facilitate recovery from errors triggered from a scripting language or after specific exceptions handlers.\n"
1193b4be Poul Sander 2025-02-03 21:28 623
                "- Always ensure that on programmers seat you have at minimum Asserts or Tooltips enabled when making direct imgui API call!"
1193b4be Poul Sander 2025-02-03 21:28 624
                "Otherwise it would severely hinder your ability to catch and correct mistakes!");
1193b4be Poul Sander 2025-02-03 21:28 625
            ImGui::Checkbox("io.ConfigErrorRecoveryEnableAssert", &io.ConfigErrorRecoveryEnableAssert);
1193b4be Poul Sander 2025-02-03 21:28 626
            ImGui::Checkbox("io.ConfigErrorRecoveryEnableDebugLog", &io.ConfigErrorRecoveryEnableDebugLog);
1193b4be Poul Sander 2025-02-03 21:28 627
            ImGui::Checkbox("io.ConfigErrorRecoveryEnableTooltip", &io.ConfigErrorRecoveryEnableTooltip);
1193b4be Poul Sander 2025-02-03 21:28 628
            if (!io.ConfigErrorRecoveryEnableAssert && !io.ConfigErrorRecoveryEnableDebugLog && !io.ConfigErrorRecoveryEnableTooltip)
1193b4be Poul Sander 2025-02-03 21:28 629
                io.ConfigErrorRecoveryEnableAssert = io.ConfigErrorRecoveryEnableDebugLog = io.ConfigErrorRecoveryEnableTooltip = true;
1193b4be Poul Sander 2025-02-03 21:28 630
1193b4be Poul Sander 2025-02-03 21:28 631
            // Also read: https://github.com/ocornut/imgui/wiki/Debug-Tools
1193b4be Poul Sander 2025-02-03 21:28 632
            ImGui::SeparatorText("Debug");
1193b4be Poul Sander 2025-02-03 21:28 633
            ImGui::Checkbox("io.ConfigDebugIsDebuggerPresent", &io.ConfigDebugIsDebuggerPresent);
1193b4be Poul Sander 2025-02-03 21:28 634
            ImGui::SameLine(); HelpMarker("Enable various tools calling IM_DEBUG_BREAK().\n\nRequires a debugger being attached, otherwise IM_DEBUG_BREAK() options will appear to crash your application.");
1193b4be Poul Sander 2025-02-03 21:28 635
            ImGui::Checkbox("io.ConfigDebugHighlightIdConflicts", &io.ConfigDebugHighlightIdConflicts);
1193b4be Poul Sander 2025-02-03 21:28 636
            ImGui::SameLine(); HelpMarker("Highlight and show an error message when multiple items have conflicting identifiers.");
1193b4be Poul Sander 2025-02-03 21:28 637
            ImGui::BeginDisabled();
1193b4be Poul Sander 2025-02-03 21:28 638
            ImGui::Checkbox("io.ConfigDebugBeginReturnValueOnce", &io.ConfigDebugBeginReturnValueOnce);
1193b4be Poul Sander 2025-02-03 21:28 639
            ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 640
            ImGui::SameLine(); HelpMarker("First calls to Begin()/BeginChild() will return false.\n\nTHIS OPTION IS DISABLED because it needs to be set at application boot-time to make sense. Showing the disabled option is a way to make this feature easier to discover.");
1193b4be Poul Sander 2025-02-03 21:28 641
            ImGui::Checkbox("io.ConfigDebugBeginReturnValueLoop", &io.ConfigDebugBeginReturnValueLoop);
1193b4be Poul Sander 2025-02-03 21:28 642
            ImGui::SameLine(); HelpMarker("Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
1193b4be Poul Sander 2025-02-03 21:28 643
            ImGui::Checkbox("io.ConfigDebugIgnoreFocusLoss", &io.ConfigDebugIgnoreFocusLoss);
1193b4be Poul Sander 2025-02-03 21:28 644
            ImGui::SameLine(); HelpMarker("Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.");
1193b4be Poul Sander 2025-02-03 21:28 645
            ImGui::Checkbox("io.ConfigDebugIniSettings", &io.ConfigDebugIniSettings);
1193b4be Poul Sander 2025-02-03 21:28 646
            ImGui::SameLine(); HelpMarker("Option to save .ini data with extra comments (particularly helpful for Docking, but makes saving slower).");
1193b4be Poul Sander 2025-02-03 21:28 647
1193b4be Poul Sander 2025-02-03 21:28 648
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 649
            ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 650
        }
1193b4be Poul Sander 2025-02-03 21:28 651
1193b4be Poul Sander 2025-02-03 21:28 652
        IMGUI_DEMO_MARKER("Configuration/Backend Flags");
1193b4be Poul Sander 2025-02-03 21:28 653
        if (ImGui::TreeNode("Backend Flags"))
1193b4be Poul Sander 2025-02-03 21:28 654
        {
1193b4be Poul Sander 2025-02-03 21:28 655
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 656
                "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
1193b4be Poul Sander 2025-02-03 21:28 657
                "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
1193b4be Poul Sander 2025-02-03 21:28 658
1193b4be Poul Sander 2025-02-03 21:28 659
            // Make a local copy to avoid modifying actual backend flags.
1193b4be Poul Sander 2025-02-03 21:28 660
            // FIXME: Maybe we need a BeginReadonly() equivalent to keep label bright?
1193b4be Poul Sander 2025-02-03 21:28 661
            ImGui::BeginDisabled();
1193b4be Poul Sander 2025-02-03 21:28 662
            ImGui::CheckboxFlags("io.BackendFlags: HasGamepad",             &io.BackendFlags, ImGuiBackendFlags_HasGamepad);
1193b4be Poul Sander 2025-02-03 21:28 663
            ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors",        &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
1193b4be Poul Sander 2025-02-03 21:28 664
            ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos",         &io.BackendFlags, ImGuiBackendFlags_HasSetMousePos);
1193b4be Poul Sander 2025-02-03 21:28 665
            ImGui::CheckboxFlags("io.BackendFlags: PlatformHasViewports",   &io.BackendFlags, ImGuiBackendFlags_PlatformHasViewports);
1193b4be Poul Sander 2025-02-03 21:28 666
            ImGui::CheckboxFlags("io.BackendFlags: HasMouseHoveredViewport",&io.BackendFlags, ImGuiBackendFlags_HasMouseHoveredViewport);
1193b4be Poul Sander 2025-02-03 21:28 667
            ImGui::CheckboxFlags("io.BackendFlags: RendererHasVtxOffset",   &io.BackendFlags, ImGuiBackendFlags_RendererHasVtxOffset);
1193b4be Poul Sander 2025-02-03 21:28 668
            ImGui::CheckboxFlags("io.BackendFlags: RendererHasViewports",   &io.BackendFlags, ImGuiBackendFlags_RendererHasViewports);
1193b4be Poul Sander 2025-02-03 21:28 669
            ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 670
1193b4be Poul Sander 2025-02-03 21:28 671
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 672
            ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 673
        }
1193b4be Poul Sander 2025-02-03 21:28 674
1193b4be Poul Sander 2025-02-03 21:28 675
        IMGUI_DEMO_MARKER("Configuration/Style");
1193b4be Poul Sander 2025-02-03 21:28 676
        if (ImGui::TreeNode("Style"))
1193b4be Poul Sander 2025-02-03 21:28 677
        {
1193b4be Poul Sander 2025-02-03 21:28 678
            ImGui::Checkbox("Style Editor", &demo_data.ShowStyleEditor);
1193b4be Poul Sander 2025-02-03 21:28 679
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 680
            HelpMarker("The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
1193b4be Poul Sander 2025-02-03 21:28 681
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 682
            ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 683
        }
1193b4be Poul Sander 2025-02-03 21:28 684
1193b4be Poul Sander 2025-02-03 21:28 685
        IMGUI_DEMO_MARKER("Configuration/Capture, Logging");
1193b4be Poul Sander 2025-02-03 21:28 686
        if (ImGui::TreeNode("Capture/Logging"))
1193b4be Poul Sander 2025-02-03 21:28 687
        {
1193b4be Poul Sander 2025-02-03 21:28 688
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 689
                "The logging API redirects all text output so you can easily capture the content of "
1193b4be Poul Sander 2025-02-03 21:28 690
                "a window or a block. Tree nodes can be automatically expanded.\n"
1193b4be Poul Sander 2025-02-03 21:28 691
                "Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
1193b4be Poul Sander 2025-02-03 21:28 692
            ImGui::LogButtons();
1193b4be Poul Sander 2025-02-03 21:28 693
1193b4be Poul Sander 2025-02-03 21:28 694
            HelpMarker("You can also call ImGui::LogText() to output directly to the log without a visual output.");
1193b4be Poul Sander 2025-02-03 21:28 695
            if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
1193b4be Poul Sander 2025-02-03 21:28 696
            {
1193b4be Poul Sander 2025-02-03 21:28 697
                ImGui::LogToClipboard();
1193b4be Poul Sander 2025-02-03 21:28 698
                ImGui::LogText("Hello, world!");
1193b4be Poul Sander 2025-02-03 21:28 699
                ImGui::LogFinish();
1193b4be Poul Sander 2025-02-03 21:28 700
            }
1193b4be Poul Sander 2025-02-03 21:28 701
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 702
        }
1193b4be Poul Sander 2025-02-03 21:28 703
    }
1193b4be Poul Sander 2025-02-03 21:28 704
1193b4be Poul Sander 2025-02-03 21:28 705
    IMGUI_DEMO_MARKER("Window options");
1193b4be Poul Sander 2025-02-03 21:28 706
    if (ImGui::CollapsingHeader("Window options"))
1193b4be Poul Sander 2025-02-03 21:28 707
    {
1193b4be Poul Sander 2025-02-03 21:28 708
        if (ImGui::BeginTable("split", 3))
1193b4be Poul Sander 2025-02-03 21:28 709
        {
1193b4be Poul Sander 2025-02-03 21:28 710
            ImGui::TableNextColumn(); ImGui::Checkbox("No titlebar", &no_titlebar);
1193b4be Poul Sander 2025-02-03 21:28 711
            ImGui::TableNextColumn(); ImGui::Checkbox("No scrollbar", &no_scrollbar);
1193b4be Poul Sander 2025-02-03 21:28 712
            ImGui::TableNextColumn(); ImGui::Checkbox("No menu", &no_menu);
1193b4be Poul Sander 2025-02-03 21:28 713
            ImGui::TableNextColumn(); ImGui::Checkbox("No move", &no_move);
1193b4be Poul Sander 2025-02-03 21:28 714
            ImGui::TableNextColumn(); ImGui::Checkbox("No resize", &no_resize);
1193b4be Poul Sander 2025-02-03 21:28 715
            ImGui::TableNextColumn(); ImGui::Checkbox("No collapse", &no_collapse);
1193b4be Poul Sander 2025-02-03 21:28 716
            ImGui::TableNextColumn(); ImGui::Checkbox("No close", &no_close);
1193b4be Poul Sander 2025-02-03 21:28 717
            ImGui::TableNextColumn(); ImGui::Checkbox("No nav", &no_nav);
1193b4be Poul Sander 2025-02-03 21:28 718
            ImGui::TableNextColumn(); ImGui::Checkbox("No background", &no_background);
1193b4be Poul Sander 2025-02-03 21:28 719
            ImGui::TableNextColumn(); ImGui::Checkbox("No bring to front", &no_bring_to_front);
1193b4be Poul Sander 2025-02-03 21:28 720
            ImGui::TableNextColumn(); ImGui::Checkbox("No docking", &no_docking);
1193b4be Poul Sander 2025-02-03 21:28 721
            ImGui::TableNextColumn(); ImGui::Checkbox("Unsaved document", &unsaved_document);
1193b4be Poul Sander 2025-02-03 21:28 722
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 723
        }
1193b4be Poul Sander 2025-02-03 21:28 724
    }
1193b4be Poul Sander 2025-02-03 21:28 725
1193b4be Poul Sander 2025-02-03 21:28 726
    // All demo contents
1193b4be Poul Sander 2025-02-03 21:28 727
    ShowDemoWindowWidgets(&demo_data);
1193b4be Poul Sander 2025-02-03 21:28 728
    ShowDemoWindowLayout();
1193b4be Poul Sander 2025-02-03 21:28 729
    ShowDemoWindowPopups();
1193b4be Poul Sander 2025-02-03 21:28 730
    ShowDemoWindowTables();
1193b4be Poul Sander 2025-02-03 21:28 731
    ShowDemoWindowInputs();
1193b4be Poul Sander 2025-02-03 21:28 732
1193b4be Poul Sander 2025-02-03 21:28 733
    // End of ShowDemoWindow()
1193b4be Poul Sander 2025-02-03 21:28 734
    ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 735
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 736
}
1193b4be Poul Sander 2025-02-03 21:28 737
1193b4be Poul Sander 2025-02-03 21:28 738
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 739
// [SECTION] ShowDemoWindowMenuBar()
1193b4be Poul Sander 2025-02-03 21:28 740
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 741
1193b4be Poul Sander 2025-02-03 21:28 742
static void ShowDemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
1193b4be Poul Sander 2025-02-03 21:28 743
{
1193b4be Poul Sander 2025-02-03 21:28 744
    IMGUI_DEMO_MARKER("Menu");
1193b4be Poul Sander 2025-02-03 21:28 745
    if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 746
    {
1193b4be Poul Sander 2025-02-03 21:28 747
        if (ImGui::BeginMenu("Menu"))
1193b4be Poul Sander 2025-02-03 21:28 748
        {
1193b4be Poul Sander 2025-02-03 21:28 749
            IMGUI_DEMO_MARKER("Menu/File");
1193b4be Poul Sander 2025-02-03 21:28 750
            ShowExampleMenuFile();
1193b4be Poul Sander 2025-02-03 21:28 751
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 752
        }
1193b4be Poul Sander 2025-02-03 21:28 753
        if (ImGui::BeginMenu("Examples"))
1193b4be Poul Sander 2025-02-03 21:28 754
        {
1193b4be Poul Sander 2025-02-03 21:28 755
            IMGUI_DEMO_MARKER("Menu/Examples");
1193b4be Poul Sander 2025-02-03 21:28 756
            ImGui::MenuItem("Main menu bar", NULL, &demo_data->ShowMainMenuBar);
1193b4be Poul Sander 2025-02-03 21:28 757
1193b4be Poul Sander 2025-02-03 21:28 758
            ImGui::SeparatorText("Mini apps");
1193b4be Poul Sander 2025-02-03 21:28 759
            ImGui::MenuItem("Assets Browser", NULL, &demo_data->ShowAppAssetsBrowser);
1193b4be Poul Sander 2025-02-03 21:28 760
            ImGui::MenuItem("Console", NULL, &demo_data->ShowAppConsole);
1193b4be Poul Sander 2025-02-03 21:28 761
            ImGui::MenuItem("Custom rendering", NULL, &demo_data->ShowAppCustomRendering);
1193b4be Poul Sander 2025-02-03 21:28 762
            ImGui::MenuItem("Documents", NULL, &demo_data->ShowAppDocuments);
1193b4be Poul Sander 2025-02-03 21:28 763
            ImGui::MenuItem("Dockspace", NULL, &demo_data->ShowAppDockSpace);
1193b4be Poul Sander 2025-02-03 21:28 764
            ImGui::MenuItem("Log", NULL, &demo_data->ShowAppLog);
1193b4be Poul Sander 2025-02-03 21:28 765
            ImGui::MenuItem("Property editor", NULL, &demo_data->ShowAppPropertyEditor);
1193b4be Poul Sander 2025-02-03 21:28 766
            ImGui::MenuItem("Simple layout", NULL, &demo_data->ShowAppLayout);
1193b4be Poul Sander 2025-02-03 21:28 767
            ImGui::MenuItem("Simple overlay", NULL, &demo_data->ShowAppSimpleOverlay);
1193b4be Poul Sander 2025-02-03 21:28 768
1193b4be Poul Sander 2025-02-03 21:28 769
            ImGui::SeparatorText("Concepts");
1193b4be Poul Sander 2025-02-03 21:28 770
            ImGui::MenuItem("Auto-resizing window", NULL, &demo_data->ShowAppAutoResize);
1193b4be Poul Sander 2025-02-03 21:28 771
            ImGui::MenuItem("Constrained-resizing window", NULL, &demo_data->ShowAppConstrainedResize);
1193b4be Poul Sander 2025-02-03 21:28 772
            ImGui::MenuItem("Fullscreen window", NULL, &demo_data->ShowAppFullscreen);
1193b4be Poul Sander 2025-02-03 21:28 773
            ImGui::MenuItem("Long text display", NULL, &demo_data->ShowAppLongText);
1193b4be Poul Sander 2025-02-03 21:28 774
            ImGui::MenuItem("Manipulating window titles", NULL, &demo_data->ShowAppWindowTitles);
1193b4be Poul Sander 2025-02-03 21:28 775
1193b4be Poul Sander 2025-02-03 21:28 776
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 777
        }
1193b4be Poul Sander 2025-02-03 21:28 778
        //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar!
1193b4be Poul Sander 2025-02-03 21:28 779
        if (ImGui::BeginMenu("Tools"))
1193b4be Poul Sander 2025-02-03 21:28 780
        {
1193b4be Poul Sander 2025-02-03 21:28 781
            IMGUI_DEMO_MARKER("Menu/Tools");
1193b4be Poul Sander 2025-02-03 21:28 782
            ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 783
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
1193b4be Poul Sander 2025-02-03 21:28 784
            const bool has_debug_tools = true;
1193b4be Poul Sander 2025-02-03 21:28 785
#else
1193b4be Poul Sander 2025-02-03 21:28 786
            const bool has_debug_tools = false;
1193b4be Poul Sander 2025-02-03 21:28 787
#endif
1193b4be Poul Sander 2025-02-03 21:28 788
            ImGui::MenuItem("Metrics/Debugger", NULL, &demo_data->ShowMetrics, has_debug_tools);
1193b4be Poul Sander 2025-02-03 21:28 789
            ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools);
1193b4be Poul Sander 2025-02-03 21:28 790
            ImGui::MenuItem("ID Stack Tool", NULL, &demo_data->ShowIDStackTool, has_debug_tools);
1193b4be Poul Sander 2025-02-03 21:28 791
            bool is_debugger_present = io.ConfigDebugIsDebuggerPresent;
1193b4be Poul Sander 2025-02-03 21:28 792
            if (ImGui::MenuItem("Item Picker", NULL, false, has_debug_tools && is_debugger_present))
1193b4be Poul Sander 2025-02-03 21:28 793
                ImGui::DebugStartItemPicker();
1193b4be Poul Sander 2025-02-03 21:28 794
            if (!is_debugger_present)
1193b4be Poul Sander 2025-02-03 21:28 795
                ImGui::SetItemTooltip("Requires io.ConfigDebugIsDebuggerPresent=true to be set.\n\nWe otherwise disable the menu option to avoid casual users crashing the application.\n\nYou can however always access the Item Picker in Metrics->Tools.");
1193b4be Poul Sander 2025-02-03 21:28 796
            ImGui::MenuItem("Style Editor", NULL, &demo_data->ShowStyleEditor);
1193b4be Poul Sander 2025-02-03 21:28 797
            ImGui::MenuItem("About Dear ImGui", NULL, &demo_data->ShowAbout);
1193b4be Poul Sander 2025-02-03 21:28 798
1193b4be Poul Sander 2025-02-03 21:28 799
            ImGui::SeparatorText("Debug Options");
1193b4be Poul Sander 2025-02-03 21:28 800
            ImGui::MenuItem("Highlight ID Conflicts", NULL, &io.ConfigDebugHighlightIdConflicts, has_debug_tools);
1193b4be Poul Sander 2025-02-03 21:28 801
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 802
        }
1193b4be Poul Sander 2025-02-03 21:28 803
        ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 804
    }
1193b4be Poul Sander 2025-02-03 21:28 805
}
1193b4be Poul Sander 2025-02-03 21:28 806
1193b4be Poul Sander 2025-02-03 21:28 807
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 808
// [SECTION] ShowDemoWindowWidgets()
1193b4be Poul Sander 2025-02-03 21:28 809
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 810
1193b4be Poul Sander 2025-02-03 21:28 811
static void ShowDemoWindowWidgets(ImGuiDemoWindowData* demo_data)
1193b4be Poul Sander 2025-02-03 21:28 812
{
1193b4be Poul Sander 2025-02-03 21:28 813
    IMGUI_DEMO_MARKER("Widgets");
1193b4be Poul Sander 2025-02-03 21:28 814
    //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
1193b4be Poul Sander 2025-02-03 21:28 815
    if (!ImGui::CollapsingHeader("Widgets"))
1193b4be Poul Sander 2025-02-03 21:28 816
        return;
1193b4be Poul Sander 2025-02-03 21:28 817
1193b4be Poul Sander 2025-02-03 21:28 818
    static bool disable_all = false; // The Checkbox for that is inside the "Disabled" section at the bottom
1193b4be Poul Sander 2025-02-03 21:28 819
    if (disable_all)
1193b4be Poul Sander 2025-02-03 21:28 820
        ImGui::BeginDisabled();
1193b4be Poul Sander 2025-02-03 21:28 821
1193b4be Poul Sander 2025-02-03 21:28 822
    IMGUI_DEMO_MARKER("Widgets/Basic");
1193b4be Poul Sander 2025-02-03 21:28 823
    if (ImGui::TreeNode("Basic"))
1193b4be Poul Sander 2025-02-03 21:28 824
    {
1193b4be Poul Sander 2025-02-03 21:28 825
        ImGui::SeparatorText("General");
1193b4be Poul Sander 2025-02-03 21:28 826
1193b4be Poul Sander 2025-02-03 21:28 827
        IMGUI_DEMO_MARKER("Widgets/Basic/Button");
1193b4be Poul Sander 2025-02-03 21:28 828
        static int clicked = 0;
1193b4be Poul Sander 2025-02-03 21:28 829
        if (ImGui::Button("Button"))
1193b4be Poul Sander 2025-02-03 21:28 830
            clicked++;
1193b4be Poul Sander 2025-02-03 21:28 831
        if (clicked & 1)
1193b4be Poul Sander 2025-02-03 21:28 832
        {
1193b4be Poul Sander 2025-02-03 21:28 833
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 834
            ImGui::Text("Thanks for clicking me!");
1193b4be Poul Sander 2025-02-03 21:28 835
        }
1193b4be Poul Sander 2025-02-03 21:28 836
1193b4be Poul Sander 2025-02-03 21:28 837
        IMGUI_DEMO_MARKER("Widgets/Basic/Checkbox");
1193b4be Poul Sander 2025-02-03 21:28 838
        static bool check = true;
1193b4be Poul Sander 2025-02-03 21:28 839
        ImGui::Checkbox("checkbox", &check);
1193b4be Poul Sander 2025-02-03 21:28 840
1193b4be Poul Sander 2025-02-03 21:28 841
        IMGUI_DEMO_MARKER("Widgets/Basic/RadioButton");
1193b4be Poul Sander 2025-02-03 21:28 842
        static int e = 0;
1193b4be Poul Sander 2025-02-03 21:28 843
        ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 844
        ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 845
        ImGui::RadioButton("radio c", &e, 2);
1193b4be Poul Sander 2025-02-03 21:28 846
1193b4be Poul Sander 2025-02-03 21:28 847
        // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
1193b4be Poul Sander 2025-02-03 21:28 848
        IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Colored)");
1193b4be Poul Sander 2025-02-03 21:28 849
        for (int i = 0; i < 7; i++)
1193b4be Poul Sander 2025-02-03 21:28 850
        {
1193b4be Poul Sander 2025-02-03 21:28 851
            if (i > 0)
1193b4be Poul Sander 2025-02-03 21:28 852
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 853
            ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 854
            ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f));
1193b4be Poul Sander 2025-02-03 21:28 855
            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f));
1193b4be Poul Sander 2025-02-03 21:28 856
            ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f));
1193b4be Poul Sander 2025-02-03 21:28 857
            ImGui::Button("Click");
1193b4be Poul Sander 2025-02-03 21:28 858
            ImGui::PopStyleColor(3);
1193b4be Poul Sander 2025-02-03 21:28 859
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 860
        }
1193b4be Poul Sander 2025-02-03 21:28 861
1193b4be Poul Sander 2025-02-03 21:28 862
        // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
1193b4be Poul Sander 2025-02-03 21:28 863
        // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
1193b4be Poul Sander 2025-02-03 21:28 864
        // See 'Demo->Layout->Text Baseline Alignment' for details.
1193b4be Poul Sander 2025-02-03 21:28 865
        ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 866
        ImGui::Text("Hold to repeat:");
1193b4be Poul Sander 2025-02-03 21:28 867
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 868
1193b4be Poul Sander 2025-02-03 21:28 869
        // Arrow buttons with Repeater
1193b4be Poul Sander 2025-02-03 21:28 870
        IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Repeating)");
1193b4be Poul Sander 2025-02-03 21:28 871
        static int counter = 0;
1193b4be Poul Sander 2025-02-03 21:28 872
        float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
1193b4be Poul Sander 2025-02-03 21:28 873
        ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true);
1193b4be Poul Sander 2025-02-03 21:28 874
        if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
1193b4be Poul Sander 2025-02-03 21:28 875
        ImGui::SameLine(0.0f, spacing);
1193b4be Poul Sander 2025-02-03 21:28 876
        if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
1193b4be Poul Sander 2025-02-03 21:28 877
        ImGui::PopItemFlag();
1193b4be Poul Sander 2025-02-03 21:28 878
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 879
        ImGui::Text("%d", counter);
1193b4be Poul Sander 2025-02-03 21:28 880
1193b4be Poul Sander 2025-02-03 21:28 881
        ImGui::Button("Tooltip");
1193b4be Poul Sander 2025-02-03 21:28 882
        ImGui::SetItemTooltip("I am a tooltip");
1193b4be Poul Sander 2025-02-03 21:28 883
1193b4be Poul Sander 2025-02-03 21:28 884
        ImGui::LabelText("label", "Value");
1193b4be Poul Sander 2025-02-03 21:28 885
1193b4be Poul Sander 2025-02-03 21:28 886
        ImGui::SeparatorText("Inputs");
1193b4be Poul Sander 2025-02-03 21:28 887
1193b4be Poul Sander 2025-02-03 21:28 888
        {
1193b4be Poul Sander 2025-02-03 21:28 889
            // To wire InputText() with std::string or any other custom string type,
1193b4be Poul Sander 2025-02-03 21:28 890
            // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
1193b4be Poul Sander 2025-02-03 21:28 891
            IMGUI_DEMO_MARKER("Widgets/Basic/InputText");
1193b4be Poul Sander 2025-02-03 21:28 892
            static char str0[128] = "Hello, world!";
1193b4be Poul Sander 2025-02-03 21:28 893
            ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
1193b4be Poul Sander 2025-02-03 21:28 894
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 895
                "USER:\n"
1193b4be Poul Sander 2025-02-03 21:28 896
                "Hold SHIFT or use mouse to select text.\n"
1193b4be Poul Sander 2025-02-03 21:28 897
                "CTRL+Left/Right to word jump.\n"
1193b4be Poul Sander 2025-02-03 21:28 898
                "CTRL+A or Double-Click to select all.\n"
1193b4be Poul Sander 2025-02-03 21:28 899
                "CTRL+X,CTRL+C,CTRL+V clipboard.\n"
1193b4be Poul Sander 2025-02-03 21:28 900
                "CTRL+Z,CTRL+Y undo/redo.\n"
1193b4be Poul Sander 2025-02-03 21:28 901
                "ESCAPE to revert.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 902
                "PROGRAMMER:\n"
1193b4be Poul Sander 2025-02-03 21:28 903
                "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
1193b4be Poul Sander 2025-02-03 21:28 904
                "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
1193b4be Poul Sander 2025-02-03 21:28 905
                "in imgui_demo.cpp).");
1193b4be Poul Sander 2025-02-03 21:28 906
1193b4be Poul Sander 2025-02-03 21:28 907
            static char str1[128] = "";
1193b4be Poul Sander 2025-02-03 21:28 908
            ImGui::InputTextWithHint("input text (w/ hint)", "enter text here", str1, IM_ARRAYSIZE(str1));
1193b4be Poul Sander 2025-02-03 21:28 909
1193b4be Poul Sander 2025-02-03 21:28 910
            IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
1193b4be Poul Sander 2025-02-03 21:28 911
            static int i0 = 123;
1193b4be Poul Sander 2025-02-03 21:28 912
            ImGui::InputInt("input int", &i0);
1193b4be Poul Sander 2025-02-03 21:28 913
1193b4be Poul Sander 2025-02-03 21:28 914
            static float f0 = 0.001f;
1193b4be Poul Sander 2025-02-03 21:28 915
            ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
1193b4be Poul Sander 2025-02-03 21:28 916
1193b4be Poul Sander 2025-02-03 21:28 917
            static double d0 = 999999.00000001;
1193b4be Poul Sander 2025-02-03 21:28 918
            ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
1193b4be Poul Sander 2025-02-03 21:28 919
1193b4be Poul Sander 2025-02-03 21:28 920
            static float f1 = 1.e10f;
1193b4be Poul Sander 2025-02-03 21:28 921
            ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
1193b4be Poul Sander 2025-02-03 21:28 922
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 923
                "You can input value using the scientific notation,\n"
1193b4be Poul Sander 2025-02-03 21:28 924
                "  e.g. \"1e+8\" becomes \"100000000\".");
1193b4be Poul Sander 2025-02-03 21:28 925
1193b4be Poul Sander 2025-02-03 21:28 926
            static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
1193b4be Poul Sander 2025-02-03 21:28 927
            ImGui::InputFloat3("input float3", vec4a);
1193b4be Poul Sander 2025-02-03 21:28 928
        }
1193b4be Poul Sander 2025-02-03 21:28 929
1193b4be Poul Sander 2025-02-03 21:28 930
        ImGui::SeparatorText("Drags");
1193b4be Poul Sander 2025-02-03 21:28 931
1193b4be Poul Sander 2025-02-03 21:28 932
        {
1193b4be Poul Sander 2025-02-03 21:28 933
            IMGUI_DEMO_MARKER("Widgets/Basic/DragInt, DragFloat");
1193b4be Poul Sander 2025-02-03 21:28 934
            static int i1 = 50, i2 = 42, i3 = 128;
1193b4be Poul Sander 2025-02-03 21:28 935
            ImGui::DragInt("drag int", &i1, 1);
1193b4be Poul Sander 2025-02-03 21:28 936
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 937
                "Click and drag to edit value.\n"
1193b4be Poul Sander 2025-02-03 21:28 938
                "Hold SHIFT/ALT for faster/slower edit.\n"
1193b4be Poul Sander 2025-02-03 21:28 939
                "Double-click or CTRL+click to input value.");
1193b4be Poul Sander 2025-02-03 21:28 940
            ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%", ImGuiSliderFlags_AlwaysClamp);
1193b4be Poul Sander 2025-02-03 21:28 941
            ImGui::DragInt("drag int wrap 100..200", &i3, 1, 100, 200, "%d", ImGuiSliderFlags_WrapAround);
1193b4be Poul Sander 2025-02-03 21:28 942
1193b4be Poul Sander 2025-02-03 21:28 943
            static float f1 = 1.00f, f2 = 0.0067f;
1193b4be Poul Sander 2025-02-03 21:28 944
            ImGui::DragFloat("drag float", &f1, 0.005f);
1193b4be Poul Sander 2025-02-03 21:28 945
            ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
1193b4be Poul Sander 2025-02-03 21:28 946
            //ImGui::DragFloat("drag wrap -1..1", &f3, 0.005f, -1.0f, 1.0f, NULL, ImGuiSliderFlags_WrapAround);
1193b4be Poul Sander 2025-02-03 21:28 947
        }
1193b4be Poul Sander 2025-02-03 21:28 948
1193b4be Poul Sander 2025-02-03 21:28 949
        ImGui::SeparatorText("Sliders");
1193b4be Poul Sander 2025-02-03 21:28 950
1193b4be Poul Sander 2025-02-03 21:28 951
        {
1193b4be Poul Sander 2025-02-03 21:28 952
            IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat");
1193b4be Poul Sander 2025-02-03 21:28 953
            static int i1 = 0;
1193b4be Poul Sander 2025-02-03 21:28 954
            ImGui::SliderInt("slider int", &i1, -1, 3);
1193b4be Poul Sander 2025-02-03 21:28 955
            ImGui::SameLine(); HelpMarker("CTRL+click to input value.");
1193b4be Poul Sander 2025-02-03 21:28 956
1193b4be Poul Sander 2025-02-03 21:28 957
            static float f1 = 0.123f, f2 = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 958
            ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
1193b4be Poul Sander 2025-02-03 21:28 959
            ImGui::SliderFloat("slider float (log)", &f2, -10.0f, 10.0f, "%.4f", ImGuiSliderFlags_Logarithmic);
1193b4be Poul Sander 2025-02-03 21:28 960
1193b4be Poul Sander 2025-02-03 21:28 961
            IMGUI_DEMO_MARKER("Widgets/Basic/SliderAngle");
1193b4be Poul Sander 2025-02-03 21:28 962
            static float angle = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 963
            ImGui::SliderAngle("slider angle", &angle);
1193b4be Poul Sander 2025-02-03 21:28 964
1193b4be Poul Sander 2025-02-03 21:28 965
            // Using the format string to display a name instead of an integer.
1193b4be Poul Sander 2025-02-03 21:28 966
            // Here we completely omit '%d' from the format string, so it'll only display a name.
1193b4be Poul Sander 2025-02-03 21:28 967
            // This technique can also be used with DragInt().
1193b4be Poul Sander 2025-02-03 21:28 968
            IMGUI_DEMO_MARKER("Widgets/Basic/Slider (enum)");
1193b4be Poul Sander 2025-02-03 21:28 969
            enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
1193b4be Poul Sander 2025-02-03 21:28 970
            static int elem = Element_Fire;
1193b4be Poul Sander 2025-02-03 21:28 971
            const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
1193b4be Poul Sander 2025-02-03 21:28 972
            const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
1193b4be Poul Sander 2025-02-03 21:28 973
            ImGui::SliderInt("slider enum", &elem, 0, Element_COUNT - 1, elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here.
1193b4be Poul Sander 2025-02-03 21:28 974
            ImGui::SameLine(); HelpMarker("Using the format string parameter to display a name instead of the underlying integer.");
1193b4be Poul Sander 2025-02-03 21:28 975
        }
1193b4be Poul Sander 2025-02-03 21:28 976
1193b4be Poul Sander 2025-02-03 21:28 977
        ImGui::SeparatorText("Selectors/Pickers");
1193b4be Poul Sander 2025-02-03 21:28 978
1193b4be Poul Sander 2025-02-03 21:28 979
        {
1193b4be Poul Sander 2025-02-03 21:28 980
            IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4");
1193b4be Poul Sander 2025-02-03 21:28 981
            static float col1[3] = { 1.0f, 0.0f, 0.2f };
1193b4be Poul Sander 2025-02-03 21:28 982
            static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
1193b4be Poul Sander 2025-02-03 21:28 983
            ImGui::ColorEdit3("color 1", col1);
1193b4be Poul Sander 2025-02-03 21:28 984
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 985
                "Click on the color square to open a color picker.\n"
1193b4be Poul Sander 2025-02-03 21:28 986
                "Click and hold to use drag and drop.\n"
1193b4be Poul Sander 2025-02-03 21:28 987
                "Right-click on the color square to show options.\n"
1193b4be Poul Sander 2025-02-03 21:28 988
                "CTRL+click on individual component to input value.\n");
1193b4be Poul Sander 2025-02-03 21:28 989
1193b4be Poul Sander 2025-02-03 21:28 990
            ImGui::ColorEdit4("color 2", col2);
1193b4be Poul Sander 2025-02-03 21:28 991
        }
1193b4be Poul Sander 2025-02-03 21:28 992
1193b4be Poul Sander 2025-02-03 21:28 993
        {
1193b4be Poul Sander 2025-02-03 21:28 994
            // Using the _simplified_ one-liner Combo() api here
1193b4be Poul Sander 2025-02-03 21:28 995
            // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
1193b4be Poul Sander 2025-02-03 21:28 996
            IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
1193b4be Poul Sander 2025-02-03 21:28 997
            const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
1193b4be Poul Sander 2025-02-03 21:28 998
            static int item_current = 0;
1193b4be Poul Sander 2025-02-03 21:28 999
            ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
1193b4be Poul Sander 2025-02-03 21:28 1000
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1001
                "Using the simplified one-liner Combo API here.\n"
1193b4be Poul Sander 2025-02-03 21:28 1002
                "Refer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
1193b4be Poul Sander 2025-02-03 21:28 1003
        }
1193b4be Poul Sander 2025-02-03 21:28 1004
1193b4be Poul Sander 2025-02-03 21:28 1005
        {
1193b4be Poul Sander 2025-02-03 21:28 1006
            // Using the _simplified_ one-liner ListBox() api here
1193b4be Poul Sander 2025-02-03 21:28 1007
            // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
1193b4be Poul Sander 2025-02-03 21:28 1008
            IMGUI_DEMO_MARKER("Widgets/Basic/ListBox");
1193b4be Poul Sander 2025-02-03 21:28 1009
            const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
1193b4be Poul Sander 2025-02-03 21:28 1010
            static int item_current = 1;
1193b4be Poul Sander 2025-02-03 21:28 1011
            ImGui::ListBox("listbox", &item_current, items, IM_ARRAYSIZE(items), 4);
1193b4be Poul Sander 2025-02-03 21:28 1012
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1013
                "Using the simplified one-liner ListBox API here.\n"
1193b4be Poul Sander 2025-02-03 21:28 1014
                "Refer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
1193b4be Poul Sander 2025-02-03 21:28 1015
        }
1193b4be Poul Sander 2025-02-03 21:28 1016
1193b4be Poul Sander 2025-02-03 21:28 1017
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1018
    }
1193b4be Poul Sander 2025-02-03 21:28 1019
1193b4be Poul Sander 2025-02-03 21:28 1020
    IMGUI_DEMO_MARKER("Widgets/Tooltips");
1193b4be Poul Sander 2025-02-03 21:28 1021
    if (ImGui::TreeNode("Tooltips"))
1193b4be Poul Sander 2025-02-03 21:28 1022
    {
1193b4be Poul Sander 2025-02-03 21:28 1023
        // Tooltips are windows following the mouse. They do not take focus away.
1193b4be Poul Sander 2025-02-03 21:28 1024
        ImGui::SeparatorText("General");
1193b4be Poul Sander 2025-02-03 21:28 1025
1193b4be Poul Sander 2025-02-03 21:28 1026
        // Typical use cases:
1193b4be Poul Sander 2025-02-03 21:28 1027
        // - Short-form (text only):      SetItemTooltip("Hello");
1193b4be Poul Sander 2025-02-03 21:28 1028
        // - Short-form (any contents):   if (BeginItemTooltip()) { Text("Hello"); EndTooltip(); }
1193b4be Poul Sander 2025-02-03 21:28 1029
1193b4be Poul Sander 2025-02-03 21:28 1030
        // - Full-form (text only):       if (IsItemHovered(...)) { SetTooltip("Hello"); }
1193b4be Poul Sander 2025-02-03 21:28 1031
        // - Full-form (any contents):    if (IsItemHovered(...) && BeginTooltip()) { Text("Hello"); EndTooltip(); }
1193b4be Poul Sander 2025-02-03 21:28 1032
1193b4be Poul Sander 2025-02-03 21:28 1033
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1034
            "Tooltip are typically created by using a IsItemHovered() + SetTooltip() sequence.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 1035
            "We provide a helper SetItemTooltip() function to perform the two with standards flags.");
1193b4be Poul Sander 2025-02-03 21:28 1036
1193b4be Poul Sander 2025-02-03 21:28 1037
        ImVec2 sz = ImVec2(-FLT_MIN, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 1038
1193b4be Poul Sander 2025-02-03 21:28 1039
        ImGui::Button("Basic", sz);
1193b4be Poul Sander 2025-02-03 21:28 1040
        ImGui::SetItemTooltip("I am a tooltip");
1193b4be Poul Sander 2025-02-03 21:28 1041
1193b4be Poul Sander 2025-02-03 21:28 1042
        ImGui::Button("Fancy", sz);
1193b4be Poul Sander 2025-02-03 21:28 1043
        if (ImGui::BeginItemTooltip())
1193b4be Poul Sander 2025-02-03 21:28 1044
        {
1193b4be Poul Sander 2025-02-03 21:28 1045
            ImGui::Text("I am a fancy tooltip");
1193b4be Poul Sander 2025-02-03 21:28 1046
            static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
1193b4be Poul Sander 2025-02-03 21:28 1047
            ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
1193b4be Poul Sander 2025-02-03 21:28 1048
            ImGui::Text("Sin(time) = %f", sinf((float)ImGui::GetTime()));
1193b4be Poul Sander 2025-02-03 21:28 1049
            ImGui::EndTooltip();
1193b4be Poul Sander 2025-02-03 21:28 1050
        }
1193b4be Poul Sander 2025-02-03 21:28 1051
1193b4be Poul Sander 2025-02-03 21:28 1052
        ImGui::SeparatorText("Always On");
1193b4be Poul Sander 2025-02-03 21:28 1053
1193b4be Poul Sander 2025-02-03 21:28 1054
        // Showcase NOT relying on a IsItemHovered() to emit a tooltip.
1193b4be Poul Sander 2025-02-03 21:28 1055
        // Here the tooltip is always emitted when 'always_on == true'.
1193b4be Poul Sander 2025-02-03 21:28 1056
        static int always_on = 0;
1193b4be Poul Sander 2025-02-03 21:28 1057
        ImGui::RadioButton("Off", &always_on, 0);
1193b4be Poul Sander 2025-02-03 21:28 1058
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1059
        ImGui::RadioButton("Always On (Simple)", &always_on, 1);
1193b4be Poul Sander 2025-02-03 21:28 1060
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1061
        ImGui::RadioButton("Always On (Advanced)", &always_on, 2);
1193b4be Poul Sander 2025-02-03 21:28 1062
        if (always_on == 1)
1193b4be Poul Sander 2025-02-03 21:28 1063
            ImGui::SetTooltip("I am following you around.");
1193b4be Poul Sander 2025-02-03 21:28 1064
        else if (always_on == 2 && ImGui::BeginTooltip())
1193b4be Poul Sander 2025-02-03 21:28 1065
        {
1193b4be Poul Sander 2025-02-03 21:28 1066
            ImGui::ProgressBar(sinf((float)ImGui::GetTime()) * 0.5f + 0.5f, ImVec2(ImGui::GetFontSize() * 25, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 1067
            ImGui::EndTooltip();
1193b4be Poul Sander 2025-02-03 21:28 1068
        }
1193b4be Poul Sander 2025-02-03 21:28 1069
1193b4be Poul Sander 2025-02-03 21:28 1070
        ImGui::SeparatorText("Custom");
1193b4be Poul Sander 2025-02-03 21:28 1071
1193b4be Poul Sander 2025-02-03 21:28 1072
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1073
            "Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() is the preferred way to standardize"
1193b4be Poul Sander 2025-02-03 21:28 1074
            "tooltip activation details across your application. You may however decide to use custom"
1193b4be Poul Sander 2025-02-03 21:28 1075
            "flags for a specific tooltip instance.");
1193b4be Poul Sander 2025-02-03 21:28 1076
1193b4be Poul Sander 2025-02-03 21:28 1077
        // The following examples are passed for documentation purpose but may not be useful to most users.
1193b4be Poul Sander 2025-02-03 21:28 1078
        // Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from
1193b4be Poul Sander 2025-02-03 21:28 1079
        // 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or keyboard/gamepad is being used.
1193b4be Poul Sander 2025-02-03 21:28 1080
        // With default settings, ImGuiHoveredFlags_ForTooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary.
1193b4be Poul Sander 2025-02-03 21:28 1081
        ImGui::Button("Manual", sz);
1193b4be Poul Sander 2025-02-03 21:28 1082
        if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
1193b4be Poul Sander 2025-02-03 21:28 1083
            ImGui::SetTooltip("I am a manually emitted tooltip.");
1193b4be Poul Sander 2025-02-03 21:28 1084
1193b4be Poul Sander 2025-02-03 21:28 1085
        ImGui::Button("DelayNone", sz);
1193b4be Poul Sander 2025-02-03 21:28 1086
        if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNone))
1193b4be Poul Sander 2025-02-03 21:28 1087
            ImGui::SetTooltip("I am a tooltip with no delay.");
1193b4be Poul Sander 2025-02-03 21:28 1088
1193b4be Poul Sander 2025-02-03 21:28 1089
        ImGui::Button("DelayShort", sz);
1193b4be Poul Sander 2025-02-03 21:28 1090
        if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_NoSharedDelay))
1193b4be Poul Sander 2025-02-03 21:28 1091
            ImGui::SetTooltip("I am a tooltip with a short delay (%0.2f sec).", ImGui::GetStyle().HoverDelayShort);
1193b4be Poul Sander 2025-02-03 21:28 1092
1193b4be Poul Sander 2025-02-03 21:28 1093
        ImGui::Button("DelayLong", sz);
1193b4be Poul Sander 2025-02-03 21:28 1094
        if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay))
1193b4be Poul Sander 2025-02-03 21:28 1095
            ImGui::SetTooltip("I am a tooltip with a long delay (%0.2f sec).", ImGui::GetStyle().HoverDelayNormal);
1193b4be Poul Sander 2025-02-03 21:28 1096
1193b4be Poul Sander 2025-02-03 21:28 1097
        ImGui::Button("Stationary", sz);
1193b4be Poul Sander 2025-02-03 21:28 1098
        if (ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary))
1193b4be Poul Sander 2025-02-03 21:28 1099
            ImGui::SetTooltip("I am a tooltip requiring mouse to be stationary before activating.");
1193b4be Poul Sander 2025-02-03 21:28 1100
1193b4be Poul Sander 2025-02-03 21:28 1101
        // Using ImGuiHoveredFlags_ForTooltip will pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav',
1193b4be Poul Sander 2025-02-03 21:28 1102
        // which default value include the ImGuiHoveredFlags_AllowWhenDisabled flag.
1193b4be Poul Sander 2025-02-03 21:28 1103
        ImGui::BeginDisabled();
1193b4be Poul Sander 2025-02-03 21:28 1104
        ImGui::Button("Disabled item", sz);
1193b4be Poul Sander 2025-02-03 21:28 1105
        if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
1193b4be Poul Sander 2025-02-03 21:28 1106
            ImGui::SetTooltip("I am a a tooltip for a disabled item.");
1193b4be Poul Sander 2025-02-03 21:28 1107
        ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 1108
1193b4be Poul Sander 2025-02-03 21:28 1109
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1110
    }
1193b4be Poul Sander 2025-02-03 21:28 1111
1193b4be Poul Sander 2025-02-03 21:28 1112
    // Testing ImGuiOnceUponAFrame helper.
1193b4be Poul Sander 2025-02-03 21:28 1113
    //static ImGuiOnceUponAFrame once;
1193b4be Poul Sander 2025-02-03 21:28 1114
    //for (int i = 0; i < 5; i++)
1193b4be Poul Sander 2025-02-03 21:28 1115
    //    if (once)
1193b4be Poul Sander 2025-02-03 21:28 1116
    //        ImGui::Text("This will be displayed only once.");
1193b4be Poul Sander 2025-02-03 21:28 1117
1193b4be Poul Sander 2025-02-03 21:28 1118
    IMGUI_DEMO_MARKER("Widgets/Tree Nodes");
1193b4be Poul Sander 2025-02-03 21:28 1119
    if (ImGui::TreeNode("Tree Nodes"))
1193b4be Poul Sander 2025-02-03 21:28 1120
    {
1193b4be Poul Sander 2025-02-03 21:28 1121
        IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees");
1193b4be Poul Sander 2025-02-03 21:28 1122
        if (ImGui::TreeNode("Basic trees"))
1193b4be Poul Sander 2025-02-03 21:28 1123
        {
1193b4be Poul Sander 2025-02-03 21:28 1124
            for (int i = 0; i < 5; i++)
1193b4be Poul Sander 2025-02-03 21:28 1125
            {
1193b4be Poul Sander 2025-02-03 21:28 1126
                // Use SetNextItemOpen() so set the default state of a node to be open. We could
1193b4be Poul Sander 2025-02-03 21:28 1127
                // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
1193b4be Poul Sander 2025-02-03 21:28 1128
                if (i == 0)
1193b4be Poul Sander 2025-02-03 21:28 1129
                    ImGui::SetNextItemOpen(true, ImGuiCond_Once);
1193b4be Poul Sander 2025-02-03 21:28 1130
1193b4be Poul Sander 2025-02-03 21:28 1131
                // Here we use PushID() to generate a unique base ID, and then the "" used as TreeNode id won't conflict.
1193b4be Poul Sander 2025-02-03 21:28 1132
                // An alternative to using 'PushID() + TreeNode("", ...)' to generate a unique ID is to use 'TreeNode((void*)(intptr_t)i, ...)',
1193b4be Poul Sander 2025-02-03 21:28 1133
                // aka generate a dummy pointer-sized value to be hashed. The demo below uses that technique. Both are fine.
1193b4be Poul Sander 2025-02-03 21:28 1134
                ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 1135
                if (ImGui::TreeNode("", "Child %d", i))
1193b4be Poul Sander 2025-02-03 21:28 1136
                {
1193b4be Poul Sander 2025-02-03 21:28 1137
                    ImGui::Text("blah blah");
1193b4be Poul Sander 2025-02-03 21:28 1138
                    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1139
                    if (ImGui::SmallButton("button")) {}
1193b4be Poul Sander 2025-02-03 21:28 1140
                    ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1141
                }
1193b4be Poul Sander 2025-02-03 21:28 1142
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 1143
            }
1193b4be Poul Sander 2025-02-03 21:28 1144
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1145
        }
1193b4be Poul Sander 2025-02-03 21:28 1146
1193b4be Poul Sander 2025-02-03 21:28 1147
        IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes");
1193b4be Poul Sander 2025-02-03 21:28 1148
        if (ImGui::TreeNode("Advanced, with Selectable nodes"))
1193b4be Poul Sander 2025-02-03 21:28 1149
        {
1193b4be Poul Sander 2025-02-03 21:28 1150
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1151
                "This is a more typical looking tree with selectable nodes.\n"
1193b4be Poul Sander 2025-02-03 21:28 1152
                "Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
1193b4be Poul Sander 2025-02-03 21:28 1153
            static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
1193b4be Poul Sander 2025-02-03 21:28 1154
            static bool align_label_with_current_x_position = false;
1193b4be Poul Sander 2025-02-03 21:28 1155
            static bool test_drag_and_drop = false;
1193b4be Poul Sander 2025-02-03 21:28 1156
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow",       &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
1193b4be Poul Sander 2025-02-03 21:28 1157
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
1193b4be Poul Sander 2025-02-03 21:28 1158
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth",    &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
1193b4be Poul Sander 2025-02-03 21:28 1159
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth",     &base_flags, ImGuiTreeNodeFlags_SpanFullWidth);
1193b4be Poul Sander 2025-02-03 21:28 1160
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth",     &base_flags, ImGuiTreeNodeFlags_SpanTextWidth); ImGui::SameLine(); HelpMarker("Reduce hit area to the text label and a bit of margin.");
1193b4be Poul Sander 2025-02-03 21:28 1161
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns",    &base_flags, ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker("For use in Tables only.");
1193b4be Poul Sander 2025-02-03 21:28 1162
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_AllowOverlap",      &base_flags, ImGuiTreeNodeFlags_AllowOverlap);
1193b4be Poul Sander 2025-02-03 21:28 1163
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_Framed",            &base_flags, ImGuiTreeNodeFlags_Framed); ImGui::SameLine(); HelpMarker("Draw frame with background (e.g. for CollapsingHeader)");
1193b4be Poul Sander 2025-02-03 21:28 1164
            ImGui::CheckboxFlags("ImGuiTreeNodeFlags_NavLeftJumpsBackHere", &base_flags, ImGuiTreeNodeFlags_NavLeftJumpsBackHere);
1193b4be Poul Sander 2025-02-03 21:28 1165
            ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
1193b4be Poul Sander 2025-02-03 21:28 1166
            ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
1193b4be Poul Sander 2025-02-03 21:28 1167
            ImGui::Text("Hello!");
1193b4be Poul Sander 2025-02-03 21:28 1168
            if (align_label_with_current_x_position)
1193b4be Poul Sander 2025-02-03 21:28 1169
                ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
1193b4be Poul Sander 2025-02-03 21:28 1170
1193b4be Poul Sander 2025-02-03 21:28 1171
            // 'selection_mask' is dumb representation of what may be user-side selection state.
1193b4be Poul Sander 2025-02-03 21:28 1172
            //  You may retain selection state inside or outside your objects in whatever format you see fit.
1193b4be Poul Sander 2025-02-03 21:28 1173
            // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
1193b4be Poul Sander 2025-02-03 21:28 1174
            /// of the loop. May be a pointer to your own node type, etc.
1193b4be Poul Sander 2025-02-03 21:28 1175
            static int selection_mask = (1 << 2);
1193b4be Poul Sander 2025-02-03 21:28 1176
            int node_clicked = -1;
1193b4be Poul Sander 2025-02-03 21:28 1177
            for (int i = 0; i < 6; i++)
1193b4be Poul Sander 2025-02-03 21:28 1178
            {
1193b4be Poul Sander 2025-02-03 21:28 1179
                // Disable the default "open on single-click behavior" + set Selected flag according to our selection.
1193b4be Poul Sander 2025-02-03 21:28 1180
                // To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection.
1193b4be Poul Sander 2025-02-03 21:28 1181
                ImGuiTreeNodeFlags node_flags = base_flags;
1193b4be Poul Sander 2025-02-03 21:28 1182
                const bool is_selected = (selection_mask & (1 << i)) != 0;
1193b4be Poul Sander 2025-02-03 21:28 1183
                if (is_selected)
1193b4be Poul Sander 2025-02-03 21:28 1184
                    node_flags |= ImGuiTreeNodeFlags_Selected;
1193b4be Poul Sander 2025-02-03 21:28 1185
                if (i < 3)
1193b4be Poul Sander 2025-02-03 21:28 1186
                {
1193b4be Poul Sander 2025-02-03 21:28 1187
                    // Items 0..2 are Tree Node
1193b4be Poul Sander 2025-02-03 21:28 1188
                    bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
1193b4be Poul Sander 2025-02-03 21:28 1189
                    if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
1193b4be Poul Sander 2025-02-03 21:28 1190
                        node_clicked = i;
1193b4be Poul Sander 2025-02-03 21:28 1191
                    if (test_drag_and_drop && ImGui::BeginDragDropSource())
1193b4be Poul Sander 2025-02-03 21:28 1192
                    {
1193b4be Poul Sander 2025-02-03 21:28 1193
                        ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
1193b4be Poul Sander 2025-02-03 21:28 1194
                        ImGui::Text("This is a drag and drop source");
1193b4be Poul Sander 2025-02-03 21:28 1195
                        ImGui::EndDragDropSource();
1193b4be Poul Sander 2025-02-03 21:28 1196
                    }
1193b4be Poul Sander 2025-02-03 21:28 1197
                    if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanTextWidth))
1193b4be Poul Sander 2025-02-03 21:28 1198
                    {
1193b4be Poul Sander 2025-02-03 21:28 1199
                        // Item 2 has an additional inline button to help demonstrate SpanTextWidth.
1193b4be Poul Sander 2025-02-03 21:28 1200
                        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1201
                        if (ImGui::SmallButton("button")) {}
1193b4be Poul Sander 2025-02-03 21:28 1202
                    }
1193b4be Poul Sander 2025-02-03 21:28 1203
                    if (node_open)
1193b4be Poul Sander 2025-02-03 21:28 1204
                    {
1193b4be Poul Sander 2025-02-03 21:28 1205
                        ImGui::BulletText("Blah blah\nBlah Blah");
1193b4be Poul Sander 2025-02-03 21:28 1206
                        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1207
                        ImGui::SmallButton("Button");
1193b4be Poul Sander 2025-02-03 21:28 1208
                        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1209
                    }
1193b4be Poul Sander 2025-02-03 21:28 1210
                }
1193b4be Poul Sander 2025-02-03 21:28 1211
                else
1193b4be Poul Sander 2025-02-03 21:28 1212
                {
1193b4be Poul Sander 2025-02-03 21:28 1213
                    // Items 3..5 are Tree Leaves
1193b4be Poul Sander 2025-02-03 21:28 1214
                    // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
1193b4be Poul Sander 2025-02-03 21:28 1215
                    // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
1193b4be Poul Sander 2025-02-03 21:28 1216
                    node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
1193b4be Poul Sander 2025-02-03 21:28 1217
                    ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
1193b4be Poul Sander 2025-02-03 21:28 1218
                    if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
1193b4be Poul Sander 2025-02-03 21:28 1219
                        node_clicked = i;
1193b4be Poul Sander 2025-02-03 21:28 1220
                    if (test_drag_and_drop && ImGui::BeginDragDropSource())
1193b4be Poul Sander 2025-02-03 21:28 1221
                    {
1193b4be Poul Sander 2025-02-03 21:28 1222
                        ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
1193b4be Poul Sander 2025-02-03 21:28 1223
                        ImGui::Text("This is a drag and drop source");
1193b4be Poul Sander 2025-02-03 21:28 1224
                        ImGui::EndDragDropSource();
1193b4be Poul Sander 2025-02-03 21:28 1225
                    }
1193b4be Poul Sander 2025-02-03 21:28 1226
                }
1193b4be Poul Sander 2025-02-03 21:28 1227
            }
1193b4be Poul Sander 2025-02-03 21:28 1228
            if (node_clicked != -1)
1193b4be Poul Sander 2025-02-03 21:28 1229
            {
1193b4be Poul Sander 2025-02-03 21:28 1230
                // Update selection state
1193b4be Poul Sander 2025-02-03 21:28 1231
                // (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
1193b4be Poul Sander 2025-02-03 21:28 1232
                if (ImGui::GetIO().KeyCtrl)
1193b4be Poul Sander 2025-02-03 21:28 1233
                    selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
1193b4be Poul Sander 2025-02-03 21:28 1234
                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
1193b4be Poul Sander 2025-02-03 21:28 1235
                    selection_mask = (1 << node_clicked);           // Click to single-select
1193b4be Poul Sander 2025-02-03 21:28 1236
            }
1193b4be Poul Sander 2025-02-03 21:28 1237
            if (align_label_with_current_x_position)
1193b4be Poul Sander 2025-02-03 21:28 1238
                ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
1193b4be Poul Sander 2025-02-03 21:28 1239
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1240
        }
1193b4be Poul Sander 2025-02-03 21:28 1241
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1242
    }
1193b4be Poul Sander 2025-02-03 21:28 1243
1193b4be Poul Sander 2025-02-03 21:28 1244
    IMGUI_DEMO_MARKER("Widgets/Collapsing Headers");
1193b4be Poul Sander 2025-02-03 21:28 1245
    if (ImGui::TreeNode("Collapsing Headers"))
1193b4be Poul Sander 2025-02-03 21:28 1246
    {
1193b4be Poul Sander 2025-02-03 21:28 1247
        static bool closable_group = true;
1193b4be Poul Sander 2025-02-03 21:28 1248
        ImGui::Checkbox("Show 2nd header", &closable_group);
1193b4be Poul Sander 2025-02-03 21:28 1249
        if (ImGui::CollapsingHeader("Header", ImGuiTreeNodeFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 1250
        {
1193b4be Poul Sander 2025-02-03 21:28 1251
            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
1193b4be Poul Sander 2025-02-03 21:28 1252
            for (int i = 0; i < 5; i++)
1193b4be Poul Sander 2025-02-03 21:28 1253
                ImGui::Text("Some content %d", i);
1193b4be Poul Sander 2025-02-03 21:28 1254
        }
1193b4be Poul Sander 2025-02-03 21:28 1255
        if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
1193b4be Poul Sander 2025-02-03 21:28 1256
        {
1193b4be Poul Sander 2025-02-03 21:28 1257
            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
1193b4be Poul Sander 2025-02-03 21:28 1258
            for (int i = 0; i < 5; i++)
1193b4be Poul Sander 2025-02-03 21:28 1259
                ImGui::Text("More content %d", i);
1193b4be Poul Sander 2025-02-03 21:28 1260
        }
1193b4be Poul Sander 2025-02-03 21:28 1261
        /*
1193b4be Poul Sander 2025-02-03 21:28 1262
        if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet))
1193b4be Poul Sander 2025-02-03 21:28 1263
            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
1193b4be Poul Sander 2025-02-03 21:28 1264
        */
1193b4be Poul Sander 2025-02-03 21:28 1265
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1266
    }
1193b4be Poul Sander 2025-02-03 21:28 1267
1193b4be Poul Sander 2025-02-03 21:28 1268
    IMGUI_DEMO_MARKER("Widgets/Bullets");
1193b4be Poul Sander 2025-02-03 21:28 1269
    if (ImGui::TreeNode("Bullets"))
1193b4be Poul Sander 2025-02-03 21:28 1270
    {
1193b4be Poul Sander 2025-02-03 21:28 1271
        ImGui::BulletText("Bullet point 1");
1193b4be Poul Sander 2025-02-03 21:28 1272
        ImGui::BulletText("Bullet point 2\nOn multiple lines");
1193b4be Poul Sander 2025-02-03 21:28 1273
        if (ImGui::TreeNode("Tree node"))
1193b4be Poul Sander 2025-02-03 21:28 1274
        {
1193b4be Poul Sander 2025-02-03 21:28 1275
            ImGui::BulletText("Another bullet point");
1193b4be Poul Sander 2025-02-03 21:28 1276
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1277
        }
1193b4be Poul Sander 2025-02-03 21:28 1278
        ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
1193b4be Poul Sander 2025-02-03 21:28 1279
        ImGui::Bullet(); ImGui::SmallButton("Button");
1193b4be Poul Sander 2025-02-03 21:28 1280
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1281
    }
1193b4be Poul Sander 2025-02-03 21:28 1282
1193b4be Poul Sander 2025-02-03 21:28 1283
    IMGUI_DEMO_MARKER("Widgets/Text");
1193b4be Poul Sander 2025-02-03 21:28 1284
    if (ImGui::TreeNode("Text"))
1193b4be Poul Sander 2025-02-03 21:28 1285
    {
1193b4be Poul Sander 2025-02-03 21:28 1286
        IMGUI_DEMO_MARKER("Widgets/Text/Colored Text");
1193b4be Poul Sander 2025-02-03 21:28 1287
        if (ImGui::TreeNode("Colorful Text"))
1193b4be Poul Sander 2025-02-03 21:28 1288
        {
1193b4be Poul Sander 2025-02-03 21:28 1289
            // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
1193b4be Poul Sander 2025-02-03 21:28 1290
            ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink");
1193b4be Poul Sander 2025-02-03 21:28 1291
            ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "Yellow");
1193b4be Poul Sander 2025-02-03 21:28 1292
            ImGui::TextDisabled("Disabled");
1193b4be Poul Sander 2025-02-03 21:28 1293
            ImGui::SameLine(); HelpMarker("The TextDisabled color is stored in ImGuiStyle.");
1193b4be Poul Sander 2025-02-03 21:28 1294
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1295
        }
1193b4be Poul Sander 2025-02-03 21:28 1296
1193b4be Poul Sander 2025-02-03 21:28 1297
        IMGUI_DEMO_MARKER("Widgets/Text/Word Wrapping");
1193b4be Poul Sander 2025-02-03 21:28 1298
        if (ImGui::TreeNode("Word Wrapping"))
1193b4be Poul Sander 2025-02-03 21:28 1299
        {
1193b4be Poul Sander 2025-02-03 21:28 1300
            // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
1193b4be Poul Sander 2025-02-03 21:28 1301
            ImGui::TextWrapped(
1193b4be Poul Sander 2025-02-03 21:28 1302
                "This text should automatically wrap on the edge of the window. The current implementation "
1193b4be Poul Sander 2025-02-03 21:28 1303
                "for text wrapping follows simple rules suitable for English and possibly other languages.");
1193b4be Poul Sander 2025-02-03 21:28 1304
            ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 1305
1193b4be Poul Sander 2025-02-03 21:28 1306
            static float wrap_width = 200.0f;
1193b4be Poul Sander 2025-02-03 21:28 1307
            ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 1308
1193b4be Poul Sander 2025-02-03 21:28 1309
            ImDrawList* draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 1310
            for (int n = 0; n < 2; n++)
1193b4be Poul Sander 2025-02-03 21:28 1311
            {
1193b4be Poul Sander 2025-02-03 21:28 1312
                ImGui::Text("Test paragraph %d:", n);
1193b4be Poul Sander 2025-02-03 21:28 1313
                ImVec2 pos = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 1314
                ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y);
1193b4be Poul Sander 2025-02-03 21:28 1315
                ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight());
1193b4be Poul Sander 2025-02-03 21:28 1316
                ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
1193b4be Poul Sander 2025-02-03 21:28 1317
                if (n == 0)
1193b4be Poul Sander 2025-02-03 21:28 1318
                    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);
1193b4be Poul Sander 2025-02-03 21:28 1319
                else
1193b4be Poul Sander 2025-02-03 21:28 1320
                    ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
1193b4be Poul Sander 2025-02-03 21:28 1321
1193b4be Poul Sander 2025-02-03 21:28 1322
                // Draw actual text bounding box, following by marker of our expected limit (should not overlap!)
1193b4be Poul Sander 2025-02-03 21:28 1323
                draw_list->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
1193b4be Poul Sander 2025-02-03 21:28 1324
                draw_list->AddRectFilled(marker_min, marker_max, IM_COL32(255, 0, 255, 255));
1193b4be Poul Sander 2025-02-03 21:28 1325
                ImGui::PopTextWrapPos();
1193b4be Poul Sander 2025-02-03 21:28 1326
            }
1193b4be Poul Sander 2025-02-03 21:28 1327
1193b4be Poul Sander 2025-02-03 21:28 1328
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1329
        }
1193b4be Poul Sander 2025-02-03 21:28 1330
1193b4be Poul Sander 2025-02-03 21:28 1331
        IMGUI_DEMO_MARKER("Widgets/Text/UTF-8 Text");
1193b4be Poul Sander 2025-02-03 21:28 1332
        if (ImGui::TreeNode("UTF-8 Text"))
1193b4be Poul Sander 2025-02-03 21:28 1333
        {
1193b4be Poul Sander 2025-02-03 21:28 1334
            // UTF-8 test with Japanese characters
1193b4be Poul Sander 2025-02-03 21:28 1335
            // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
1193b4be Poul Sander 2025-02-03 21:28 1336
            // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
1193b4be Poul Sander 2025-02-03 21:28 1337
            // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
1193b4be Poul Sander 2025-02-03 21:28 1338
            //   can save your source files as 'UTF-8 without signature').
1193b4be Poul Sander 2025-02-03 21:28 1339
            // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8
1193b4be Poul Sander 2025-02-03 21:28 1340
            //   CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants.
1193b4be Poul Sander 2025-02-03 21:28 1341
            //   Don't do this in your application! Please use u8"text in any language" in your application!
1193b4be Poul Sander 2025-02-03 21:28 1342
            // Note that characters values are preserved even by InputText() if the font cannot be displayed,
1193b4be Poul Sander 2025-02-03 21:28 1343
            // so you can safely copy & paste garbled characters into another application.
1193b4be Poul Sander 2025-02-03 21:28 1344
            ImGui::TextWrapped(
1193b4be Poul Sander 2025-02-03 21:28 1345
                "CJK text will only appear if the font was loaded with the appropriate CJK character ranges. "
1193b4be Poul Sander 2025-02-03 21:28 1346
                "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. "
1193b4be Poul Sander 2025-02-03 21:28 1347
                "Read docs/FONTS.md for details.");
1193b4be Poul Sander 2025-02-03 21:28 1348
            ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)");
1193b4be Poul Sander 2025-02-03 21:28 1349
            ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
1193b4be Poul Sander 2025-02-03 21:28 1350
            static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
1193b4be Poul Sander 2025-02-03 21:28 1351
            //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
1193b4be Poul Sander 2025-02-03 21:28 1352
            ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 1353
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1354
        }
1193b4be Poul Sander 2025-02-03 21:28 1355
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1356
    }
1193b4be Poul Sander 2025-02-03 21:28 1357
1193b4be Poul Sander 2025-02-03 21:28 1358
    IMGUI_DEMO_MARKER("Widgets/Images");
1193b4be Poul Sander 2025-02-03 21:28 1359
    if (ImGui::TreeNode("Images"))
1193b4be Poul Sander 2025-02-03 21:28 1360
    {
1193b4be Poul Sander 2025-02-03 21:28 1361
        ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 1362
        ImGui::TextWrapped(
1193b4be Poul Sander 2025-02-03 21:28 1363
            "Below we are displaying the font texture (which is the only texture we have access to in this demo). "
1193b4be Poul Sander 2025-02-03 21:28 1364
            "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. "
1193b4be Poul Sander 2025-02-03 21:28 1365
            "Hover the texture for a zoomed view!");
1193b4be Poul Sander 2025-02-03 21:28 1366
1193b4be Poul Sander 2025-02-03 21:28 1367
        // Below we are displaying the font texture because it is the only texture we have access to inside the demo!
1193b4be Poul Sander 2025-02-03 21:28 1368
        // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that
1193b4be Poul Sander 2025-02-03 21:28 1369
        // will be passed to the rendering backend via the ImDrawCmd structure.
1193b4be Poul Sander 2025-02-03 21:28 1370
        // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top
1193b4be Poul Sander 2025-02-03 21:28 1371
        // of their respective source file to specify what they expect to be stored in ImTextureID, for example:
1193b4be Poul Sander 2025-02-03 21:28 1372
        // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer
1193b4be Poul Sander 2025-02-03 21:28 1373
        // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc.
1193b4be Poul Sander 2025-02-03 21:28 1374
        // More:
1193b4be Poul Sander 2025-02-03 21:28 1375
        // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers
1193b4be Poul Sander 2025-02-03 21:28 1376
        //   to ImGui::Image(), and gather width/height through your own functions, etc.
1193b4be Poul Sander 2025-02-03 21:28 1377
        // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer,
1193b4be Poul Sander 2025-02-03 21:28 1378
        //   it will help you debug issues if you are confused about it.
1193b4be Poul Sander 2025-02-03 21:28 1379
        // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
1193b4be Poul Sander 2025-02-03 21:28 1380
        // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
1193b4be Poul Sander 2025-02-03 21:28 1381
        // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
1193b4be Poul Sander 2025-02-03 21:28 1382
        ImTextureID my_tex_id = io.Fonts->TexID;
1193b4be Poul Sander 2025-02-03 21:28 1383
        float my_tex_w = (float)io.Fonts->TexWidth;
1193b4be Poul Sander 2025-02-03 21:28 1384
        float my_tex_h = (float)io.Fonts->TexHeight;
1193b4be Poul Sander 2025-02-03 21:28 1385
        {
1193b4be Poul Sander 2025-02-03 21:28 1386
            static bool use_text_color_for_tint = false;
1193b4be Poul Sander 2025-02-03 21:28 1387
            ImGui::Checkbox("Use Text Color for Tint", &use_text_color_for_tint);
1193b4be Poul Sander 2025-02-03 21:28 1388
            ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
1193b4be Poul Sander 2025-02-03 21:28 1389
            ImVec2 pos = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 1390
            ImVec2 uv_min = ImVec2(0.0f, 0.0f);                 // Top-left
1193b4be Poul Sander 2025-02-03 21:28 1391
            ImVec2 uv_max = ImVec2(1.0f, 1.0f);                 // Lower-right
1193b4be Poul Sander 2025-02-03 21:28 1392
            ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
1193b4be Poul Sander 2025-02-03 21:28 1393
            ImVec4 border_col = ImGui::GetStyleColorVec4(ImGuiCol_Border);
1193b4be Poul Sander 2025-02-03 21:28 1394
            ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, tint_col, border_col);
1193b4be Poul Sander 2025-02-03 21:28 1395
            if (ImGui::BeginItemTooltip())
1193b4be Poul Sander 2025-02-03 21:28 1396
            {
1193b4be Poul Sander 2025-02-03 21:28 1397
                float region_sz = 32.0f;
1193b4be Poul Sander 2025-02-03 21:28 1398
                float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
1193b4be Poul Sander 2025-02-03 21:28 1399
                float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
1193b4be Poul Sander 2025-02-03 21:28 1400
                float zoom = 4.0f;
1193b4be Poul Sander 2025-02-03 21:28 1401
                if (region_x < 0.0f) { region_x = 0.0f; }
1193b4be Poul Sander 2025-02-03 21:28 1402
                else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
1193b4be Poul Sander 2025-02-03 21:28 1403
                if (region_y < 0.0f) { region_y = 0.0f; }
1193b4be Poul Sander 2025-02-03 21:28 1404
                else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
1193b4be Poul Sander 2025-02-03 21:28 1405
                ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
1193b4be Poul Sander 2025-02-03 21:28 1406
                ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
1193b4be Poul Sander 2025-02-03 21:28 1407
                ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
1193b4be Poul Sander 2025-02-03 21:28 1408
                ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
1193b4be Poul Sander 2025-02-03 21:28 1409
                ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col);
1193b4be Poul Sander 2025-02-03 21:28 1410
                ImGui::EndTooltip();
1193b4be Poul Sander 2025-02-03 21:28 1411
            }
1193b4be Poul Sander 2025-02-03 21:28 1412
        }
1193b4be Poul Sander 2025-02-03 21:28 1413
1193b4be Poul Sander 2025-02-03 21:28 1414
        IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons");
1193b4be Poul Sander 2025-02-03 21:28 1415
        ImGui::TextWrapped("And now some textured buttons..");
1193b4be Poul Sander 2025-02-03 21:28 1416
        static int pressed_count = 0;
1193b4be Poul Sander 2025-02-03 21:28 1417
        for (int i = 0; i < 8; i++)
1193b4be Poul Sander 2025-02-03 21:28 1418
        {
1193b4be Poul Sander 2025-02-03 21:28 1419
            // UV coordinates are often (0.0f, 0.0f) and (1.0f, 1.0f) to display an entire textures.
1193b4be Poul Sander 2025-02-03 21:28 1420
            // Here are trying to display only a 32x32 pixels area of the texture, hence the UV computation.
1193b4be Poul Sander 2025-02-03 21:28 1421
            // Read about UV coordinates here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
1193b4be Poul Sander 2025-02-03 21:28 1422
            ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 1423
            if (i > 0)
1193b4be Poul Sander 2025-02-03 21:28 1424
                ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(i - 1.0f, i - 1.0f));
1193b4be Poul Sander 2025-02-03 21:28 1425
            ImVec2 size = ImVec2(32.0f, 32.0f);                         // Size of the image we want to make visible
1193b4be Poul Sander 2025-02-03 21:28 1426
            ImVec2 uv0 = ImVec2(0.0f, 0.0f);                            // UV coordinates for lower-left
1193b4be Poul Sander 2025-02-03 21:28 1427
            ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h);    // UV coordinates for (32,32) in our texture
1193b4be Poul Sander 2025-02-03 21:28 1428
            ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);             // Black background
1193b4be Poul Sander 2025-02-03 21:28 1429
            ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);           // No tint
1193b4be Poul Sander 2025-02-03 21:28 1430
            if (ImGui::ImageButton("", my_tex_id, size, uv0, uv1, bg_col, tint_col))
1193b4be Poul Sander 2025-02-03 21:28 1431
                pressed_count += 1;
1193b4be Poul Sander 2025-02-03 21:28 1432
            if (i > 0)
1193b4be Poul Sander 2025-02-03 21:28 1433
                ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 1434
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 1435
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1436
        }
1193b4be Poul Sander 2025-02-03 21:28 1437
        ImGui::NewLine();
1193b4be Poul Sander 2025-02-03 21:28 1438
        ImGui::Text("Pressed %d times.", pressed_count);
1193b4be Poul Sander 2025-02-03 21:28 1439
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1440
    }
1193b4be Poul Sander 2025-02-03 21:28 1441
1193b4be Poul Sander 2025-02-03 21:28 1442
    IMGUI_DEMO_MARKER("Widgets/Combo");
1193b4be Poul Sander 2025-02-03 21:28 1443
    if (ImGui::TreeNode("Combo"))
1193b4be Poul Sander 2025-02-03 21:28 1444
    {
1193b4be Poul Sander 2025-02-03 21:28 1445
        // Combo Boxes are also called "Dropdown" in other systems
1193b4be Poul Sander 2025-02-03 21:28 1446
        // Expose flags as checkbox for the demo
1193b4be Poul Sander 2025-02-03 21:28 1447
        static ImGuiComboFlags flags = 0;
1193b4be Poul Sander 2025-02-03 21:28 1448
        ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", &flags, ImGuiComboFlags_PopupAlignLeft);
1193b4be Poul Sander 2025-02-03 21:28 1449
        ImGui::SameLine(); HelpMarker("Only makes a difference if the popup is larger than the combo");
1193b4be Poul Sander 2025-02-03 21:28 1450
        if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", &flags, ImGuiComboFlags_NoArrowButton))
1193b4be Poul Sander 2025-02-03 21:28 1451
            flags &= ~ImGuiComboFlags_NoPreview;     // Clear incompatible flags
1193b4be Poul Sander 2025-02-03 21:28 1452
        if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", &flags, ImGuiComboFlags_NoPreview))
1193b4be Poul Sander 2025-02-03 21:28 1453
            flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear incompatible flags
1193b4be Poul Sander 2025-02-03 21:28 1454
        if (ImGui::CheckboxFlags("ImGuiComboFlags_WidthFitPreview", &flags, ImGuiComboFlags_WidthFitPreview))
1193b4be Poul Sander 2025-02-03 21:28 1455
            flags &= ~ImGuiComboFlags_NoPreview;
1193b4be Poul Sander 2025-02-03 21:28 1456
1193b4be Poul Sander 2025-02-03 21:28 1457
        // Override default popup height
1193b4be Poul Sander 2025-02-03 21:28 1458
        if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightSmall", &flags, ImGuiComboFlags_HeightSmall))
1193b4be Poul Sander 2025-02-03 21:28 1459
            flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightSmall);
1193b4be Poul Sander 2025-02-03 21:28 1460
        if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightRegular", &flags, ImGuiComboFlags_HeightRegular))
1193b4be Poul Sander 2025-02-03 21:28 1461
            flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightRegular);
1193b4be Poul Sander 2025-02-03 21:28 1462
        if (ImGui::CheckboxFlags("ImGuiComboFlags_HeightLargest", &flags, ImGuiComboFlags_HeightLargest))
1193b4be Poul Sander 2025-02-03 21:28 1463
            flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightLargest);
1193b4be Poul Sander 2025-02-03 21:28 1464
1193b4be Poul Sander 2025-02-03 21:28 1465
        // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
1193b4be Poul Sander 2025-02-03 21:28 1466
        // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
1193b4be Poul Sander 2025-02-03 21:28 1467
        // stored in the object itself, etc.)
1193b4be Poul Sander 2025-02-03 21:28 1468
        const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
1193b4be Poul Sander 2025-02-03 21:28 1469
        static int item_selected_idx = 0; // Here we store our selection data as an index.
1193b4be Poul Sander 2025-02-03 21:28 1470
1193b4be Poul Sander 2025-02-03 21:28 1471
        // Pass in the preview value visible before opening the combo (it could technically be different contents or not pulled from items[])
1193b4be Poul Sander 2025-02-03 21:28 1472
        const char* combo_preview_value = items[item_selected_idx];
1193b4be Poul Sander 2025-02-03 21:28 1473
1193b4be Poul Sander 2025-02-03 21:28 1474
        if (ImGui::BeginCombo("combo 1", combo_preview_value, flags))
1193b4be Poul Sander 2025-02-03 21:28 1475
        {
1193b4be Poul Sander 2025-02-03 21:28 1476
            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1193b4be Poul Sander 2025-02-03 21:28 1477
            {
1193b4be Poul Sander 2025-02-03 21:28 1478
                const bool is_selected = (item_selected_idx == n);
1193b4be Poul Sander 2025-02-03 21:28 1479
                if (ImGui::Selectable(items[n], is_selected))
1193b4be Poul Sander 2025-02-03 21:28 1480
                    item_selected_idx = n;
1193b4be Poul Sander 2025-02-03 21:28 1481
1193b4be Poul Sander 2025-02-03 21:28 1482
                // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1193b4be Poul Sander 2025-02-03 21:28 1483
                if (is_selected)
1193b4be Poul Sander 2025-02-03 21:28 1484
                    ImGui::SetItemDefaultFocus();
1193b4be Poul Sander 2025-02-03 21:28 1485
            }
1193b4be Poul Sander 2025-02-03 21:28 1486
            ImGui::EndCombo();
1193b4be Poul Sander 2025-02-03 21:28 1487
        }
1193b4be Poul Sander 2025-02-03 21:28 1488
1193b4be Poul Sander 2025-02-03 21:28 1489
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 1490
        ImGui::SeparatorText("One-liner variants");
1193b4be Poul Sander 2025-02-03 21:28 1491
        HelpMarker("Flags above don't apply to this section.");
1193b4be Poul Sander 2025-02-03 21:28 1492
1193b4be Poul Sander 2025-02-03 21:28 1493
        // Simplified one-liner Combo() API, using values packed in a single constant string
1193b4be Poul Sander 2025-02-03 21:28 1494
        // This is a convenience for when the selection set is small and known at compile-time.
1193b4be Poul Sander 2025-02-03 21:28 1495
        static int item_current_2 = 0;
1193b4be Poul Sander 2025-02-03 21:28 1496
        ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
1193b4be Poul Sander 2025-02-03 21:28 1497
1193b4be Poul Sander 2025-02-03 21:28 1498
        // Simplified one-liner Combo() using an array of const char*
1193b4be Poul Sander 2025-02-03 21:28 1499
        // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control.
1193b4be Poul Sander 2025-02-03 21:28 1500
        static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
1193b4be Poul Sander 2025-02-03 21:28 1501
        ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
1193b4be Poul Sander 2025-02-03 21:28 1502
1193b4be Poul Sander 2025-02-03 21:28 1503
        // Simplified one-liner Combo() using an accessor function
1193b4be Poul Sander 2025-02-03 21:28 1504
        static int item_current_4 = 0;
1193b4be Poul Sander 2025-02-03 21:28 1505
        ImGui::Combo("combo 4 (function)", &item_current_4, [](void* data, int n) { return ((const char**)data)[n]; }, items, IM_ARRAYSIZE(items));
1193b4be Poul Sander 2025-02-03 21:28 1506
1193b4be Poul Sander 2025-02-03 21:28 1507
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1508
    }
1193b4be Poul Sander 2025-02-03 21:28 1509
1193b4be Poul Sander 2025-02-03 21:28 1510
    IMGUI_DEMO_MARKER("Widgets/List Boxes");
1193b4be Poul Sander 2025-02-03 21:28 1511
    if (ImGui::TreeNode("List boxes"))
1193b4be Poul Sander 2025-02-03 21:28 1512
    {
1193b4be Poul Sander 2025-02-03 21:28 1513
        // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild()
1193b4be Poul Sander 2025-02-03 21:28 1514
        // using the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
1193b4be Poul Sander 2025-02-03 21:28 1515
        // You may be tempted to simply use BeginChild() directly. However note that BeginChild() requires EndChild()
1193b4be Poul Sander 2025-02-03 21:28 1516
        // to always be called (inconsistent with BeginListBox()/EndListBox()).
1193b4be Poul Sander 2025-02-03 21:28 1517
1193b4be Poul Sander 2025-02-03 21:28 1518
        // Using the generic BeginListBox() API, you have full control over how to display the combo contents.
1193b4be Poul Sander 2025-02-03 21:28 1519
        // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
1193b4be Poul Sander 2025-02-03 21:28 1520
        // stored in the object itself, etc.)
1193b4be Poul Sander 2025-02-03 21:28 1521
        const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
1193b4be Poul Sander 2025-02-03 21:28 1522
        static int item_selected_idx = 0; // Here we store our selected data as an index.
1193b4be Poul Sander 2025-02-03 21:28 1523
1193b4be Poul Sander 2025-02-03 21:28 1524
        static bool item_highlight = false;
1193b4be Poul Sander 2025-02-03 21:28 1525
        int item_highlighted_idx = -1; // Here we store our highlighted data as an index.
1193b4be Poul Sander 2025-02-03 21:28 1526
        ImGui::Checkbox("Highlight hovered item in second listbox", &item_highlight);
1193b4be Poul Sander 2025-02-03 21:28 1527
1193b4be Poul Sander 2025-02-03 21:28 1528
        if (ImGui::BeginListBox("listbox 1"))
1193b4be Poul Sander 2025-02-03 21:28 1529
        {
1193b4be Poul Sander 2025-02-03 21:28 1530
            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1193b4be Poul Sander 2025-02-03 21:28 1531
            {
1193b4be Poul Sander 2025-02-03 21:28 1532
                const bool is_selected = (item_selected_idx == n);
1193b4be Poul Sander 2025-02-03 21:28 1533
                if (ImGui::Selectable(items[n], is_selected))
1193b4be Poul Sander 2025-02-03 21:28 1534
                    item_selected_idx = n;
1193b4be Poul Sander 2025-02-03 21:28 1535
1193b4be Poul Sander 2025-02-03 21:28 1536
                if (item_highlight && ImGui::IsItemHovered())
1193b4be Poul Sander 2025-02-03 21:28 1537
                    item_highlighted_idx = n;
1193b4be Poul Sander 2025-02-03 21:28 1538
1193b4be Poul Sander 2025-02-03 21:28 1539
                // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1193b4be Poul Sander 2025-02-03 21:28 1540
                if (is_selected)
1193b4be Poul Sander 2025-02-03 21:28 1541
                    ImGui::SetItemDefaultFocus();
1193b4be Poul Sander 2025-02-03 21:28 1542
            }
1193b4be Poul Sander 2025-02-03 21:28 1543
            ImGui::EndListBox();
1193b4be Poul Sander 2025-02-03 21:28 1544
        }
1193b4be Poul Sander 2025-02-03 21:28 1545
        ImGui::SameLine(); HelpMarker("Here we are sharing selection state between both boxes.");
1193b4be Poul Sander 2025-02-03 21:28 1546
1193b4be Poul Sander 2025-02-03 21:28 1547
        // Custom size: use all width, 5 items tall
1193b4be Poul Sander 2025-02-03 21:28 1548
        ImGui::Text("Full-width:");
1193b4be Poul Sander 2025-02-03 21:28 1549
        if (ImGui::BeginListBox("##listbox 2", ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing())))
1193b4be Poul Sander 2025-02-03 21:28 1550
        {
1193b4be Poul Sander 2025-02-03 21:28 1551
            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1193b4be Poul Sander 2025-02-03 21:28 1552
            {
1193b4be Poul Sander 2025-02-03 21:28 1553
                bool is_selected = (item_selected_idx == n);
1193b4be Poul Sander 2025-02-03 21:28 1554
                ImGuiSelectableFlags flags = (item_highlighted_idx == n) ? ImGuiSelectableFlags_Highlight : 0;
1193b4be Poul Sander 2025-02-03 21:28 1555
                if (ImGui::Selectable(items[n], is_selected, flags))
1193b4be Poul Sander 2025-02-03 21:28 1556
                    item_selected_idx = n;
1193b4be Poul Sander 2025-02-03 21:28 1557
1193b4be Poul Sander 2025-02-03 21:28 1558
                // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1193b4be Poul Sander 2025-02-03 21:28 1559
                if (is_selected)
1193b4be Poul Sander 2025-02-03 21:28 1560
                    ImGui::SetItemDefaultFocus();
1193b4be Poul Sander 2025-02-03 21:28 1561
            }
1193b4be Poul Sander 2025-02-03 21:28 1562
            ImGui::EndListBox();
1193b4be Poul Sander 2025-02-03 21:28 1563
        }
1193b4be Poul Sander 2025-02-03 21:28 1564
1193b4be Poul Sander 2025-02-03 21:28 1565
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1566
    }
1193b4be Poul Sander 2025-02-03 21:28 1567
1193b4be Poul Sander 2025-02-03 21:28 1568
    IMGUI_DEMO_MARKER("Widgets/Selectables");
1193b4be Poul Sander 2025-02-03 21:28 1569
    //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
1193b4be Poul Sander 2025-02-03 21:28 1570
    if (ImGui::TreeNode("Selectables"))
1193b4be Poul Sander 2025-02-03 21:28 1571
    {
1193b4be Poul Sander 2025-02-03 21:28 1572
        // Selectable() has 2 overloads:
1193b4be Poul Sander 2025-02-03 21:28 1573
        // - The one taking "bool selected" as a read-only selection information.
1193b4be Poul Sander 2025-02-03 21:28 1574
        //   When Selectable() has been clicked it returns true and you can alter selection state accordingly.
1193b4be Poul Sander 2025-02-03 21:28 1575
        // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
1193b4be Poul Sander 2025-02-03 21:28 1576
        // The earlier is more flexible, as in real application your selection may be stored in many different ways
1193b4be Poul Sander 2025-02-03 21:28 1577
        // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc).
1193b4be Poul Sander 2025-02-03 21:28 1578
        IMGUI_DEMO_MARKER("Widgets/Selectables/Basic");
1193b4be Poul Sander 2025-02-03 21:28 1579
        if (ImGui::TreeNode("Basic"))
1193b4be Poul Sander 2025-02-03 21:28 1580
        {
1193b4be Poul Sander 2025-02-03 21:28 1581
            static bool selection[5] = { false, true, false, false };
1193b4be Poul Sander 2025-02-03 21:28 1582
            ImGui::Selectable("1. I am selectable", &selection[0]);
1193b4be Poul Sander 2025-02-03 21:28 1583
            ImGui::Selectable("2. I am selectable", &selection[1]);
1193b4be Poul Sander 2025-02-03 21:28 1584
            ImGui::Selectable("3. I am selectable", &selection[2]);
1193b4be Poul Sander 2025-02-03 21:28 1585
            if (ImGui::Selectable("4. I am double clickable", selection[3], ImGuiSelectableFlags_AllowDoubleClick))
1193b4be Poul Sander 2025-02-03 21:28 1586
                if (ImGui::IsMouseDoubleClicked(0))
1193b4be Poul Sander 2025-02-03 21:28 1587
                    selection[3] = !selection[3];
1193b4be Poul Sander 2025-02-03 21:28 1588
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1589
        }
1193b4be Poul Sander 2025-02-03 21:28 1590
1193b4be Poul Sander 2025-02-03 21:28 1591
        IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more items on the same line");
1193b4be Poul Sander 2025-02-03 21:28 1592
        if (ImGui::TreeNode("Rendering more items on the same line"))
1193b4be Poul Sander 2025-02-03 21:28 1593
        {
1193b4be Poul Sander 2025-02-03 21:28 1594
            // (1) Using SetNextItemAllowOverlap()
1193b4be Poul Sander 2025-02-03 21:28 1595
            // (2) Using the Selectable() override that takes "bool* p_selected" parameter, the bool value is toggled automatically.
1193b4be Poul Sander 2025-02-03 21:28 1596
            static bool selected[3] = { false, false, false };
1193b4be Poul Sander 2025-02-03 21:28 1597
            ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("main.c",    &selected[0]); ImGui::SameLine(); ImGui::SmallButton("Link 1");
1193b4be Poul Sander 2025-02-03 21:28 1598
            ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(); ImGui::SmallButton("Link 2");
1193b4be Poul Sander 2025-02-03 21:28 1599
            ImGui::SetNextItemAllowOverlap(); ImGui::Selectable("Hello.h",   &selected[2]); ImGui::SameLine(); ImGui::SmallButton("Link 3");
1193b4be Poul Sander 2025-02-03 21:28 1600
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1601
        }
1193b4be Poul Sander 2025-02-03 21:28 1602
1193b4be Poul Sander 2025-02-03 21:28 1603
        IMGUI_DEMO_MARKER("Widgets/Selectables/In Tables");
1193b4be Poul Sander 2025-02-03 21:28 1604
        if (ImGui::TreeNode("In Tables"))
1193b4be Poul Sander 2025-02-03 21:28 1605
        {
1193b4be Poul Sander 2025-02-03 21:28 1606
            static bool selected[10] = {};
1193b4be Poul Sander 2025-02-03 21:28 1607
1193b4be Poul Sander 2025-02-03 21:28 1608
            if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
1193b4be Poul Sander 2025-02-03 21:28 1609
            {
1193b4be Poul Sander 2025-02-03 21:28 1610
                for (int i = 0; i < 10; i++)
1193b4be Poul Sander 2025-02-03 21:28 1611
                {
1193b4be Poul Sander 2025-02-03 21:28 1612
                    char label[32];
1193b4be Poul Sander 2025-02-03 21:28 1613
                    sprintf(label, "Item %d", i);
1193b4be Poul Sander 2025-02-03 21:28 1614
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 1615
                    ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap
1193b4be Poul Sander 2025-02-03 21:28 1616
                }
1193b4be Poul Sander 2025-02-03 21:28 1617
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 1618
            }
1193b4be Poul Sander 2025-02-03 21:28 1619
            ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 1620
            if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
1193b4be Poul Sander 2025-02-03 21:28 1621
            {
1193b4be Poul Sander 2025-02-03 21:28 1622
                for (int i = 0; i < 10; i++)
1193b4be Poul Sander 2025-02-03 21:28 1623
                {
1193b4be Poul Sander 2025-02-03 21:28 1624
                    char label[32];
1193b4be Poul Sander 2025-02-03 21:28 1625
                    sprintf(label, "Item %d", i);
1193b4be Poul Sander 2025-02-03 21:28 1626
                    ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 1627
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 1628
                    ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns);
1193b4be Poul Sander 2025-02-03 21:28 1629
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 1630
                    ImGui::Text("Some other contents");
1193b4be Poul Sander 2025-02-03 21:28 1631
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 1632
                    ImGui::Text("123456");
1193b4be Poul Sander 2025-02-03 21:28 1633
                }
1193b4be Poul Sander 2025-02-03 21:28 1634
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 1635
            }
1193b4be Poul Sander 2025-02-03 21:28 1636
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1637
        }
1193b4be Poul Sander 2025-02-03 21:28 1638
1193b4be Poul Sander 2025-02-03 21:28 1639
        IMGUI_DEMO_MARKER("Widgets/Selectables/Grid");
1193b4be Poul Sander 2025-02-03 21:28 1640
        if (ImGui::TreeNode("Grid"))
1193b4be Poul Sander 2025-02-03 21:28 1641
        {
1193b4be Poul Sander 2025-02-03 21:28 1642
            static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
1193b4be Poul Sander 2025-02-03 21:28 1643
1193b4be Poul Sander 2025-02-03 21:28 1644
            // Add in a bit of silly fun...
1193b4be Poul Sander 2025-02-03 21:28 1645
            const float time = (float)ImGui::GetTime();
1193b4be Poul Sander 2025-02-03 21:28 1646
            const bool winning_state = memchr(selected, 0, sizeof(selected)) == NULL; // If all cells are selected...
1193b4be Poul Sander 2025-02-03 21:28 1647
            if (winning_state)
1193b4be Poul Sander 2025-02-03 21:28 1648
                ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f + 0.5f * cosf(time * 2.0f), 0.5f + 0.5f * sinf(time * 3.0f)));
1193b4be Poul Sander 2025-02-03 21:28 1649
1193b4be Poul Sander 2025-02-03 21:28 1650
            for (int y = 0; y < 4; y++)
1193b4be Poul Sander 2025-02-03 21:28 1651
                for (int x = 0; x < 4; x++)
1193b4be Poul Sander 2025-02-03 21:28 1652
                {
1193b4be Poul Sander 2025-02-03 21:28 1653
                    if (x > 0)
1193b4be Poul Sander 2025-02-03 21:28 1654
                        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1655
                    ImGui::PushID(y * 4 + x);
1193b4be Poul Sander 2025-02-03 21:28 1656
                    if (ImGui::Selectable("Sailor", selected[y][x] != 0, 0, ImVec2(50, 50)))
1193b4be Poul Sander 2025-02-03 21:28 1657
                    {
1193b4be Poul Sander 2025-02-03 21:28 1658
                        // Toggle clicked cell + toggle neighbors
1193b4be Poul Sander 2025-02-03 21:28 1659
                        selected[y][x] ^= 1;
1193b4be Poul Sander 2025-02-03 21:28 1660
                        if (x > 0) { selected[y][x - 1] ^= 1; }
1193b4be Poul Sander 2025-02-03 21:28 1661
                        if (x < 3) { selected[y][x + 1] ^= 1; }
1193b4be Poul Sander 2025-02-03 21:28 1662
                        if (y > 0) { selected[y - 1][x] ^= 1; }
1193b4be Poul Sander 2025-02-03 21:28 1663
                        if (y < 3) { selected[y + 1][x] ^= 1; }
1193b4be Poul Sander 2025-02-03 21:28 1664
                    }
1193b4be Poul Sander 2025-02-03 21:28 1665
                    ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 1666
                }
1193b4be Poul Sander 2025-02-03 21:28 1667
1193b4be Poul Sander 2025-02-03 21:28 1668
            if (winning_state)
1193b4be Poul Sander 2025-02-03 21:28 1669
                ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 1670
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1671
        }
1193b4be Poul Sander 2025-02-03 21:28 1672
        IMGUI_DEMO_MARKER("Widgets/Selectables/Alignment");
1193b4be Poul Sander 2025-02-03 21:28 1673
        if (ImGui::TreeNode("Alignment"))
1193b4be Poul Sander 2025-02-03 21:28 1674
        {
1193b4be Poul Sander 2025-02-03 21:28 1675
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1676
                "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item "
1193b4be Poul Sander 2025-02-03 21:28 1677
                "basis using PushStyleVar(). You'll probably want to always keep your default situation to "
1193b4be Poul Sander 2025-02-03 21:28 1678
                "left-align otherwise it becomes difficult to layout multiple items on a same line");
1193b4be Poul Sander 2025-02-03 21:28 1679
            static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true };
1193b4be Poul Sander 2025-02-03 21:28 1680
            for (int y = 0; y < 3; y++)
1193b4be Poul Sander 2025-02-03 21:28 1681
            {
1193b4be Poul Sander 2025-02-03 21:28 1682
                for (int x = 0; x < 3; x++)
1193b4be Poul Sander 2025-02-03 21:28 1683
                {
1193b4be Poul Sander 2025-02-03 21:28 1684
                    ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
1193b4be Poul Sander 2025-02-03 21:28 1685
                    char name[32];
1193b4be Poul Sander 2025-02-03 21:28 1686
                    sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
1193b4be Poul Sander 2025-02-03 21:28 1687
                    if (x > 0) ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1688
                    ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
1193b4be Poul Sander 2025-02-03 21:28 1689
                    ImGui::Selectable(name, &selected[3 * y + x], ImGuiSelectableFlags_None, ImVec2(80, 80));
1193b4be Poul Sander 2025-02-03 21:28 1690
                    ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 1691
                }
1193b4be Poul Sander 2025-02-03 21:28 1692
            }
1193b4be Poul Sander 2025-02-03 21:28 1693
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1694
        }
1193b4be Poul Sander 2025-02-03 21:28 1695
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1696
    }
1193b4be Poul Sander 2025-02-03 21:28 1697
1193b4be Poul Sander 2025-02-03 21:28 1698
    ShowDemoWindowMultiSelect(demo_data);
1193b4be Poul Sander 2025-02-03 21:28 1699
1193b4be Poul Sander 2025-02-03 21:28 1700
    // To wire InputText() with std::string or any other custom string type,
1193b4be Poul Sander 2025-02-03 21:28 1701
    // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
1193b4be Poul Sander 2025-02-03 21:28 1702
    IMGUI_DEMO_MARKER("Widgets/Text Input");
1193b4be Poul Sander 2025-02-03 21:28 1703
    if (ImGui::TreeNode("Text Input"))
1193b4be Poul Sander 2025-02-03 21:28 1704
    {
1193b4be Poul Sander 2025-02-03 21:28 1705
        IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input");
1193b4be Poul Sander 2025-02-03 21:28 1706
        if (ImGui::TreeNode("Multi-line Text Input"))
1193b4be Poul Sander 2025-02-03 21:28 1707
        {
1193b4be Poul Sander 2025-02-03 21:28 1708
            // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
1193b4be Poul Sander 2025-02-03 21:28 1709
            // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
1193b4be Poul Sander 2025-02-03 21:28 1710
            static char text[1024 * 16] =
1193b4be Poul Sander 2025-02-03 21:28 1711
                "/*\n"
1193b4be Poul Sander 2025-02-03 21:28 1712
                " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
1193b4be Poul Sander 2025-02-03 21:28 1713
                " the hexadecimal encoding of one offending instruction,\n"
1193b4be Poul Sander 2025-02-03 21:28 1714
                " more formally, the invalid operand with locked CMPXCHG8B\n"
1193b4be Poul Sander 2025-02-03 21:28 1715
                " instruction bug, is a design flaw in the majority of\n"
1193b4be Poul Sander 2025-02-03 21:28 1716
                " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
1193b4be Poul Sander 2025-02-03 21:28 1717
                " processors (all in the P5 microarchitecture).\n"
1193b4be Poul Sander 2025-02-03 21:28 1718
                "*/\n\n"
1193b4be Poul Sander 2025-02-03 21:28 1719
                "label:\n"
1193b4be Poul Sander 2025-02-03 21:28 1720
                "\tlock cmpxchg8b eax\n";
1193b4be Poul Sander 2025-02-03 21:28 1721
1193b4be Poul Sander 2025-02-03 21:28 1722
            static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
1193b4be Poul Sander 2025-02-03 21:28 1723
            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)");
1193b4be Poul Sander 2025-02-03 21:28 1724
            ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
1193b4be Poul Sander 2025-02-03 21:28 1725
            ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
1193b4be Poul Sander 2025-02-03 21:28 1726
            ImGui::SameLine(); HelpMarker("When _AllowTabInput is set, passing through the widget with Tabbing doesn't automatically activate it, in order to also cycling through subsequent widgets.");
1193b4be Poul Sander 2025-02-03 21:28 1727
            ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
1193b4be Poul Sander 2025-02-03 21:28 1728
            ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
1193b4be Poul Sander 2025-02-03 21:28 1729
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1730
        }
1193b4be Poul Sander 2025-02-03 21:28 1731
1193b4be Poul Sander 2025-02-03 21:28 1732
        IMGUI_DEMO_MARKER("Widgets/Text Input/Filtered Text Input");
1193b4be Poul Sander 2025-02-03 21:28 1733
        if (ImGui::TreeNode("Filtered Text Input"))
1193b4be Poul Sander 2025-02-03 21:28 1734
        {
1193b4be Poul Sander 2025-02-03 21:28 1735
            struct TextFilters
1193b4be Poul Sander 2025-02-03 21:28 1736
            {
1193b4be Poul Sander 2025-02-03 21:28 1737
                // Modify character input by altering 'data->Eventchar' (ImGuiInputTextFlags_CallbackCharFilter callback)
1193b4be Poul Sander 2025-02-03 21:28 1738
                static int FilterCasingSwap(ImGuiInputTextCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 1739
                {
1193b4be Poul Sander 2025-02-03 21:28 1740
                    if (data->EventChar >= 'a' && data->EventChar <= 'z')       { data->EventChar -= 'a' - 'A'; } // Lowercase becomes uppercase
1193b4be Poul Sander 2025-02-03 21:28 1741
                    else if (data->EventChar >= 'A' && data->EventChar <= 'Z')  { data->EventChar += 'a' - 'A'; } // Uppercase becomes lowercase
1193b4be Poul Sander 2025-02-03 21:28 1742
                    return 0;
1193b4be Poul Sander 2025-02-03 21:28 1743
                }
1193b4be Poul Sander 2025-02-03 21:28 1744
1193b4be Poul Sander 2025-02-03 21:28 1745
                // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i', otherwise return 1 (filter out)
1193b4be Poul Sander 2025-02-03 21:28 1746
                static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 1747
                {
1193b4be Poul Sander 2025-02-03 21:28 1748
                    if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar))
1193b4be Poul Sander 2025-02-03 21:28 1749
                        return 0;
1193b4be Poul Sander 2025-02-03 21:28 1750
                    return 1;
1193b4be Poul Sander 2025-02-03 21:28 1751
                }
1193b4be Poul Sander 2025-02-03 21:28 1752
            };
1193b4be Poul Sander 2025-02-03 21:28 1753
1193b4be Poul Sander 2025-02-03 21:28 1754
            static char buf1[32] = ""; ImGui::InputText("default",     buf1, 32);
1193b4be Poul Sander 2025-02-03 21:28 1755
            static char buf2[32] = ""; ImGui::InputText("decimal",     buf2, 32, ImGuiInputTextFlags_CharsDecimal);
1193b4be Poul Sander 2025-02-03 21:28 1756
            static char buf3[32] = ""; ImGui::InputText("hexadecimal", buf3, 32, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
1193b4be Poul Sander 2025-02-03 21:28 1757
            static char buf4[32] = ""; ImGui::InputText("uppercase",   buf4, 32, ImGuiInputTextFlags_CharsUppercase);
1193b4be Poul Sander 2025-02-03 21:28 1758
            static char buf5[32] = ""; ImGui::InputText("no blank",    buf5, 32, ImGuiInputTextFlags_CharsNoBlank);
1193b4be Poul Sander 2025-02-03 21:28 1759
            static char buf6[32] = ""; ImGui::InputText("casing swap", buf6, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters.
1193b4be Poul Sander 2025-02-03 21:28 1760
            static char buf7[32] = ""; ImGui::InputText("\"imgui\"",   buf7, 32, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters.
1193b4be Poul Sander 2025-02-03 21:28 1761
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1762
        }
1193b4be Poul Sander 2025-02-03 21:28 1763
1193b4be Poul Sander 2025-02-03 21:28 1764
        IMGUI_DEMO_MARKER("Widgets/Text Input/Password input");
1193b4be Poul Sander 2025-02-03 21:28 1765
        if (ImGui::TreeNode("Password Input"))
1193b4be Poul Sander 2025-02-03 21:28 1766
        {
1193b4be Poul Sander 2025-02-03 21:28 1767
            static char password[64] = "password123";
1193b4be Poul Sander 2025-02-03 21:28 1768
            ImGui::InputText("password", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
1193b4be Poul Sander 2025-02-03 21:28 1769
            ImGui::SameLine(); HelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
1193b4be Poul Sander 2025-02-03 21:28 1770
            ImGui::InputTextWithHint("password (w/ hint)", "<password>", password, IM_ARRAYSIZE(password), ImGuiInputTextFlags_Password);
1193b4be Poul Sander 2025-02-03 21:28 1771
            ImGui::InputText("password (clear)", password, IM_ARRAYSIZE(password));
1193b4be Poul Sander 2025-02-03 21:28 1772
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1773
        }
1193b4be Poul Sander 2025-02-03 21:28 1774
1193b4be Poul Sander 2025-02-03 21:28 1775
        IMGUI_DEMO_MARKER("Widgets/Text Input/Completion, History, Edit Callbacks");
1193b4be Poul Sander 2025-02-03 21:28 1776
        if (ImGui::TreeNode("Completion, History, Edit Callbacks"))
1193b4be Poul Sander 2025-02-03 21:28 1777
        {
1193b4be Poul Sander 2025-02-03 21:28 1778
            struct Funcs
1193b4be Poul Sander 2025-02-03 21:28 1779
            {
1193b4be Poul Sander 2025-02-03 21:28 1780
                static int MyCallback(ImGuiInputTextCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 1781
                {
1193b4be Poul Sander 2025-02-03 21:28 1782
                    if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
1193b4be Poul Sander 2025-02-03 21:28 1783
                    {
1193b4be Poul Sander 2025-02-03 21:28 1784
                        data->InsertChars(data->CursorPos, "..");
1193b4be Poul Sander 2025-02-03 21:28 1785
                    }
1193b4be Poul Sander 2025-02-03 21:28 1786
                    else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
1193b4be Poul Sander 2025-02-03 21:28 1787
                    {
1193b4be Poul Sander 2025-02-03 21:28 1788
                        if (data->EventKey == ImGuiKey_UpArrow)
1193b4be Poul Sander 2025-02-03 21:28 1789
                        {
1193b4be Poul Sander 2025-02-03 21:28 1790
                            data->DeleteChars(0, data->BufTextLen);
1193b4be Poul Sander 2025-02-03 21:28 1791
                            data->InsertChars(0, "Pressed Up!");
1193b4be Poul Sander 2025-02-03 21:28 1792
                            data->SelectAll();
1193b4be Poul Sander 2025-02-03 21:28 1793
                        }
1193b4be Poul Sander 2025-02-03 21:28 1794
                        else if (data->EventKey == ImGuiKey_DownArrow)
1193b4be Poul Sander 2025-02-03 21:28 1795
                        {
1193b4be Poul Sander 2025-02-03 21:28 1796
                            data->DeleteChars(0, data->BufTextLen);
1193b4be Poul Sander 2025-02-03 21:28 1797
                            data->InsertChars(0, "Pressed Down!");
1193b4be Poul Sander 2025-02-03 21:28 1798
                            data->SelectAll();
1193b4be Poul Sander 2025-02-03 21:28 1799
                        }
1193b4be Poul Sander 2025-02-03 21:28 1800
                    }
1193b4be Poul Sander 2025-02-03 21:28 1801
                    else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
1193b4be Poul Sander 2025-02-03 21:28 1802
                    {
1193b4be Poul Sander 2025-02-03 21:28 1803
                        // Toggle casing of first character
1193b4be Poul Sander 2025-02-03 21:28 1804
                        char c = data->Buf[0];
1193b4be Poul Sander 2025-02-03 21:28 1805
                        if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32;
1193b4be Poul Sander 2025-02-03 21:28 1806
                        data->BufDirty = true;
1193b4be Poul Sander 2025-02-03 21:28 1807
1193b4be Poul Sander 2025-02-03 21:28 1808
                        // Increment a counter
1193b4be Poul Sander 2025-02-03 21:28 1809
                        int* p_int = (int*)data->UserData;
1193b4be Poul Sander 2025-02-03 21:28 1810
                        *p_int = *p_int + 1;
1193b4be Poul Sander 2025-02-03 21:28 1811
                    }
1193b4be Poul Sander 2025-02-03 21:28 1812
                    return 0;
1193b4be Poul Sander 2025-02-03 21:28 1813
                }
1193b4be Poul Sander 2025-02-03 21:28 1814
            };
1193b4be Poul Sander 2025-02-03 21:28 1815
            static char buf1[64];
1193b4be Poul Sander 2025-02-03 21:28 1816
            ImGui::InputText("Completion", buf1, 64, ImGuiInputTextFlags_CallbackCompletion, Funcs::MyCallback);
1193b4be Poul Sander 2025-02-03 21:28 1817
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1818
                "Here we append \"..\" each time Tab is pressed. "
1193b4be Poul Sander 2025-02-03 21:28 1819
                "See 'Examples>Console' for a more meaningful demonstration of using this callback.");
1193b4be Poul Sander 2025-02-03 21:28 1820
1193b4be Poul Sander 2025-02-03 21:28 1821
            static char buf2[64];
1193b4be Poul Sander 2025-02-03 21:28 1822
            ImGui::InputText("History", buf2, 64, ImGuiInputTextFlags_CallbackHistory, Funcs::MyCallback);
1193b4be Poul Sander 2025-02-03 21:28 1823
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1824
                "Here we replace and select text each time Up/Down are pressed. "
1193b4be Poul Sander 2025-02-03 21:28 1825
                "See 'Examples>Console' for a more meaningful demonstration of using this callback.");
1193b4be Poul Sander 2025-02-03 21:28 1826
1193b4be Poul Sander 2025-02-03 21:28 1827
            static char buf3[64];
1193b4be Poul Sander 2025-02-03 21:28 1828
            static int edit_count = 0;
1193b4be Poul Sander 2025-02-03 21:28 1829
            ImGui::InputText("Edit", buf3, 64, ImGuiInputTextFlags_CallbackEdit, Funcs::MyCallback, (void*)&edit_count);
1193b4be Poul Sander 2025-02-03 21:28 1830
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1831
                "Here we toggle the casing of the first character on every edit + count edits.");
1193b4be Poul Sander 2025-02-03 21:28 1832
            ImGui::SameLine(); ImGui::Text("(%d)", edit_count);
1193b4be Poul Sander 2025-02-03 21:28 1833
1193b4be Poul Sander 2025-02-03 21:28 1834
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1835
        }
1193b4be Poul Sander 2025-02-03 21:28 1836
1193b4be Poul Sander 2025-02-03 21:28 1837
        IMGUI_DEMO_MARKER("Widgets/Text Input/Resize Callback");
1193b4be Poul Sander 2025-02-03 21:28 1838
        if (ImGui::TreeNode("Resize Callback"))
1193b4be Poul Sander 2025-02-03 21:28 1839
        {
1193b4be Poul Sander 2025-02-03 21:28 1840
            // To wire InputText() with std::string or any other custom string type,
1193b4be Poul Sander 2025-02-03 21:28 1841
            // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper
1193b4be Poul Sander 2025-02-03 21:28 1842
            // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string.
1193b4be Poul Sander 2025-02-03 21:28 1843
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 1844
                "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n"
1193b4be Poul Sander 2025-02-03 21:28 1845
                "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string.");
1193b4be Poul Sander 2025-02-03 21:28 1846
            struct Funcs
1193b4be Poul Sander 2025-02-03 21:28 1847
            {
1193b4be Poul Sander 2025-02-03 21:28 1848
                static int MyResizeCallback(ImGuiInputTextCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 1849
                {
1193b4be Poul Sander 2025-02-03 21:28 1850
                    if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
1193b4be Poul Sander 2025-02-03 21:28 1851
                    {
1193b4be Poul Sander 2025-02-03 21:28 1852
                        ImVector<char>* my_str = (ImVector<char>*)data->UserData;
1193b4be Poul Sander 2025-02-03 21:28 1853
                        IM_ASSERT(my_str->begin() == data->Buf);
1193b4be Poul Sander 2025-02-03 21:28 1854
                        my_str->resize(data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1
1193b4be Poul Sander 2025-02-03 21:28 1855
                        data->Buf = my_str->begin();
1193b4be Poul Sander 2025-02-03 21:28 1856
                    }
1193b4be Poul Sander 2025-02-03 21:28 1857
                    return 0;
1193b4be Poul Sander 2025-02-03 21:28 1858
                }
1193b4be Poul Sander 2025-02-03 21:28 1859
1193b4be Poul Sander 2025-02-03 21:28 1860
                // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace.
1193b4be Poul Sander 2025-02-03 21:28 1861
                // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)'
1193b4be Poul Sander 2025-02-03 21:28 1862
                static bool MyInputTextMultiline(const char* label, ImVector<char>* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
1193b4be Poul Sander 2025-02-03 21:28 1863
                {
1193b4be Poul Sander 2025-02-03 21:28 1864
                    IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
1193b4be Poul Sander 2025-02-03 21:28 1865
                    return ImGui::InputTextMultiline(label, my_str->begin(), (size_t)my_str->size(), size, flags | ImGuiInputTextFlags_CallbackResize, Funcs::MyResizeCallback, (void*)my_str);
1193b4be Poul Sander 2025-02-03 21:28 1866
                }
1193b4be Poul Sander 2025-02-03 21:28 1867
            };
1193b4be Poul Sander 2025-02-03 21:28 1868
1193b4be Poul Sander 2025-02-03 21:28 1869
            // For this demo we are using ImVector as a string container.
1193b4be Poul Sander 2025-02-03 21:28 1870
            // Note that because we need to store a terminating zero character, our size/capacity are 1 more
1193b4be Poul Sander 2025-02-03 21:28 1871
            // than usually reported by a typical string class.
1193b4be Poul Sander 2025-02-03 21:28 1872
            static ImVector<char> my_str;
1193b4be Poul Sander 2025-02-03 21:28 1873
            if (my_str.empty())
1193b4be Poul Sander 2025-02-03 21:28 1874
                my_str.push_back(0);
1193b4be Poul Sander 2025-02-03 21:28 1875
            Funcs::MyInputTextMultiline("##MyStr", &my_str, ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16));
1193b4be Poul Sander 2025-02-03 21:28 1876
            ImGui::Text("Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity());
1193b4be Poul Sander 2025-02-03 21:28 1877
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1878
        }
1193b4be Poul Sander 2025-02-03 21:28 1879
1193b4be Poul Sander 2025-02-03 21:28 1880
        IMGUI_DEMO_MARKER("Widgets/Text Input/Miscellaneous");
1193b4be Poul Sander 2025-02-03 21:28 1881
        if (ImGui::TreeNode("Miscellaneous"))
1193b4be Poul Sander 2025-02-03 21:28 1882
        {
1193b4be Poul Sander 2025-02-03 21:28 1883
            static char buf1[16];
1193b4be Poul Sander 2025-02-03 21:28 1884
            static ImGuiInputTextFlags flags = ImGuiInputTextFlags_EscapeClearsAll;
1193b4be Poul Sander 2025-02-03 21:28 1885
            ImGui::CheckboxFlags("ImGuiInputTextFlags_EscapeClearsAll", &flags, ImGuiInputTextFlags_EscapeClearsAll);
1193b4be Poul Sander 2025-02-03 21:28 1886
            ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
1193b4be Poul Sander 2025-02-03 21:28 1887
            ImGui::CheckboxFlags("ImGuiInputTextFlags_NoUndoRedo", &flags, ImGuiInputTextFlags_NoUndoRedo);
1193b4be Poul Sander 2025-02-03 21:28 1888
            ImGui::InputText("Hello", buf1, IM_ARRAYSIZE(buf1), flags);
1193b4be Poul Sander 2025-02-03 21:28 1889
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1890
        }
1193b4be Poul Sander 2025-02-03 21:28 1891
1193b4be Poul Sander 2025-02-03 21:28 1892
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1893
    }
1193b4be Poul Sander 2025-02-03 21:28 1894
1193b4be Poul Sander 2025-02-03 21:28 1895
    // Tabs
1193b4be Poul Sander 2025-02-03 21:28 1896
    IMGUI_DEMO_MARKER("Widgets/Tabs");
1193b4be Poul Sander 2025-02-03 21:28 1897
    if (ImGui::TreeNode("Tabs"))
1193b4be Poul Sander 2025-02-03 21:28 1898
    {
1193b4be Poul Sander 2025-02-03 21:28 1899
        IMGUI_DEMO_MARKER("Widgets/Tabs/Basic");
1193b4be Poul Sander 2025-02-03 21:28 1900
        if (ImGui::TreeNode("Basic"))
1193b4be Poul Sander 2025-02-03 21:28 1901
        {
1193b4be Poul Sander 2025-02-03 21:28 1902
            ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 1903
            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1193b4be Poul Sander 2025-02-03 21:28 1904
            {
1193b4be Poul Sander 2025-02-03 21:28 1905
                if (ImGui::BeginTabItem("Avocado"))
1193b4be Poul Sander 2025-02-03 21:28 1906
                {
1193b4be Poul Sander 2025-02-03 21:28 1907
                    ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
1193b4be Poul Sander 2025-02-03 21:28 1908
                    ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 1909
                }
1193b4be Poul Sander 2025-02-03 21:28 1910
                if (ImGui::BeginTabItem("Broccoli"))
1193b4be Poul Sander 2025-02-03 21:28 1911
                {
1193b4be Poul Sander 2025-02-03 21:28 1912
                    ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
1193b4be Poul Sander 2025-02-03 21:28 1913
                    ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 1914
                }
1193b4be Poul Sander 2025-02-03 21:28 1915
                if (ImGui::BeginTabItem("Cucumber"))
1193b4be Poul Sander 2025-02-03 21:28 1916
                {
1193b4be Poul Sander 2025-02-03 21:28 1917
                    ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
1193b4be Poul Sander 2025-02-03 21:28 1918
                    ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 1919
                }
1193b4be Poul Sander 2025-02-03 21:28 1920
                ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 1921
            }
1193b4be Poul Sander 2025-02-03 21:28 1922
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 1923
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1924
        }
1193b4be Poul Sander 2025-02-03 21:28 1925
1193b4be Poul Sander 2025-02-03 21:28 1926
        IMGUI_DEMO_MARKER("Widgets/Tabs/Advanced & Close Button");
1193b4be Poul Sander 2025-02-03 21:28 1927
        if (ImGui::TreeNode("Advanced & Close Button"))
1193b4be Poul Sander 2025-02-03 21:28 1928
        {
1193b4be Poul Sander 2025-02-03 21:28 1929
            // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
1193b4be Poul Sander 2025-02-03 21:28 1930
            static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
1193b4be Poul Sander 2025-02-03 21:28 1931
            ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable);
1193b4be Poul Sander 2025-02-03 21:28 1932
            ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
1193b4be Poul Sander 2025-02-03 21:28 1933
            ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
1193b4be Poul Sander 2025-02-03 21:28 1934
            ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
1193b4be Poul Sander 2025-02-03 21:28 1935
            ImGui::CheckboxFlags("ImGuiTabBarFlags_DrawSelectedOverline", &tab_bar_flags, ImGuiTabBarFlags_DrawSelectedOverline);
1193b4be Poul Sander 2025-02-03 21:28 1936
            if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
1193b4be Poul Sander 2025-02-03 21:28 1937
                tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
1193b4be Poul Sander 2025-02-03 21:28 1938
            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
1193b4be Poul Sander 2025-02-03 21:28 1939
                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
1193b4be Poul Sander 2025-02-03 21:28 1940
            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
1193b4be Poul Sander 2025-02-03 21:28 1941
                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
1193b4be Poul Sander 2025-02-03 21:28 1942
1193b4be Poul Sander 2025-02-03 21:28 1943
            // Tab Bar
1193b4be Poul Sander 2025-02-03 21:28 1944
            ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 1945
            ImGui::Text("Opened:");
1193b4be Poul Sander 2025-02-03 21:28 1946
            const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
1193b4be Poul Sander 2025-02-03 21:28 1947
            static bool opened[4] = { true, true, true, true }; // Persistent user state
1193b4be Poul Sander 2025-02-03 21:28 1948
            for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1193b4be Poul Sander 2025-02-03 21:28 1949
            {
1193b4be Poul Sander 2025-02-03 21:28 1950
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 1951
                ImGui::Checkbox(names[n], &opened[n]);
1193b4be Poul Sander 2025-02-03 21:28 1952
            }
1193b4be Poul Sander 2025-02-03 21:28 1953
1193b4be Poul Sander 2025-02-03 21:28 1954
            // Passing a bool* to BeginTabItem() is similar to passing one to Begin():
1193b4be Poul Sander 2025-02-03 21:28 1955
            // the underlying bool will be set to false when the tab is closed.
1193b4be Poul Sander 2025-02-03 21:28 1956
            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1193b4be Poul Sander 2025-02-03 21:28 1957
            {
1193b4be Poul Sander 2025-02-03 21:28 1958
                for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1193b4be Poul Sander 2025-02-03 21:28 1959
                    if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 1960
                    {
1193b4be Poul Sander 2025-02-03 21:28 1961
                        ImGui::Text("This is the %s tab!", names[n]);
1193b4be Poul Sander 2025-02-03 21:28 1962
                        if (n & 1)
1193b4be Poul Sander 2025-02-03 21:28 1963
                            ImGui::Text("I am an odd tab.");
1193b4be Poul Sander 2025-02-03 21:28 1964
                        ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 1965
                    }
1193b4be Poul Sander 2025-02-03 21:28 1966
                ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 1967
            }
1193b4be Poul Sander 2025-02-03 21:28 1968
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 1969
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 1970
        }
1193b4be Poul Sander 2025-02-03 21:28 1971
1193b4be Poul Sander 2025-02-03 21:28 1972
        IMGUI_DEMO_MARKER("Widgets/Tabs/TabItemButton & Leading-Trailing flags");
1193b4be Poul Sander 2025-02-03 21:28 1973
        if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags"))
1193b4be Poul Sander 2025-02-03 21:28 1974
        {
1193b4be Poul Sander 2025-02-03 21:28 1975
            static ImVector<int> active_tabs;
1193b4be Poul Sander 2025-02-03 21:28 1976
            static int next_tab_id = 0;
1193b4be Poul Sander 2025-02-03 21:28 1977
            if (next_tab_id == 0) // Initialize with some default tabs
1193b4be Poul Sander 2025-02-03 21:28 1978
                for (int i = 0; i < 3; i++)
1193b4be Poul Sander 2025-02-03 21:28 1979
                    active_tabs.push_back(next_tab_id++);
1193b4be Poul Sander 2025-02-03 21:28 1980
1193b4be Poul Sander 2025-02-03 21:28 1981
            // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together.
1193b4be Poul Sander 2025-02-03 21:28 1982
            // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags...
1193b4be Poul Sander 2025-02-03 21:28 1983
            // but they tend to make more sense together)
1193b4be Poul Sander 2025-02-03 21:28 1984
            static bool show_leading_button = true;
1193b4be Poul Sander 2025-02-03 21:28 1985
            static bool show_trailing_button = true;
1193b4be Poul Sander 2025-02-03 21:28 1986
            ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button);
1193b4be Poul Sander 2025-02-03 21:28 1987
            ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button);
1193b4be Poul Sander 2025-02-03 21:28 1988
1193b4be Poul Sander 2025-02-03 21:28 1989
            // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
1193b4be Poul Sander 2025-02-03 21:28 1990
            static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown;
1193b4be Poul Sander 2025-02-03 21:28 1991
            ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
1193b4be Poul Sander 2025-02-03 21:28 1992
            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
1193b4be Poul Sander 2025-02-03 21:28 1993
                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
1193b4be Poul Sander 2025-02-03 21:28 1994
            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
1193b4be Poul Sander 2025-02-03 21:28 1995
                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
1193b4be Poul Sander 2025-02-03 21:28 1996
1193b4be Poul Sander 2025-02-03 21:28 1997
            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1193b4be Poul Sander 2025-02-03 21:28 1998
            {
1193b4be Poul Sander 2025-02-03 21:28 1999
                // Demo a Leading TabItemButton(): click the "?" button to open a menu
1193b4be Poul Sander 2025-02-03 21:28 2000
                if (show_leading_button)
1193b4be Poul Sander 2025-02-03 21:28 2001
                    if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip))
1193b4be Poul Sander 2025-02-03 21:28 2002
                        ImGui::OpenPopup("MyHelpMenu");
1193b4be Poul Sander 2025-02-03 21:28 2003
                if (ImGui::BeginPopup("MyHelpMenu"))
1193b4be Poul Sander 2025-02-03 21:28 2004
                {
1193b4be Poul Sander 2025-02-03 21:28 2005
                    ImGui::Selectable("Hello!");
1193b4be Poul Sander 2025-02-03 21:28 2006
                    ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 2007
                }
1193b4be Poul Sander 2025-02-03 21:28 2008
1193b4be Poul Sander 2025-02-03 21:28 2009
                // Demo Trailing Tabs: click the "+" button to add a new tab.
1193b4be Poul Sander 2025-02-03 21:28 2010
                // (In your app you may want to use a font icon instead of the "+")
1193b4be Poul Sander 2025-02-03 21:28 2011
                // We submit it before the regular tabs, but thanks to the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
1193b4be Poul Sander 2025-02-03 21:28 2012
                if (show_trailing_button)
1193b4be Poul Sander 2025-02-03 21:28 2013
                    if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
1193b4be Poul Sander 2025-02-03 21:28 2014
                        active_tabs.push_back(next_tab_id++); // Add new tab
1193b4be Poul Sander 2025-02-03 21:28 2015
1193b4be Poul Sander 2025-02-03 21:28 2016
                // Submit our regular tabs
1193b4be Poul Sander 2025-02-03 21:28 2017
                for (int n = 0; n < active_tabs.Size; )
1193b4be Poul Sander 2025-02-03 21:28 2018
                {
1193b4be Poul Sander 2025-02-03 21:28 2019
                    bool open = true;
1193b4be Poul Sander 2025-02-03 21:28 2020
                    char name[16];
1193b4be Poul Sander 2025-02-03 21:28 2021
                    snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]);
1193b4be Poul Sander 2025-02-03 21:28 2022
                    if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 2023
                    {
1193b4be Poul Sander 2025-02-03 21:28 2024
                        ImGui::Text("This is the %s tab!", name);
1193b4be Poul Sander 2025-02-03 21:28 2025
                        ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 2026
                    }
1193b4be Poul Sander 2025-02-03 21:28 2027
1193b4be Poul Sander 2025-02-03 21:28 2028
                    if (!open)
1193b4be Poul Sander 2025-02-03 21:28 2029
                        active_tabs.erase(active_tabs.Data + n);
1193b4be Poul Sander 2025-02-03 21:28 2030
                    else
1193b4be Poul Sander 2025-02-03 21:28 2031
                        n++;
1193b4be Poul Sander 2025-02-03 21:28 2032
                }
1193b4be Poul Sander 2025-02-03 21:28 2033
1193b4be Poul Sander 2025-02-03 21:28 2034
                ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 2035
            }
1193b4be Poul Sander 2025-02-03 21:28 2036
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 2037
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2038
        }
1193b4be Poul Sander 2025-02-03 21:28 2039
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2040
    }
1193b4be Poul Sander 2025-02-03 21:28 2041
1193b4be Poul Sander 2025-02-03 21:28 2042
    // Plot/Graph widgets are not very good.
1193b4be Poul Sander 2025-02-03 21:28 2043
    // Consider using a third-party library such as ImPlot: https://github.com/epezent/implot
1193b4be Poul Sander 2025-02-03 21:28 2044
    // (see others https://github.com/ocornut/imgui/wiki/Useful-Extensions)
1193b4be Poul Sander 2025-02-03 21:28 2045
    IMGUI_DEMO_MARKER("Widgets/Plotting");
1193b4be Poul Sander 2025-02-03 21:28 2046
    if (ImGui::TreeNode("Plotting"))
1193b4be Poul Sander 2025-02-03 21:28 2047
    {
1193b4be Poul Sander 2025-02-03 21:28 2048
        static bool animate = true;
1193b4be Poul Sander 2025-02-03 21:28 2049
        ImGui::Checkbox("Animate", &animate);
1193b4be Poul Sander 2025-02-03 21:28 2050
1193b4be Poul Sander 2025-02-03 21:28 2051
        // Plot as lines and plot as histogram
1193b4be Poul Sander 2025-02-03 21:28 2052
        static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
1193b4be Poul Sander 2025-02-03 21:28 2053
        ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
1193b4be Poul Sander 2025-02-03 21:28 2054
        ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0, 80.0f));
1193b4be Poul Sander 2025-02-03 21:28 2055
        //ImGui::SameLine(); HelpMarker("Consider using ImPlot instead!");
1193b4be Poul Sander 2025-02-03 21:28 2056
1193b4be Poul Sander 2025-02-03 21:28 2057
        // Fill an array of contiguous float values to plot
1193b4be Poul Sander 2025-02-03 21:28 2058
        // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
1193b4be Poul Sander 2025-02-03 21:28 2059
        // and the sizeof() of your structure in the "stride" parameter.
1193b4be Poul Sander 2025-02-03 21:28 2060
        static float values[90] = {};
1193b4be Poul Sander 2025-02-03 21:28 2061
        static int values_offset = 0;
1193b4be Poul Sander 2025-02-03 21:28 2062
        static double refresh_time = 0.0;
1193b4be Poul Sander 2025-02-03 21:28 2063
        if (!animate || refresh_time == 0.0)
1193b4be Poul Sander 2025-02-03 21:28 2064
            refresh_time = ImGui::GetTime();
1193b4be Poul Sander 2025-02-03 21:28 2065
        while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
1193b4be Poul Sander 2025-02-03 21:28 2066
        {
1193b4be Poul Sander 2025-02-03 21:28 2067
            static float phase = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 2068
            values[values_offset] = cosf(phase);
1193b4be Poul Sander 2025-02-03 21:28 2069
            values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
1193b4be Poul Sander 2025-02-03 21:28 2070
            phase += 0.10f * values_offset;
1193b4be Poul Sander 2025-02-03 21:28 2071
            refresh_time += 1.0f / 60.0f;
1193b4be Poul Sander 2025-02-03 21:28 2072
        }
1193b4be Poul Sander 2025-02-03 21:28 2073
1193b4be Poul Sander 2025-02-03 21:28 2074
        // Plots can display overlay texts
1193b4be Poul Sander 2025-02-03 21:28 2075
        // (in this example, we will display an average value)
1193b4be Poul Sander 2025-02-03 21:28 2076
        {
1193b4be Poul Sander 2025-02-03 21:28 2077
            float average = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 2078
            for (int n = 0; n < IM_ARRAYSIZE(values); n++)
1193b4be Poul Sander 2025-02-03 21:28 2079
                average += values[n];
1193b4be Poul Sander 2025-02-03 21:28 2080
            average /= (float)IM_ARRAYSIZE(values);
1193b4be Poul Sander 2025-02-03 21:28 2081
            char overlay[32];
1193b4be Poul Sander 2025-02-03 21:28 2082
            sprintf(overlay, "avg %f", average);
1193b4be Poul Sander 2025-02-03 21:28 2083
            ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, overlay, -1.0f, 1.0f, ImVec2(0, 80.0f));
1193b4be Poul Sander 2025-02-03 21:28 2084
        }
1193b4be Poul Sander 2025-02-03 21:28 2085
1193b4be Poul Sander 2025-02-03 21:28 2086
        // Use functions to generate output
1193b4be Poul Sander 2025-02-03 21:28 2087
        // FIXME: This is actually VERY awkward because current plot API only pass in indices.
1193b4be Poul Sander 2025-02-03 21:28 2088
        // We probably want an API passing floats and user provide sample rate/count.
1193b4be Poul Sander 2025-02-03 21:28 2089
        struct Funcs
1193b4be Poul Sander 2025-02-03 21:28 2090
        {
1193b4be Poul Sander 2025-02-03 21:28 2091
            static float Sin(void*, int i) { return sinf(i * 0.1f); }
1193b4be Poul Sander 2025-02-03 21:28 2092
            static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
1193b4be Poul Sander 2025-02-03 21:28 2093
        };
1193b4be Poul Sander 2025-02-03 21:28 2094
        static int func_type = 0, display_count = 70;
1193b4be Poul Sander 2025-02-03 21:28 2095
        ImGui::SeparatorText("Functions");
1193b4be Poul Sander 2025-02-03 21:28 2096
        ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 2097
        ImGui::Combo("func", &func_type, "Sin\0Saw\0");
1193b4be Poul Sander 2025-02-03 21:28 2098
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2099
        ImGui::SliderInt("Sample count", &display_count, 1, 400);
1193b4be Poul Sander 2025-02-03 21:28 2100
        float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
1193b4be Poul Sander 2025-02-03 21:28 2101
        ImGui::PlotLines("Lines##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
1193b4be Poul Sander 2025-02-03 21:28 2102
        ImGui::PlotHistogram("Histogram##2", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0, 80));
1193b4be Poul Sander 2025-02-03 21:28 2103
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 2104
1193b4be Poul Sander 2025-02-03 21:28 2105
        ImGui::Text("Need better plotting and graphing? Consider using ImPlot:");
1193b4be Poul Sander 2025-02-03 21:28 2106
        ImGui::TextLinkOpenURL("https://github.com/epezent/implot");
1193b4be Poul Sander 2025-02-03 21:28 2107
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 2108
1193b4be Poul Sander 2025-02-03 21:28 2109
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2110
    }
1193b4be Poul Sander 2025-02-03 21:28 2111
1193b4be Poul Sander 2025-02-03 21:28 2112
    IMGUI_DEMO_MARKER("Widgets/Progress Bars");
1193b4be Poul Sander 2025-02-03 21:28 2113
    if (ImGui::TreeNode("Progress Bars"))
1193b4be Poul Sander 2025-02-03 21:28 2114
    {
1193b4be Poul Sander 2025-02-03 21:28 2115
        // Animate a simple progress bar
1193b4be Poul Sander 2025-02-03 21:28 2116
        static float progress = 0.0f, progress_dir = 1.0f;
1193b4be Poul Sander 2025-02-03 21:28 2117
        progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
1193b4be Poul Sander 2025-02-03 21:28 2118
        if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
1193b4be Poul Sander 2025-02-03 21:28 2119
        if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
1193b4be Poul Sander 2025-02-03 21:28 2120
1193b4be Poul Sander 2025-02-03 21:28 2121
        // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
1193b4be Poul Sander 2025-02-03 21:28 2122
        // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
1193b4be Poul Sander 2025-02-03 21:28 2123
        ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 2124
        ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 2125
        ImGui::Text("Progress Bar");
1193b4be Poul Sander 2025-02-03 21:28 2126
1193b4be Poul Sander 2025-02-03 21:28 2127
        float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2128
        char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 2129
        sprintf(buf, "%d/%d", (int)(progress_saturated * 1753), 1753);
1193b4be Poul Sander 2025-02-03 21:28 2130
        ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
1193b4be Poul Sander 2025-02-03 21:28 2131
1193b4be Poul Sander 2025-02-03 21:28 2132
        // Pass an animated negative value, e.g. -1.0f * (float)ImGui::GetTime() is the recommended value.
1193b4be Poul Sander 2025-02-03 21:28 2133
        // Adjust the factor if you want to adjust the animation speed.
1193b4be Poul Sander 2025-02-03 21:28 2134
        ImGui::ProgressBar(-1.0f * (float)ImGui::GetTime(), ImVec2(0.0f, 0.0f), "Searching..");
1193b4be Poul Sander 2025-02-03 21:28 2135
        ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 2136
        ImGui::Text("Indeterminate");
1193b4be Poul Sander 2025-02-03 21:28 2137
1193b4be Poul Sander 2025-02-03 21:28 2138
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2139
    }
1193b4be Poul Sander 2025-02-03 21:28 2140
1193b4be Poul Sander 2025-02-03 21:28 2141
    IMGUI_DEMO_MARKER("Widgets/Color");
1193b4be Poul Sander 2025-02-03 21:28 2142
    if (ImGui::TreeNode("Color/Picker Widgets"))
1193b4be Poul Sander 2025-02-03 21:28 2143
    {
1193b4be Poul Sander 2025-02-03 21:28 2144
        static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
1193b4be Poul Sander 2025-02-03 21:28 2145
1193b4be Poul Sander 2025-02-03 21:28 2146
        static bool alpha_preview = true;
1193b4be Poul Sander 2025-02-03 21:28 2147
        static bool alpha_half_preview = false;
1193b4be Poul Sander 2025-02-03 21:28 2148
        static bool drag_and_drop = true;
1193b4be Poul Sander 2025-02-03 21:28 2149
        static bool options_menu = true;
1193b4be Poul Sander 2025-02-03 21:28 2150
        static bool hdr = false;
1193b4be Poul Sander 2025-02-03 21:28 2151
        ImGui::SeparatorText("Options");
1193b4be Poul Sander 2025-02-03 21:28 2152
        ImGui::Checkbox("With Alpha Preview", &alpha_preview);
1193b4be Poul Sander 2025-02-03 21:28 2153
        ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
1193b4be Poul Sander 2025-02-03 21:28 2154
        ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
1193b4be Poul Sander 2025-02-03 21:28 2155
        ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); HelpMarker("Right-click on the individual color widget to show options.");
1193b4be Poul Sander 2025-02-03 21:28 2156
        ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); HelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
1193b4be Poul Sander 2025-02-03 21:28 2157
        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);
1193b4be Poul Sander 2025-02-03 21:28 2158
1193b4be Poul Sander 2025-02-03 21:28 2159
        IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit");
1193b4be Poul Sander 2025-02-03 21:28 2160
        ImGui::SeparatorText("Inline color editor");
1193b4be Poul Sander 2025-02-03 21:28 2161
        ImGui::Text("Color widget:");
1193b4be Poul Sander 2025-02-03 21:28 2162
        ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 2163
            "Click on the color square to open a color picker.\n"
1193b4be Poul Sander 2025-02-03 21:28 2164
            "CTRL+click on individual component to input value.\n");
1193b4be Poul Sander 2025-02-03 21:28 2165
        ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
1193b4be Poul Sander 2025-02-03 21:28 2166
1193b4be Poul Sander 2025-02-03 21:28 2167
        IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)");
1193b4be Poul Sander 2025-02-03 21:28 2168
        ImGui::Text("Color widget HSV with Alpha:");
1193b4be Poul Sander 2025-02-03 21:28 2169
        ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_DisplayHSV | misc_flags);
1193b4be Poul Sander 2025-02-03 21:28 2170
1193b4be Poul Sander 2025-02-03 21:28 2171
        IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (float display)");
1193b4be Poul Sander 2025-02-03 21:28 2172
        ImGui::Text("Color widget with Float Display:");
1193b4be Poul Sander 2025-02-03 21:28 2173
        ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
1193b4be Poul Sander 2025-02-03 21:28 2174
1193b4be Poul Sander 2025-02-03 21:28 2175
        IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with Picker)");
1193b4be Poul Sander 2025-02-03 21:28 2176
        ImGui::Text("Color button with Picker:");
1193b4be Poul Sander 2025-02-03 21:28 2177
        ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 2178
            "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n"
1193b4be Poul Sander 2025-02-03 21:28 2179
            "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only "
1193b4be Poul Sander 2025-02-03 21:28 2180
            "be used for the tooltip and picker popup.");
1193b4be Poul Sander 2025-02-03 21:28 2181
        ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
1193b4be Poul Sander 2025-02-03 21:28 2182
1193b4be Poul Sander 2025-02-03 21:28 2183
        IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with custom Picker popup)");
1193b4be Poul Sander 2025-02-03 21:28 2184
        ImGui::Text("Color button with Custom Picker Popup:");
1193b4be Poul Sander 2025-02-03 21:28 2185
1193b4be Poul Sander 2025-02-03 21:28 2186
        // Generate a default palette. The palette will persist and can be edited.
1193b4be Poul Sander 2025-02-03 21:28 2187
        static bool saved_palette_init = true;
1193b4be Poul Sander 2025-02-03 21:28 2188
        static ImVec4 saved_palette[32] = {};
1193b4be Poul Sander 2025-02-03 21:28 2189
        if (saved_palette_init)
1193b4be Poul Sander 2025-02-03 21:28 2190
        {
1193b4be Poul Sander 2025-02-03 21:28 2191
            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1193b4be Poul Sander 2025-02-03 21:28 2192
            {
1193b4be Poul Sander 2025-02-03 21:28 2193
                ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f,
1193b4be Poul Sander 2025-02-03 21:28 2194
                    saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
1193b4be Poul Sander 2025-02-03 21:28 2195
                saved_palette[n].w = 1.0f; // Alpha
1193b4be Poul Sander 2025-02-03 21:28 2196
            }
1193b4be Poul Sander 2025-02-03 21:28 2197
            saved_palette_init = false;
1193b4be Poul Sander 2025-02-03 21:28 2198
        }
1193b4be Poul Sander 2025-02-03 21:28 2199
1193b4be Poul Sander 2025-02-03 21:28 2200
        static ImVec4 backup_color;
1193b4be Poul Sander 2025-02-03 21:28 2201
        bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
1193b4be Poul Sander 2025-02-03 21:28 2202
        ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 2203
        open_popup |= ImGui::Button("Palette");
1193b4be Poul Sander 2025-02-03 21:28 2204
        if (open_popup)
1193b4be Poul Sander 2025-02-03 21:28 2205
        {
1193b4be Poul Sander 2025-02-03 21:28 2206
            ImGui::OpenPopup("mypicker");
1193b4be Poul Sander 2025-02-03 21:28 2207
            backup_color = color;
1193b4be Poul Sander 2025-02-03 21:28 2208
        }
1193b4be Poul Sander 2025-02-03 21:28 2209
        if (ImGui::BeginPopup("mypicker"))
1193b4be Poul Sander 2025-02-03 21:28 2210
        {
1193b4be Poul Sander 2025-02-03 21:28 2211
            ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
1193b4be Poul Sander 2025-02-03 21:28 2212
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 2213
            ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
1193b4be Poul Sander 2025-02-03 21:28 2214
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2215
1193b4be Poul Sander 2025-02-03 21:28 2216
            ImGui::BeginGroup(); // Lock X position
1193b4be Poul Sander 2025-02-03 21:28 2217
            ImGui::Text("Current");
1193b4be Poul Sander 2025-02-03 21:28 2218
            ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40));
1193b4be Poul Sander 2025-02-03 21:28 2219
            ImGui::Text("Previous");
1193b4be Poul Sander 2025-02-03 21:28 2220
            if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60, 40)))
1193b4be Poul Sander 2025-02-03 21:28 2221
                color = backup_color;
1193b4be Poul Sander 2025-02-03 21:28 2222
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 2223
            ImGui::Text("Palette");
1193b4be Poul Sander 2025-02-03 21:28 2224
            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1193b4be Poul Sander 2025-02-03 21:28 2225
            {
1193b4be Poul Sander 2025-02-03 21:28 2226
                ImGui::PushID(n);
1193b4be Poul Sander 2025-02-03 21:28 2227
                if ((n % 8) != 0)
1193b4be Poul Sander 2025-02-03 21:28 2228
                    ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
1193b4be Poul Sander 2025-02-03 21:28 2229
1193b4be Poul Sander 2025-02-03 21:28 2230
                ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
1193b4be Poul Sander 2025-02-03 21:28 2231
                if (ImGui::ColorButton("##palette", saved_palette[n], palette_button_flags, ImVec2(20, 20)))
1193b4be Poul Sander 2025-02-03 21:28 2232
                    color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
1193b4be Poul Sander 2025-02-03 21:28 2233
1193b4be Poul Sander 2025-02-03 21:28 2234
                // Allow user to drop colors into each palette entry. Note that ColorButton() is already a
1193b4be Poul Sander 2025-02-03 21:28 2235
                // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag.
1193b4be Poul Sander 2025-02-03 21:28 2236
                if (ImGui::BeginDragDropTarget())
1193b4be Poul Sander 2025-02-03 21:28 2237
                {
1193b4be Poul Sander 2025-02-03 21:28 2238
                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
1193b4be Poul Sander 2025-02-03 21:28 2239
                        memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
1193b4be Poul Sander 2025-02-03 21:28 2240
                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
1193b4be Poul Sander 2025-02-03 21:28 2241
                        memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
1193b4be Poul Sander 2025-02-03 21:28 2242
                    ImGui::EndDragDropTarget();
1193b4be Poul Sander 2025-02-03 21:28 2243
                }
1193b4be Poul Sander 2025-02-03 21:28 2244
1193b4be Poul Sander 2025-02-03 21:28 2245
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2246
            }
1193b4be Poul Sander 2025-02-03 21:28 2247
            ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 2248
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 2249
        }
1193b4be Poul Sander 2025-02-03 21:28 2250
1193b4be Poul Sander 2025-02-03 21:28 2251
        IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (simple)");
1193b4be Poul Sander 2025-02-03 21:28 2252
        ImGui::Text("Color button only:");
1193b4be Poul Sander 2025-02-03 21:28 2253
        static bool no_border = false;
1193b4be Poul Sander 2025-02-03 21:28 2254
        ImGui::Checkbox("ImGuiColorEditFlags_NoBorder", &no_border);
1193b4be Poul Sander 2025-02-03 21:28 2255
        ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), ImVec2(80, 80));
1193b4be Poul Sander 2025-02-03 21:28 2256
1193b4be Poul Sander 2025-02-03 21:28 2257
        IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker");
1193b4be Poul Sander 2025-02-03 21:28 2258
        ImGui::SeparatorText("Color picker");
1193b4be Poul Sander 2025-02-03 21:28 2259
        static bool alpha = true;
1193b4be Poul Sander 2025-02-03 21:28 2260
        static bool alpha_bar = true;
1193b4be Poul Sander 2025-02-03 21:28 2261
        static bool side_preview = true;
1193b4be Poul Sander 2025-02-03 21:28 2262
        static bool ref_color = false;
1193b4be Poul Sander 2025-02-03 21:28 2263
        static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 2264
        static int display_mode = 0;
1193b4be Poul Sander 2025-02-03 21:28 2265
        static int picker_mode = 0;
1193b4be Poul Sander 2025-02-03 21:28 2266
        ImGui::Checkbox("With Alpha", &alpha);
1193b4be Poul Sander 2025-02-03 21:28 2267
        ImGui::Checkbox("With Alpha Bar", &alpha_bar);
1193b4be Poul Sander 2025-02-03 21:28 2268
        ImGui::Checkbox("With Side Preview", &side_preview);
1193b4be Poul Sander 2025-02-03 21:28 2269
        if (side_preview)
1193b4be Poul Sander 2025-02-03 21:28 2270
        {
1193b4be Poul Sander 2025-02-03 21:28 2271
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2272
            ImGui::Checkbox("With Ref Color", &ref_color);
1193b4be Poul Sander 2025-02-03 21:28 2273
            if (ref_color)
1193b4be Poul Sander 2025-02-03 21:28 2274
            {
1193b4be Poul Sander 2025-02-03 21:28 2275
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2276
                ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
1193b4be Poul Sander 2025-02-03 21:28 2277
            }
1193b4be Poul Sander 2025-02-03 21:28 2278
        }
1193b4be Poul Sander 2025-02-03 21:28 2279
        ImGui::Combo("Display Mode", &display_mode, "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
1193b4be Poul Sander 2025-02-03 21:28 2280
        ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 2281
            "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
1193b4be Poul Sander 2025-02-03 21:28 2282
            "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
1193b4be Poul Sander 2025-02-03 21:28 2283
            "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
1193b4be Poul Sander 2025-02-03 21:28 2284
        ImGui::SameLine(); HelpMarker("When not specified explicitly (Auto/Current mode), user can right-click the picker to change mode.");
1193b4be Poul Sander 2025-02-03 21:28 2285
        ImGuiColorEditFlags flags = misc_flags;
1193b4be Poul Sander 2025-02-03 21:28 2286
        if (!alpha)            flags |= ImGuiColorEditFlags_NoAlpha;        // This is by default if you call ColorPicker3() instead of ColorPicker4()
1193b4be Poul Sander 2025-02-03 21:28 2287
        if (alpha_bar)         flags |= ImGuiColorEditFlags_AlphaBar;
1193b4be Poul Sander 2025-02-03 21:28 2288
        if (!side_preview)     flags |= ImGuiColorEditFlags_NoSidePreview;
1193b4be Poul Sander 2025-02-03 21:28 2289
        if (picker_mode == 1)  flags |= ImGuiColorEditFlags_PickerHueBar;
1193b4be Poul Sander 2025-02-03 21:28 2290
        if (picker_mode == 2)  flags |= ImGuiColorEditFlags_PickerHueWheel;
1193b4be Poul Sander 2025-02-03 21:28 2291
        if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;       // Disable all RGB/HSV/Hex displays
1193b4be Poul Sander 2025-02-03 21:28 2292
        if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB;     // Override display mode
1193b4be Poul Sander 2025-02-03 21:28 2293
        if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
1193b4be Poul Sander 2025-02-03 21:28 2294
        if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
1193b4be Poul Sander 2025-02-03 21:28 2295
        ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
1193b4be Poul Sander 2025-02-03 21:28 2296
1193b4be Poul Sander 2025-02-03 21:28 2297
        ImGui::Text("Set defaults in code:");
1193b4be Poul Sander 2025-02-03 21:28 2298
        ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 2299
            "SetColorEditOptions() is designed to allow you to set boot-time default.\n"
1193b4be Poul Sander 2025-02-03 21:28 2300
            "We don't have Push/Pop functions because you can force options on a per-widget basis if needed,"
1193b4be Poul Sander 2025-02-03 21:28 2301
            "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid"
1193b4be Poul Sander 2025-02-03 21:28 2302
            "encouraging you to persistently save values that aren't forward-compatible.");
1193b4be Poul Sander 2025-02-03 21:28 2303
        if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
1193b4be Poul Sander 2025-02-03 21:28 2304
            ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
1193b4be Poul Sander 2025-02-03 21:28 2305
        if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
1193b4be Poul Sander 2025-02-03 21:28 2306
            ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
1193b4be Poul Sander 2025-02-03 21:28 2307
1193b4be Poul Sander 2025-02-03 21:28 2308
        // Always display a small version of both types of pickers
1193b4be Poul Sander 2025-02-03 21:28 2309
        // (that's in order to make it more visible in the demo to people who are skimming quickly through it)
1193b4be Poul Sander 2025-02-03 21:28 2310
        ImGui::Text("Both types:");
1193b4be Poul Sander 2025-02-03 21:28 2311
        float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f;
1193b4be Poul Sander 2025-02-03 21:28 2312
        ImGui::SetNextItemWidth(w);
1193b4be Poul Sander 2025-02-03 21:28 2313
        ImGui::ColorPicker3("##MyColor##5", (float*)&color, ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
1193b4be Poul Sander 2025-02-03 21:28 2314
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2315
        ImGui::SetNextItemWidth(w);
1193b4be Poul Sander 2025-02-03 21:28 2316
        ImGui::ColorPicker3("##MyColor##6", (float*)&color, ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
1193b4be Poul Sander 2025-02-03 21:28 2317
1193b4be Poul Sander 2025-02-03 21:28 2318
        // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
1193b4be Poul Sander 2025-02-03 21:28 2319
        static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
1193b4be Poul Sander 2025-02-03 21:28 2320
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 2321
        ImGui::Text("HSV encoded colors");
1193b4be Poul Sander 2025-02-03 21:28 2322
        ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 2323
            "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV"
1193b4be Poul Sander 2025-02-03 21:28 2324
            "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the"
1193b4be Poul Sander 2025-02-03 21:28 2325
            "added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
1193b4be Poul Sander 2025-02-03 21:28 2326
        ImGui::Text("Color widget with InputHSV:");
1193b4be Poul Sander 2025-02-03 21:28 2327
        ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
1193b4be Poul Sander 2025-02-03 21:28 2328
        ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
1193b4be Poul Sander 2025-02-03 21:28 2329
        ImGui::DragFloat4("Raw HSV values", (float*)&color_hsv, 0.01f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2330
1193b4be Poul Sander 2025-02-03 21:28 2331
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2332
    }
1193b4be Poul Sander 2025-02-03 21:28 2333
1193b4be Poul Sander 2025-02-03 21:28 2334
    IMGUI_DEMO_MARKER("Widgets/Drag and Slider Flags");
1193b4be Poul Sander 2025-02-03 21:28 2335
    if (ImGui::TreeNode("Drag/Slider Flags"))
1193b4be Poul Sander 2025-02-03 21:28 2336
    {
1193b4be Poul Sander 2025-02-03 21:28 2337
        // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
1193b4be Poul Sander 2025-02-03 21:28 2338
        static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 2339
        ImGui::CheckboxFlags("ImGuiSliderFlags_AlwaysClamp", &flags, ImGuiSliderFlags_AlwaysClamp);
1193b4be Poul Sander 2025-02-03 21:28 2340
        ImGui::CheckboxFlags("ImGuiSliderFlags_ClampOnInput", &flags, ImGuiSliderFlags_ClampOnInput);
1193b4be Poul Sander 2025-02-03 21:28 2341
        ImGui::SameLine(); HelpMarker("Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.");
1193b4be Poul Sander 2025-02-03 21:28 2342
        ImGui::CheckboxFlags("ImGuiSliderFlags_ClampZeroRange", &flags, ImGuiSliderFlags_ClampZeroRange);
1193b4be Poul Sander 2025-02-03 21:28 2343
        ImGui::SameLine(); HelpMarker("Clamp even if min==max==0.0f. Otherwise DragXXX functions don't clamp.");
1193b4be Poul Sander 2025-02-03 21:28 2344
        ImGui::CheckboxFlags("ImGuiSliderFlags_Logarithmic", &flags, ImGuiSliderFlags_Logarithmic);
1193b4be Poul Sander 2025-02-03 21:28 2345
        ImGui::SameLine(); HelpMarker("Enable logarithmic editing (more precision for small values).");
1193b4be Poul Sander 2025-02-03 21:28 2346
        ImGui::CheckboxFlags("ImGuiSliderFlags_NoRoundToFormat", &flags, ImGuiSliderFlags_NoRoundToFormat);
1193b4be Poul Sander 2025-02-03 21:28 2347
        ImGui::SameLine(); HelpMarker("Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
1193b4be Poul Sander 2025-02-03 21:28 2348
        ImGui::CheckboxFlags("ImGuiSliderFlags_NoInput", &flags, ImGuiSliderFlags_NoInput);
1193b4be Poul Sander 2025-02-03 21:28 2349
        ImGui::SameLine(); HelpMarker("Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
1193b4be Poul Sander 2025-02-03 21:28 2350
        ImGui::CheckboxFlags("ImGuiSliderFlags_WrapAround", &flags, ImGuiSliderFlags_WrapAround);
1193b4be Poul Sander 2025-02-03 21:28 2351
        ImGui::SameLine(); HelpMarker("Enable wrapping around from max to min and from min to max (only supported by DragXXX() functions)");
1193b4be Poul Sander 2025-02-03 21:28 2352
1193b4be Poul Sander 2025-02-03 21:28 2353
        // Drags
1193b4be Poul Sander 2025-02-03 21:28 2354
        static float drag_f = 0.5f;
1193b4be Poul Sander 2025-02-03 21:28 2355
        static int drag_i = 50;
1193b4be Poul Sander 2025-02-03 21:28 2356
        ImGui::Text("Underlying float value: %f", drag_f);
1193b4be Poul Sander 2025-02-03 21:28 2357
        ImGui::DragFloat("DragFloat (0 -> 1)", &drag_f, 0.005f, 0.0f, 1.0f, "%.3f", flags);
1193b4be Poul Sander 2025-02-03 21:28 2358
        ImGui::DragFloat("DragFloat (0 -> +inf)", &drag_f, 0.005f, 0.0f, FLT_MAX, "%.3f", flags);
1193b4be Poul Sander 2025-02-03 21:28 2359
        ImGui::DragFloat("DragFloat (-inf -> 1)", &drag_f, 0.005f, -FLT_MAX, 1.0f, "%.3f", flags);
1193b4be Poul Sander 2025-02-03 21:28 2360
        ImGui::DragFloat("DragFloat (-inf -> +inf)", &drag_f, 0.005f, -FLT_MAX, +FLT_MAX, "%.3f", flags);
1193b4be Poul Sander 2025-02-03 21:28 2361
        //ImGui::DragFloat("DragFloat (0 -> 0)", &drag_f, 0.005f, 0.0f, 0.0f, "%.3f", flags);           // To test ClampZeroRange
1193b4be Poul Sander 2025-02-03 21:28 2362
        //ImGui::DragFloat("DragFloat (100 -> 100)", &drag_f, 0.005f, 100.0f, 100.0f, "%.3f", flags);
1193b4be Poul Sander 2025-02-03 21:28 2363
        ImGui::DragInt("DragInt (0 -> 100)", &drag_i, 0.5f, 0, 100, "%d", flags);
1193b4be Poul Sander 2025-02-03 21:28 2364
1193b4be Poul Sander 2025-02-03 21:28 2365
        // Sliders
1193b4be Poul Sander 2025-02-03 21:28 2366
        static float slider_f = 0.5f;
1193b4be Poul Sander 2025-02-03 21:28 2367
        static int slider_i = 50;
1193b4be Poul Sander 2025-02-03 21:28 2368
        const ImGuiSliderFlags flags_for_sliders = flags & ~ImGuiSliderFlags_WrapAround;
1193b4be Poul Sander 2025-02-03 21:28 2369
        ImGui::Text("Underlying float value: %f", slider_f);
1193b4be Poul Sander 2025-02-03 21:28 2370
        ImGui::SliderFloat("SliderFloat (0 -> 1)", &slider_f, 0.0f, 1.0f, "%.3f", flags_for_sliders);
1193b4be Poul Sander 2025-02-03 21:28 2371
        ImGui::SliderInt("SliderInt (0 -> 100)", &slider_i, 0, 100, "%d", flags_for_sliders);
1193b4be Poul Sander 2025-02-03 21:28 2372
1193b4be Poul Sander 2025-02-03 21:28 2373
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2374
    }
1193b4be Poul Sander 2025-02-03 21:28 2375
1193b4be Poul Sander 2025-02-03 21:28 2376
    IMGUI_DEMO_MARKER("Widgets/Range Widgets");
1193b4be Poul Sander 2025-02-03 21:28 2377
    if (ImGui::TreeNode("Range Widgets"))
1193b4be Poul Sander 2025-02-03 21:28 2378
    {
1193b4be Poul Sander 2025-02-03 21:28 2379
        static float begin = 10, end = 90;
1193b4be Poul Sander 2025-02-03 21:28 2380
        static int begin_i = 100, end_i = 1000;
1193b4be Poul Sander 2025-02-03 21:28 2381
        ImGui::DragFloatRange2("range float", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%", ImGuiSliderFlags_AlwaysClamp);
1193b4be Poul Sander 2025-02-03 21:28 2382
        ImGui::DragIntRange2("range int", &begin_i, &end_i, 5, 0, 1000, "Min: %d units", "Max: %d units");
1193b4be Poul Sander 2025-02-03 21:28 2383
        ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
1193b4be Poul Sander 2025-02-03 21:28 2384
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2385
    }
1193b4be Poul Sander 2025-02-03 21:28 2386
1193b4be Poul Sander 2025-02-03 21:28 2387
    IMGUI_DEMO_MARKER("Widgets/Data Types");
1193b4be Poul Sander 2025-02-03 21:28 2388
    if (ImGui::TreeNode("Data Types"))
1193b4be Poul Sander 2025-02-03 21:28 2389
    {
1193b4be Poul Sander 2025-02-03 21:28 2390
        // DragScalar/InputScalar/SliderScalar functions allow various data types
1193b4be Poul Sander 2025-02-03 21:28 2391
        // - signed/unsigned
1193b4be Poul Sander 2025-02-03 21:28 2392
        // - 8/16/32/64-bits
1193b4be Poul Sander 2025-02-03 21:28 2393
        // - integer/float/double
1193b4be Poul Sander 2025-02-03 21:28 2394
        // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum
1193b4be Poul Sander 2025-02-03 21:28 2395
        // to pass the type, and passing all arguments by pointer.
1193b4be Poul Sander 2025-02-03 21:28 2396
        // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each type.
1193b4be Poul Sander 2025-02-03 21:28 2397
        // In practice, if you frequently use a given type that is not covered by the normal API entry points,
1193b4be Poul Sander 2025-02-03 21:28 2398
        // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*,
1193b4be Poul Sander 2025-02-03 21:28 2399
        // and then pass their address to the generic function. For example:
1193b4be Poul Sander 2025-02-03 21:28 2400
        //   bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
1193b4be Poul Sander 2025-02-03 21:28 2401
        //   {
1193b4be Poul Sander 2025-02-03 21:28 2402
        //      return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
1193b4be Poul Sander 2025-02-03 21:28 2403
        //   }
1193b4be Poul Sander 2025-02-03 21:28 2404
1193b4be Poul Sander 2025-02-03 21:28 2405
        // Setup limits (as helper variables so we can take their address, as explained above)
1193b4be Poul Sander 2025-02-03 21:28 2406
        // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
1193b4be Poul Sander 2025-02-03 21:28 2407
        #ifndef LLONG_MIN
1193b4be Poul Sander 2025-02-03 21:28 2408
        ImS64 LLONG_MIN = -9223372036854775807LL - 1;
1193b4be Poul Sander 2025-02-03 21:28 2409
        ImS64 LLONG_MAX = 9223372036854775807LL;
1193b4be Poul Sander 2025-02-03 21:28 2410
        ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
1193b4be Poul Sander 2025-02-03 21:28 2411
        #endif
1193b4be Poul Sander 2025-02-03 21:28 2412
        const char    s8_zero  = 0,   s8_one  = 1,   s8_fifty  = 50, s8_min  = -128,        s8_max = 127;
1193b4be Poul Sander 2025-02-03 21:28 2413
        const ImU8    u8_zero  = 0,   u8_one  = 1,   u8_fifty  = 50, u8_min  = 0,           u8_max = 255;
1193b4be Poul Sander 2025-02-03 21:28 2414
        const short   s16_zero = 0,   s16_one = 1,   s16_fifty = 50, s16_min = -32768,      s16_max = 32767;
1193b4be Poul Sander 2025-02-03 21:28 2415
        const ImU16   u16_zero = 0,   u16_one = 1,   u16_fifty = 50, u16_min = 0,           u16_max = 65535;
1193b4be Poul Sander 2025-02-03 21:28 2416
        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;
1193b4be Poul Sander 2025-02-03 21:28 2417
        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;
1193b4be Poul Sander 2025-02-03 21:28 2418
        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;
1193b4be Poul Sander 2025-02-03 21:28 2419
        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;
1193b4be Poul Sander 2025-02-03 21:28 2420
        const float   f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
1193b4be Poul Sander 2025-02-03 21:28 2421
        const double  f64_zero = 0.,  f64_one = 1.,  f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
1193b4be Poul Sander 2025-02-03 21:28 2422
1193b4be Poul Sander 2025-02-03 21:28 2423
        // State
1193b4be Poul Sander 2025-02-03 21:28 2424
        static char   s8_v  = 127;
1193b4be Poul Sander 2025-02-03 21:28 2425
        static ImU8   u8_v  = 255;
1193b4be Poul Sander 2025-02-03 21:28 2426
        static short  s16_v = 32767;
1193b4be Poul Sander 2025-02-03 21:28 2427
        static ImU16  u16_v = 65535;
1193b4be Poul Sander 2025-02-03 21:28 2428
        static ImS32  s32_v = -1;
1193b4be Poul Sander 2025-02-03 21:28 2429
        static ImU32  u32_v = (ImU32)-1;
1193b4be Poul Sander 2025-02-03 21:28 2430
        static ImS64  s64_v = -1;
1193b4be Poul Sander 2025-02-03 21:28 2431
        static ImU64  u64_v = (ImU64)-1;
1193b4be Poul Sander 2025-02-03 21:28 2432
        static float  f32_v = 0.123f;
1193b4be Poul Sander 2025-02-03 21:28 2433
        static double f64_v = 90000.01234567890123456789;
1193b4be Poul Sander 2025-02-03 21:28 2434
1193b4be Poul Sander 2025-02-03 21:28 2435
        const float drag_speed = 0.2f;
1193b4be Poul Sander 2025-02-03 21:28 2436
        static bool drag_clamp = false;
1193b4be Poul Sander 2025-02-03 21:28 2437
        IMGUI_DEMO_MARKER("Widgets/Data Types/Drags");
1193b4be Poul Sander 2025-02-03 21:28 2438
        ImGui::SeparatorText("Drags");
1193b4be Poul Sander 2025-02-03 21:28 2439
        ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp);
1193b4be Poul Sander 2025-02-03 21:28 2440
        ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 2441
            "As with every widget in dear imgui, we never modify values unless there is a user interaction.\n"
1193b4be Poul Sander 2025-02-03 21:28 2442
            "You can override the clamping limits by using CTRL+Click to input a value.");
1193b4be Poul Sander 2025-02-03 21:28 2443
        ImGui::DragScalar("drag s8",        ImGuiDataType_S8,     &s8_v,  drag_speed, drag_clamp ? &s8_zero  : NULL, drag_clamp ? &s8_fifty  : NULL);
1193b4be Poul Sander 2025-02-03 21:28 2444
        ImGui::DragScalar("drag u8",        ImGuiDataType_U8,     &u8_v,  drag_speed, drag_clamp ? &u8_zero  : NULL, drag_clamp ? &u8_fifty  : NULL, "%u ms");
1193b4be Poul Sander 2025-02-03 21:28 2445
        ImGui::DragScalar("drag s16",       ImGuiDataType_S16,    &s16_v, drag_speed, drag_clamp ? &s16_zero : NULL, drag_clamp ? &s16_fifty : NULL);
1193b4be Poul Sander 2025-02-03 21:28 2446
        ImGui::DragScalar("drag u16",       ImGuiDataType_U16,    &u16_v, drag_speed, drag_clamp ? &u16_zero : NULL, drag_clamp ? &u16_fifty : NULL, "%u ms");
1193b4be Poul Sander 2025-02-03 21:28 2447
        ImGui::DragScalar("drag s32",       ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
1193b4be Poul Sander 2025-02-03 21:28 2448
        ImGui::DragScalar("drag s32 hex",   ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL, "0x%08X");
1193b4be Poul Sander 2025-02-03 21:28 2449
        ImGui::DragScalar("drag u32",       ImGuiDataType_U32,    &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
1193b4be Poul Sander 2025-02-03 21:28 2450
        ImGui::DragScalar("drag s64",       ImGuiDataType_S64,    &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
1193b4be Poul Sander 2025-02-03 21:28 2451
        ImGui::DragScalar("drag u64",       ImGuiDataType_U64,    &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
1193b4be Poul Sander 2025-02-03 21:28 2452
        ImGui::DragScalar("drag float",     ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f");
1193b4be Poul Sander 2025-02-03 21:28 2453
        ImGui::DragScalar("drag float log", ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", ImGuiSliderFlags_Logarithmic);
1193b4be Poul Sander 2025-02-03 21:28 2454
        ImGui::DragScalar("drag double",    ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL,     "%.10f grams");
1193b4be Poul Sander 2025-02-03 21:28 2455
        ImGui::DragScalar("drag double log",ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", ImGuiSliderFlags_Logarithmic);
1193b4be Poul Sander 2025-02-03 21:28 2456
1193b4be Poul Sander 2025-02-03 21:28 2457
        IMGUI_DEMO_MARKER("Widgets/Data Types/Sliders");
1193b4be Poul Sander 2025-02-03 21:28 2458
        ImGui::SeparatorText("Sliders");
1193b4be Poul Sander 2025-02-03 21:28 2459
        ImGui::SliderScalar("slider s8 full",       ImGuiDataType_S8,     &s8_v,  &s8_min,   &s8_max,   "%d");
1193b4be Poul Sander 2025-02-03 21:28 2460
        ImGui::SliderScalar("slider u8 full",       ImGuiDataType_U8,     &u8_v,  &u8_min,   &u8_max,   "%u");
1193b4be Poul Sander 2025-02-03 21:28 2461
        ImGui::SliderScalar("slider s16 full",      ImGuiDataType_S16,    &s16_v, &s16_min,  &s16_max,  "%d");
1193b4be Poul Sander 2025-02-03 21:28 2462
        ImGui::SliderScalar("slider u16 full",      ImGuiDataType_U16,    &u16_v, &u16_min,  &u16_max,  "%u");
1193b4be Poul Sander 2025-02-03 21:28 2463
        ImGui::SliderScalar("slider s32 low",       ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty,"%d");
1193b4be Poul Sander 2025-02-03 21:28 2464
        ImGui::SliderScalar("slider s32 high",      ImGuiDataType_S32,    &s32_v, &s32_hi_a, &s32_hi_b, "%d");
1193b4be Poul Sander 2025-02-03 21:28 2465
        ImGui::SliderScalar("slider s32 full",      ImGuiDataType_S32,    &s32_v, &s32_min,  &s32_max,  "%d");
1193b4be Poul Sander 2025-02-03 21:28 2466
        ImGui::SliderScalar("slider s32 hex",       ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty, "0x%04X");
1193b4be Poul Sander 2025-02-03 21:28 2467
        ImGui::SliderScalar("slider u32 low",       ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u");
1193b4be Poul Sander 2025-02-03 21:28 2468
        ImGui::SliderScalar("slider u32 high",      ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u");
1193b4be Poul Sander 2025-02-03 21:28 2469
        ImGui::SliderScalar("slider u32 full",      ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u");
1193b4be Poul Sander 2025-02-03 21:28 2470
        ImGui::SliderScalar("slider s64 low",       ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%" PRId64);
1193b4be Poul Sander 2025-02-03 21:28 2471
        ImGui::SliderScalar("slider s64 high",      ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%" PRId64);
1193b4be Poul Sander 2025-02-03 21:28 2472
        ImGui::SliderScalar("slider s64 full",      ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%" PRId64);
1193b4be Poul Sander 2025-02-03 21:28 2473
        ImGui::SliderScalar("slider u64 low",       ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%" PRIu64 " ms");
1193b4be Poul Sander 2025-02-03 21:28 2474
        ImGui::SliderScalar("slider u64 high",      ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%" PRIu64 " ms");
1193b4be Poul Sander 2025-02-03 21:28 2475
        ImGui::SliderScalar("slider u64 full",      ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%" PRIu64 " ms");
1193b4be Poul Sander 2025-02-03 21:28 2476
        ImGui::SliderScalar("slider float low",     ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one);
1193b4be Poul Sander 2025-02-03 21:28 2477
        ImGui::SliderScalar("slider float low log", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
1193b4be Poul Sander 2025-02-03 21:28 2478
        ImGui::SliderScalar("slider float high",    ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e");
1193b4be Poul Sander 2025-02-03 21:28 2479
        ImGui::SliderScalar("slider double low",    ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f grams");
1193b4be Poul Sander 2025-02-03 21:28 2480
        ImGui::SliderScalar("slider double low log",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", ImGuiSliderFlags_Logarithmic);
1193b4be Poul Sander 2025-02-03 21:28 2481
        ImGui::SliderScalar("slider double high",   ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams");
1193b4be Poul Sander 2025-02-03 21:28 2482
1193b4be Poul Sander 2025-02-03 21:28 2483
        ImGui::SeparatorText("Sliders (reverse)");
1193b4be Poul Sander 2025-02-03 21:28 2484
        ImGui::SliderScalar("slider s8 reverse",    ImGuiDataType_S8,   &s8_v,  &s8_max,    &s8_min,   "%d");
1193b4be Poul Sander 2025-02-03 21:28 2485
        ImGui::SliderScalar("slider u8 reverse",    ImGuiDataType_U8,   &u8_v,  &u8_max,    &u8_min,   "%u");
1193b4be Poul Sander 2025-02-03 21:28 2486
        ImGui::SliderScalar("slider s32 reverse",   ImGuiDataType_S32,  &s32_v, &s32_fifty, &s32_zero, "%d");
1193b4be Poul Sander 2025-02-03 21:28 2487
        ImGui::SliderScalar("slider u32 reverse",   ImGuiDataType_U32,  &u32_v, &u32_fifty, &u32_zero, "%u");
1193b4be Poul Sander 2025-02-03 21:28 2488
        ImGui::SliderScalar("slider s64 reverse",   ImGuiDataType_S64,  &s64_v, &s64_fifty, &s64_zero, "%" PRId64);
1193b4be Poul Sander 2025-02-03 21:28 2489
        ImGui::SliderScalar("slider u64 reverse",   ImGuiDataType_U64,  &u64_v, &u64_fifty, &u64_zero, "%" PRIu64 " ms");
1193b4be Poul Sander 2025-02-03 21:28 2490
1193b4be Poul Sander 2025-02-03 21:28 2491
        IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs");
1193b4be Poul Sander 2025-02-03 21:28 2492
        static bool inputs_step = true;
1193b4be Poul Sander 2025-02-03 21:28 2493
        static ImGuiInputTextFlags flags = ImGuiInputTextFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 2494
        ImGui::SeparatorText("Inputs");
1193b4be Poul Sander 2025-02-03 21:28 2495
        ImGui::Checkbox("Show step buttons", &inputs_step);
1193b4be Poul Sander 2025-02-03 21:28 2496
        ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
1193b4be Poul Sander 2025-02-03 21:28 2497
        ImGui::CheckboxFlags("ImGuiInputTextFlags_ParseEmptyRefVal", &flags, ImGuiInputTextFlags_ParseEmptyRefVal);
1193b4be Poul Sander 2025-02-03 21:28 2498
        ImGui::CheckboxFlags("ImGuiInputTextFlags_DisplayEmptyRefVal", &flags, ImGuiInputTextFlags_DisplayEmptyRefVal);
1193b4be Poul Sander 2025-02-03 21:28 2499
        ImGui::InputScalar("input s8",      ImGuiDataType_S8,     &s8_v,  inputs_step ? &s8_one  : NULL, NULL, "%d", flags);
1193b4be Poul Sander 2025-02-03 21:28 2500
        ImGui::InputScalar("input u8",      ImGuiDataType_U8,     &u8_v,  inputs_step ? &u8_one  : NULL, NULL, "%u", flags);
1193b4be Poul Sander 2025-02-03 21:28 2501
        ImGui::InputScalar("input s16",     ImGuiDataType_S16,    &s16_v, inputs_step ? &s16_one : NULL, NULL, "%d", flags);
1193b4be Poul Sander 2025-02-03 21:28 2502
        ImGui::InputScalar("input u16",     ImGuiDataType_U16,    &u16_v, inputs_step ? &u16_one : NULL, NULL, "%u", flags);
1193b4be Poul Sander 2025-02-03 21:28 2503
        ImGui::InputScalar("input s32",     ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d", flags);
1193b4be Poul Sander 2025-02-03 21:28 2504
        ImGui::InputScalar("input s32 hex", ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%04X", flags);
1193b4be Poul Sander 2025-02-03 21:28 2505
        ImGui::InputScalar("input u32",     ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u", flags);
1193b4be Poul Sander 2025-02-03 21:28 2506
        ImGui::InputScalar("input u32 hex", ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", flags);
1193b4be Poul Sander 2025-02-03 21:28 2507
        ImGui::InputScalar("input s64",     ImGuiDataType_S64,    &s64_v, inputs_step ? &s64_one : NULL, NULL, NULL, flags);
1193b4be Poul Sander 2025-02-03 21:28 2508
        ImGui::InputScalar("input u64",     ImGuiDataType_U64,    &u64_v, inputs_step ? &u64_one : NULL, NULL, NULL, flags);
1193b4be Poul Sander 2025-02-03 21:28 2509
        ImGui::InputScalar("input float",   ImGuiDataType_Float,  &f32_v, inputs_step ? &f32_one : NULL, NULL, NULL, flags);
1193b4be Poul Sander 2025-02-03 21:28 2510
        ImGui::InputScalar("input double",  ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL, NULL, NULL, flags);
1193b4be Poul Sander 2025-02-03 21:28 2511
1193b4be Poul Sander 2025-02-03 21:28 2512
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2513
    }
1193b4be Poul Sander 2025-02-03 21:28 2514
1193b4be Poul Sander 2025-02-03 21:28 2515
    IMGUI_DEMO_MARKER("Widgets/Multi-component Widgets");
1193b4be Poul Sander 2025-02-03 21:28 2516
    if (ImGui::TreeNode("Multi-component Widgets"))
1193b4be Poul Sander 2025-02-03 21:28 2517
    {
1193b4be Poul Sander 2025-02-03 21:28 2518
        static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
1193b4be Poul Sander 2025-02-03 21:28 2519
        static int vec4i[4] = { 1, 5, 100, 255 };
1193b4be Poul Sander 2025-02-03 21:28 2520
1193b4be Poul Sander 2025-02-03 21:28 2521
        ImGui::SeparatorText("2-wide");
1193b4be Poul Sander 2025-02-03 21:28 2522
        ImGui::InputFloat2("input float2", vec4f);
1193b4be Poul Sander 2025-02-03 21:28 2523
        ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2524
        ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2525
        ImGui::InputInt2("input int2", vec4i);
1193b4be Poul Sander 2025-02-03 21:28 2526
        ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
1193b4be Poul Sander 2025-02-03 21:28 2527
        ImGui::SliderInt2("slider int2", vec4i, 0, 255);
1193b4be Poul Sander 2025-02-03 21:28 2528
1193b4be Poul Sander 2025-02-03 21:28 2529
        ImGui::SeparatorText("3-wide");
1193b4be Poul Sander 2025-02-03 21:28 2530
        ImGui::InputFloat3("input float3", vec4f);
1193b4be Poul Sander 2025-02-03 21:28 2531
        ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2532
        ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2533
        ImGui::InputInt3("input int3", vec4i);
1193b4be Poul Sander 2025-02-03 21:28 2534
        ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
1193b4be Poul Sander 2025-02-03 21:28 2535
        ImGui::SliderInt3("slider int3", vec4i, 0, 255);
1193b4be Poul Sander 2025-02-03 21:28 2536
1193b4be Poul Sander 2025-02-03 21:28 2537
        ImGui::SeparatorText("4-wide");
1193b4be Poul Sander 2025-02-03 21:28 2538
        ImGui::InputFloat4("input float4", vec4f);
1193b4be Poul Sander 2025-02-03 21:28 2539
        ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2540
        ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 2541
        ImGui::InputInt4("input int4", vec4i);
1193b4be Poul Sander 2025-02-03 21:28 2542
        ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
1193b4be Poul Sander 2025-02-03 21:28 2543
        ImGui::SliderInt4("slider int4", vec4i, 0, 255);
1193b4be Poul Sander 2025-02-03 21:28 2544
1193b4be Poul Sander 2025-02-03 21:28 2545
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2546
    }
1193b4be Poul Sander 2025-02-03 21:28 2547
1193b4be Poul Sander 2025-02-03 21:28 2548
    IMGUI_DEMO_MARKER("Widgets/Vertical Sliders");
1193b4be Poul Sander 2025-02-03 21:28 2549
    if (ImGui::TreeNode("Vertical Sliders"))
1193b4be Poul Sander 2025-02-03 21:28 2550
    {
1193b4be Poul Sander 2025-02-03 21:28 2551
        const float spacing = 4;
1193b4be Poul Sander 2025-02-03 21:28 2552
        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1193b4be Poul Sander 2025-02-03 21:28 2553
1193b4be Poul Sander 2025-02-03 21:28 2554
        static int int_value = 0;
1193b4be Poul Sander 2025-02-03 21:28 2555
        ImGui::VSliderInt("##int", ImVec2(18, 160), &int_value, 0, 5);
1193b4be Poul Sander 2025-02-03 21:28 2556
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2557
1193b4be Poul Sander 2025-02-03 21:28 2558
        static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
1193b4be Poul Sander 2025-02-03 21:28 2559
        ImGui::PushID("set1");
1193b4be Poul Sander 2025-02-03 21:28 2560
        for (int i = 0; i < 7; i++)
1193b4be Poul Sander 2025-02-03 21:28 2561
        {
1193b4be Poul Sander 2025-02-03 21:28 2562
            if (i > 0) ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2563
            ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 2564
            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i / 7.0f, 0.5f, 0.5f));
1193b4be Poul Sander 2025-02-03 21:28 2565
            ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.5f));
1193b4be Poul Sander 2025-02-03 21:28 2566
            ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.5f));
1193b4be Poul Sander 2025-02-03 21:28 2567
            ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i / 7.0f, 0.9f, 0.9f));
1193b4be Poul Sander 2025-02-03 21:28 2568
            ImGui::VSliderFloat("##v", ImVec2(18, 160), &values[i], 0.0f, 1.0f, "");
1193b4be Poul Sander 2025-02-03 21:28 2569
            if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1193b4be Poul Sander 2025-02-03 21:28 2570
                ImGui::SetTooltip("%.3f", values[i]);
1193b4be Poul Sander 2025-02-03 21:28 2571
            ImGui::PopStyleColor(4);
1193b4be Poul Sander 2025-02-03 21:28 2572
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2573
        }
1193b4be Poul Sander 2025-02-03 21:28 2574
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2575
1193b4be Poul Sander 2025-02-03 21:28 2576
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2577
        ImGui::PushID("set2");
1193b4be Poul Sander 2025-02-03 21:28 2578
        static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
1193b4be Poul Sander 2025-02-03 21:28 2579
        const int rows = 3;
1193b4be Poul Sander 2025-02-03 21:28 2580
        const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
1193b4be Poul Sander 2025-02-03 21:28 2581
        for (int nx = 0; nx < 4; nx++)
1193b4be Poul Sander 2025-02-03 21:28 2582
        {
1193b4be Poul Sander 2025-02-03 21:28 2583
            if (nx > 0) ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2584
            ImGui::BeginGroup();
1193b4be Poul Sander 2025-02-03 21:28 2585
            for (int ny = 0; ny < rows; ny++)
1193b4be Poul Sander 2025-02-03 21:28 2586
            {
1193b4be Poul Sander 2025-02-03 21:28 2587
                ImGui::PushID(nx * rows + ny);
1193b4be Poul Sander 2025-02-03 21:28 2588
                ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
1193b4be Poul Sander 2025-02-03 21:28 2589
                if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1193b4be Poul Sander 2025-02-03 21:28 2590
                    ImGui::SetTooltip("%.3f", values2[nx]);
1193b4be Poul Sander 2025-02-03 21:28 2591
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2592
            }
1193b4be Poul Sander 2025-02-03 21:28 2593
            ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 2594
        }
1193b4be Poul Sander 2025-02-03 21:28 2595
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2596
1193b4be Poul Sander 2025-02-03 21:28 2597
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2598
        ImGui::PushID("set3");
1193b4be Poul Sander 2025-02-03 21:28 2599
        for (int i = 0; i < 4; i++)
1193b4be Poul Sander 2025-02-03 21:28 2600
        {
1193b4be Poul Sander 2025-02-03 21:28 2601
            if (i > 0) ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2602
            ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 2603
            ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
1193b4be Poul Sander 2025-02-03 21:28 2604
            ImGui::VSliderFloat("##v", ImVec2(40, 160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
1193b4be Poul Sander 2025-02-03 21:28 2605
            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 2606
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2607
        }
1193b4be Poul Sander 2025-02-03 21:28 2608
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2609
        ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 2610
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2611
    }
1193b4be Poul Sander 2025-02-03 21:28 2612
1193b4be Poul Sander 2025-02-03 21:28 2613
    IMGUI_DEMO_MARKER("Widgets/Drag and drop");
1193b4be Poul Sander 2025-02-03 21:28 2614
    if (ImGui::TreeNode("Drag and Drop"))
1193b4be Poul Sander 2025-02-03 21:28 2615
    {
1193b4be Poul Sander 2025-02-03 21:28 2616
        IMGUI_DEMO_MARKER("Widgets/Drag and drop/Standard widgets");
1193b4be Poul Sander 2025-02-03 21:28 2617
        if (ImGui::TreeNode("Drag and drop in standard widgets"))
1193b4be Poul Sander 2025-02-03 21:28 2618
        {
1193b4be Poul Sander 2025-02-03 21:28 2619
            // ColorEdit widgets automatically act as drag source and drag target.
1193b4be Poul Sander 2025-02-03 21:28 2620
            // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F
1193b4be Poul Sander 2025-02-03 21:28 2621
            // to allow your own widgets to use colors in their drag and drop interaction.
1193b4be Poul Sander 2025-02-03 21:28 2622
            // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo.
1193b4be Poul Sander 2025-02-03 21:28 2623
            HelpMarker("You can drag from the color squares.");
1193b4be Poul Sander 2025-02-03 21:28 2624
            static float col1[3] = { 1.0f, 0.0f, 0.2f };
1193b4be Poul Sander 2025-02-03 21:28 2625
            static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
1193b4be Poul Sander 2025-02-03 21:28 2626
            ImGui::ColorEdit3("color 1", col1);
1193b4be Poul Sander 2025-02-03 21:28 2627
            ImGui::ColorEdit4("color 2", col2);
1193b4be Poul Sander 2025-02-03 21:28 2628
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2629
        }
1193b4be Poul Sander 2025-02-03 21:28 2630
1193b4be Poul Sander 2025-02-03 21:28 2631
        IMGUI_DEMO_MARKER("Widgets/Drag and drop/Copy-swap items");
1193b4be Poul Sander 2025-02-03 21:28 2632
        if (ImGui::TreeNode("Drag and drop to copy/swap items"))
1193b4be Poul Sander 2025-02-03 21:28 2633
        {
1193b4be Poul Sander 2025-02-03 21:28 2634
            enum Mode
1193b4be Poul Sander 2025-02-03 21:28 2635
            {
1193b4be Poul Sander 2025-02-03 21:28 2636
                Mode_Copy,
1193b4be Poul Sander 2025-02-03 21:28 2637
                Mode_Move,
1193b4be Poul Sander 2025-02-03 21:28 2638
                Mode_Swap
1193b4be Poul Sander 2025-02-03 21:28 2639
            };
1193b4be Poul Sander 2025-02-03 21:28 2640
            static int mode = 0;
1193b4be Poul Sander 2025-02-03 21:28 2641
            if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2642
            if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2643
            if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
1193b4be Poul Sander 2025-02-03 21:28 2644
            static const char* names[9] =
1193b4be Poul Sander 2025-02-03 21:28 2645
            {
1193b4be Poul Sander 2025-02-03 21:28 2646
                "Bobby", "Beatrice", "Betty",
1193b4be Poul Sander 2025-02-03 21:28 2647
                "Brianna", "Barry", "Bernard",
1193b4be Poul Sander 2025-02-03 21:28 2648
                "Bibi", "Blaine", "Bryn"
1193b4be Poul Sander 2025-02-03 21:28 2649
            };
1193b4be Poul Sander 2025-02-03 21:28 2650
            for (int n = 0; n < IM_ARRAYSIZE(names); n++)
1193b4be Poul Sander 2025-02-03 21:28 2651
            {
1193b4be Poul Sander 2025-02-03 21:28 2652
                ImGui::PushID(n);
1193b4be Poul Sander 2025-02-03 21:28 2653
                if ((n % 3) != 0)
1193b4be Poul Sander 2025-02-03 21:28 2654
                    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2655
                ImGui::Button(names[n], ImVec2(60, 60));
1193b4be Poul Sander 2025-02-03 21:28 2656
1193b4be Poul Sander 2025-02-03 21:28 2657
                // Our buttons are both drag sources and drag targets here!
1193b4be Poul Sander 2025-02-03 21:28 2658
                if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 2659
                {
1193b4be Poul Sander 2025-02-03 21:28 2660
                    // Set payload to carry the index of our item (could be anything)
1193b4be Poul Sander 2025-02-03 21:28 2661
                    ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));
1193b4be Poul Sander 2025-02-03 21:28 2662
1193b4be Poul Sander 2025-02-03 21:28 2663
                    // Display preview (could be anything, e.g. when dragging an image we could decide to display
1193b4be Poul Sander 2025-02-03 21:28 2664
                    // the filename and a small preview of the image, etc.)
1193b4be Poul Sander 2025-02-03 21:28 2665
                    if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }
1193b4be Poul Sander 2025-02-03 21:28 2666
                    if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
1193b4be Poul Sander 2025-02-03 21:28 2667
                    if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
1193b4be Poul Sander 2025-02-03 21:28 2668
                    ImGui::EndDragDropSource();
1193b4be Poul Sander 2025-02-03 21:28 2669
                }
1193b4be Poul Sander 2025-02-03 21:28 2670
                if (ImGui::BeginDragDropTarget())
1193b4be Poul Sander 2025-02-03 21:28 2671
                {
1193b4be Poul Sander 2025-02-03 21:28 2672
                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
1193b4be Poul Sander 2025-02-03 21:28 2673
                    {
1193b4be Poul Sander 2025-02-03 21:28 2674
                        IM_ASSERT(payload->DataSize == sizeof(int));
1193b4be Poul Sander 2025-02-03 21:28 2675
                        int payload_n = *(const int*)payload->Data;
1193b4be Poul Sander 2025-02-03 21:28 2676
                        if (mode == Mode_Copy)
1193b4be Poul Sander 2025-02-03 21:28 2677
                        {
1193b4be Poul Sander 2025-02-03 21:28 2678
                            names[n] = names[payload_n];
1193b4be Poul Sander 2025-02-03 21:28 2679
                        }
1193b4be Poul Sander 2025-02-03 21:28 2680
                        if (mode == Mode_Move)
1193b4be Poul Sander 2025-02-03 21:28 2681
                        {
1193b4be Poul Sander 2025-02-03 21:28 2682
                            names[n] = names[payload_n];
1193b4be Poul Sander 2025-02-03 21:28 2683
                            names[payload_n] = "";
1193b4be Poul Sander 2025-02-03 21:28 2684
                        }
1193b4be Poul Sander 2025-02-03 21:28 2685
                        if (mode == Mode_Swap)
1193b4be Poul Sander 2025-02-03 21:28 2686
                        {
1193b4be Poul Sander 2025-02-03 21:28 2687
                            const char* tmp = names[n];
1193b4be Poul Sander 2025-02-03 21:28 2688
                            names[n] = names[payload_n];
1193b4be Poul Sander 2025-02-03 21:28 2689
                            names[payload_n] = tmp;
1193b4be Poul Sander 2025-02-03 21:28 2690
                        }
1193b4be Poul Sander 2025-02-03 21:28 2691
                    }
1193b4be Poul Sander 2025-02-03 21:28 2692
                    ImGui::EndDragDropTarget();
1193b4be Poul Sander 2025-02-03 21:28 2693
                }
1193b4be Poul Sander 2025-02-03 21:28 2694
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 2695
            }
1193b4be Poul Sander 2025-02-03 21:28 2696
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2697
        }
1193b4be Poul Sander 2025-02-03 21:28 2698
1193b4be Poul Sander 2025-02-03 21:28 2699
        IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)");
1193b4be Poul Sander 2025-02-03 21:28 2700
        if (ImGui::TreeNode("Drag to reorder items (simple)"))
1193b4be Poul Sander 2025-02-03 21:28 2701
        {
1193b4be Poul Sander 2025-02-03 21:28 2702
            // FIXME: there is temporary (usually single-frame) ID Conflict during reordering as a same item may be submitting twice.
1193b4be Poul Sander 2025-02-03 21:28 2703
            // This code was always slightly faulty but in a way which was not easily noticeable.
1193b4be Poul Sander 2025-02-03 21:28 2704
            // Until we fix this, enable ImGuiItemFlags_AllowDuplicateId to disable detecting the issue.
1193b4be Poul Sander 2025-02-03 21:28 2705
            ImGui::PushItemFlag(ImGuiItemFlags_AllowDuplicateId, true);
1193b4be Poul Sander 2025-02-03 21:28 2706
1193b4be Poul Sander 2025-02-03 21:28 2707
            // Simple reordering
1193b4be Poul Sander 2025-02-03 21:28 2708
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 2709
                "We don't use the drag and drop api at all here! "
1193b4be Poul Sander 2025-02-03 21:28 2710
                "Instead we query when the item is held but not hovered, and order items accordingly.");
1193b4be Poul Sander 2025-02-03 21:28 2711
            static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
1193b4be Poul Sander 2025-02-03 21:28 2712
            for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
1193b4be Poul Sander 2025-02-03 21:28 2713
            {
1193b4be Poul Sander 2025-02-03 21:28 2714
                const char* item = item_names[n];
1193b4be Poul Sander 2025-02-03 21:28 2715
                ImGui::Selectable(item);
1193b4be Poul Sander 2025-02-03 21:28 2716
1193b4be Poul Sander 2025-02-03 21:28 2717
                if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
1193b4be Poul Sander 2025-02-03 21:28 2718
                {
1193b4be Poul Sander 2025-02-03 21:28 2719
                    int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
1193b4be Poul Sander 2025-02-03 21:28 2720
                    if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
1193b4be Poul Sander 2025-02-03 21:28 2721
                    {
1193b4be Poul Sander 2025-02-03 21:28 2722
                        item_names[n] = item_names[n_next];
1193b4be Poul Sander 2025-02-03 21:28 2723
                        item_names[n_next] = item;
1193b4be Poul Sander 2025-02-03 21:28 2724
                        ImGui::ResetMouseDragDelta();
1193b4be Poul Sander 2025-02-03 21:28 2725
                    }
1193b4be Poul Sander 2025-02-03 21:28 2726
                }
1193b4be Poul Sander 2025-02-03 21:28 2727
            }
1193b4be Poul Sander 2025-02-03 21:28 2728
1193b4be Poul Sander 2025-02-03 21:28 2729
            ImGui::PopItemFlag();
1193b4be Poul Sander 2025-02-03 21:28 2730
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2731
        }
1193b4be Poul Sander 2025-02-03 21:28 2732
1193b4be Poul Sander 2025-02-03 21:28 2733
        IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Tooltip at target location");
1193b4be Poul Sander 2025-02-03 21:28 2734
        if (ImGui::TreeNode("Tooltip at target location"))
1193b4be Poul Sander 2025-02-03 21:28 2735
        {
1193b4be Poul Sander 2025-02-03 21:28 2736
            for (int n = 0; n < 2; n++)
1193b4be Poul Sander 2025-02-03 21:28 2737
            {
1193b4be Poul Sander 2025-02-03 21:28 2738
                // Drop targets
1193b4be Poul Sander 2025-02-03 21:28 2739
                ImGui::Button(n ? "drop here##1" : "drop here##0");
1193b4be Poul Sander 2025-02-03 21:28 2740
                if (ImGui::BeginDragDropTarget())
1193b4be Poul Sander 2025-02-03 21:28 2741
                {
1193b4be Poul Sander 2025-02-03 21:28 2742
                    ImGuiDragDropFlags drop_target_flags = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoPreviewTooltip;
1193b4be Poul Sander 2025-02-03 21:28 2743
                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, drop_target_flags))
1193b4be Poul Sander 2025-02-03 21:28 2744
                    {
1193b4be Poul Sander 2025-02-03 21:28 2745
                        IM_UNUSED(payload);
1193b4be Poul Sander 2025-02-03 21:28 2746
                        ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
1193b4be Poul Sander 2025-02-03 21:28 2747
                        ImGui::SetTooltip("Cannot drop here!");
1193b4be Poul Sander 2025-02-03 21:28 2748
                    }
1193b4be Poul Sander 2025-02-03 21:28 2749
                    ImGui::EndDragDropTarget();
1193b4be Poul Sander 2025-02-03 21:28 2750
                }
1193b4be Poul Sander 2025-02-03 21:28 2751
1193b4be Poul Sander 2025-02-03 21:28 2752
                // Drop source
1193b4be Poul Sander 2025-02-03 21:28 2753
                static ImVec4 col4 = { 1.0f, 0.0f, 0.2f, 1.0f };
1193b4be Poul Sander 2025-02-03 21:28 2754
                if (n == 0)
1193b4be Poul Sander 2025-02-03 21:28 2755
                    ImGui::ColorButton("drag me", col4);
1193b4be Poul Sander 2025-02-03 21:28 2756
1193b4be Poul Sander 2025-02-03 21:28 2757
            }
1193b4be Poul Sander 2025-02-03 21:28 2758
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2759
        }
1193b4be Poul Sander 2025-02-03 21:28 2760
1193b4be Poul Sander 2025-02-03 21:28 2761
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2762
    }
1193b4be Poul Sander 2025-02-03 21:28 2763
1193b4be Poul Sander 2025-02-03 21:28 2764
    IMGUI_DEMO_MARKER("Widgets/Querying Item Status (Edited,Active,Hovered etc.)");
1193b4be Poul Sander 2025-02-03 21:28 2765
    if (ImGui::TreeNode("Querying Item Status (Edited/Active/Hovered etc.)"))
1193b4be Poul Sander 2025-02-03 21:28 2766
    {
1193b4be Poul Sander 2025-02-03 21:28 2767
        // Select an item type
1193b4be Poul Sander 2025-02-03 21:28 2768
        const char* item_names[] =
1193b4be Poul Sander 2025-02-03 21:28 2769
        {
1193b4be Poul Sander 2025-02-03 21:28 2770
            "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputTextMultiline", "InputFloat",
1193b4be Poul Sander 2025-02-03 21:28 2771
            "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"
1193b4be Poul Sander 2025-02-03 21:28 2772
        };
1193b4be Poul Sander 2025-02-03 21:28 2773
        static int item_type = 4;
1193b4be Poul Sander 2025-02-03 21:28 2774
        static bool item_disabled = false;
1193b4be Poul Sander 2025-02-03 21:28 2775
        ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
1193b4be Poul Sander 2025-02-03 21:28 2776
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2777
        HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
1193b4be Poul Sander 2025-02-03 21:28 2778
        ImGui::Checkbox("Item Disabled",  &item_disabled);
1193b4be Poul Sander 2025-02-03 21:28 2779
1193b4be Poul Sander 2025-02-03 21:28 2780
        // Submit selected items so we can query their status in the code following it.
1193b4be Poul Sander 2025-02-03 21:28 2781
        bool ret = false;
1193b4be Poul Sander 2025-02-03 21:28 2782
        static bool b = false;
1193b4be Poul Sander 2025-02-03 21:28 2783
        static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
1193b4be Poul Sander 2025-02-03 21:28 2784
        static char str[16] = {};
1193b4be Poul Sander 2025-02-03 21:28 2785
        if (item_disabled)
1193b4be Poul Sander 2025-02-03 21:28 2786
            ImGui::BeginDisabled(true);
1193b4be Poul Sander 2025-02-03 21:28 2787
        if (item_type == 0) { ImGui::Text("ITEM: Text"); }                                              // Testing text items with no identifier/interaction
1193b4be Poul Sander 2025-02-03 21:28 2788
        if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); }                                    // Testing button
1193b4be Poul Sander 2025-02-03 21:28 2789
        if (item_type == 2) { ImGui::PushItemFlag(ImGuiItemFlags_ButtonRepeat, true); ret = ImGui::Button("ITEM: Button"); ImGui::PopItemFlag(); } // Testing button (with repeater)
1193b4be Poul Sander 2025-02-03 21:28 2790
        if (item_type == 3) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); }                            // Testing checkbox
1193b4be Poul Sander 2025-02-03 21:28 2791
        if (item_type == 4) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
1193b4be Poul Sander 2025-02-03 21:28 2792
        if (item_type == 5) { ret = ImGui::InputText("ITEM: InputText", &str[0], IM_ARRAYSIZE(str)); }  // Testing input text (which handles tabbing)
1193b4be Poul Sander 2025-02-03 21:28 2793
        if (item_type == 6) { ret = ImGui::InputTextMultiline("ITEM: InputTextMultiline", &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which uses a child window)
1193b4be Poul Sander 2025-02-03 21:28 2794
        if (item_type == 7) { ret = ImGui::InputFloat("ITEM: InputFloat", col4f, 1.0f); }               // Testing +/- buttons on scalar input
1193b4be Poul Sander 2025-02-03 21:28 2795
        if (item_type == 8) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); }                   // Testing multi-component items (IsItemXXX flags are reported merged)
1193b4be Poul Sander 2025-02-03 21:28 2796
        if (item_type == 9) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
1193b4be Poul Sander 2025-02-03 21:28 2797
        if (item_type == 10){ ret = ImGui::Selectable("ITEM: Selectable"); }                            // Testing selectable item
1193b4be Poul Sander 2025-02-03 21:28 2798
        if (item_type == 11){ ret = ImGui::MenuItem("ITEM: MenuItem"); }                                // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
1193b4be Poul Sander 2025-02-03 21:28 2799
        if (item_type == 12){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); }     // Testing tree node
1193b4be Poul Sander 2025-02-03 21:28 2800
        if (item_type == 13){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
1193b4be Poul Sander 2025-02-03 21:28 2801
        if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); }
1193b4be Poul Sander 2025-02-03 21:28 2802
        if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
1193b4be Poul Sander 2025-02-03 21:28 2803
1193b4be Poul Sander 2025-02-03 21:28 2804
        bool hovered_delay_none = ImGui::IsItemHovered();
1193b4be Poul Sander 2025-02-03 21:28 2805
        bool hovered_delay_stationary = ImGui::IsItemHovered(ImGuiHoveredFlags_Stationary);
1193b4be Poul Sander 2025-02-03 21:28 2806
        bool hovered_delay_short = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort);
1193b4be Poul Sander 2025-02-03 21:28 2807
        bool hovered_delay_normal = ImGui::IsItemHovered(ImGuiHoveredFlags_DelayNormal);
1193b4be Poul Sander 2025-02-03 21:28 2808
        bool hovered_delay_tooltip = ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip); // = Normal + Stationary
1193b4be Poul Sander 2025-02-03 21:28 2809
1193b4be Poul Sander 2025-02-03 21:28 2810
        // Display the values of IsItemHovered() and other common item state functions.
1193b4be Poul Sander 2025-02-03 21:28 2811
        // Note that the ImGuiHoveredFlags_XXX flags can be combined.
1193b4be Poul Sander 2025-02-03 21:28 2812
        // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
1193b4be Poul Sander 2025-02-03 21:28 2813
        // we query every state in a single call to avoid storing them and to simplify the code.
1193b4be Poul Sander 2025-02-03 21:28 2814
        ImGui::BulletText(
1193b4be Poul Sander 2025-02-03 21:28 2815
            "Return value = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2816
            "IsItemFocused() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2817
            "IsItemHovered() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2818
            "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2819
            "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2820
            "IsItemHovered(_AllowWhenOverlappedByItem) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2821
            "IsItemHovered(_AllowWhenOverlappedByWindow) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2822
            "IsItemHovered(_AllowWhenDisabled) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2823
            "IsItemHovered(_RectOnly) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2824
            "IsItemActive() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2825
            "IsItemEdited() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2826
            "IsItemActivated() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2827
            "IsItemDeactivated() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2828
            "IsItemDeactivatedAfterEdit() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2829
            "IsItemVisible() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2830
            "IsItemClicked() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2831
            "IsItemToggledOpen() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2832
            "GetItemRectMin() = (%.1f, %.1f)\n"
1193b4be Poul Sander 2025-02-03 21:28 2833
            "GetItemRectMax() = (%.1f, %.1f)\n"
1193b4be Poul Sander 2025-02-03 21:28 2834
            "GetItemRectSize() = (%.1f, %.1f)",
1193b4be Poul Sander 2025-02-03 21:28 2835
            ret,
1193b4be Poul Sander 2025-02-03 21:28 2836
            ImGui::IsItemFocused(),
1193b4be Poul Sander 2025-02-03 21:28 2837
            ImGui::IsItemHovered(),
1193b4be Poul Sander 2025-02-03 21:28 2838
            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1193b4be Poul Sander 2025-02-03 21:28 2839
            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1193b4be Poul Sander 2025-02-03 21:28 2840
            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByItem),
1193b4be Poul Sander 2025-02-03 21:28 2841
            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlappedByWindow),
1193b4be Poul Sander 2025-02-03 21:28 2842
            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled),
1193b4be Poul Sander 2025-02-03 21:28 2843
            ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
1193b4be Poul Sander 2025-02-03 21:28 2844
            ImGui::IsItemActive(),
1193b4be Poul Sander 2025-02-03 21:28 2845
            ImGui::IsItemEdited(),
1193b4be Poul Sander 2025-02-03 21:28 2846
            ImGui::IsItemActivated(),
1193b4be Poul Sander 2025-02-03 21:28 2847
            ImGui::IsItemDeactivated(),
1193b4be Poul Sander 2025-02-03 21:28 2848
            ImGui::IsItemDeactivatedAfterEdit(),
1193b4be Poul Sander 2025-02-03 21:28 2849
            ImGui::IsItemVisible(),
1193b4be Poul Sander 2025-02-03 21:28 2850
            ImGui::IsItemClicked(),
1193b4be Poul Sander 2025-02-03 21:28 2851
            ImGui::IsItemToggledOpen(),
1193b4be Poul Sander 2025-02-03 21:28 2852
            ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
1193b4be Poul Sander 2025-02-03 21:28 2853
            ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
1193b4be Poul Sander 2025-02-03 21:28 2854
            ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
1193b4be Poul Sander 2025-02-03 21:28 2855
        );
1193b4be Poul Sander 2025-02-03 21:28 2856
        ImGui::BulletText(
1193b4be Poul Sander 2025-02-03 21:28 2857
            "with Hovering Delay or Stationary test:\n"
1193b4be Poul Sander 2025-02-03 21:28 2858
            "IsItemHovered() = = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2859
            "IsItemHovered(_Stationary) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2860
            "IsItemHovered(_DelayShort) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2861
            "IsItemHovered(_DelayNormal) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2862
            "IsItemHovered(_Tooltip) = %d",
1193b4be Poul Sander 2025-02-03 21:28 2863
            hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip);
1193b4be Poul Sander 2025-02-03 21:28 2864
1193b4be Poul Sander 2025-02-03 21:28 2865
        if (item_disabled)
1193b4be Poul Sander 2025-02-03 21:28 2866
            ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 2867
1193b4be Poul Sander 2025-02-03 21:28 2868
        char buf[1] = "";
1193b4be Poul Sander 2025-02-03 21:28 2869
        ImGui::InputText("unused", buf, IM_ARRAYSIZE(buf), ImGuiInputTextFlags_ReadOnly);
1193b4be Poul Sander 2025-02-03 21:28 2870
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 2871
        HelpMarker("This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status.");
1193b4be Poul Sander 2025-02-03 21:28 2872
1193b4be Poul Sander 2025-02-03 21:28 2873
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2874
    }
1193b4be Poul Sander 2025-02-03 21:28 2875
1193b4be Poul Sander 2025-02-03 21:28 2876
    IMGUI_DEMO_MARKER("Widgets/Querying Window Status (Focused,Hovered etc.)");
1193b4be Poul Sander 2025-02-03 21:28 2877
    if (ImGui::TreeNode("Querying Window Status (Focused/Hovered etc.)"))
1193b4be Poul Sander 2025-02-03 21:28 2878
    {
1193b4be Poul Sander 2025-02-03 21:28 2879
        static bool embed_all_inside_a_child_window = false;
1193b4be Poul Sander 2025-02-03 21:28 2880
        ImGui::Checkbox("Embed everything inside a child window for testing _RootWindow flag.", &embed_all_inside_a_child_window);
1193b4be Poul Sander 2025-02-03 21:28 2881
        if (embed_all_inside_a_child_window)
1193b4be Poul Sander 2025-02-03 21:28 2882
            ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), ImGuiChildFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 2883
1193b4be Poul Sander 2025-02-03 21:28 2884
        // Testing IsWindowFocused() function with its various flags.
1193b4be Poul Sander 2025-02-03 21:28 2885
        ImGui::BulletText(
1193b4be Poul Sander 2025-02-03 21:28 2886
            "IsWindowFocused() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2887
            "IsWindowFocused(_ChildWindows) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2888
            "IsWindowFocused(_ChildWindows|_NoPopupHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2889
            "IsWindowFocused(_ChildWindows|_DockHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2890
            "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2891
            "IsWindowFocused(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2892
            "IsWindowFocused(_ChildWindows|_RootWindow|_DockHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2893
            "IsWindowFocused(_RootWindow) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2894
            "IsWindowFocused(_RootWindow|_NoPopupHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2895
            "IsWindowFocused(_RootWindow|_DockHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2896
            "IsWindowFocused(_AnyWindow) = %d\n",
1193b4be Poul Sander 2025-02-03 21:28 2897
            ImGui::IsWindowFocused(),
1193b4be Poul Sander 2025-02-03 21:28 2898
            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
1193b4be Poul Sander 2025-02-03 21:28 2899
            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2900
            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_DockHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2901
            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
1193b4be Poul Sander 2025-02-03 21:28 2902
            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2903
            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_DockHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2904
            ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
1193b4be Poul Sander 2025-02-03 21:28 2905
            ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2906
            ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_DockHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2907
            ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
1193b4be Poul Sander 2025-02-03 21:28 2908
1193b4be Poul Sander 2025-02-03 21:28 2909
        // Testing IsWindowHovered() function with its various flags.
1193b4be Poul Sander 2025-02-03 21:28 2910
        ImGui::BulletText(
1193b4be Poul Sander 2025-02-03 21:28 2911
            "IsWindowHovered() = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2912
            "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2913
            "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2914
            "IsWindowHovered(_ChildWindows) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2915
            "IsWindowHovered(_ChildWindows|_NoPopupHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2916
            "IsWindowHovered(_ChildWindows|_DockHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2917
            "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2918
            "IsWindowHovered(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2919
            "IsWindowHovered(_ChildWindows|_RootWindow|_DockHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2920
            "IsWindowHovered(_RootWindow) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2921
            "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2922
            "IsWindowHovered(_RootWindow|_DockHierarchy) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2923
            "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2924
            "IsWindowHovered(_AnyWindow) = %d\n"
1193b4be Poul Sander 2025-02-03 21:28 2925
            "IsWindowHovered(_Stationary) = %d\n",
1193b4be Poul Sander 2025-02-03 21:28 2926
            ImGui::IsWindowHovered(),
1193b4be Poul Sander 2025-02-03 21:28 2927
            ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1193b4be Poul Sander 2025-02-03 21:28 2928
            ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1193b4be Poul Sander 2025-02-03 21:28 2929
            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
1193b4be Poul Sander 2025-02-03 21:28 2930
            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2931
            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_DockHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2932
            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
1193b4be Poul Sander 2025-02-03 21:28 2933
            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2934
            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_DockHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2935
            ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
1193b4be Poul Sander 2025-02-03 21:28 2936
            ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2937
            ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_DockHierarchy),
1193b4be Poul Sander 2025-02-03 21:28 2938
            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1193b4be Poul Sander 2025-02-03 21:28 2939
            ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow),
1193b4be Poul Sander 2025-02-03 21:28 2940
            ImGui::IsWindowHovered(ImGuiHoveredFlags_Stationary));
1193b4be Poul Sander 2025-02-03 21:28 2941
1193b4be Poul Sander 2025-02-03 21:28 2942
        ImGui::BeginChild("child", ImVec2(0, 50), ImGuiChildFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 2943
        ImGui::Text("This is another child window for testing the _ChildWindows flag.");
1193b4be Poul Sander 2025-02-03 21:28 2944
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 2945
        if (embed_all_inside_a_child_window)
1193b4be Poul Sander 2025-02-03 21:28 2946
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 2947
1193b4be Poul Sander 2025-02-03 21:28 2948
        // Calling IsItemHovered() after begin returns the hovered status of the title bar.
1193b4be Poul Sander 2025-02-03 21:28 2949
        // This is useful in particular if you want to create a context menu associated to the title bar of a window.
1193b4be Poul Sander 2025-02-03 21:28 2950
        // This will also work when docked into a Tab (the Tab replace the Title Bar and guarantee the same properties).
1193b4be Poul Sander 2025-02-03 21:28 2951
        static bool test_window = false;
1193b4be Poul Sander 2025-02-03 21:28 2952
        ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
1193b4be Poul Sander 2025-02-03 21:28 2953
        if (test_window)
1193b4be Poul Sander 2025-02-03 21:28 2954
        {
1193b4be Poul Sander 2025-02-03 21:28 2955
            // FIXME-DOCK: This window cannot be docked within the ImGui Demo window, this will cause a feedback loop and get them stuck.
1193b4be Poul Sander 2025-02-03 21:28 2956
            // Could we fix this through an ImGuiWindowClass feature? Or an API call to tag our parent as "don't skip items"?
1193b4be Poul Sander 2025-02-03 21:28 2957
            ImGui::Begin("Title bar Hovered/Active tests", &test_window);
1193b4be Poul Sander 2025-02-03 21:28 2958
            if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
1193b4be Poul Sander 2025-02-03 21:28 2959
            {
1193b4be Poul Sander 2025-02-03 21:28 2960
                if (ImGui::MenuItem("Close")) { test_window = false; }
1193b4be Poul Sander 2025-02-03 21:28 2961
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 2962
            }
1193b4be Poul Sander 2025-02-03 21:28 2963
            ImGui::Text(
1193b4be Poul Sander 2025-02-03 21:28 2964
                "IsItemHovered() after begin = %d (== is title bar hovered)\n"
1193b4be Poul Sander 2025-02-03 21:28 2965
                "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
1193b4be Poul Sander 2025-02-03 21:28 2966
                ImGui::IsItemHovered(), ImGui::IsItemActive());
1193b4be Poul Sander 2025-02-03 21:28 2967
            ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 2968
        }
1193b4be Poul Sander 2025-02-03 21:28 2969
1193b4be Poul Sander 2025-02-03 21:28 2970
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2971
    }
1193b4be Poul Sander 2025-02-03 21:28 2972
1193b4be Poul Sander 2025-02-03 21:28 2973
    // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd:
1193b4be Poul Sander 2025-02-03 21:28 2974
    // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space)
1193b4be Poul Sander 2025-02-03 21:28 2975
    if (disable_all)
1193b4be Poul Sander 2025-02-03 21:28 2976
        ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 2977
1193b4be Poul Sander 2025-02-03 21:28 2978
    IMGUI_DEMO_MARKER("Widgets/Disable Block");
1193b4be Poul Sander 2025-02-03 21:28 2979
    if (ImGui::TreeNode("Disable block"))
1193b4be Poul Sander 2025-02-03 21:28 2980
    {
1193b4be Poul Sander 2025-02-03 21:28 2981
        ImGui::Checkbox("Disable entire section above", &disable_all);
1193b4be Poul Sander 2025-02-03 21:28 2982
        ImGui::SameLine(); HelpMarker("Demonstrate using BeginDisabled()/EndDisabled() across this section.");
1193b4be Poul Sander 2025-02-03 21:28 2983
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 2984
    }
1193b4be Poul Sander 2025-02-03 21:28 2985
1193b4be Poul Sander 2025-02-03 21:28 2986
    IMGUI_DEMO_MARKER("Widgets/Text Filter");
1193b4be Poul Sander 2025-02-03 21:28 2987
    if (ImGui::TreeNode("Text Filter"))
1193b4be Poul Sander 2025-02-03 21:28 2988
    {
1193b4be Poul Sander 2025-02-03 21:28 2989
        // Helper class to easy setup a text filter.
1193b4be Poul Sander 2025-02-03 21:28 2990
        // You may want to implement a more feature-full filtering scheme in your own application.
1193b4be Poul Sander 2025-02-03 21:28 2991
        HelpMarker("Not a widget per-se, but ImGuiTextFilter is a helper to perform simple filtering on text strings.");
1193b4be Poul Sander 2025-02-03 21:28 2992
        static ImGuiTextFilter filter;
1193b4be Poul Sander 2025-02-03 21:28 2993
        ImGui::Text("Filter usage:\n"
1193b4be Poul Sander 2025-02-03 21:28 2994
            "  \"\"         display all lines\n"
1193b4be Poul Sander 2025-02-03 21:28 2995
            "  \"xxx\"      display lines containing \"xxx\"\n"
1193b4be Poul Sander 2025-02-03 21:28 2996
            "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
1193b4be Poul Sander 2025-02-03 21:28 2997
            "  \"-xxx\"     hide lines containing \"xxx\"");
1193b4be Poul Sander 2025-02-03 21:28 2998
        filter.Draw();
1193b4be Poul Sander 2025-02-03 21:28 2999
        const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
1193b4be Poul Sander 2025-02-03 21:28 3000
        for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
1193b4be Poul Sander 2025-02-03 21:28 3001
            if (filter.PassFilter(lines[i]))
1193b4be Poul Sander 2025-02-03 21:28 3002
                ImGui::BulletText("%s", lines[i]);
1193b4be Poul Sander 2025-02-03 21:28 3003
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3004
    }
1193b4be Poul Sander 2025-02-03 21:28 3005
}
1193b4be Poul Sander 2025-02-03 21:28 3006
1193b4be Poul Sander 2025-02-03 21:28 3007
static const char* ExampleNames[] =
1193b4be Poul Sander 2025-02-03 21:28 3008
{
1193b4be Poul Sander 2025-02-03 21:28 3009
    "Artichoke", "Arugula", "Asparagus", "Avocado", "Bamboo Shoots", "Bean Sprouts", "Beans", "Beet", "Belgian Endive", "Bell Pepper",
1193b4be Poul Sander 2025-02-03 21:28 3010
    "Bitter Gourd", "Bok Choy", "Broccoli", "Brussels Sprouts", "Burdock Root", "Cabbage", "Calabash", "Capers", "Carrot", "Cassava",
1193b4be Poul Sander 2025-02-03 21:28 3011
    "Cauliflower", "Celery", "Celery Root", "Celcuce", "Chayote", "Chinese Broccoli", "Corn", "Cucumber"
1193b4be Poul Sander 2025-02-03 21:28 3012
};
1193b4be Poul Sander 2025-02-03 21:28 3013
1193b4be Poul Sander 2025-02-03 21:28 3014
// Extra functions to add deletion support to ImGuiSelectionBasicStorage
1193b4be Poul Sander 2025-02-03 21:28 3015
struct ExampleSelectionWithDeletion : ImGuiSelectionBasicStorage
1193b4be Poul Sander 2025-02-03 21:28 3016
{
1193b4be Poul Sander 2025-02-03 21:28 3017
    // Find which item should be Focused after deletion.
1193b4be Poul Sander 2025-02-03 21:28 3018
    // Call _before_ item submission. Retunr an index in the before-deletion item list, your item loop should call SetKeyboardFocusHere() on it.
1193b4be Poul Sander 2025-02-03 21:28 3019
    // The subsequent ApplyDeletionPostLoop() code will use it to apply Selection.
1193b4be Poul Sander 2025-02-03 21:28 3020
    // - We cannot provide this logic in core Dear ImGui because we don't have access to selection data.
1193b4be Poul Sander 2025-02-03 21:28 3021
    // - We don't actually manipulate the ImVector<> here, only in ApplyDeletionPostLoop(), but using similar API for consistency and flexibility.
1193b4be Poul Sander 2025-02-03 21:28 3022
    // - Important: Deletion only works if the underlying ImGuiID for your items are stable: aka not depend on their index, but on e.g. item id/ptr.
1193b4be Poul Sander 2025-02-03 21:28 3023
    // FIXME-MULTISELECT: Doesn't take account of the possibility focus target will be moved during deletion. Need refocus or scroll offset.
1193b4be Poul Sander 2025-02-03 21:28 3024
    int ApplyDeletionPreLoop(ImGuiMultiSelectIO* ms_io, int items_count)
1193b4be Poul Sander 2025-02-03 21:28 3025
    {
1193b4be Poul Sander 2025-02-03 21:28 3026
        if (Size == 0)
1193b4be Poul Sander 2025-02-03 21:28 3027
            return -1;
1193b4be Poul Sander 2025-02-03 21:28 3028
1193b4be Poul Sander 2025-02-03 21:28 3029
        // If focused item is not selected...
1193b4be Poul Sander 2025-02-03 21:28 3030
        const int focused_idx = (int)ms_io->NavIdItem;  // Index of currently focused item
1193b4be Poul Sander 2025-02-03 21:28 3031
        if (ms_io->NavIdSelected == false)  // This is merely a shortcut, == Contains(adapter->IndexToStorage(items, focused_idx))
1193b4be Poul Sander 2025-02-03 21:28 3032
        {
1193b4be Poul Sander 2025-02-03 21:28 3033
            ms_io->RangeSrcReset = true;    // Request to recover RangeSrc from NavId next frame. Would be ok to reset even when NavIdSelected==true, but it would take an extra frame to recover RangeSrc when deleting a selected item.
1193b4be Poul Sander 2025-02-03 21:28 3034
            return focused_idx;             // Request to focus same item after deletion.
1193b4be Poul Sander 2025-02-03 21:28 3035
        }
1193b4be Poul Sander 2025-02-03 21:28 3036
1193b4be Poul Sander 2025-02-03 21:28 3037
        // If focused item is selected: land on first unselected item after focused item.
1193b4be Poul Sander 2025-02-03 21:28 3038
        for (int idx = focused_idx + 1; idx < items_count; idx++)
1193b4be Poul Sander 2025-02-03 21:28 3039
            if (!Contains(GetStorageIdFromIndex(idx)))
1193b4be Poul Sander 2025-02-03 21:28 3040
                return idx;
1193b4be Poul Sander 2025-02-03 21:28 3041
1193b4be Poul Sander 2025-02-03 21:28 3042
        // If focused item is selected: otherwise return last unselected item before focused item.
1193b4be Poul Sander 2025-02-03 21:28 3043
        for (int idx = IM_MIN(focused_idx, items_count) - 1; idx >= 0; idx--)
1193b4be Poul Sander 2025-02-03 21:28 3044
            if (!Contains(GetStorageIdFromIndex(idx)))
1193b4be Poul Sander 2025-02-03 21:28 3045
                return idx;
1193b4be Poul Sander 2025-02-03 21:28 3046
1193b4be Poul Sander 2025-02-03 21:28 3047
        return -1;
1193b4be Poul Sander 2025-02-03 21:28 3048
    }
1193b4be Poul Sander 2025-02-03 21:28 3049
1193b4be Poul Sander 2025-02-03 21:28 3050
    // Rewrite item list (delete items) + update selection.
1193b4be Poul Sander 2025-02-03 21:28 3051
    // - Call after EndMultiSelect()
1193b4be Poul Sander 2025-02-03 21:28 3052
    // - We cannot provide this logic in core Dear ImGui because we don't have access to your items, nor to selection data.
1193b4be Poul Sander 2025-02-03 21:28 3053
    template<typename ITEM_TYPE>
1193b4be Poul Sander 2025-02-03 21:28 3054
    void ApplyDeletionPostLoop(ImGuiMultiSelectIO* ms_io, ImVector<ITEM_TYPE>& items, int item_curr_idx_to_select)
1193b4be Poul Sander 2025-02-03 21:28 3055
    {
1193b4be Poul Sander 2025-02-03 21:28 3056
        // Rewrite item list (delete items) + convert old selection index (before deletion) to new selection index (after selection).
1193b4be Poul Sander 2025-02-03 21:28 3057
        // If NavId was not part of selection, we will stay on same item.
1193b4be Poul Sander 2025-02-03 21:28 3058
        ImVector<ITEM_TYPE> new_items;
1193b4be Poul Sander 2025-02-03 21:28 3059
        new_items.reserve(items.Size - Size);
1193b4be Poul Sander 2025-02-03 21:28 3060
        int item_next_idx_to_select = -1;
1193b4be Poul Sander 2025-02-03 21:28 3061
        for (int idx = 0; idx < items.Size; idx++)
1193b4be Poul Sander 2025-02-03 21:28 3062
        {
1193b4be Poul Sander 2025-02-03 21:28 3063
            if (!Contains(GetStorageIdFromIndex(idx)))
1193b4be Poul Sander 2025-02-03 21:28 3064
                new_items.push_back(items[idx]);
1193b4be Poul Sander 2025-02-03 21:28 3065
            if (item_curr_idx_to_select == idx)
1193b4be Poul Sander 2025-02-03 21:28 3066
                item_next_idx_to_select = new_items.Size - 1;
1193b4be Poul Sander 2025-02-03 21:28 3067
        }
1193b4be Poul Sander 2025-02-03 21:28 3068
        items.swap(new_items);
1193b4be Poul Sander 2025-02-03 21:28 3069
1193b4be Poul Sander 2025-02-03 21:28 3070
        // Update selection
1193b4be Poul Sander 2025-02-03 21:28 3071
        Clear();
1193b4be Poul Sander 2025-02-03 21:28 3072
        if (item_next_idx_to_select != -1 && ms_io->NavIdSelected)
1193b4be Poul Sander 2025-02-03 21:28 3073
            SetItemSelected(GetStorageIdFromIndex(item_next_idx_to_select), true);
1193b4be Poul Sander 2025-02-03 21:28 3074
    }
1193b4be Poul Sander 2025-02-03 21:28 3075
};
1193b4be Poul Sander 2025-02-03 21:28 3076
1193b4be Poul Sander 2025-02-03 21:28 3077
// Example: Implement dual list box storage and interface
1193b4be Poul Sander 2025-02-03 21:28 3078
struct ExampleDualListBox
1193b4be Poul Sander 2025-02-03 21:28 3079
{
1193b4be Poul Sander 2025-02-03 21:28 3080
    ImVector<ImGuiID>           Items[2];               // ID is index into ExampleName[]
1193b4be Poul Sander 2025-02-03 21:28 3081
    ImGuiSelectionBasicStorage  Selections[2];          // Store ExampleItemId into selection
1193b4be Poul Sander 2025-02-03 21:28 3082
    bool                        OptKeepSorted = true;
1193b4be Poul Sander 2025-02-03 21:28 3083
1193b4be Poul Sander 2025-02-03 21:28 3084
    void MoveAll(int src, int dst)
1193b4be Poul Sander 2025-02-03 21:28 3085
    {
1193b4be Poul Sander 2025-02-03 21:28 3086
        IM_ASSERT((src == 0 && dst == 1) || (src == 1 && dst == 0));
1193b4be Poul Sander 2025-02-03 21:28 3087
        for (ImGuiID item_id : Items[src])
1193b4be Poul Sander 2025-02-03 21:28 3088
            Items[dst].push_back(item_id);
1193b4be Poul Sander 2025-02-03 21:28 3089
        Items[src].clear();
1193b4be Poul Sander 2025-02-03 21:28 3090
        SortItems(dst);
1193b4be Poul Sander 2025-02-03 21:28 3091
        Selections[src].Swap(Selections[dst]);
1193b4be Poul Sander 2025-02-03 21:28 3092
        Selections[src].Clear();
1193b4be Poul Sander 2025-02-03 21:28 3093
    }
1193b4be Poul Sander 2025-02-03 21:28 3094
    void MoveSelected(int src, int dst)
1193b4be Poul Sander 2025-02-03 21:28 3095
    {
1193b4be Poul Sander 2025-02-03 21:28 3096
        for (int src_n = 0; src_n < Items[src].Size; src_n++)
1193b4be Poul Sander 2025-02-03 21:28 3097
        {
1193b4be Poul Sander 2025-02-03 21:28 3098
            ImGuiID item_id = Items[src][src_n];
1193b4be Poul Sander 2025-02-03 21:28 3099
            if (!Selections[src].Contains(item_id))
1193b4be Poul Sander 2025-02-03 21:28 3100
                continue;
1193b4be Poul Sander 2025-02-03 21:28 3101
            Items[src].erase(&Items[src][src_n]); // FIXME-OPT: Could be implemented more optimally (rebuild src items and swap)
1193b4be Poul Sander 2025-02-03 21:28 3102
            Items[dst].push_back(item_id);
1193b4be Poul Sander 2025-02-03 21:28 3103
            src_n--;
1193b4be Poul Sander 2025-02-03 21:28 3104
        }
1193b4be Poul Sander 2025-02-03 21:28 3105
        if (OptKeepSorted)
1193b4be Poul Sander 2025-02-03 21:28 3106
            SortItems(dst);
1193b4be Poul Sander 2025-02-03 21:28 3107
        Selections[src].Swap(Selections[dst]);
1193b4be Poul Sander 2025-02-03 21:28 3108
        Selections[src].Clear();
1193b4be Poul Sander 2025-02-03 21:28 3109
    }
1193b4be Poul Sander 2025-02-03 21:28 3110
    void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, int side)
1193b4be Poul Sander 2025-02-03 21:28 3111
    {
1193b4be Poul Sander 2025-02-03 21:28 3112
        // In this example we store item id in selection (instead of item index)
1193b4be Poul Sander 2025-02-03 21:28 3113
        Selections[side].UserData = Items[side].Data;
1193b4be Poul Sander 2025-02-03 21:28 3114
        Selections[side].AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImGuiID* items = (ImGuiID*)self->UserData; return items[idx]; };
1193b4be Poul Sander 2025-02-03 21:28 3115
        Selections[side].ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3116
    }
1193b4be Poul Sander 2025-02-03 21:28 3117
    static int IMGUI_CDECL CompareItemsByValue(const void* lhs, const void* rhs)
1193b4be Poul Sander 2025-02-03 21:28 3118
    {
1193b4be Poul Sander 2025-02-03 21:28 3119
        const int* a = (const int*)lhs;
1193b4be Poul Sander 2025-02-03 21:28 3120
        const int* b = (const int*)rhs;
1193b4be Poul Sander 2025-02-03 21:28 3121
        return (*a - *b) > 0 ? +1 : -1;
1193b4be Poul Sander 2025-02-03 21:28 3122
    }
1193b4be Poul Sander 2025-02-03 21:28 3123
    void SortItems(int n)
1193b4be Poul Sander 2025-02-03 21:28 3124
    {
1193b4be Poul Sander 2025-02-03 21:28 3125
        qsort(Items[n].Data, (size_t)Items[n].Size, sizeof(Items[n][0]), CompareItemsByValue);
1193b4be Poul Sander 2025-02-03 21:28 3126
    }
1193b4be Poul Sander 2025-02-03 21:28 3127
    void Show()
1193b4be Poul Sander 2025-02-03 21:28 3128
    {
1193b4be Poul Sander 2025-02-03 21:28 3129
        //ImGui::Checkbox("Sorted", &OptKeepSorted);
1193b4be Poul Sander 2025-02-03 21:28 3130
        if (ImGui::BeginTable("split", 3, ImGuiTableFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 3131
        {
1193b4be Poul Sander 2025-02-03 21:28 3132
            ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);    // Left side
1193b4be Poul Sander 2025-02-03 21:28 3133
            ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);      // Buttons
1193b4be Poul Sander 2025-02-03 21:28 3134
            ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);    // Right side
1193b4be Poul Sander 2025-02-03 21:28 3135
            ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 3136
1193b4be Poul Sander 2025-02-03 21:28 3137
            int request_move_selected = -1;
1193b4be Poul Sander 2025-02-03 21:28 3138
            int request_move_all = -1;
1193b4be Poul Sander 2025-02-03 21:28 3139
            float child_height_0 = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 3140
            for (int side = 0; side < 2; side++)
1193b4be Poul Sander 2025-02-03 21:28 3141
            {
1193b4be Poul Sander 2025-02-03 21:28 3142
                // FIXME-MULTISELECT: Dual List Box: Add context menus
1193b4be Poul Sander 2025-02-03 21:28 3143
                // FIXME-NAV: Using ImGuiWindowFlags_NavFlattened exhibit many issues.
1193b4be Poul Sander 2025-02-03 21:28 3144
                ImVector<ImGuiID>& items = Items[side];
1193b4be Poul Sander 2025-02-03 21:28 3145
                ImGuiSelectionBasicStorage& selection = Selections[side];
1193b4be Poul Sander 2025-02-03 21:28 3146
1193b4be Poul Sander 2025-02-03 21:28 3147
                ImGui::TableSetColumnIndex((side == 0) ? 0 : 2);
1193b4be Poul Sander 2025-02-03 21:28 3148
                ImGui::Text("%s (%d)", (side == 0) ? "Available" : "Basket", items.Size);
1193b4be Poul Sander 2025-02-03 21:28 3149
1193b4be Poul Sander 2025-02-03 21:28 3150
                // Submit scrolling range to avoid glitches on moving/deletion
1193b4be Poul Sander 2025-02-03 21:28 3151
                const float items_height = ImGui::GetTextLineHeightWithSpacing();
1193b4be Poul Sander 2025-02-03 21:28 3152
                ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height));
1193b4be Poul Sander 2025-02-03 21:28 3153
1193b4be Poul Sander 2025-02-03 21:28 3154
                bool child_visible;
1193b4be Poul Sander 2025-02-03 21:28 3155
                if (side == 0)
1193b4be Poul Sander 2025-02-03 21:28 3156
                {
1193b4be Poul Sander 2025-02-03 21:28 3157
                    // Left child is resizable
1193b4be Poul Sander 2025-02-03 21:28 3158
                    ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetFrameHeightWithSpacing() * 4), ImVec2(FLT_MAX, FLT_MAX));
1193b4be Poul Sander 2025-02-03 21:28 3159
                    child_visible = ImGui::BeginChild("0", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY);
1193b4be Poul Sander 2025-02-03 21:28 3160
                    child_height_0 = ImGui::GetWindowSize().y;
1193b4be Poul Sander 2025-02-03 21:28 3161
                }
1193b4be Poul Sander 2025-02-03 21:28 3162
                else
1193b4be Poul Sander 2025-02-03 21:28 3163
                {
1193b4be Poul Sander 2025-02-03 21:28 3164
                    // Right child use same height as left one
1193b4be Poul Sander 2025-02-03 21:28 3165
                    child_visible = ImGui::BeginChild("1", ImVec2(-FLT_MIN, child_height_0), ImGuiChildFlags_FrameStyle);
1193b4be Poul Sander 2025-02-03 21:28 3166
                }
1193b4be Poul Sander 2025-02-03 21:28 3167
                if (child_visible)
1193b4be Poul Sander 2025-02-03 21:28 3168
                {
1193b4be Poul Sander 2025-02-03 21:28 3169
                    ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 3170
                    ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
1193b4be Poul Sander 2025-02-03 21:28 3171
                    ApplySelectionRequests(ms_io, side);
1193b4be Poul Sander 2025-02-03 21:28 3172
1193b4be Poul Sander 2025-02-03 21:28 3173
                    for (int item_n = 0; item_n < items.Size; item_n++)
1193b4be Poul Sander 2025-02-03 21:28 3174
                    {
1193b4be Poul Sander 2025-02-03 21:28 3175
                        ImGuiID item_id = items[item_n];
1193b4be Poul Sander 2025-02-03 21:28 3176
                        bool item_is_selected = selection.Contains(item_id);
1193b4be Poul Sander 2025-02-03 21:28 3177
                        ImGui::SetNextItemSelectionUserData(item_n);
1193b4be Poul Sander 2025-02-03 21:28 3178
                        ImGui::Selectable(ExampleNames[item_id], item_is_selected, ImGuiSelectableFlags_AllowDoubleClick);
1193b4be Poul Sander 2025-02-03 21:28 3179
                        if (ImGui::IsItemFocused())
1193b4be Poul Sander 2025-02-03 21:28 3180
                        {
1193b4be Poul Sander 2025-02-03 21:28 3181
                            // FIXME-MULTISELECT: Dual List Box: Transfer focus
1193b4be Poul Sander 2025-02-03 21:28 3182
                            if (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::IsKeyPressed(ImGuiKey_KeypadEnter))
1193b4be Poul Sander 2025-02-03 21:28 3183
                                request_move_selected = side;
1193b4be Poul Sander 2025-02-03 21:28 3184
                            if (ImGui::IsMouseDoubleClicked(0)) // FIXME-MULTISELECT: Double-click on multi-selection?
1193b4be Poul Sander 2025-02-03 21:28 3185
                                request_move_selected = side;
1193b4be Poul Sander 2025-02-03 21:28 3186
                        }
1193b4be Poul Sander 2025-02-03 21:28 3187
                    }
1193b4be Poul Sander 2025-02-03 21:28 3188
1193b4be Poul Sander 2025-02-03 21:28 3189
                    ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3190
                    ApplySelectionRequests(ms_io, side);
1193b4be Poul Sander 2025-02-03 21:28 3191
                }
1193b4be Poul Sander 2025-02-03 21:28 3192
                ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 3193
            }
1193b4be Poul Sander 2025-02-03 21:28 3194
1193b4be Poul Sander 2025-02-03 21:28 3195
            // Buttons columns
1193b4be Poul Sander 2025-02-03 21:28 3196
            ImGui::TableSetColumnIndex(1);
1193b4be Poul Sander 2025-02-03 21:28 3197
            ImGui::NewLine();
1193b4be Poul Sander 2025-02-03 21:28 3198
            //ImVec2 button_sz = { ImGui::CalcTextSize(">>").x + ImGui::GetStyle().FramePadding.x * 2.0f, ImGui::GetFrameHeight() + padding.y * 2.0f };
1193b4be Poul Sander 2025-02-03 21:28 3199
            ImVec2 button_sz = { ImGui::GetFrameHeight(), ImGui::GetFrameHeight() };
1193b4be Poul Sander 2025-02-03 21:28 3200
1193b4be Poul Sander 2025-02-03 21:28 3201
            // (Using BeginDisabled()/EndDisabled() works but feels distracting given how it is currently visualized)
1193b4be Poul Sander 2025-02-03 21:28 3202
            if (ImGui::Button(">>", button_sz))
1193b4be Poul Sander 2025-02-03 21:28 3203
                request_move_all = 0;
1193b4be Poul Sander 2025-02-03 21:28 3204
            if (ImGui::Button(">", button_sz))
1193b4be Poul Sander 2025-02-03 21:28 3205
                request_move_selected = 0;
1193b4be Poul Sander 2025-02-03 21:28 3206
            if (ImGui::Button("<", button_sz))
1193b4be Poul Sander 2025-02-03 21:28 3207
                request_move_selected = 1;
1193b4be Poul Sander 2025-02-03 21:28 3208
            if (ImGui::Button("<<", button_sz))
1193b4be Poul Sander 2025-02-03 21:28 3209
                request_move_all = 1;
1193b4be Poul Sander 2025-02-03 21:28 3210
1193b4be Poul Sander 2025-02-03 21:28 3211
            // Process requests
1193b4be Poul Sander 2025-02-03 21:28 3212
            if (request_move_all != -1)
1193b4be Poul Sander 2025-02-03 21:28 3213
                MoveAll(request_move_all, request_move_all ^ 1);
1193b4be Poul Sander 2025-02-03 21:28 3214
            if (request_move_selected != -1)
1193b4be Poul Sander 2025-02-03 21:28 3215
                MoveSelected(request_move_selected, request_move_selected ^ 1);
1193b4be Poul Sander 2025-02-03 21:28 3216
1193b4be Poul Sander 2025-02-03 21:28 3217
            // FIXME-MULTISELECT: Support action from outside
1193b4be Poul Sander 2025-02-03 21:28 3218
            /*
1193b4be Poul Sander 2025-02-03 21:28 3219
            if (OptKeepSorted == false)
1193b4be Poul Sander 2025-02-03 21:28 3220
            {
1193b4be Poul Sander 2025-02-03 21:28 3221
                ImGui::NewLine();
1193b4be Poul Sander 2025-02-03 21:28 3222
                if (ImGui::ArrowButton("MoveUp", ImGuiDir_Up)) {}
1193b4be Poul Sander 2025-02-03 21:28 3223
                if (ImGui::ArrowButton("MoveDown", ImGuiDir_Down)) {}
1193b4be Poul Sander 2025-02-03 21:28 3224
            }
1193b4be Poul Sander 2025-02-03 21:28 3225
            */
1193b4be Poul Sander 2025-02-03 21:28 3226
1193b4be Poul Sander 2025-02-03 21:28 3227
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 3228
        }
1193b4be Poul Sander 2025-02-03 21:28 3229
    }
1193b4be Poul Sander 2025-02-03 21:28 3230
};
1193b4be Poul Sander 2025-02-03 21:28 3231
1193b4be Poul Sander 2025-02-03 21:28 3232
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 3233
// [SECTION] ShowDemoWindowMultiSelect()
1193b4be Poul Sander 2025-02-03 21:28 3234
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 3235
// Multi-selection demos
1193b4be Poul Sander 2025-02-03 21:28 3236
// Also read: https://github.com/ocornut/imgui/wiki/Multi-Select
1193b4be Poul Sander 2025-02-03 21:28 3237
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 3238
1193b4be Poul Sander 2025-02-03 21:28 3239
static void ShowDemoWindowMultiSelect(ImGuiDemoWindowData* demo_data)
1193b4be Poul Sander 2025-02-03 21:28 3240
{
1193b4be Poul Sander 2025-02-03 21:28 3241
    IMGUI_DEMO_MARKER("Widgets/Selection State & Multi-Select");
1193b4be Poul Sander 2025-02-03 21:28 3242
    if (ImGui::TreeNode("Selection State & Multi-Select"))
1193b4be Poul Sander 2025-02-03 21:28 3243
    {
1193b4be Poul Sander 2025-02-03 21:28 3244
        HelpMarker("Selections can be built using Selectable(), TreeNode() or other widgets. Selection state is owned by application code/data.");
1193b4be Poul Sander 2025-02-03 21:28 3245
1193b4be Poul Sander 2025-02-03 21:28 3246
        // Without any fancy API: manage single-selection yourself.
1193b4be Poul Sander 2025-02-03 21:28 3247
        IMGUI_DEMO_MARKER("Widgets/Selection State/Single-Select");
1193b4be Poul Sander 2025-02-03 21:28 3248
        if (ImGui::TreeNode("Single-Select"))
1193b4be Poul Sander 2025-02-03 21:28 3249
        {
1193b4be Poul Sander 2025-02-03 21:28 3250
            static int selected = -1;
1193b4be Poul Sander 2025-02-03 21:28 3251
            for (int n = 0; n < 5; n++)
1193b4be Poul Sander 2025-02-03 21:28 3252
            {
1193b4be Poul Sander 2025-02-03 21:28 3253
                char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 3254
                sprintf(buf, "Object %d", n);
1193b4be Poul Sander 2025-02-03 21:28 3255
                if (ImGui::Selectable(buf, selected == n))
1193b4be Poul Sander 2025-02-03 21:28 3256
                    selected = n;
1193b4be Poul Sander 2025-02-03 21:28 3257
            }
1193b4be Poul Sander 2025-02-03 21:28 3258
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3259
        }
1193b4be Poul Sander 2025-02-03 21:28 3260
1193b4be Poul Sander 2025-02-03 21:28 3261
        // Demonstrate implementation a most-basic form of multi-selection manually
1193b4be Poul Sander 2025-02-03 21:28 3262
        // This doesn't support the SHIFT modifier which requires BeginMultiSelect()!
1193b4be Poul Sander 2025-02-03 21:28 3263
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (manual/simplified, without BeginMultiSelect)");
1193b4be Poul Sander 2025-02-03 21:28 3264
        if (ImGui::TreeNode("Multi-Select (manual/simplified, without BeginMultiSelect)"))
1193b4be Poul Sander 2025-02-03 21:28 3265
        {
1193b4be Poul Sander 2025-02-03 21:28 3266
            HelpMarker("Hold CTRL and click to select multiple items.");
1193b4be Poul Sander 2025-02-03 21:28 3267
            static bool selection[5] = { false, false, false, false, false };
1193b4be Poul Sander 2025-02-03 21:28 3268
            for (int n = 0; n < 5; n++)
1193b4be Poul Sander 2025-02-03 21:28 3269
            {
1193b4be Poul Sander 2025-02-03 21:28 3270
                char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 3271
                sprintf(buf, "Object %d", n);
1193b4be Poul Sander 2025-02-03 21:28 3272
                if (ImGui::Selectable(buf, selection[n]))
1193b4be Poul Sander 2025-02-03 21:28 3273
                {
1193b4be Poul Sander 2025-02-03 21:28 3274
                    if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held
1193b4be Poul Sander 2025-02-03 21:28 3275
                        memset(selection, 0, sizeof(selection));
1193b4be Poul Sander 2025-02-03 21:28 3276
                    selection[n] ^= 1; // Toggle current item
1193b4be Poul Sander 2025-02-03 21:28 3277
                }
1193b4be Poul Sander 2025-02-03 21:28 3278
            }
1193b4be Poul Sander 2025-02-03 21:28 3279
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3280
        }
1193b4be Poul Sander 2025-02-03 21:28 3281
1193b4be Poul Sander 2025-02-03 21:28 3282
        // Demonstrate handling proper multi-selection using the BeginMultiSelect/EndMultiSelect API.
1193b4be Poul Sander 2025-02-03 21:28 3283
        // SHIFT+Click w/ CTRL and other standard features are supported.
1193b4be Poul Sander 2025-02-03 21:28 3284
        // We use the ImGuiSelectionBasicStorage helper which you may freely reimplement.
1193b4be Poul Sander 2025-02-03 21:28 3285
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select");
1193b4be Poul Sander 2025-02-03 21:28 3286
        if (ImGui::TreeNode("Multi-Select"))
1193b4be Poul Sander 2025-02-03 21:28 3287
        {
1193b4be Poul Sander 2025-02-03 21:28 3288
            ImGui::Text("Supported features:");
1193b4be Poul Sander 2025-02-03 21:28 3289
            ImGui::BulletText("Keyboard navigation (arrows, page up/down, home/end, space).");
1193b4be Poul Sander 2025-02-03 21:28 3290
            ImGui::BulletText("Ctrl modifier to preserve and toggle selection.");
1193b4be Poul Sander 2025-02-03 21:28 3291
            ImGui::BulletText("Shift modifier for range selection.");
1193b4be Poul Sander 2025-02-03 21:28 3292
            ImGui::BulletText("CTRL+A to select all.");
1193b4be Poul Sander 2025-02-03 21:28 3293
            ImGui::BulletText("Escape to clear selection.");
1193b4be Poul Sander 2025-02-03 21:28 3294
            ImGui::BulletText("Click and drag to box-select.");
1193b4be Poul Sander 2025-02-03 21:28 3295
            ImGui::Text("Tip: Use 'Demo->Tools->Debug Log->Selection' to see selection requests as they happen.");
1193b4be Poul Sander 2025-02-03 21:28 3296
1193b4be Poul Sander 2025-02-03 21:28 3297
            // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection
1193b4be Poul Sander 2025-02-03 21:28 3298
            const int ITEMS_COUNT = 50;
1193b4be Poul Sander 2025-02-03 21:28 3299
            static ImGuiSelectionBasicStorage selection;
1193b4be Poul Sander 2025-02-03 21:28 3300
            ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3301
1193b4be Poul Sander 2025-02-03 21:28 3302
            // The BeginChild() has no purpose for selection logic, other that offering a scrolling region.
1193b4be Poul Sander 2025-02-03 21:28 3303
            if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
1193b4be Poul Sander 2025-02-03 21:28 3304
            {
1193b4be Poul Sander 2025-02-03 21:28 3305
                ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
1193b4be Poul Sander 2025-02-03 21:28 3306
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3307
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3308
1193b4be Poul Sander 2025-02-03 21:28 3309
                for (int n = 0; n < ITEMS_COUNT; n++)
1193b4be Poul Sander 2025-02-03 21:28 3310
                {
1193b4be Poul Sander 2025-02-03 21:28 3311
                    char label[64];
1193b4be Poul Sander 2025-02-03 21:28 3312
                    sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
1193b4be Poul Sander 2025-02-03 21:28 3313
                    bool item_is_selected = selection.Contains((ImGuiID)n);
1193b4be Poul Sander 2025-02-03 21:28 3314
                    ImGui::SetNextItemSelectionUserData(n);
1193b4be Poul Sander 2025-02-03 21:28 3315
                    ImGui::Selectable(label, item_is_selected);
1193b4be Poul Sander 2025-02-03 21:28 3316
                }
1193b4be Poul Sander 2025-02-03 21:28 3317
1193b4be Poul Sander 2025-02-03 21:28 3318
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3319
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3320
            }
1193b4be Poul Sander 2025-02-03 21:28 3321
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 3322
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3323
        }
1193b4be Poul Sander 2025-02-03 21:28 3324
1193b4be Poul Sander 2025-02-03 21:28 3325
        // Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect()
1193b4be Poul Sander 2025-02-03 21:28 3326
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (with clipper)");
1193b4be Poul Sander 2025-02-03 21:28 3327
        if (ImGui::TreeNode("Multi-Select (with clipper)"))
1193b4be Poul Sander 2025-02-03 21:28 3328
        {
1193b4be Poul Sander 2025-02-03 21:28 3329
            // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection
1193b4be Poul Sander 2025-02-03 21:28 3330
            static ImGuiSelectionBasicStorage selection;
1193b4be Poul Sander 2025-02-03 21:28 3331
1193b4be Poul Sander 2025-02-03 21:28 3332
            ImGui::Text("Added features:");
1193b4be Poul Sander 2025-02-03 21:28 3333
            ImGui::BulletText("Using ImGuiListClipper.");
1193b4be Poul Sander 2025-02-03 21:28 3334
1193b4be Poul Sander 2025-02-03 21:28 3335
            const int ITEMS_COUNT = 10000;
1193b4be Poul Sander 2025-02-03 21:28 3336
            ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3337
            if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
1193b4be Poul Sander 2025-02-03 21:28 3338
            {
1193b4be Poul Sander 2025-02-03 21:28 3339
                ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
1193b4be Poul Sander 2025-02-03 21:28 3340
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3341
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3342
1193b4be Poul Sander 2025-02-03 21:28 3343
                ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 3344
                clipper.Begin(ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3345
                if (ms_io->RangeSrcItem != -1)
1193b4be Poul Sander 2025-02-03 21:28 3346
                    clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
1193b4be Poul Sander 2025-02-03 21:28 3347
                while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 3348
                {
1193b4be Poul Sander 2025-02-03 21:28 3349
                    for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
1193b4be Poul Sander 2025-02-03 21:28 3350
                    {
1193b4be Poul Sander 2025-02-03 21:28 3351
                        char label[64];
1193b4be Poul Sander 2025-02-03 21:28 3352
                        sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
1193b4be Poul Sander 2025-02-03 21:28 3353
                        bool item_is_selected = selection.Contains((ImGuiID)n);
1193b4be Poul Sander 2025-02-03 21:28 3354
                        ImGui::SetNextItemSelectionUserData(n);
1193b4be Poul Sander 2025-02-03 21:28 3355
                        ImGui::Selectable(label, item_is_selected);
1193b4be Poul Sander 2025-02-03 21:28 3356
                    }
1193b4be Poul Sander 2025-02-03 21:28 3357
                }
1193b4be Poul Sander 2025-02-03 21:28 3358
1193b4be Poul Sander 2025-02-03 21:28 3359
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3360
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3361
            }
1193b4be Poul Sander 2025-02-03 21:28 3362
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 3363
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3364
        }
1193b4be Poul Sander 2025-02-03 21:28 3365
1193b4be Poul Sander 2025-02-03 21:28 3366
        // Demonstrate dynamic item list + deletion support using the BeginMultiSelect/EndMultiSelect API.
1193b4be Poul Sander 2025-02-03 21:28 3367
        // In order to support Deletion without any glitches you need to:
1193b4be Poul Sander 2025-02-03 21:28 3368
        // - (1) If items are submitted in their own scrolling area, submit contents size SetNextWindowContentSize() ahead of time to prevent one-frame readjustment of scrolling.
1193b4be Poul Sander 2025-02-03 21:28 3369
        // - (2) Items needs to have persistent ID Stack identifier = ID needs to not depends on their index. PushID(index) = KO. PushID(item_id) = OK. This is in order to focus items reliably after a selection.
1193b4be Poul Sander 2025-02-03 21:28 3370
        // - (3) BeginXXXX process
1193b4be Poul Sander 2025-02-03 21:28 3371
        // - (4) Focus process
1193b4be Poul Sander 2025-02-03 21:28 3372
        // - (5) EndXXXX process
1193b4be Poul Sander 2025-02-03 21:28 3373
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (with deletion)");
1193b4be Poul Sander 2025-02-03 21:28 3374
        if (ImGui::TreeNode("Multi-Select (with deletion)"))
1193b4be Poul Sander 2025-02-03 21:28 3375
        {
1193b4be Poul Sander 2025-02-03 21:28 3376
            // Storing items data separately from selection data.
1193b4be Poul Sander 2025-02-03 21:28 3377
            // (you may decide to store selection data inside your item (aka intrusive storage) if you don't need multiple views over same items)
1193b4be Poul Sander 2025-02-03 21:28 3378
            // Use a custom selection.Adapter: store item identifier in Selection (instead of index)
1193b4be Poul Sander 2025-02-03 21:28 3379
            static ImVector<ImGuiID> items;
1193b4be Poul Sander 2025-02-03 21:28 3380
            static ExampleSelectionWithDeletion selection;
1193b4be Poul Sander 2025-02-03 21:28 3381
            selection.UserData = (void*)&items;
1193b4be Poul Sander 2025-02-03 21:28 3382
            selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self, int idx) { ImVector<ImGuiID>* p_items = (ImVector<ImGuiID>*)self->UserData; return (*p_items)[idx]; }; // Index -> ID
1193b4be Poul Sander 2025-02-03 21:28 3383
1193b4be Poul Sander 2025-02-03 21:28 3384
            ImGui::Text("Added features:");
1193b4be Poul Sander 2025-02-03 21:28 3385
            ImGui::BulletText("Dynamic list with Delete key support.");
1193b4be Poul Sander 2025-02-03 21:28 3386
            ImGui::Text("Selection size: %d/%d", selection.Size, items.Size);
1193b4be Poul Sander 2025-02-03 21:28 3387
1193b4be Poul Sander 2025-02-03 21:28 3388
            // Initialize default list with 50 items + button to add/remove items.
1193b4be Poul Sander 2025-02-03 21:28 3389
            static ImGuiID items_next_id = 0;
1193b4be Poul Sander 2025-02-03 21:28 3390
            if (items_next_id == 0)
1193b4be Poul Sander 2025-02-03 21:28 3391
                for (ImGuiID n = 0; n < 50; n++)
1193b4be Poul Sander 2025-02-03 21:28 3392
                    items.push_back(items_next_id++);
1193b4be Poul Sander 2025-02-03 21:28 3393
            if (ImGui::SmallButton("Add 20 items"))     { for (int n = 0; n < 20; n++) { items.push_back(items_next_id++); } }
1193b4be Poul Sander 2025-02-03 21:28 3394
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 3395
            if (ImGui::SmallButton("Remove 20 items"))  { for (int n = IM_MIN(20, items.Size); n > 0; n--) { selection.SetItemSelected(items.back(), false); items.pop_back(); } }
1193b4be Poul Sander 2025-02-03 21:28 3396
1193b4be Poul Sander 2025-02-03 21:28 3397
            // (1) Extra to support deletion: Submit scrolling range to avoid glitches on deletion
1193b4be Poul Sander 2025-02-03 21:28 3398
            const float items_height = ImGui::GetTextLineHeightWithSpacing();
1193b4be Poul Sander 2025-02-03 21:28 3399
            ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height));
1193b4be Poul Sander 2025-02-03 21:28 3400
1193b4be Poul Sander 2025-02-03 21:28 3401
            if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
1193b4be Poul Sander 2025-02-03 21:28 3402
            {
1193b4be Poul Sander 2025-02-03 21:28 3403
                ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
1193b4be Poul Sander 2025-02-03 21:28 3404
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
1193b4be Poul Sander 2025-02-03 21:28 3405
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3406
1193b4be Poul Sander 2025-02-03 21:28 3407
                const bool want_delete = ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0);
1193b4be Poul Sander 2025-02-03 21:28 3408
                const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1;
1193b4be Poul Sander 2025-02-03 21:28 3409
1193b4be Poul Sander 2025-02-03 21:28 3410
                for (int n = 0; n < items.Size; n++)
1193b4be Poul Sander 2025-02-03 21:28 3411
                {
1193b4be Poul Sander 2025-02-03 21:28 3412
                    const ImGuiID item_id = items[n];
1193b4be Poul Sander 2025-02-03 21:28 3413
                    char label[64];
1193b4be Poul Sander 2025-02-03 21:28 3414
                    sprintf(label, "Object %05u: %s", item_id, ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)]);
1193b4be Poul Sander 2025-02-03 21:28 3415
1193b4be Poul Sander 2025-02-03 21:28 3416
                    bool item_is_selected = selection.Contains(item_id);
1193b4be Poul Sander 2025-02-03 21:28 3417
                    ImGui::SetNextItemSelectionUserData(n);
1193b4be Poul Sander 2025-02-03 21:28 3418
                    ImGui::Selectable(label, item_is_selected);
1193b4be Poul Sander 2025-02-03 21:28 3419
                    if (item_curr_idx_to_focus == n)
1193b4be Poul Sander 2025-02-03 21:28 3420
                        ImGui::SetKeyboardFocusHere(-1);
1193b4be Poul Sander 2025-02-03 21:28 3421
                }
1193b4be Poul Sander 2025-02-03 21:28 3422
1193b4be Poul Sander 2025-02-03 21:28 3423
                // Apply multi-select requests
1193b4be Poul Sander 2025-02-03 21:28 3424
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3425
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3426
                if (want_delete)
1193b4be Poul Sander 2025-02-03 21:28 3427
                    selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus);
1193b4be Poul Sander 2025-02-03 21:28 3428
            }
1193b4be Poul Sander 2025-02-03 21:28 3429
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 3430
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3431
        }
1193b4be Poul Sander 2025-02-03 21:28 3432
1193b4be Poul Sander 2025-02-03 21:28 3433
        // Implement a Dual List Box (#6648)
1193b4be Poul Sander 2025-02-03 21:28 3434
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (dual list box)");
1193b4be Poul Sander 2025-02-03 21:28 3435
        if (ImGui::TreeNode("Multi-Select (dual list box)"))
1193b4be Poul Sander 2025-02-03 21:28 3436
        {
1193b4be Poul Sander 2025-02-03 21:28 3437
            // Init default state
1193b4be Poul Sander 2025-02-03 21:28 3438
            static ExampleDualListBox dlb;
1193b4be Poul Sander 2025-02-03 21:28 3439
            if (dlb.Items[0].Size == 0 && dlb.Items[1].Size == 0)
1193b4be Poul Sander 2025-02-03 21:28 3440
                for (int item_id = 0; item_id < IM_ARRAYSIZE(ExampleNames); item_id++)
1193b4be Poul Sander 2025-02-03 21:28 3441
                    dlb.Items[0].push_back((ImGuiID)item_id);
1193b4be Poul Sander 2025-02-03 21:28 3442
1193b4be Poul Sander 2025-02-03 21:28 3443
            // Show
1193b4be Poul Sander 2025-02-03 21:28 3444
            dlb.Show();
1193b4be Poul Sander 2025-02-03 21:28 3445
1193b4be Poul Sander 2025-02-03 21:28 3446
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3447
        }
1193b4be Poul Sander 2025-02-03 21:28 3448
1193b4be Poul Sander 2025-02-03 21:28 3449
        // Demonstrate using the clipper with BeginMultiSelect()/EndMultiSelect()
1193b4be Poul Sander 2025-02-03 21:28 3450
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (in a table)");
1193b4be Poul Sander 2025-02-03 21:28 3451
        if (ImGui::TreeNode("Multi-Select (in a table)"))
1193b4be Poul Sander 2025-02-03 21:28 3452
        {
1193b4be Poul Sander 2025-02-03 21:28 3453
            static ImGuiSelectionBasicStorage selection;
1193b4be Poul Sander 2025-02-03 21:28 3454
1193b4be Poul Sander 2025-02-03 21:28 3455
            const int ITEMS_COUNT = 10000;
1193b4be Poul Sander 2025-02-03 21:28 3456
            ImGui::Text("Selection: %d/%d", selection.Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3457
            if (ImGui::BeginTable("##Basket", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter))
1193b4be Poul Sander 2025-02-03 21:28 3458
            {
1193b4be Poul Sander 2025-02-03 21:28 3459
                ImGui::TableSetupColumn("Object");
1193b4be Poul Sander 2025-02-03 21:28 3460
                ImGui::TableSetupColumn("Action");
1193b4be Poul Sander 2025-02-03 21:28 3461
                ImGui::TableSetupScrollFreeze(0, 1);
1193b4be Poul Sander 2025-02-03 21:28 3462
                ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 3463
1193b4be Poul Sander 2025-02-03 21:28 3464
                ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
1193b4be Poul Sander 2025-02-03 21:28 3465
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3466
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3467
1193b4be Poul Sander 2025-02-03 21:28 3468
                ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 3469
                clipper.Begin(ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3470
                if (ms_io->RangeSrcItem != -1)
1193b4be Poul Sander 2025-02-03 21:28 3471
                    clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
1193b4be Poul Sander 2025-02-03 21:28 3472
                while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 3473
                {
1193b4be Poul Sander 2025-02-03 21:28 3474
                    for (int n = clipper.DisplayStart; n < clipper.DisplayEnd; n++)
1193b4be Poul Sander 2025-02-03 21:28 3475
                    {
1193b4be Poul Sander 2025-02-03 21:28 3476
                        ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 3477
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 3478
                        char label[64];
1193b4be Poul Sander 2025-02-03 21:28 3479
                        sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
1193b4be Poul Sander 2025-02-03 21:28 3480
                        bool item_is_selected = selection.Contains((ImGuiID)n);
1193b4be Poul Sander 2025-02-03 21:28 3481
                        ImGui::SetNextItemSelectionUserData(n);
1193b4be Poul Sander 2025-02-03 21:28 3482
                        ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap);
1193b4be Poul Sander 2025-02-03 21:28 3483
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 3484
                        ImGui::SmallButton("hello");
1193b4be Poul Sander 2025-02-03 21:28 3485
                    }
1193b4be Poul Sander 2025-02-03 21:28 3486
                }
1193b4be Poul Sander 2025-02-03 21:28 3487
1193b4be Poul Sander 2025-02-03 21:28 3488
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3489
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3490
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 3491
            }
1193b4be Poul Sander 2025-02-03 21:28 3492
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3493
        }
1193b4be Poul Sander 2025-02-03 21:28 3494
1193b4be Poul Sander 2025-02-03 21:28 3495
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (checkboxes)");
1193b4be Poul Sander 2025-02-03 21:28 3496
        if (ImGui::TreeNode("Multi-Select (checkboxes)"))
1193b4be Poul Sander 2025-02-03 21:28 3497
        {
1193b4be Poul Sander 2025-02-03 21:28 3498
            ImGui::Text("In a list of checkboxes (not selectable):");
1193b4be Poul Sander 2025-02-03 21:28 3499
            ImGui::BulletText("Using _NoAutoSelect + _NoAutoClear flags.");
1193b4be Poul Sander 2025-02-03 21:28 3500
            ImGui::BulletText("Shift+Click to check multiple boxes.");
1193b4be Poul Sander 2025-02-03 21:28 3501
            ImGui::BulletText("Shift+Keyboard to copy current value to other boxes.");
1193b4be Poul Sander 2025-02-03 21:28 3502
1193b4be Poul Sander 2025-02-03 21:28 3503
            // If you have an array of checkboxes, you may want to use NoAutoSelect + NoAutoClear and the ImGuiSelectionExternalStorage helper.
1193b4be Poul Sander 2025-02-03 21:28 3504
            static bool items[20] = {};
1193b4be Poul Sander 2025-02-03 21:28 3505
            static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_NoAutoSelect | ImGuiMultiSelectFlags_NoAutoClear | ImGuiMultiSelectFlags_ClearOnEscape;
1193b4be Poul Sander 2025-02-03 21:28 3506
            ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect);
1193b4be Poul Sander 2025-02-03 21:28 3507
            ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear);
1193b4be Poul Sander 2025-02-03 21:28 3508
            ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d); // Cannot use ImGuiMultiSelectFlags_BoxSelect1d as checkboxes are varying width.
1193b4be Poul Sander 2025-02-03 21:28 3509
1193b4be Poul Sander 2025-02-03 21:28 3510
            if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY))
1193b4be Poul Sander 2025-02-03 21:28 3511
            {
1193b4be Poul Sander 2025-02-03 21:28 3512
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, -1, IM_ARRAYSIZE(items));
1193b4be Poul Sander 2025-02-03 21:28 3513
                ImGuiSelectionExternalStorage storage_wrapper;
1193b4be Poul Sander 2025-02-03 21:28 3514
                storage_wrapper.UserData = (void*)items;
1193b4be Poul Sander 2025-02-03 21:28 3515
                storage_wrapper.AdapterSetItemSelected = [](ImGuiSelectionExternalStorage* self, int n, bool selected) { bool* array = (bool*)self->UserData; array[n] = selected; };
1193b4be Poul Sander 2025-02-03 21:28 3516
                storage_wrapper.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3517
                for (int n = 0; n < 20; n++)
1193b4be Poul Sander 2025-02-03 21:28 3518
                {
1193b4be Poul Sander 2025-02-03 21:28 3519
                    char label[32];
1193b4be Poul Sander 2025-02-03 21:28 3520
                    sprintf(label, "Item %d", n);
1193b4be Poul Sander 2025-02-03 21:28 3521
                    ImGui::SetNextItemSelectionUserData(n);
1193b4be Poul Sander 2025-02-03 21:28 3522
                    ImGui::Checkbox(label, &items[n]);
1193b4be Poul Sander 2025-02-03 21:28 3523
                }
1193b4be Poul Sander 2025-02-03 21:28 3524
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3525
                storage_wrapper.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3526
            }
1193b4be Poul Sander 2025-02-03 21:28 3527
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 3528
1193b4be Poul Sander 2025-02-03 21:28 3529
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3530
        }
1193b4be Poul Sander 2025-02-03 21:28 3531
1193b4be Poul Sander 2025-02-03 21:28 3532
        // Demonstrate individual selection scopes in same window
1193b4be Poul Sander 2025-02-03 21:28 3533
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (multiple scopes)");
1193b4be Poul Sander 2025-02-03 21:28 3534
        if (ImGui::TreeNode("Multi-Select (multiple scopes)"))
1193b4be Poul Sander 2025-02-03 21:28 3535
        {
1193b4be Poul Sander 2025-02-03 21:28 3536
            // Use default select: Pass index to SetNextItemSelectionUserData(), store index in Selection
1193b4be Poul Sander 2025-02-03 21:28 3537
            const int SCOPES_COUNT = 3;
1193b4be Poul Sander 2025-02-03 21:28 3538
            const int ITEMS_COUNT = 8; // Per scope
1193b4be Poul Sander 2025-02-03 21:28 3539
            static ImGuiSelectionBasicStorage selections_data[SCOPES_COUNT];
1193b4be Poul Sander 2025-02-03 21:28 3540
1193b4be Poul Sander 2025-02-03 21:28 3541
            // Use ImGuiMultiSelectFlags_ScopeRect to not affect other selections in same window.
1193b4be Poul Sander 2025-02-03 21:28 3542
            static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ScopeRect | ImGuiMultiSelectFlags_ClearOnEscape;// | ImGuiMultiSelectFlags_ClearOnClickVoid;
1193b4be Poul Sander 2025-02-03 21:28 3543
            if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeWindow", &flags, ImGuiMultiSelectFlags_ScopeWindow) && (flags & ImGuiMultiSelectFlags_ScopeWindow))
1193b4be Poul Sander 2025-02-03 21:28 3544
                flags &= ~ImGuiMultiSelectFlags_ScopeRect;
1193b4be Poul Sander 2025-02-03 21:28 3545
            if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeRect", &flags, ImGuiMultiSelectFlags_ScopeRect) && (flags & ImGuiMultiSelectFlags_ScopeRect))
1193b4be Poul Sander 2025-02-03 21:28 3546
                flags &= ~ImGuiMultiSelectFlags_ScopeWindow;
1193b4be Poul Sander 2025-02-03 21:28 3547
            ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickVoid);
1193b4be Poul Sander 2025-02-03 21:28 3548
            ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d);
1193b4be Poul Sander 2025-02-03 21:28 3549
1193b4be Poul Sander 2025-02-03 21:28 3550
            for (int selection_scope_n = 0; selection_scope_n < SCOPES_COUNT; selection_scope_n++)
1193b4be Poul Sander 2025-02-03 21:28 3551
            {
1193b4be Poul Sander 2025-02-03 21:28 3552
                ImGui::PushID(selection_scope_n);
1193b4be Poul Sander 2025-02-03 21:28 3553
                ImGuiSelectionBasicStorage* selection = &selections_data[selection_scope_n];
1193b4be Poul Sander 2025-02-03 21:28 3554
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection->Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3555
                selection->ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3556
1193b4be Poul Sander 2025-02-03 21:28 3557
                ImGui::SeparatorText("Selection scope");
1193b4be Poul Sander 2025-02-03 21:28 3558
                ImGui::Text("Selection size: %d/%d", selection->Size, ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 3559
1193b4be Poul Sander 2025-02-03 21:28 3560
                for (int n = 0; n < ITEMS_COUNT; n++)
1193b4be Poul Sander 2025-02-03 21:28 3561
                {
1193b4be Poul Sander 2025-02-03 21:28 3562
                    char label[64];
1193b4be Poul Sander 2025-02-03 21:28 3563
                    sprintf(label, "Object %05d: %s", n, ExampleNames[n % IM_ARRAYSIZE(ExampleNames)]);
1193b4be Poul Sander 2025-02-03 21:28 3564
                    bool item_is_selected = selection->Contains((ImGuiID)n);
1193b4be Poul Sander 2025-02-03 21:28 3565
                    ImGui::SetNextItemSelectionUserData(n);
1193b4be Poul Sander 2025-02-03 21:28 3566
                    ImGui::Selectable(label, item_is_selected);
1193b4be Poul Sander 2025-02-03 21:28 3567
                }
1193b4be Poul Sander 2025-02-03 21:28 3568
1193b4be Poul Sander 2025-02-03 21:28 3569
                // Apply multi-select requests
1193b4be Poul Sander 2025-02-03 21:28 3570
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3571
                selection->ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3572
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 3573
            }
1193b4be Poul Sander 2025-02-03 21:28 3574
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3575
        }
1193b4be Poul Sander 2025-02-03 21:28 3576
1193b4be Poul Sander 2025-02-03 21:28 3577
        // See ShowExampleAppAssetsBrowser()
1193b4be Poul Sander 2025-02-03 21:28 3578
        if (ImGui::TreeNode("Multi-Select (tiled assets browser)"))
1193b4be Poul Sander 2025-02-03 21:28 3579
        {
1193b4be Poul Sander 2025-02-03 21:28 3580
            ImGui::Checkbox("Assets Browser", &demo_data->ShowAppAssetsBrowser);
1193b4be Poul Sander 2025-02-03 21:28 3581
            ImGui::Text("(also access from 'Examples->Assets Browser' in menu)");
1193b4be Poul Sander 2025-02-03 21:28 3582
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3583
        }
1193b4be Poul Sander 2025-02-03 21:28 3584
1193b4be Poul Sander 2025-02-03 21:28 3585
        // Demonstrate supporting multiple-selection in a tree.
1193b4be Poul Sander 2025-02-03 21:28 3586
        // - We don't use linear indices for selection user data, but our ExampleTreeNode* pointer directly!
1193b4be Poul Sander 2025-02-03 21:28 3587
        //   This showcase how SetNextItemSelectionUserData() never assume indices!
1193b4be Poul Sander 2025-02-03 21:28 3588
        // - The difficulty here is to "interpolate" from RangeSrcItem to RangeDstItem in the SetAll/SetRange request.
1193b4be Poul Sander 2025-02-03 21:28 3589
        //   We want this interpolation to match what the user sees: in visible order, skipping closed nodes.
1193b4be Poul Sander 2025-02-03 21:28 3590
        //   This is implemented by our TreeGetNextNodeInVisibleOrder() user-space helper.
1193b4be Poul Sander 2025-02-03 21:28 3591
        // - Important: In a real codebase aiming to implement full-featured selectable tree with custom filtering, you
1193b4be Poul Sander 2025-02-03 21:28 3592
        //   are more likely to build an array mapping sequential indices to visible tree nodes, since your
1193b4be Poul Sander 2025-02-03 21:28 3593
        //   filtering/search + clipping process will benefit from it. Having this will make this interpolation much easier.
1193b4be Poul Sander 2025-02-03 21:28 3594
        // - Consider this a prototype: we are working toward simplifying some of it.
1193b4be Poul Sander 2025-02-03 21:28 3595
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (trees)");
1193b4be Poul Sander 2025-02-03 21:28 3596
        if (ImGui::TreeNode("Multi-Select (trees)"))
1193b4be Poul Sander 2025-02-03 21:28 3597
        {
1193b4be Poul Sander 2025-02-03 21:28 3598
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 3599
                "This is rather advanced and experimental. If you are getting started with multi-select,"
1193b4be Poul Sander 2025-02-03 21:28 3600
                "please don't start by looking at how to use it for a tree!\n\n"
1193b4be Poul Sander 2025-02-03 21:28 3601
                "Future versions will try to simplify and formalize some of this.");
1193b4be Poul Sander 2025-02-03 21:28 3602
1193b4be Poul Sander 2025-02-03 21:28 3603
            struct ExampleTreeFuncs
1193b4be Poul Sander 2025-02-03 21:28 3604
            {
1193b4be Poul Sander 2025-02-03 21:28 3605
                static void DrawNode(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection)
1193b4be Poul Sander 2025-02-03 21:28 3606
                {
1193b4be Poul Sander 2025-02-03 21:28 3607
                    ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
1193b4be Poul Sander 2025-02-03 21:28 3608
                    tree_node_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere; // Enable pressing left to jump to parent
1193b4be Poul Sander 2025-02-03 21:28 3609
                    if (node->Childs.Size == 0)
1193b4be Poul Sander 2025-02-03 21:28 3610
                        tree_node_flags |= ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_Leaf;
1193b4be Poul Sander 2025-02-03 21:28 3611
                    if (selection->Contains((ImGuiID)node->UID))
1193b4be Poul Sander 2025-02-03 21:28 3612
                        tree_node_flags |= ImGuiTreeNodeFlags_Selected;
1193b4be Poul Sander 2025-02-03 21:28 3613
1193b4be Poul Sander 2025-02-03 21:28 3614
                    // Using SetNextItemStorageID() to specify storage id, so we can easily peek into
1193b4be Poul Sander 2025-02-03 21:28 3615
                    // the storage holding open/close stage, using our TreeNodeGetOpen/TreeNodeSetOpen() functions.
1193b4be Poul Sander 2025-02-03 21:28 3616
                    ImGui::SetNextItemSelectionUserData((ImGuiSelectionUserData)(intptr_t)node);
1193b4be Poul Sander 2025-02-03 21:28 3617
                    ImGui::SetNextItemStorageID((ImGuiID)node->UID);
1193b4be Poul Sander 2025-02-03 21:28 3618
                    if (ImGui::TreeNodeEx(node->Name, tree_node_flags))
1193b4be Poul Sander 2025-02-03 21:28 3619
                    {
1193b4be Poul Sander 2025-02-03 21:28 3620
                        for (ExampleTreeNode* child : node->Childs)
1193b4be Poul Sander 2025-02-03 21:28 3621
                            DrawNode(child, selection);
1193b4be Poul Sander 2025-02-03 21:28 3622
                        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3623
                    }
1193b4be Poul Sander 2025-02-03 21:28 3624
                    else if (ImGui::IsItemToggledOpen())
1193b4be Poul Sander 2025-02-03 21:28 3625
                    {
1193b4be Poul Sander 2025-02-03 21:28 3626
                        TreeCloseAndUnselectChildNodes(node, selection);
1193b4be Poul Sander 2025-02-03 21:28 3627
                    }
1193b4be Poul Sander 2025-02-03 21:28 3628
                }
1193b4be Poul Sander 2025-02-03 21:28 3629
1193b4be Poul Sander 2025-02-03 21:28 3630
                static bool TreeNodeGetOpen(ExampleTreeNode* node)
1193b4be Poul Sander 2025-02-03 21:28 3631
                {
1193b4be Poul Sander 2025-02-03 21:28 3632
                    return ImGui::GetStateStorage()->GetBool((ImGuiID)node->UID);
1193b4be Poul Sander 2025-02-03 21:28 3633
                }
1193b4be Poul Sander 2025-02-03 21:28 3634
1193b4be Poul Sander 2025-02-03 21:28 3635
                static void TreeNodeSetOpen(ExampleTreeNode* node, bool open)
1193b4be Poul Sander 2025-02-03 21:28 3636
                {
1193b4be Poul Sander 2025-02-03 21:28 3637
                    ImGui::GetStateStorage()->SetBool((ImGuiID)node->UID, open);
1193b4be Poul Sander 2025-02-03 21:28 3638
                }
1193b4be Poul Sander 2025-02-03 21:28 3639
1193b4be Poul Sander 2025-02-03 21:28 3640
                // When closing a node: 1) close and unselect all child nodes, 2) select parent if any child was selected.
1193b4be Poul Sander 2025-02-03 21:28 3641
                // FIXME: This is currently handled by user logic but I'm hoping to eventually provide tree node
1193b4be Poul Sander 2025-02-03 21:28 3642
                // features to do this automatically, e.g. a ImGuiTreeNodeFlags_AutoCloseChildNodes etc.
1193b4be Poul Sander 2025-02-03 21:28 3643
                static int TreeCloseAndUnselectChildNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, int depth = 0)
1193b4be Poul Sander 2025-02-03 21:28 3644
                {
1193b4be Poul Sander 2025-02-03 21:28 3645
                    // Recursive close (the test for depth == 0 is because we call this on a node that was just closed!)
1193b4be Poul Sander 2025-02-03 21:28 3646
                    int unselected_count = selection->Contains((ImGuiID)node->UID) ? 1 : 0;
1193b4be Poul Sander 2025-02-03 21:28 3647
                    if (depth == 0 || TreeNodeGetOpen(node))
1193b4be Poul Sander 2025-02-03 21:28 3648
                    {
1193b4be Poul Sander 2025-02-03 21:28 3649
                        for (ExampleTreeNode* child : node->Childs)
1193b4be Poul Sander 2025-02-03 21:28 3650
                            unselected_count += TreeCloseAndUnselectChildNodes(child, selection, depth + 1);
1193b4be Poul Sander 2025-02-03 21:28 3651
                        TreeNodeSetOpen(node, false);
1193b4be Poul Sander 2025-02-03 21:28 3652
                    }
1193b4be Poul Sander 2025-02-03 21:28 3653
1193b4be Poul Sander 2025-02-03 21:28 3654
                    // Select root node if any of its child was selected, otherwise unselect
1193b4be Poul Sander 2025-02-03 21:28 3655
                    selection->SetItemSelected((ImGuiID)node->UID, (depth == 0 && unselected_count > 0));
1193b4be Poul Sander 2025-02-03 21:28 3656
                    return unselected_count;
1193b4be Poul Sander 2025-02-03 21:28 3657
                }
1193b4be Poul Sander 2025-02-03 21:28 3658
1193b4be Poul Sander 2025-02-03 21:28 3659
                // Apply multi-selection requests
1193b4be Poul Sander 2025-02-03 21:28 3660
                static void ApplySelectionRequests(ImGuiMultiSelectIO* ms_io, ExampleTreeNode* tree, ImGuiSelectionBasicStorage* selection)
1193b4be Poul Sander 2025-02-03 21:28 3661
                {
1193b4be Poul Sander 2025-02-03 21:28 3662
                    for (ImGuiSelectionRequest& req : ms_io->Requests)
1193b4be Poul Sander 2025-02-03 21:28 3663
                    {
1193b4be Poul Sander 2025-02-03 21:28 3664
                        if (req.Type == ImGuiSelectionRequestType_SetAll)
1193b4be Poul Sander 2025-02-03 21:28 3665
                        {
1193b4be Poul Sander 2025-02-03 21:28 3666
                            if (req.Selected)
1193b4be Poul Sander 2025-02-03 21:28 3667
                                TreeSetAllInOpenNodes(tree, selection, req.Selected);
1193b4be Poul Sander 2025-02-03 21:28 3668
                            else
1193b4be Poul Sander 2025-02-03 21:28 3669
                                selection->Clear();
1193b4be Poul Sander 2025-02-03 21:28 3670
                        }
1193b4be Poul Sander 2025-02-03 21:28 3671
                        else if (req.Type == ImGuiSelectionRequestType_SetRange)
1193b4be Poul Sander 2025-02-03 21:28 3672
                        {
1193b4be Poul Sander 2025-02-03 21:28 3673
                            ExampleTreeNode* first_node = (ExampleTreeNode*)(intptr_t)req.RangeFirstItem;
1193b4be Poul Sander 2025-02-03 21:28 3674
                            ExampleTreeNode* last_node = (ExampleTreeNode*)(intptr_t)req.RangeLastItem;
1193b4be Poul Sander 2025-02-03 21:28 3675
                            for (ExampleTreeNode* node = first_node; node != NULL; node = TreeGetNextNodeInVisibleOrder(node, last_node))
1193b4be Poul Sander 2025-02-03 21:28 3676
                                selection->SetItemSelected((ImGuiID)node->UID, req.Selected);
1193b4be Poul Sander 2025-02-03 21:28 3677
                        }
1193b4be Poul Sander 2025-02-03 21:28 3678
                    }
1193b4be Poul Sander 2025-02-03 21:28 3679
                }
1193b4be Poul Sander 2025-02-03 21:28 3680
1193b4be Poul Sander 2025-02-03 21:28 3681
                static void TreeSetAllInOpenNodes(ExampleTreeNode* node, ImGuiSelectionBasicStorage* selection, bool selected)
1193b4be Poul Sander 2025-02-03 21:28 3682
                {
1193b4be Poul Sander 2025-02-03 21:28 3683
                    if (node->Parent != NULL) // Root node isn't visible nor selectable in our scheme
1193b4be Poul Sander 2025-02-03 21:28 3684
                        selection->SetItemSelected((ImGuiID)node->UID, selected);
1193b4be Poul Sander 2025-02-03 21:28 3685
                    if (node->Parent == NULL || TreeNodeGetOpen(node))
1193b4be Poul Sander 2025-02-03 21:28 3686
                        for (ExampleTreeNode* child : node->Childs)
1193b4be Poul Sander 2025-02-03 21:28 3687
                            TreeSetAllInOpenNodes(child, selection, selected);
1193b4be Poul Sander 2025-02-03 21:28 3688
                }
1193b4be Poul Sander 2025-02-03 21:28 3689
1193b4be Poul Sander 2025-02-03 21:28 3690
                // Interpolate in *user-visible order* AND only *over opened nodes*.
1193b4be Poul Sander 2025-02-03 21:28 3691
                // If you have a sequential mapping tables (e.g. generated after a filter/search pass) this would be simpler.
1193b4be Poul Sander 2025-02-03 21:28 3692
                // Here the tricks are that:
1193b4be Poul Sander 2025-02-03 21:28 3693
                // - we store/maintain ExampleTreeNode::IndexInParent which allows implementing a linear iterator easily, without searches, without recursion.
1193b4be Poul Sander 2025-02-03 21:28 3694
                //   this could be replaced by a search in parent, aka 'int index_in_parent = curr_node->Parent->Childs.find_index(curr_node)'
1193b4be Poul Sander 2025-02-03 21:28 3695
                //   which would only be called when crossing from child to a parent, aka not too much.
1193b4be Poul Sander 2025-02-03 21:28 3696
                // - we call SetNextItemStorageID() before our TreeNode() calls with an ID which doesn't relate to UI stack,
1193b4be Poul Sander 2025-02-03 21:28 3697
                //   making it easier to call TreeNodeGetOpen()/TreeNodeSetOpen() from any location.
1193b4be Poul Sander 2025-02-03 21:28 3698
                static ExampleTreeNode* TreeGetNextNodeInVisibleOrder(ExampleTreeNode* curr_node, ExampleTreeNode* last_node)
1193b4be Poul Sander 2025-02-03 21:28 3699
                {
1193b4be Poul Sander 2025-02-03 21:28 3700
                    // Reached last node
1193b4be Poul Sander 2025-02-03 21:28 3701
                    if (curr_node == last_node)
1193b4be Poul Sander 2025-02-03 21:28 3702
                        return NULL;
1193b4be Poul Sander 2025-02-03 21:28 3703
1193b4be Poul Sander 2025-02-03 21:28 3704
                    // Recurse into childs. Query storage to tell if the node is open.
1193b4be Poul Sander 2025-02-03 21:28 3705
                    if (curr_node->Childs.Size > 0 && TreeNodeGetOpen(curr_node))
1193b4be Poul Sander 2025-02-03 21:28 3706
                        return curr_node->Childs[0];
1193b4be Poul Sander 2025-02-03 21:28 3707
1193b4be Poul Sander 2025-02-03 21:28 3708
                    // Next sibling, then into our own parent
1193b4be Poul Sander 2025-02-03 21:28 3709
                    while (curr_node->Parent != NULL)
1193b4be Poul Sander 2025-02-03 21:28 3710
                    {
1193b4be Poul Sander 2025-02-03 21:28 3711
                        if (curr_node->IndexInParent + 1 < curr_node->Parent->Childs.Size)
1193b4be Poul Sander 2025-02-03 21:28 3712
                            return curr_node->Parent->Childs[curr_node->IndexInParent + 1];
1193b4be Poul Sander 2025-02-03 21:28 3713
                        curr_node = curr_node->Parent;
1193b4be Poul Sander 2025-02-03 21:28 3714
                    }
1193b4be Poul Sander 2025-02-03 21:28 3715
                    return NULL;
1193b4be Poul Sander 2025-02-03 21:28 3716
                }
1193b4be Poul Sander 2025-02-03 21:28 3717
1193b4be Poul Sander 2025-02-03 21:28 3718
            }; // ExampleTreeFuncs
1193b4be Poul Sander 2025-02-03 21:28 3719
1193b4be Poul Sander 2025-02-03 21:28 3720
            static ImGuiSelectionBasicStorage selection;
1193b4be Poul Sander 2025-02-03 21:28 3721
            if (demo_data->DemoTree == NULL)
1193b4be Poul Sander 2025-02-03 21:28 3722
                demo_data->DemoTree = ExampleTree_CreateDemoTree(); // Create tree once
1193b4be Poul Sander 2025-02-03 21:28 3723
            ImGui::Text("Selection size: %d", selection.Size);
1193b4be Poul Sander 2025-02-03 21:28 3724
1193b4be Poul Sander 2025-02-03 21:28 3725
            if (ImGui::BeginChild("##Tree", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
1193b4be Poul Sander 2025-02-03 21:28 3726
            {
1193b4be Poul Sander 2025-02-03 21:28 3727
                ExampleTreeNode* tree = demo_data->DemoTree;
1193b4be Poul Sander 2025-02-03 21:28 3728
                ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect2d;
1193b4be Poul Sander 2025-02-03 21:28 3729
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, selection.Size, -1);
1193b4be Poul Sander 2025-02-03 21:28 3730
                ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection);
1193b4be Poul Sander 2025-02-03 21:28 3731
                for (ExampleTreeNode* node : tree->Childs)
1193b4be Poul Sander 2025-02-03 21:28 3732
                    ExampleTreeFuncs::DrawNode(node, &selection);
1193b4be Poul Sander 2025-02-03 21:28 3733
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3734
                ExampleTreeFuncs::ApplySelectionRequests(ms_io, tree, &selection);
1193b4be Poul Sander 2025-02-03 21:28 3735
            }
1193b4be Poul Sander 2025-02-03 21:28 3736
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 3737
1193b4be Poul Sander 2025-02-03 21:28 3738
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3739
        }
1193b4be Poul Sander 2025-02-03 21:28 3740
1193b4be Poul Sander 2025-02-03 21:28 3741
        // Advanced demonstration of BeginMultiSelect()
1193b4be Poul Sander 2025-02-03 21:28 3742
        // - Showcase clipping.
1193b4be Poul Sander 2025-02-03 21:28 3743
        // - Showcase deletion.
1193b4be Poul Sander 2025-02-03 21:28 3744
        // - Showcase basic drag and drop.
1193b4be Poul Sander 2025-02-03 21:28 3745
        // - Showcase TreeNode variant (note that tree node don't expand in the demo: supporting expanding tree nodes + clipping a separate thing).
1193b4be Poul Sander 2025-02-03 21:28 3746
        // - Showcase using inside a table.
1193b4be Poul Sander 2025-02-03 21:28 3747
        IMGUI_DEMO_MARKER("Widgets/Selection State/Multi-Select (advanced)");
1193b4be Poul Sander 2025-02-03 21:28 3748
        //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
1193b4be Poul Sander 2025-02-03 21:28 3749
        if (ImGui::TreeNode("Multi-Select (advanced)"))
1193b4be Poul Sander 2025-02-03 21:28 3750
        {
1193b4be Poul Sander 2025-02-03 21:28 3751
            // Options
1193b4be Poul Sander 2025-02-03 21:28 3752
            enum WidgetType { WidgetType_Selectable, WidgetType_TreeNode };
1193b4be Poul Sander 2025-02-03 21:28 3753
            static bool use_clipper = true;
1193b4be Poul Sander 2025-02-03 21:28 3754
            static bool use_deletion = true;
1193b4be Poul Sander 2025-02-03 21:28 3755
            static bool use_drag_drop = true;
1193b4be Poul Sander 2025-02-03 21:28 3756
            static bool show_in_table = false;
1193b4be Poul Sander 2025-02-03 21:28 3757
            static bool show_color_button = true;
1193b4be Poul Sander 2025-02-03 21:28 3758
            static ImGuiMultiSelectFlags flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_BoxSelect1d;
1193b4be Poul Sander 2025-02-03 21:28 3759
            static WidgetType widget_type = WidgetType_Selectable;
1193b4be Poul Sander 2025-02-03 21:28 3760
1193b4be Poul Sander 2025-02-03 21:28 3761
            if (ImGui::TreeNode("Options"))
1193b4be Poul Sander 2025-02-03 21:28 3762
            {
1193b4be Poul Sander 2025-02-03 21:28 3763
                if (ImGui::RadioButton("Selectables", widget_type == WidgetType_Selectable)) { widget_type = WidgetType_Selectable; }
1193b4be Poul Sander 2025-02-03 21:28 3764
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 3765
                if (ImGui::RadioButton("Tree nodes", widget_type == WidgetType_TreeNode)) { widget_type = WidgetType_TreeNode; }
1193b4be Poul Sander 2025-02-03 21:28 3766
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 3767
                HelpMarker("TreeNode() is technically supported but... using this correctly is more complicated (you need some sort of linear/random access to your tree, which is suited to advanced trees setups already implementing filters and clipper. We will work toward simplifying and demoing this.\n\nFor now the tree demo is actually a little bit meaningless because it is an empty tree with only root nodes.");
1193b4be Poul Sander 2025-02-03 21:28 3768
                ImGui::Checkbox("Enable clipper", &use_clipper);
1193b4be Poul Sander 2025-02-03 21:28 3769
                ImGui::Checkbox("Enable deletion", &use_deletion);
1193b4be Poul Sander 2025-02-03 21:28 3770
                ImGui::Checkbox("Enable drag & drop", &use_drag_drop);
1193b4be Poul Sander 2025-02-03 21:28 3771
                ImGui::Checkbox("Show in a table", &show_in_table);
1193b4be Poul Sander 2025-02-03 21:28 3772
                ImGui::Checkbox("Show color button", &show_color_button);
1193b4be Poul Sander 2025-02-03 21:28 3773
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SingleSelect", &flags, ImGuiMultiSelectFlags_SingleSelect);
1193b4be Poul Sander 2025-02-03 21:28 3774
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoSelectAll", &flags, ImGuiMultiSelectFlags_NoSelectAll);
1193b4be Poul Sander 2025-02-03 21:28 3775
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoRangeSelect", &flags, ImGuiMultiSelectFlags_NoRangeSelect);
1193b4be Poul Sander 2025-02-03 21:28 3776
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoSelect", &flags, ImGuiMultiSelectFlags_NoAutoSelect);
1193b4be Poul Sander 2025-02-03 21:28 3777
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClear", &flags, ImGuiMultiSelectFlags_NoAutoClear);
1193b4be Poul Sander 2025-02-03 21:28 3778
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_NoAutoClearOnReselect", &flags, ImGuiMultiSelectFlags_NoAutoClearOnReselect);
1193b4be Poul Sander 2025-02-03 21:28 3779
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect1d", &flags, ImGuiMultiSelectFlags_BoxSelect1d);
1193b4be Poul Sander 2025-02-03 21:28 3780
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelect2d", &flags, ImGuiMultiSelectFlags_BoxSelect2d);
1193b4be Poul Sander 2025-02-03 21:28 3781
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_BoxSelectNoScroll", &flags, ImGuiMultiSelectFlags_BoxSelectNoScroll);
1193b4be Poul Sander 2025-02-03 21:28 3782
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnEscape", &flags, ImGuiMultiSelectFlags_ClearOnEscape);
1193b4be Poul Sander 2025-02-03 21:28 3783
                ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ClearOnClickVoid", &flags, ImGuiMultiSelectFlags_ClearOnClickVoid);
1193b4be Poul Sander 2025-02-03 21:28 3784
                if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeWindow", &flags, ImGuiMultiSelectFlags_ScopeWindow) && (flags & ImGuiMultiSelectFlags_ScopeWindow))
1193b4be Poul Sander 2025-02-03 21:28 3785
                    flags &= ~ImGuiMultiSelectFlags_ScopeRect;
1193b4be Poul Sander 2025-02-03 21:28 3786
                if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_ScopeRect", &flags, ImGuiMultiSelectFlags_ScopeRect) && (flags & ImGuiMultiSelectFlags_ScopeRect))
1193b4be Poul Sander 2025-02-03 21:28 3787
                    flags &= ~ImGuiMultiSelectFlags_ScopeWindow;
1193b4be Poul Sander 2025-02-03 21:28 3788
                if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SelectOnClick", &flags, ImGuiMultiSelectFlags_SelectOnClick) && (flags & ImGuiMultiSelectFlags_SelectOnClick))
1193b4be Poul Sander 2025-02-03 21:28 3789
                    flags &= ~ImGuiMultiSelectFlags_SelectOnClickRelease;
1193b4be Poul Sander 2025-02-03 21:28 3790
                if (ImGui::CheckboxFlags("ImGuiMultiSelectFlags_SelectOnClickRelease", &flags, ImGuiMultiSelectFlags_SelectOnClickRelease) && (flags & ImGuiMultiSelectFlags_SelectOnClickRelease))
1193b4be Poul Sander 2025-02-03 21:28 3791
                    flags &= ~ImGuiMultiSelectFlags_SelectOnClick;
1193b4be Poul Sander 2025-02-03 21:28 3792
                ImGui::SameLine(); HelpMarker("Allow dragging an unselected item without altering selection.");
1193b4be Poul Sander 2025-02-03 21:28 3793
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3794
            }
1193b4be Poul Sander 2025-02-03 21:28 3795
1193b4be Poul Sander 2025-02-03 21:28 3796
            // Initialize default list with 1000 items.
1193b4be Poul Sander 2025-02-03 21:28 3797
            // Use default selection.Adapter: Pass index to SetNextItemSelectionUserData(), store index in Selection
1193b4be Poul Sander 2025-02-03 21:28 3798
            static ImVector<int> items;
1193b4be Poul Sander 2025-02-03 21:28 3799
            static int items_next_id = 0;
1193b4be Poul Sander 2025-02-03 21:28 3800
            if (items_next_id == 0) { for (int n = 0; n < 1000; n++) { items.push_back(items_next_id++); } }
1193b4be Poul Sander 2025-02-03 21:28 3801
            static ExampleSelectionWithDeletion selection;
1193b4be Poul Sander 2025-02-03 21:28 3802
            static bool request_deletion_from_menu = false; // Queue deletion triggered from context menu
1193b4be Poul Sander 2025-02-03 21:28 3803
1193b4be Poul Sander 2025-02-03 21:28 3804
            ImGui::Text("Selection size: %d/%d", selection.Size, items.Size);
1193b4be Poul Sander 2025-02-03 21:28 3805
1193b4be Poul Sander 2025-02-03 21:28 3806
            const float items_height = (widget_type == WidgetType_TreeNode) ? ImGui::GetTextLineHeight() : ImGui::GetTextLineHeightWithSpacing();
1193b4be Poul Sander 2025-02-03 21:28 3807
            ImGui::SetNextWindowContentSize(ImVec2(0.0f, items.Size * items_height));
1193b4be Poul Sander 2025-02-03 21:28 3808
            if (ImGui::BeginChild("##Basket", ImVec2(-FLT_MIN, ImGui::GetFontSize() * 20), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_ResizeY))
1193b4be Poul Sander 2025-02-03 21:28 3809
            {
1193b4be Poul Sander 2025-02-03 21:28 3810
                ImVec2 color_button_sz(ImGui::GetFontSize(), ImGui::GetFontSize());
1193b4be Poul Sander 2025-02-03 21:28 3811
                if (widget_type == WidgetType_TreeNode)
1193b4be Poul Sander 2025-02-03 21:28 3812
                    ImGui::PushStyleVarY(ImGuiStyleVar_ItemSpacing, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 3813
1193b4be Poul Sander 2025-02-03 21:28 3814
                ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(flags, selection.Size, items.Size);
1193b4be Poul Sander 2025-02-03 21:28 3815
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3816
1193b4be Poul Sander 2025-02-03 21:28 3817
                const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (selection.Size > 0)) || request_deletion_from_menu;
1193b4be Poul Sander 2025-02-03 21:28 3818
                const int item_curr_idx_to_focus = want_delete ? selection.ApplyDeletionPreLoop(ms_io, items.Size) : -1;
1193b4be Poul Sander 2025-02-03 21:28 3819
                request_deletion_from_menu = false;
1193b4be Poul Sander 2025-02-03 21:28 3820
1193b4be Poul Sander 2025-02-03 21:28 3821
                if (show_in_table)
1193b4be Poul Sander 2025-02-03 21:28 3822
                {
1193b4be Poul Sander 2025-02-03 21:28 3823
                    if (widget_type == WidgetType_TreeNode)
1193b4be Poul Sander 2025-02-03 21:28 3824
                        ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0.0f, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 3825
                    ImGui::BeginTable("##Split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_NoPadOuterX);
1193b4be Poul Sander 2025-02-03 21:28 3826
                    ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.70f);
1193b4be Poul Sander 2025-02-03 21:28 3827
                    ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 0.30f);
1193b4be Poul Sander 2025-02-03 21:28 3828
                    //ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacingY, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 3829
                }
1193b4be Poul Sander 2025-02-03 21:28 3830
1193b4be Poul Sander 2025-02-03 21:28 3831
                ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 3832
                if (use_clipper)
1193b4be Poul Sander 2025-02-03 21:28 3833
                {
1193b4be Poul Sander 2025-02-03 21:28 3834
                    clipper.Begin(items.Size);
1193b4be Poul Sander 2025-02-03 21:28 3835
                    if (item_curr_idx_to_focus != -1)
1193b4be Poul Sander 2025-02-03 21:28 3836
                        clipper.IncludeItemByIndex(item_curr_idx_to_focus); // Ensure focused item is not clipped.
1193b4be Poul Sander 2025-02-03 21:28 3837
                    if (ms_io->RangeSrcItem != -1)
1193b4be Poul Sander 2025-02-03 21:28 3838
                        clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem); // Ensure RangeSrc item is not clipped.
1193b4be Poul Sander 2025-02-03 21:28 3839
                }
1193b4be Poul Sander 2025-02-03 21:28 3840
1193b4be Poul Sander 2025-02-03 21:28 3841
                while (!use_clipper || clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 3842
                {
1193b4be Poul Sander 2025-02-03 21:28 3843
                    const int item_begin = use_clipper ? clipper.DisplayStart : 0;
1193b4be Poul Sander 2025-02-03 21:28 3844
                    const int item_end = use_clipper ? clipper.DisplayEnd : items.Size;
1193b4be Poul Sander 2025-02-03 21:28 3845
                    for (int n = item_begin; n < item_end; n++)
1193b4be Poul Sander 2025-02-03 21:28 3846
                    {
1193b4be Poul Sander 2025-02-03 21:28 3847
                        if (show_in_table)
1193b4be Poul Sander 2025-02-03 21:28 3848
                            ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 3849
1193b4be Poul Sander 2025-02-03 21:28 3850
                        const int item_id = items[n];
1193b4be Poul Sander 2025-02-03 21:28 3851
                        const char* item_category = ExampleNames[item_id % IM_ARRAYSIZE(ExampleNames)];
1193b4be Poul Sander 2025-02-03 21:28 3852
                        char label[64];
1193b4be Poul Sander 2025-02-03 21:28 3853
                        sprintf(label, "Object %05d: %s", item_id, item_category);
1193b4be Poul Sander 2025-02-03 21:28 3854
1193b4be Poul Sander 2025-02-03 21:28 3855
                        // IMPORTANT: for deletion refocus to work we need object ID to be stable,
1193b4be Poul Sander 2025-02-03 21:28 3856
                        // aka not depend on their index in the list. Here we use our persistent item_id
1193b4be Poul Sander 2025-02-03 21:28 3857
                        // instead of index to build a unique ID that will persist.
1193b4be Poul Sander 2025-02-03 21:28 3858
                        // (If we used PushID(index) instead, focus wouldn't be restored correctly after deletion).
1193b4be Poul Sander 2025-02-03 21:28 3859
                        ImGui::PushID(item_id);
1193b4be Poul Sander 2025-02-03 21:28 3860
1193b4be Poul Sander 2025-02-03 21:28 3861
                        // Emit a color button, to test that Shift+LeftArrow landing on an item that is not part
1193b4be Poul Sander 2025-02-03 21:28 3862
                        // of the selection scope doesn't erroneously alter our selection.
1193b4be Poul Sander 2025-02-03 21:28 3863
                        if (show_color_button)
1193b4be Poul Sander 2025-02-03 21:28 3864
                        {
1193b4be Poul Sander 2025-02-03 21:28 3865
                            ImU32 dummy_col = (ImU32)((unsigned int)n * 0xC250B74B) | IM_COL32_A_MASK;
1193b4be Poul Sander 2025-02-03 21:28 3866
                            ImGui::ColorButton("##", ImColor(dummy_col), ImGuiColorEditFlags_NoTooltip, color_button_sz);
1193b4be Poul Sander 2025-02-03 21:28 3867
                            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 3868
                        }
1193b4be Poul Sander 2025-02-03 21:28 3869
1193b4be Poul Sander 2025-02-03 21:28 3870
                        // Submit item
1193b4be Poul Sander 2025-02-03 21:28 3871
                        bool item_is_selected = selection.Contains((ImGuiID)n);
1193b4be Poul Sander 2025-02-03 21:28 3872
                        bool item_is_open = false;
1193b4be Poul Sander 2025-02-03 21:28 3873
                        ImGui::SetNextItemSelectionUserData(n);
1193b4be Poul Sander 2025-02-03 21:28 3874
                        if (widget_type == WidgetType_Selectable)
1193b4be Poul Sander 2025-02-03 21:28 3875
                        {
1193b4be Poul Sander 2025-02-03 21:28 3876
                            ImGui::Selectable(label, item_is_selected, ImGuiSelectableFlags_None);
1193b4be Poul Sander 2025-02-03 21:28 3877
                        }
1193b4be Poul Sander 2025-02-03 21:28 3878
                        else if (widget_type == WidgetType_TreeNode)
1193b4be Poul Sander 2025-02-03 21:28 3879
                        {
1193b4be Poul Sander 2025-02-03 21:28 3880
                            ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
1193b4be Poul Sander 2025-02-03 21:28 3881
                            if (item_is_selected)
1193b4be Poul Sander 2025-02-03 21:28 3882
                                tree_node_flags |= ImGuiTreeNodeFlags_Selected;
1193b4be Poul Sander 2025-02-03 21:28 3883
                            item_is_open = ImGui::TreeNodeEx(label, tree_node_flags);
1193b4be Poul Sander 2025-02-03 21:28 3884
                        }
1193b4be Poul Sander 2025-02-03 21:28 3885
1193b4be Poul Sander 2025-02-03 21:28 3886
                        // Focus (for after deletion)
1193b4be Poul Sander 2025-02-03 21:28 3887
                        if (item_curr_idx_to_focus == n)
1193b4be Poul Sander 2025-02-03 21:28 3888
                            ImGui::SetKeyboardFocusHere(-1);
1193b4be Poul Sander 2025-02-03 21:28 3889
1193b4be Poul Sander 2025-02-03 21:28 3890
                        // Drag and Drop
1193b4be Poul Sander 2025-02-03 21:28 3891
                        if (use_drag_drop && ImGui::BeginDragDropSource())
1193b4be Poul Sander 2025-02-03 21:28 3892
                        {
1193b4be Poul Sander 2025-02-03 21:28 3893
                            // Create payload with full selection OR single unselected item.
1193b4be Poul Sander 2025-02-03 21:28 3894
                            // (the later is only possible when using ImGuiMultiSelectFlags_SelectOnClickRelease)
1193b4be Poul Sander 2025-02-03 21:28 3895
                            if (ImGui::GetDragDropPayload() == NULL)
1193b4be Poul Sander 2025-02-03 21:28 3896
                            {
1193b4be Poul Sander 2025-02-03 21:28 3897
                                ImVector<int> payload_items;
1193b4be Poul Sander 2025-02-03 21:28 3898
                                void* it = NULL;
1193b4be Poul Sander 2025-02-03 21:28 3899
                                ImGuiID id = 0;
1193b4be Poul Sander 2025-02-03 21:28 3900
                                if (!item_is_selected)
1193b4be Poul Sander 2025-02-03 21:28 3901
                                    payload_items.push_back(item_id);
1193b4be Poul Sander 2025-02-03 21:28 3902
                                else
1193b4be Poul Sander 2025-02-03 21:28 3903
                                    while (selection.GetNextSelectedItem(&it, &id))
1193b4be Poul Sander 2025-02-03 21:28 3904
                                        payload_items.push_back((int)id);
1193b4be Poul Sander 2025-02-03 21:28 3905
                                ImGui::SetDragDropPayload("MULTISELECT_DEMO_ITEMS", payload_items.Data, (size_t)payload_items.size_in_bytes());
1193b4be Poul Sander 2025-02-03 21:28 3906
                            }
1193b4be Poul Sander 2025-02-03 21:28 3907
1193b4be Poul Sander 2025-02-03 21:28 3908
                            // Display payload content in tooltip
1193b4be Poul Sander 2025-02-03 21:28 3909
                            const ImGuiPayload* payload = ImGui::GetDragDropPayload();
1193b4be Poul Sander 2025-02-03 21:28 3910
                            const int* payload_items = (int*)payload->Data;
1193b4be Poul Sander 2025-02-03 21:28 3911
                            const int payload_count = (int)payload->DataSize / (int)sizeof(int);
1193b4be Poul Sander 2025-02-03 21:28 3912
                            if (payload_count == 1)
1193b4be Poul Sander 2025-02-03 21:28 3913
                                ImGui::Text("Object %05d: %s", payload_items[0], ExampleNames[payload_items[0] % IM_ARRAYSIZE(ExampleNames)]);
1193b4be Poul Sander 2025-02-03 21:28 3914
                            else
1193b4be Poul Sander 2025-02-03 21:28 3915
                                ImGui::Text("Dragging %d objects", payload_count);
1193b4be Poul Sander 2025-02-03 21:28 3916
1193b4be Poul Sander 2025-02-03 21:28 3917
                            ImGui::EndDragDropSource();
1193b4be Poul Sander 2025-02-03 21:28 3918
                        }
1193b4be Poul Sander 2025-02-03 21:28 3919
1193b4be Poul Sander 2025-02-03 21:28 3920
                        if (widget_type == WidgetType_TreeNode && item_is_open)
1193b4be Poul Sander 2025-02-03 21:28 3921
                            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3922
1193b4be Poul Sander 2025-02-03 21:28 3923
                        // Right-click: context menu
1193b4be Poul Sander 2025-02-03 21:28 3924
                        if (ImGui::BeginPopupContextItem())
1193b4be Poul Sander 2025-02-03 21:28 3925
                        {
1193b4be Poul Sander 2025-02-03 21:28 3926
                            ImGui::BeginDisabled(!use_deletion || selection.Size == 0);
1193b4be Poul Sander 2025-02-03 21:28 3927
                            sprintf(label, "Delete %d item(s)###DeleteSelected", selection.Size);
1193b4be Poul Sander 2025-02-03 21:28 3928
                            if (ImGui::Selectable(label))
1193b4be Poul Sander 2025-02-03 21:28 3929
                                request_deletion_from_menu = true;
1193b4be Poul Sander 2025-02-03 21:28 3930
                            ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 3931
                            ImGui::Selectable("Close");
1193b4be Poul Sander 2025-02-03 21:28 3932
                            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 3933
                        }
1193b4be Poul Sander 2025-02-03 21:28 3934
1193b4be Poul Sander 2025-02-03 21:28 3935
                        // Demo content within a table
1193b4be Poul Sander 2025-02-03 21:28 3936
                        if (show_in_table)
1193b4be Poul Sander 2025-02-03 21:28 3937
                        {
1193b4be Poul Sander 2025-02-03 21:28 3938
                            ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 3939
                            ImGui::SetNextItemWidth(-FLT_MIN);
1193b4be Poul Sander 2025-02-03 21:28 3940
                            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1193b4be Poul Sander 2025-02-03 21:28 3941
                            ImGui::InputText("###NoLabel", (char*)(void*)item_category, strlen(item_category), ImGuiInputTextFlags_ReadOnly);
1193b4be Poul Sander 2025-02-03 21:28 3942
                            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 3943
                        }
1193b4be Poul Sander 2025-02-03 21:28 3944
1193b4be Poul Sander 2025-02-03 21:28 3945
                        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 3946
                    }
1193b4be Poul Sander 2025-02-03 21:28 3947
                    if (!use_clipper)
1193b4be Poul Sander 2025-02-03 21:28 3948
                        break;
1193b4be Poul Sander 2025-02-03 21:28 3949
                }
1193b4be Poul Sander 2025-02-03 21:28 3950
1193b4be Poul Sander 2025-02-03 21:28 3951
                if (show_in_table)
1193b4be Poul Sander 2025-02-03 21:28 3952
                {
1193b4be Poul Sander 2025-02-03 21:28 3953
                    ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 3954
                    if (widget_type == WidgetType_TreeNode)
1193b4be Poul Sander 2025-02-03 21:28 3955
                        ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 3956
                }
1193b4be Poul Sander 2025-02-03 21:28 3957
1193b4be Poul Sander 2025-02-03 21:28 3958
                // Apply multi-select requests
1193b4be Poul Sander 2025-02-03 21:28 3959
                ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 3960
                selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 3961
                if (want_delete)
1193b4be Poul Sander 2025-02-03 21:28 3962
                    selection.ApplyDeletionPostLoop(ms_io, items, item_curr_idx_to_focus);
1193b4be Poul Sander 2025-02-03 21:28 3963
1193b4be Poul Sander 2025-02-03 21:28 3964
                if (widget_type == WidgetType_TreeNode)
1193b4be Poul Sander 2025-02-03 21:28 3965
                    ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 3966
            }
1193b4be Poul Sander 2025-02-03 21:28 3967
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 3968
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3969
        }
1193b4be Poul Sander 2025-02-03 21:28 3970
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 3971
    }
1193b4be Poul Sander 2025-02-03 21:28 3972
}
1193b4be Poul Sander 2025-02-03 21:28 3973
1193b4be Poul Sander 2025-02-03 21:28 3974
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 3975
// [SECTION] ShowDemoWindowLayout()
1193b4be Poul Sander 2025-02-03 21:28 3976
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 3977
1193b4be Poul Sander 2025-02-03 21:28 3978
static void ShowDemoWindowLayout()
1193b4be Poul Sander 2025-02-03 21:28 3979
{
1193b4be Poul Sander 2025-02-03 21:28 3980
    IMGUI_DEMO_MARKER("Layout");
1193b4be Poul Sander 2025-02-03 21:28 3981
    if (!ImGui::CollapsingHeader("Layout & Scrolling"))
1193b4be Poul Sander 2025-02-03 21:28 3982
        return;
1193b4be Poul Sander 2025-02-03 21:28 3983
1193b4be Poul Sander 2025-02-03 21:28 3984
    IMGUI_DEMO_MARKER("Layout/Child windows");
1193b4be Poul Sander 2025-02-03 21:28 3985
    if (ImGui::TreeNode("Child windows"))
1193b4be Poul Sander 2025-02-03 21:28 3986
    {
1193b4be Poul Sander 2025-02-03 21:28 3987
        ImGui::SeparatorText("Child windows");
1193b4be Poul Sander 2025-02-03 21:28 3988
1193b4be Poul Sander 2025-02-03 21:28 3989
        HelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
1193b4be Poul Sander 2025-02-03 21:28 3990
        static bool disable_mouse_wheel = false;
1193b4be Poul Sander 2025-02-03 21:28 3991
        static bool disable_menu = false;
1193b4be Poul Sander 2025-02-03 21:28 3992
        ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
1193b4be Poul Sander 2025-02-03 21:28 3993
        ImGui::Checkbox("Disable Menu", &disable_menu);
1193b4be Poul Sander 2025-02-03 21:28 3994
1193b4be Poul Sander 2025-02-03 21:28 3995
        // Child 1: no border, enable horizontal scrollbar
1193b4be Poul Sander 2025-02-03 21:28 3996
        {
1193b4be Poul Sander 2025-02-03 21:28 3997
            ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
1193b4be Poul Sander 2025-02-03 21:28 3998
            if (disable_mouse_wheel)
1193b4be Poul Sander 2025-02-03 21:28 3999
                window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
1193b4be Poul Sander 2025-02-03 21:28 4000
            ImGui::BeginChild("ChildL", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 260), ImGuiChildFlags_None, window_flags);
1193b4be Poul Sander 2025-02-03 21:28 4001
            for (int i = 0; i < 100; i++)
1193b4be Poul Sander 2025-02-03 21:28 4002
                ImGui::Text("%04d: scrollable region", i);
1193b4be Poul Sander 2025-02-03 21:28 4003
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4004
        }
1193b4be Poul Sander 2025-02-03 21:28 4005
1193b4be Poul Sander 2025-02-03 21:28 4006
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4007
1193b4be Poul Sander 2025-02-03 21:28 4008
        // Child 2: rounded border
1193b4be Poul Sander 2025-02-03 21:28 4009
        {
1193b4be Poul Sander 2025-02-03 21:28 4010
            ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 4011
            if (disable_mouse_wheel)
1193b4be Poul Sander 2025-02-03 21:28 4012
                window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
1193b4be Poul Sander 2025-02-03 21:28 4013
            if (!disable_menu)
1193b4be Poul Sander 2025-02-03 21:28 4014
                window_flags |= ImGuiWindowFlags_MenuBar;
1193b4be Poul Sander 2025-02-03 21:28 4015
            ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
1193b4be Poul Sander 2025-02-03 21:28 4016
            ImGui::BeginChild("ChildR", ImVec2(0, 260), ImGuiChildFlags_Borders, window_flags);
1193b4be Poul Sander 2025-02-03 21:28 4017
            if (!disable_menu && ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 4018
            {
1193b4be Poul Sander 2025-02-03 21:28 4019
                if (ImGui::BeginMenu("Menu"))
1193b4be Poul Sander 2025-02-03 21:28 4020
                {
1193b4be Poul Sander 2025-02-03 21:28 4021
                    ShowExampleMenuFile();
1193b4be Poul Sander 2025-02-03 21:28 4022
                    ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 4023
                }
1193b4be Poul Sander 2025-02-03 21:28 4024
                ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 4025
            }
1193b4be Poul Sander 2025-02-03 21:28 4026
            if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
1193b4be Poul Sander 2025-02-03 21:28 4027
            {
1193b4be Poul Sander 2025-02-03 21:28 4028
                for (int i = 0; i < 100; i++)
1193b4be Poul Sander 2025-02-03 21:28 4029
                {
1193b4be Poul Sander 2025-02-03 21:28 4030
                    char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 4031
                    sprintf(buf, "%03d", i);
1193b4be Poul Sander 2025-02-03 21:28 4032
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 4033
                    ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 4034
                }
1193b4be Poul Sander 2025-02-03 21:28 4035
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 4036
            }
1193b4be Poul Sander 2025-02-03 21:28 4037
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4038
            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 4039
        }
1193b4be Poul Sander 2025-02-03 21:28 4040
1193b4be Poul Sander 2025-02-03 21:28 4041
        // Child 3: manual-resize
1193b4be Poul Sander 2025-02-03 21:28 4042
        ImGui::SeparatorText("Manual-resize");
1193b4be Poul Sander 2025-02-03 21:28 4043
        {
1193b4be Poul Sander 2025-02-03 21:28 4044
            HelpMarker("Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents.");
1193b4be Poul Sander 2025-02-03 21:28 4045
            //if (ImGui::Button("Set Height to 200"))
1193b4be Poul Sander 2025-02-03 21:28 4046
            //    ImGui::SetNextWindowSize(ImVec2(-FLT_MIN, 200.0f));
1193b4be Poul Sander 2025-02-03 21:28 4047
1193b4be Poul Sander 2025-02-03 21:28 4048
            ImGui::PushStyleColor(ImGuiCol_ChildBg, ImGui::GetStyleColorVec4(ImGuiCol_FrameBg));
1193b4be Poul Sander 2025-02-03 21:28 4049
            if (ImGui::BeginChild("ResizableChild", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeY))
1193b4be Poul Sander 2025-02-03 21:28 4050
                for (int n = 0; n < 10; n++)
1193b4be Poul Sander 2025-02-03 21:28 4051
                    ImGui::Text("Line %04d", n);
1193b4be Poul Sander 2025-02-03 21:28 4052
            ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 4053
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4054
        }
1193b4be Poul Sander 2025-02-03 21:28 4055
1193b4be Poul Sander 2025-02-03 21:28 4056
        // Child 4: auto-resizing height with a limit
1193b4be Poul Sander 2025-02-03 21:28 4057
        ImGui::SeparatorText("Auto-resize with constraints");
1193b4be Poul Sander 2025-02-03 21:28 4058
        {
1193b4be Poul Sander 2025-02-03 21:28 4059
            static int draw_lines = 3;
1193b4be Poul Sander 2025-02-03 21:28 4060
            static int max_height_in_lines = 10;
1193b4be Poul Sander 2025-02-03 21:28 4061
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 4062
            ImGui::DragInt("Lines Count", &draw_lines, 0.2f);
1193b4be Poul Sander 2025-02-03 21:28 4063
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 4064
            ImGui::DragInt("Max Height (in Lines)", &max_height_in_lines, 0.2f);
1193b4be Poul Sander 2025-02-03 21:28 4065
1193b4be Poul Sander 2025-02-03 21:28 4066
            ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 1), ImVec2(FLT_MAX, ImGui::GetTextLineHeightWithSpacing() * max_height_in_lines));
1193b4be Poul Sander 2025-02-03 21:28 4067
            if (ImGui::BeginChild("ConstrainedChild", ImVec2(-FLT_MIN, 0.0f), ImGuiChildFlags_Borders | ImGuiChildFlags_AutoResizeY))
1193b4be Poul Sander 2025-02-03 21:28 4068
                for (int n = 0; n < draw_lines; n++)
1193b4be Poul Sander 2025-02-03 21:28 4069
                    ImGui::Text("Line %04d", n);
1193b4be Poul Sander 2025-02-03 21:28 4070
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4071
        }
1193b4be Poul Sander 2025-02-03 21:28 4072
1193b4be Poul Sander 2025-02-03 21:28 4073
        ImGui::SeparatorText("Misc/Advanced");
1193b4be Poul Sander 2025-02-03 21:28 4074
1193b4be Poul Sander 2025-02-03 21:28 4075
        // Demonstrate a few extra things
1193b4be Poul Sander 2025-02-03 21:28 4076
        // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
1193b4be Poul Sander 2025-02-03 21:28 4077
        // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window)
1193b4be Poul Sander 2025-02-03 21:28 4078
        //   You can also call SetNextWindowPos() to position the child window. The parent window will effectively
1193b4be Poul Sander 2025-02-03 21:28 4079
        //   layout from this position.
1193b4be Poul Sander 2025-02-03 21:28 4080
        // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from
1193b4be Poul Sander 2025-02-03 21:28 4081
        //   the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details.
1193b4be Poul Sander 2025-02-03 21:28 4082
        {
1193b4be Poul Sander 2025-02-03 21:28 4083
            static int offset_x = 0;
1193b4be Poul Sander 2025-02-03 21:28 4084
            static bool override_bg_color = true;
1193b4be Poul Sander 2025-02-03 21:28 4085
            static ImGuiChildFlags child_flags = ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY;
1193b4be Poul Sander 2025-02-03 21:28 4086
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 4087
            ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
1193b4be Poul Sander 2025-02-03 21:28 4088
            ImGui::Checkbox("Override ChildBg color", &override_bg_color);
1193b4be Poul Sander 2025-02-03 21:28 4089
            ImGui::CheckboxFlags("ImGuiChildFlags_Borders", &child_flags, ImGuiChildFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 4090
            ImGui::CheckboxFlags("ImGuiChildFlags_AlwaysUseWindowPadding", &child_flags, ImGuiChildFlags_AlwaysUseWindowPadding);
1193b4be Poul Sander 2025-02-03 21:28 4091
            ImGui::CheckboxFlags("ImGuiChildFlags_ResizeX", &child_flags, ImGuiChildFlags_ResizeX);
1193b4be Poul Sander 2025-02-03 21:28 4092
            ImGui::CheckboxFlags("ImGuiChildFlags_ResizeY", &child_flags, ImGuiChildFlags_ResizeY);
1193b4be Poul Sander 2025-02-03 21:28 4093
            ImGui::CheckboxFlags("ImGuiChildFlags_FrameStyle", &child_flags, ImGuiChildFlags_FrameStyle);
1193b4be Poul Sander 2025-02-03 21:28 4094
            ImGui::SameLine(); HelpMarker("Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding.");
1193b4be Poul Sander 2025-02-03 21:28 4095
            if (child_flags & ImGuiChildFlags_FrameStyle)
1193b4be Poul Sander 2025-02-03 21:28 4096
                override_bg_color = false;
1193b4be Poul Sander 2025-02-03 21:28 4097
1193b4be Poul Sander 2025-02-03 21:28 4098
            ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
1193b4be Poul Sander 2025-02-03 21:28 4099
            if (override_bg_color)
1193b4be Poul Sander 2025-02-03 21:28 4100
                ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
1193b4be Poul Sander 2025-02-03 21:28 4101
            ImGui::BeginChild("Red", ImVec2(200, 100), child_flags, ImGuiWindowFlags_None);
1193b4be Poul Sander 2025-02-03 21:28 4102
            if (override_bg_color)
1193b4be Poul Sander 2025-02-03 21:28 4103
                ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 4104
1193b4be Poul Sander 2025-02-03 21:28 4105
            for (int n = 0; n < 50; n++)
1193b4be Poul Sander 2025-02-03 21:28 4106
                ImGui::Text("Some test %d", n);
1193b4be Poul Sander 2025-02-03 21:28 4107
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4108
            bool child_is_hovered = ImGui::IsItemHovered();
1193b4be Poul Sander 2025-02-03 21:28 4109
            ImVec2 child_rect_min = ImGui::GetItemRectMin();
1193b4be Poul Sander 2025-02-03 21:28 4110
            ImVec2 child_rect_max = ImGui::GetItemRectMax();
1193b4be Poul Sander 2025-02-03 21:28 4111
            ImGui::Text("Hovered: %d", child_is_hovered);
1193b4be Poul Sander 2025-02-03 21:28 4112
            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);
1193b4be Poul Sander 2025-02-03 21:28 4113
        }
1193b4be Poul Sander 2025-02-03 21:28 4114
1193b4be Poul Sander 2025-02-03 21:28 4115
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4116
    }
1193b4be Poul Sander 2025-02-03 21:28 4117
1193b4be Poul Sander 2025-02-03 21:28 4118
    IMGUI_DEMO_MARKER("Layout/Widgets Width");
1193b4be Poul Sander 2025-02-03 21:28 4119
    if (ImGui::TreeNode("Widgets Width"))
1193b4be Poul Sander 2025-02-03 21:28 4120
    {
1193b4be Poul Sander 2025-02-03 21:28 4121
        static float f = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 4122
        static bool show_indented_items = true;
1193b4be Poul Sander 2025-02-03 21:28 4123
        ImGui::Checkbox("Show indented items", &show_indented_items);
1193b4be Poul Sander 2025-02-03 21:28 4124
1193b4be Poul Sander 2025-02-03 21:28 4125
        // Use SetNextItemWidth() to set the width of a single upcoming item.
1193b4be Poul Sander 2025-02-03 21:28 4126
        // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
1193b4be Poul Sander 2025-02-03 21:28 4127
        // In real code use you'll probably want to choose width values that are proportional to your font size
1193b4be Poul Sander 2025-02-03 21:28 4128
        // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
1193b4be Poul Sander 2025-02-03 21:28 4129
1193b4be Poul Sander 2025-02-03 21:28 4130
        ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
1193b4be Poul Sander 2025-02-03 21:28 4131
        ImGui::SameLine(); HelpMarker("Fixed width.");
1193b4be Poul Sander 2025-02-03 21:28 4132
        ImGui::PushItemWidth(100);
1193b4be Poul Sander 2025-02-03 21:28 4133
        ImGui::DragFloat("float##1b", &f);
1193b4be Poul Sander 2025-02-03 21:28 4134
        if (show_indented_items)
1193b4be Poul Sander 2025-02-03 21:28 4135
        {
1193b4be Poul Sander 2025-02-03 21:28 4136
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4137
            ImGui::DragFloat("float (indented)##1b", &f);
1193b4be Poul Sander 2025-02-03 21:28 4138
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4139
        }
1193b4be Poul Sander 2025-02-03 21:28 4140
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4141
1193b4be Poul Sander 2025-02-03 21:28 4142
        ImGui::Text("SetNextItemWidth/PushItemWidth(-100)");
1193b4be Poul Sander 2025-02-03 21:28 4143
        ImGui::SameLine(); HelpMarker("Align to right edge minus 100");
1193b4be Poul Sander 2025-02-03 21:28 4144
        ImGui::PushItemWidth(-100);
1193b4be Poul Sander 2025-02-03 21:28 4145
        ImGui::DragFloat("float##2a", &f);
1193b4be Poul Sander 2025-02-03 21:28 4146
        if (show_indented_items)
1193b4be Poul Sander 2025-02-03 21:28 4147
        {
1193b4be Poul Sander 2025-02-03 21:28 4148
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4149
            ImGui::DragFloat("float (indented)##2b", &f);
1193b4be Poul Sander 2025-02-03 21:28 4150
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4151
        }
1193b4be Poul Sander 2025-02-03 21:28 4152
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4153
1193b4be Poul Sander 2025-02-03 21:28 4154
        ImGui::Text("SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
1193b4be Poul Sander 2025-02-03 21:28 4155
        ImGui::SameLine(); HelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
1193b4be Poul Sander 2025-02-03 21:28 4156
        ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 4157
        ImGui::DragFloat("float##3a", &f);
1193b4be Poul Sander 2025-02-03 21:28 4158
        if (show_indented_items)
1193b4be Poul Sander 2025-02-03 21:28 4159
        {
1193b4be Poul Sander 2025-02-03 21:28 4160
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4161
            ImGui::DragFloat("float (indented)##3b", &f);
1193b4be Poul Sander 2025-02-03 21:28 4162
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4163
        }
1193b4be Poul Sander 2025-02-03 21:28 4164
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4165
1193b4be Poul Sander 2025-02-03 21:28 4166
        ImGui::Text("SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)");
1193b4be Poul Sander 2025-02-03 21:28 4167
        ImGui::SameLine(); HelpMarker("Align to right edge minus half");
1193b4be Poul Sander 2025-02-03 21:28 4168
        ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 4169
        ImGui::DragFloat("float##4a", &f);
1193b4be Poul Sander 2025-02-03 21:28 4170
        if (show_indented_items)
1193b4be Poul Sander 2025-02-03 21:28 4171
        {
1193b4be Poul Sander 2025-02-03 21:28 4172
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4173
            ImGui::DragFloat("float (indented)##4b", &f);
1193b4be Poul Sander 2025-02-03 21:28 4174
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4175
        }
1193b4be Poul Sander 2025-02-03 21:28 4176
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4177
1193b4be Poul Sander 2025-02-03 21:28 4178
        // Demonstrate using PushItemWidth to surround three items.
1193b4be Poul Sander 2025-02-03 21:28 4179
        // Calling SetNextItemWidth() before each of them would have the same effect.
1193b4be Poul Sander 2025-02-03 21:28 4180
        ImGui::Text("SetNextItemWidth/PushItemWidth(-FLT_MIN)");
1193b4be Poul Sander 2025-02-03 21:28 4181
        ImGui::SameLine(); HelpMarker("Align to right edge");
1193b4be Poul Sander 2025-02-03 21:28 4182
        ImGui::PushItemWidth(-FLT_MIN);
1193b4be Poul Sander 2025-02-03 21:28 4183
        ImGui::DragFloat("##float5a", &f);
1193b4be Poul Sander 2025-02-03 21:28 4184
        if (show_indented_items)
1193b4be Poul Sander 2025-02-03 21:28 4185
        {
1193b4be Poul Sander 2025-02-03 21:28 4186
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4187
            ImGui::DragFloat("float (indented)##5b", &f);
1193b4be Poul Sander 2025-02-03 21:28 4188
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4189
        }
1193b4be Poul Sander 2025-02-03 21:28 4190
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4191
1193b4be Poul Sander 2025-02-03 21:28 4192
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4193
    }
1193b4be Poul Sander 2025-02-03 21:28 4194
1193b4be Poul Sander 2025-02-03 21:28 4195
    IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout");
1193b4be Poul Sander 2025-02-03 21:28 4196
    if (ImGui::TreeNode("Basic Horizontal Layout"))
1193b4be Poul Sander 2025-02-03 21:28 4197
    {
1193b4be Poul Sander 2025-02-03 21:28 4198
        ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1193b4be Poul Sander 2025-02-03 21:28 4199
1193b4be Poul Sander 2025-02-03 21:28 4200
        // Text
1193b4be Poul Sander 2025-02-03 21:28 4201
        IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine");
1193b4be Poul Sander 2025-02-03 21:28 4202
        ImGui::Text("Two items: Hello"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4203
        ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
1193b4be Poul Sander 2025-02-03 21:28 4204
1193b4be Poul Sander 2025-02-03 21:28 4205
        // Adjust spacing
1193b4be Poul Sander 2025-02-03 21:28 4206
        ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
1193b4be Poul Sander 2025-02-03 21:28 4207
        ImGui::TextColored(ImVec4(1, 1, 0, 1), "Sailor");
1193b4be Poul Sander 2025-02-03 21:28 4208
1193b4be Poul Sander 2025-02-03 21:28 4209
        // Button
1193b4be Poul Sander 2025-02-03 21:28 4210
        ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 4211
        ImGui::Text("Normal buttons"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4212
        ImGui::Button("Banana"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4213
        ImGui::Button("Apple"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4214
        ImGui::Button("Corniflower");
1193b4be Poul Sander 2025-02-03 21:28 4215
1193b4be Poul Sander 2025-02-03 21:28 4216
        // Button
1193b4be Poul Sander 2025-02-03 21:28 4217
        ImGui::Text("Small buttons"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4218
        ImGui::SmallButton("Like this one"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4219
        ImGui::Text("can fit within a text block.");
1193b4be Poul Sander 2025-02-03 21:28 4220
1193b4be Poul Sander 2025-02-03 21:28 4221
        // Aligned to arbitrary position. Easy/cheap column.
1193b4be Poul Sander 2025-02-03 21:28 4222
        IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (with offset)");
1193b4be Poul Sander 2025-02-03 21:28 4223
        ImGui::Text("Aligned");
1193b4be Poul Sander 2025-02-03 21:28 4224
        ImGui::SameLine(150); ImGui::Text("x=150");
1193b4be Poul Sander 2025-02-03 21:28 4225
        ImGui::SameLine(300); ImGui::Text("x=300");
1193b4be Poul Sander 2025-02-03 21:28 4226
        ImGui::Text("Aligned");
1193b4be Poul Sander 2025-02-03 21:28 4227
        ImGui::SameLine(150); ImGui::SmallButton("x=150");
1193b4be Poul Sander 2025-02-03 21:28 4228
        ImGui::SameLine(300); ImGui::SmallButton("x=300");
1193b4be Poul Sander 2025-02-03 21:28 4229
1193b4be Poul Sander 2025-02-03 21:28 4230
        // Checkbox
1193b4be Poul Sander 2025-02-03 21:28 4231
        IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (more)");
1193b4be Poul Sander 2025-02-03 21:28 4232
        static bool c1 = false, c2 = false, c3 = false, c4 = false;
1193b4be Poul Sander 2025-02-03 21:28 4233
        ImGui::Checkbox("My", &c1); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4234
        ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4235
        ImGui::Checkbox("Is", &c3); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4236
        ImGui::Checkbox("Rich", &c4);
1193b4be Poul Sander 2025-02-03 21:28 4237
1193b4be Poul Sander 2025-02-03 21:28 4238
        // Various
1193b4be Poul Sander 2025-02-03 21:28 4239
        static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
1193b4be Poul Sander 2025-02-03 21:28 4240
        ImGui::PushItemWidth(80);
1193b4be Poul Sander 2025-02-03 21:28 4241
        const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
1193b4be Poul Sander 2025-02-03 21:28 4242
        static int item = -1;
1193b4be Poul Sander 2025-02-03 21:28 4243
        ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4244
        ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4245
        ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4246
        ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
1193b4be Poul Sander 2025-02-03 21:28 4247
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4248
1193b4be Poul Sander 2025-02-03 21:28 4249
        ImGui::PushItemWidth(80);
1193b4be Poul Sander 2025-02-03 21:28 4250
        ImGui::Text("Lists:");
1193b4be Poul Sander 2025-02-03 21:28 4251
        static int selection[4] = { 0, 1, 2, 3 };
1193b4be Poul Sander 2025-02-03 21:28 4252
        for (int i = 0; i < 4; i++)
1193b4be Poul Sander 2025-02-03 21:28 4253
        {
1193b4be Poul Sander 2025-02-03 21:28 4254
            if (i > 0) ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4255
            ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 4256
            ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
1193b4be Poul Sander 2025-02-03 21:28 4257
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 4258
            //ImGui::SetItemTooltip("ListBox %d hovered", i);
1193b4be Poul Sander 2025-02-03 21:28 4259
        }
1193b4be Poul Sander 2025-02-03 21:28 4260
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4261
1193b4be Poul Sander 2025-02-03 21:28 4262
        // Dummy
1193b4be Poul Sander 2025-02-03 21:28 4263
        IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Dummy");
1193b4be Poul Sander 2025-02-03 21:28 4264
        ImVec2 button_sz(40, 40);
1193b4be Poul Sander 2025-02-03 21:28 4265
        ImGui::Button("A", button_sz); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4266
        ImGui::Dummy(button_sz); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4267
        ImGui::Button("B", button_sz);
1193b4be Poul Sander 2025-02-03 21:28 4268
1193b4be Poul Sander 2025-02-03 21:28 4269
        // Manually wrapping
1193b4be Poul Sander 2025-02-03 21:28 4270
        // (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
1193b4be Poul Sander 2025-02-03 21:28 4271
        IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Manual wrapping");
1193b4be Poul Sander 2025-02-03 21:28 4272
        ImGui::Text("Manual wrapping:");
1193b4be Poul Sander 2025-02-03 21:28 4273
        ImGuiStyle& style = ImGui::GetStyle();
1193b4be Poul Sander 2025-02-03 21:28 4274
        int buttons_count = 20;
1193b4be Poul Sander 2025-02-03 21:28 4275
        float window_visible_x2 = ImGui::GetCursorScreenPos().x + ImGui::GetContentRegionAvail().x;
1193b4be Poul Sander 2025-02-03 21:28 4276
        for (int n = 0; n < buttons_count; n++)
1193b4be Poul Sander 2025-02-03 21:28 4277
        {
1193b4be Poul Sander 2025-02-03 21:28 4278
            ImGui::PushID(n);
1193b4be Poul Sander 2025-02-03 21:28 4279
            ImGui::Button("Box", button_sz);
1193b4be Poul Sander 2025-02-03 21:28 4280
            float last_button_x2 = ImGui::GetItemRectMax().x;
1193b4be Poul Sander 2025-02-03 21:28 4281
            float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
1193b4be Poul Sander 2025-02-03 21:28 4282
            if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
1193b4be Poul Sander 2025-02-03 21:28 4283
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4284
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 4285
        }
1193b4be Poul Sander 2025-02-03 21:28 4286
1193b4be Poul Sander 2025-02-03 21:28 4287
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4288
    }
1193b4be Poul Sander 2025-02-03 21:28 4289
1193b4be Poul Sander 2025-02-03 21:28 4290
    IMGUI_DEMO_MARKER("Layout/Groups");
1193b4be Poul Sander 2025-02-03 21:28 4291
    if (ImGui::TreeNode("Groups"))
1193b4be Poul Sander 2025-02-03 21:28 4292
    {
1193b4be Poul Sander 2025-02-03 21:28 4293
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 4294
            "BeginGroup() basically locks the horizontal position for new line. "
1193b4be Poul Sander 2025-02-03 21:28 4295
            "EndGroup() bundles the whole group so that you can use \"item\" functions such as "
1193b4be Poul Sander 2025-02-03 21:28 4296
            "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group.");
1193b4be Poul Sander 2025-02-03 21:28 4297
        ImGui::BeginGroup();
1193b4be Poul Sander 2025-02-03 21:28 4298
        {
1193b4be Poul Sander 2025-02-03 21:28 4299
            ImGui::BeginGroup();
1193b4be Poul Sander 2025-02-03 21:28 4300
            ImGui::Button("AAA");
1193b4be Poul Sander 2025-02-03 21:28 4301
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4302
            ImGui::Button("BBB");
1193b4be Poul Sander 2025-02-03 21:28 4303
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4304
            ImGui::BeginGroup();
1193b4be Poul Sander 2025-02-03 21:28 4305
            ImGui::Button("CCC");
1193b4be Poul Sander 2025-02-03 21:28 4306
            ImGui::Button("DDD");
1193b4be Poul Sander 2025-02-03 21:28 4307
            ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 4308
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4309
            ImGui::Button("EEE");
1193b4be Poul Sander 2025-02-03 21:28 4310
            ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 4311
            ImGui::SetItemTooltip("First group hovered");
1193b4be Poul Sander 2025-02-03 21:28 4312
        }
1193b4be Poul Sander 2025-02-03 21:28 4313
        // Capture the group size and create widgets using the same size
1193b4be Poul Sander 2025-02-03 21:28 4314
        ImVec2 size = ImGui::GetItemRectSize();
1193b4be Poul Sander 2025-02-03 21:28 4315
        const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
1193b4be Poul Sander 2025-02-03 21:28 4316
        ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
1193b4be Poul Sander 2025-02-03 21:28 4317
1193b4be Poul Sander 2025-02-03 21:28 4318
        ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
1193b4be Poul Sander 2025-02-03 21:28 4319
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4320
        ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
1193b4be Poul Sander 2025-02-03 21:28 4321
        ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 4322
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4323
1193b4be Poul Sander 2025-02-03 21:28 4324
        ImGui::Button("LEVERAGE\nBUZZWORD", size);
1193b4be Poul Sander 2025-02-03 21:28 4325
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4326
1193b4be Poul Sander 2025-02-03 21:28 4327
        if (ImGui::BeginListBox("List", size))
1193b4be Poul Sander 2025-02-03 21:28 4328
        {
1193b4be Poul Sander 2025-02-03 21:28 4329
            ImGui::Selectable("Selected", true);
1193b4be Poul Sander 2025-02-03 21:28 4330
            ImGui::Selectable("Not Selected", false);
1193b4be Poul Sander 2025-02-03 21:28 4331
            ImGui::EndListBox();
1193b4be Poul Sander 2025-02-03 21:28 4332
        }
1193b4be Poul Sander 2025-02-03 21:28 4333
1193b4be Poul Sander 2025-02-03 21:28 4334
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4335
    }
1193b4be Poul Sander 2025-02-03 21:28 4336
1193b4be Poul Sander 2025-02-03 21:28 4337
    IMGUI_DEMO_MARKER("Layout/Text Baseline Alignment");
1193b4be Poul Sander 2025-02-03 21:28 4338
    if (ImGui::TreeNode("Text Baseline Alignment"))
1193b4be Poul Sander 2025-02-03 21:28 4339
    {
1193b4be Poul Sander 2025-02-03 21:28 4340
        {
1193b4be Poul Sander 2025-02-03 21:28 4341
            ImGui::BulletText("Text baseline:");
1193b4be Poul Sander 2025-02-03 21:28 4342
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 4343
                "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. "
1193b4be Poul Sander 2025-02-03 21:28 4344
                "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets.");
1193b4be Poul Sander 2025-02-03 21:28 4345
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4346
1193b4be Poul Sander 2025-02-03 21:28 4347
            ImGui::Text("KO Blahblah"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4348
            ImGui::Button("Some framed item"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4349
            HelpMarker("Baseline of button will look misaligned with text..");
1193b4be Poul Sander 2025-02-03 21:28 4350
1193b4be Poul Sander 2025-02-03 21:28 4351
            // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
1193b4be Poul Sander 2025-02-03 21:28 4352
            // (because we don't know what's coming after the Text() statement, we need to move the text baseline
1193b4be Poul Sander 2025-02-03 21:28 4353
            // down by FramePadding.y ahead of time)
1193b4be Poul Sander 2025-02-03 21:28 4354
            ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 4355
            ImGui::Text("OK Blahblah"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4356
            ImGui::Button("Some framed item##2"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4357
            HelpMarker("We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
1193b4be Poul Sander 2025-02-03 21:28 4358
1193b4be Poul Sander 2025-02-03 21:28 4359
            // SmallButton() uses the same vertical padding as Text
1193b4be Poul Sander 2025-02-03 21:28 4360
            ImGui::Button("TEST##1"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4361
            ImGui::Text("TEST"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4362
            ImGui::SmallButton("TEST##2");
1193b4be Poul Sander 2025-02-03 21:28 4363
1193b4be Poul Sander 2025-02-03 21:28 4364
            // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
1193b4be Poul Sander 2025-02-03 21:28 4365
            ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 4366
            ImGui::Text("Text aligned to framed item"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4367
            ImGui::Button("Item##1"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4368
            ImGui::Text("Item"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4369
            ImGui::SmallButton("Item##2"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4370
            ImGui::Button("Item##3");
1193b4be Poul Sander 2025-02-03 21:28 4371
1193b4be Poul Sander 2025-02-03 21:28 4372
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4373
        }
1193b4be Poul Sander 2025-02-03 21:28 4374
1193b4be Poul Sander 2025-02-03 21:28 4375
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 4376
1193b4be Poul Sander 2025-02-03 21:28 4377
        {
1193b4be Poul Sander 2025-02-03 21:28 4378
            ImGui::BulletText("Multi-line text:");
1193b4be Poul Sander 2025-02-03 21:28 4379
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4380
            ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4381
            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4382
            ImGui::Text("Banana");
1193b4be Poul Sander 2025-02-03 21:28 4383
1193b4be Poul Sander 2025-02-03 21:28 4384
            ImGui::Text("Banana"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4385
            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4386
            ImGui::Text("One\nTwo\nThree");
1193b4be Poul Sander 2025-02-03 21:28 4387
1193b4be Poul Sander 2025-02-03 21:28 4388
            ImGui::Button("HOP##1"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4389
            ImGui::Text("Banana"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4390
            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4391
            ImGui::Text("Banana");
1193b4be Poul Sander 2025-02-03 21:28 4392
1193b4be Poul Sander 2025-02-03 21:28 4393
            ImGui::Button("HOP##2"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4394
            ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4395
            ImGui::Text("Banana");
1193b4be Poul Sander 2025-02-03 21:28 4396
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4397
        }
1193b4be Poul Sander 2025-02-03 21:28 4398
1193b4be Poul Sander 2025-02-03 21:28 4399
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 4400
1193b4be Poul Sander 2025-02-03 21:28 4401
        {
1193b4be Poul Sander 2025-02-03 21:28 4402
            ImGui::BulletText("Misc items:");
1193b4be Poul Sander 2025-02-03 21:28 4403
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 4404
1193b4be Poul Sander 2025-02-03 21:28 4405
            // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button.
1193b4be Poul Sander 2025-02-03 21:28 4406
            ImGui::Button("80x80", ImVec2(80, 80));
1193b4be Poul Sander 2025-02-03 21:28 4407
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4408
            ImGui::Button("50x50", ImVec2(50, 50));
1193b4be Poul Sander 2025-02-03 21:28 4409
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4410
            ImGui::Button("Button()");
1193b4be Poul Sander 2025-02-03 21:28 4411
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4412
            ImGui::SmallButton("SmallButton()");
1193b4be Poul Sander 2025-02-03 21:28 4413
1193b4be Poul Sander 2025-02-03 21:28 4414
            // Tree
1193b4be Poul Sander 2025-02-03 21:28 4415
            const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
1193b4be Poul Sander 2025-02-03 21:28 4416
            ImGui::Button("Button##1");
1193b4be Poul Sander 2025-02-03 21:28 4417
            ImGui::SameLine(0.0f, spacing);
1193b4be Poul Sander 2025-02-03 21:28 4418
            if (ImGui::TreeNode("Node##1"))
1193b4be Poul Sander 2025-02-03 21:28 4419
            {
1193b4be Poul Sander 2025-02-03 21:28 4420
                // Placeholder tree data
1193b4be Poul Sander 2025-02-03 21:28 4421
                for (int i = 0; i < 6; i++)
1193b4be Poul Sander 2025-02-03 21:28 4422
                    ImGui::BulletText("Item %d..", i);
1193b4be Poul Sander 2025-02-03 21:28 4423
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4424
            }
1193b4be Poul Sander 2025-02-03 21:28 4425
1193b4be Poul Sander 2025-02-03 21:28 4426
            // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget.
1193b4be Poul Sander 2025-02-03 21:28 4427
            // Otherwise you can use SmallButton() (smaller fit).
1193b4be Poul Sander 2025-02-03 21:28 4428
            ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 4429
1193b4be Poul Sander 2025-02-03 21:28 4430
            // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add
1193b4be Poul Sander 2025-02-03 21:28 4431
            // other contents below the node.
1193b4be Poul Sander 2025-02-03 21:28 4432
            bool node_open = ImGui::TreeNode("Node##2");
1193b4be Poul Sander 2025-02-03 21:28 4433
            ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
1193b4be Poul Sander 2025-02-03 21:28 4434
            if (node_open)
1193b4be Poul Sander 2025-02-03 21:28 4435
            {
1193b4be Poul Sander 2025-02-03 21:28 4436
                // Placeholder tree data
1193b4be Poul Sander 2025-02-03 21:28 4437
                for (int i = 0; i < 6; i++)
1193b4be Poul Sander 2025-02-03 21:28 4438
                    ImGui::BulletText("Item %d..", i);
1193b4be Poul Sander 2025-02-03 21:28 4439
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4440
            }
1193b4be Poul Sander 2025-02-03 21:28 4441
1193b4be Poul Sander 2025-02-03 21:28 4442
            // Bullet
1193b4be Poul Sander 2025-02-03 21:28 4443
            ImGui::Button("Button##3");
1193b4be Poul Sander 2025-02-03 21:28 4444
            ImGui::SameLine(0.0f, spacing);
1193b4be Poul Sander 2025-02-03 21:28 4445
            ImGui::BulletText("Bullet text");
1193b4be Poul Sander 2025-02-03 21:28 4446
1193b4be Poul Sander 2025-02-03 21:28 4447
            ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 4448
            ImGui::BulletText("Node");
1193b4be Poul Sander 2025-02-03 21:28 4449
            ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
1193b4be Poul Sander 2025-02-03 21:28 4450
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 4451
        }
1193b4be Poul Sander 2025-02-03 21:28 4452
1193b4be Poul Sander 2025-02-03 21:28 4453
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4454
    }
1193b4be Poul Sander 2025-02-03 21:28 4455
1193b4be Poul Sander 2025-02-03 21:28 4456
    IMGUI_DEMO_MARKER("Layout/Scrolling");
1193b4be Poul Sander 2025-02-03 21:28 4457
    if (ImGui::TreeNode("Scrolling"))
1193b4be Poul Sander 2025-02-03 21:28 4458
    {
1193b4be Poul Sander 2025-02-03 21:28 4459
        // Vertical scroll functions
1193b4be Poul Sander 2025-02-03 21:28 4460
        IMGUI_DEMO_MARKER("Layout/Scrolling/Vertical");
1193b4be Poul Sander 2025-02-03 21:28 4461
        HelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
1193b4be Poul Sander 2025-02-03 21:28 4462
1193b4be Poul Sander 2025-02-03 21:28 4463
        static int track_item = 50;
1193b4be Poul Sander 2025-02-03 21:28 4464
        static bool enable_track = true;
1193b4be Poul Sander 2025-02-03 21:28 4465
        static bool enable_extra_decorations = false;
1193b4be Poul Sander 2025-02-03 21:28 4466
        static float scroll_to_off_px = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 4467
        static float scroll_to_pos_px = 200.0f;
1193b4be Poul Sander 2025-02-03 21:28 4468
1193b4be Poul Sander 2025-02-03 21:28 4469
        ImGui::Checkbox("Decoration", &enable_extra_decorations);
1193b4be Poul Sander 2025-02-03 21:28 4470
1193b4be Poul Sander 2025-02-03 21:28 4471
        ImGui::Checkbox("Track", &enable_track);
1193b4be Poul Sander 2025-02-03 21:28 4472
        ImGui::PushItemWidth(100);
1193b4be Poul Sander 2025-02-03 21:28 4473
        ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
1193b4be Poul Sander 2025-02-03 21:28 4474
1193b4be Poul Sander 2025-02-03 21:28 4475
        bool scroll_to_off = ImGui::Button("Scroll Offset");
1193b4be Poul Sander 2025-02-03 21:28 4476
        ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
1193b4be Poul Sander 2025-02-03 21:28 4477
1193b4be Poul Sander 2025-02-03 21:28 4478
        bool scroll_to_pos = ImGui::Button("Scroll To Pos");
1193b4be Poul Sander 2025-02-03 21:28 4479
        ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
1193b4be Poul Sander 2025-02-03 21:28 4480
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 4481
1193b4be Poul Sander 2025-02-03 21:28 4482
        if (scroll_to_off || scroll_to_pos)
1193b4be Poul Sander 2025-02-03 21:28 4483
            enable_track = false;
1193b4be Poul Sander 2025-02-03 21:28 4484
1193b4be Poul Sander 2025-02-03 21:28 4485
        ImGuiStyle& style = ImGui::GetStyle();
1193b4be Poul Sander 2025-02-03 21:28 4486
        float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
1193b4be Poul Sander 2025-02-03 21:28 4487
        if (child_w < 1.0f)
1193b4be Poul Sander 2025-02-03 21:28 4488
            child_w = 1.0f;
1193b4be Poul Sander 2025-02-03 21:28 4489
        ImGui::PushID("##VerticalScrolling");
1193b4be Poul Sander 2025-02-03 21:28 4490
        for (int i = 0; i < 5; i++)
1193b4be Poul Sander 2025-02-03 21:28 4491
        {
1193b4be Poul Sander 2025-02-03 21:28 4492
            if (i > 0) ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4493
            ImGui::BeginGroup();
1193b4be Poul Sander 2025-02-03 21:28 4494
            const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
1193b4be Poul Sander 2025-02-03 21:28 4495
            ImGui::TextUnformatted(names[i]);
1193b4be Poul Sander 2025-02-03 21:28 4496
1193b4be Poul Sander 2025-02-03 21:28 4497
            const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
1193b4be Poul Sander 2025-02-03 21:28 4498
            const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
1193b4be Poul Sander 2025-02-03 21:28 4499
            const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), ImGuiChildFlags_Borders, child_flags);
1193b4be Poul Sander 2025-02-03 21:28 4500
            if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 4501
            {
1193b4be Poul Sander 2025-02-03 21:28 4502
                ImGui::TextUnformatted("abc");
1193b4be Poul Sander 2025-02-03 21:28 4503
                ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 4504
            }
1193b4be Poul Sander 2025-02-03 21:28 4505
            if (scroll_to_off)
1193b4be Poul Sander 2025-02-03 21:28 4506
                ImGui::SetScrollY(scroll_to_off_px);
1193b4be Poul Sander 2025-02-03 21:28 4507
            if (scroll_to_pos)
1193b4be Poul Sander 2025-02-03 21:28 4508
                ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
1193b4be Poul Sander 2025-02-03 21:28 4509
            if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
1193b4be Poul Sander 2025-02-03 21:28 4510
            {
1193b4be Poul Sander 2025-02-03 21:28 4511
                for (int item = 0; item < 100; item++)
1193b4be Poul Sander 2025-02-03 21:28 4512
                {
1193b4be Poul Sander 2025-02-03 21:28 4513
                    if (enable_track && item == track_item)
1193b4be Poul Sander 2025-02-03 21:28 4514
                    {
1193b4be Poul Sander 2025-02-03 21:28 4515
                        ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
1193b4be Poul Sander 2025-02-03 21:28 4516
                        ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
1193b4be Poul Sander 2025-02-03 21:28 4517
                    }
1193b4be Poul Sander 2025-02-03 21:28 4518
                    else
1193b4be Poul Sander 2025-02-03 21:28 4519
                    {
1193b4be Poul Sander 2025-02-03 21:28 4520
                        ImGui::Text("Item %d", item);
1193b4be Poul Sander 2025-02-03 21:28 4521
                    }
1193b4be Poul Sander 2025-02-03 21:28 4522
                }
1193b4be Poul Sander 2025-02-03 21:28 4523
            }
1193b4be Poul Sander 2025-02-03 21:28 4524
            float scroll_y = ImGui::GetScrollY();
1193b4be Poul Sander 2025-02-03 21:28 4525
            float scroll_max_y = ImGui::GetScrollMaxY();
1193b4be Poul Sander 2025-02-03 21:28 4526
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4527
            ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
1193b4be Poul Sander 2025-02-03 21:28 4528
            ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 4529
        }
1193b4be Poul Sander 2025-02-03 21:28 4530
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 4531
1193b4be Poul Sander 2025-02-03 21:28 4532
        // Horizontal scroll functions
1193b4be Poul Sander 2025-02-03 21:28 4533
        IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal");
1193b4be Poul Sander 2025-02-03 21:28 4534
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 4535
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 4536
            "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 4537
            "Because the clipping rectangle of most window hides half worth of WindowPadding on the "
1193b4be Poul Sander 2025-02-03 21:28 4538
            "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the "
1193b4be Poul Sander 2025-02-03 21:28 4539
            "equivalent SetScrollFromPosY(+1) wouldn't.");
1193b4be Poul Sander 2025-02-03 21:28 4540
        ImGui::PushID("##HorizontalScrolling");
1193b4be Poul Sander 2025-02-03 21:28 4541
        for (int i = 0; i < 5; i++)
1193b4be Poul Sander 2025-02-03 21:28 4542
        {
1193b4be Poul Sander 2025-02-03 21:28 4543
            float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
1193b4be Poul Sander 2025-02-03 21:28 4544
            ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
1193b4be Poul Sander 2025-02-03 21:28 4545
            ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
1193b4be Poul Sander 2025-02-03 21:28 4546
            bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), ImGuiChildFlags_Borders, child_flags);
1193b4be Poul Sander 2025-02-03 21:28 4547
            if (scroll_to_off)
1193b4be Poul Sander 2025-02-03 21:28 4548
                ImGui::SetScrollX(scroll_to_off_px);
1193b4be Poul Sander 2025-02-03 21:28 4549
            if (scroll_to_pos)
1193b4be Poul Sander 2025-02-03 21:28 4550
                ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
1193b4be Poul Sander 2025-02-03 21:28 4551
            if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
1193b4be Poul Sander 2025-02-03 21:28 4552
            {
1193b4be Poul Sander 2025-02-03 21:28 4553
                for (int item = 0; item < 100; item++)
1193b4be Poul Sander 2025-02-03 21:28 4554
                {
1193b4be Poul Sander 2025-02-03 21:28 4555
                    if (item > 0)
1193b4be Poul Sander 2025-02-03 21:28 4556
                        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4557
                    if (enable_track && item == track_item)
1193b4be Poul Sander 2025-02-03 21:28 4558
                    {
1193b4be Poul Sander 2025-02-03 21:28 4559
                        ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
1193b4be Poul Sander 2025-02-03 21:28 4560
                        ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
1193b4be Poul Sander 2025-02-03 21:28 4561
                    }
1193b4be Poul Sander 2025-02-03 21:28 4562
                    else
1193b4be Poul Sander 2025-02-03 21:28 4563
                    {
1193b4be Poul Sander 2025-02-03 21:28 4564
                        ImGui::Text("Item %d", item);
1193b4be Poul Sander 2025-02-03 21:28 4565
                    }
1193b4be Poul Sander 2025-02-03 21:28 4566
                }
1193b4be Poul Sander 2025-02-03 21:28 4567
            }
1193b4be Poul Sander 2025-02-03 21:28 4568
            float scroll_x = ImGui::GetScrollX();
1193b4be Poul Sander 2025-02-03 21:28 4569
            float scroll_max_x = ImGui::GetScrollMaxX();
1193b4be Poul Sander 2025-02-03 21:28 4570
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4571
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4572
            const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
1193b4be Poul Sander 2025-02-03 21:28 4573
            ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
1193b4be Poul Sander 2025-02-03 21:28 4574
            ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 4575
        }
1193b4be Poul Sander 2025-02-03 21:28 4576
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 4577
1193b4be Poul Sander 2025-02-03 21:28 4578
        // Miscellaneous Horizontal Scrolling Demo
1193b4be Poul Sander 2025-02-03 21:28 4579
        IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal (more)");
1193b4be Poul Sander 2025-02-03 21:28 4580
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 4581
            "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 4582
            "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin().");
1193b4be Poul Sander 2025-02-03 21:28 4583
        static int lines = 7;
1193b4be Poul Sander 2025-02-03 21:28 4584
        ImGui::SliderInt("Lines", &lines, 1, 15);
1193b4be Poul Sander 2025-02-03 21:28 4585
        ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
1193b4be Poul Sander 2025-02-03 21:28 4586
        ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
1193b4be Poul Sander 2025-02-03 21:28 4587
        ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
1193b4be Poul Sander 2025-02-03 21:28 4588
        ImGui::BeginChild("scrolling", scrolling_child_size, ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar);
1193b4be Poul Sander 2025-02-03 21:28 4589
        for (int line = 0; line < lines; line++)
1193b4be Poul Sander 2025-02-03 21:28 4590
        {
1193b4be Poul Sander 2025-02-03 21:28 4591
            // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
1193b4be Poul Sander 2025-02-03 21:28 4592
            // If you want to create your own time line for a real application you may be better off manipulating
1193b4be Poul Sander 2025-02-03 21:28 4593
            // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
1193b4be Poul Sander 2025-02-03 21:28 4594
            // yourself. You may also want to use the lower-level ImDrawList API.
1193b4be Poul Sander 2025-02-03 21:28 4595
            int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
1193b4be Poul Sander 2025-02-03 21:28 4596
            for (int n = 0; n < num_buttons; n++)
1193b4be Poul Sander 2025-02-03 21:28 4597
            {
1193b4be Poul Sander 2025-02-03 21:28 4598
                if (n > 0) ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4599
                ImGui::PushID(n + line * 1000);
1193b4be Poul Sander 2025-02-03 21:28 4600
                char num_buf[16];
1193b4be Poul Sander 2025-02-03 21:28 4601
                sprintf(num_buf, "%d", n);
1193b4be Poul Sander 2025-02-03 21:28 4602
                const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
1193b4be Poul Sander 2025-02-03 21:28 4603
                float hue = n * 0.05f;
1193b4be Poul Sander 2025-02-03 21:28 4604
                ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
1193b4be Poul Sander 2025-02-03 21:28 4605
                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
1193b4be Poul Sander 2025-02-03 21:28 4606
                ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
1193b4be Poul Sander 2025-02-03 21:28 4607
                ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 4608
                ImGui::PopStyleColor(3);
1193b4be Poul Sander 2025-02-03 21:28 4609
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 4610
            }
1193b4be Poul Sander 2025-02-03 21:28 4611
        }
1193b4be Poul Sander 2025-02-03 21:28 4612
        float scroll_x = ImGui::GetScrollX();
1193b4be Poul Sander 2025-02-03 21:28 4613
        float scroll_max_x = ImGui::GetScrollMaxX();
1193b4be Poul Sander 2025-02-03 21:28 4614
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4615
        ImGui::PopStyleVar(2);
1193b4be Poul Sander 2025-02-03 21:28 4616
        float scroll_x_delta = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 4617
        ImGui::SmallButton("<<");
1193b4be Poul Sander 2025-02-03 21:28 4618
        if (ImGui::IsItemActive())
1193b4be Poul Sander 2025-02-03 21:28 4619
            scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
1193b4be Poul Sander 2025-02-03 21:28 4620
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4621
        ImGui::Text("Scroll from code"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4622
        ImGui::SmallButton(">>");
1193b4be Poul Sander 2025-02-03 21:28 4623
        if (ImGui::IsItemActive())
1193b4be Poul Sander 2025-02-03 21:28 4624
            scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
1193b4be Poul Sander 2025-02-03 21:28 4625
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4626
        ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
1193b4be Poul Sander 2025-02-03 21:28 4627
        if (scroll_x_delta != 0.0f)
1193b4be Poul Sander 2025-02-03 21:28 4628
        {
1193b4be Poul Sander 2025-02-03 21:28 4629
            // Demonstrate a trick: you can use Begin to set yourself in the context of another window
1193b4be Poul Sander 2025-02-03 21:28 4630
            // (here we are already out of your child window)
1193b4be Poul Sander 2025-02-03 21:28 4631
            ImGui::BeginChild("scrolling");
1193b4be Poul Sander 2025-02-03 21:28 4632
            ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
1193b4be Poul Sander 2025-02-03 21:28 4633
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4634
        }
1193b4be Poul Sander 2025-02-03 21:28 4635
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 4636
1193b4be Poul Sander 2025-02-03 21:28 4637
        static bool show_horizontal_contents_size_demo_window = false;
1193b4be Poul Sander 2025-02-03 21:28 4638
        ImGui::Checkbox("Show Horizontal contents size demo window", &show_horizontal_contents_size_demo_window);
1193b4be Poul Sander 2025-02-03 21:28 4639
1193b4be Poul Sander 2025-02-03 21:28 4640
        if (show_horizontal_contents_size_demo_window)
1193b4be Poul Sander 2025-02-03 21:28 4641
        {
1193b4be Poul Sander 2025-02-03 21:28 4642
            static bool show_h_scrollbar = true;
1193b4be Poul Sander 2025-02-03 21:28 4643
            static bool show_button = true;
1193b4be Poul Sander 2025-02-03 21:28 4644
            static bool show_tree_nodes = true;
1193b4be Poul Sander 2025-02-03 21:28 4645
            static bool show_text_wrapped = false;
1193b4be Poul Sander 2025-02-03 21:28 4646
            static bool show_columns = true;
1193b4be Poul Sander 2025-02-03 21:28 4647
            static bool show_tab_bar = true;
1193b4be Poul Sander 2025-02-03 21:28 4648
            static bool show_child = false;
1193b4be Poul Sander 2025-02-03 21:28 4649
            static bool explicit_content_size = false;
1193b4be Poul Sander 2025-02-03 21:28 4650
            static float contents_size_x = 300.0f;
1193b4be Poul Sander 2025-02-03 21:28 4651
            if (explicit_content_size)
1193b4be Poul Sander 2025-02-03 21:28 4652
                ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 4653
            ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
1193b4be Poul Sander 2025-02-03 21:28 4654
            IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal contents size demo window");
1193b4be Poul Sander 2025-02-03 21:28 4655
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
1193b4be Poul Sander 2025-02-03 21:28 4656
            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
1193b4be Poul Sander 2025-02-03 21:28 4657
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 4658
                "Test how different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 4659
                "Use 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
1193b4be Poul Sander 2025-02-03 21:28 4660
            ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
1193b4be Poul Sander 2025-02-03 21:28 4661
            ImGui::Checkbox("Button", &show_button);            // Will grow contents size (unless explicitly overwritten)
1193b4be Poul Sander 2025-02-03 21:28 4662
            ImGui::Checkbox("Tree nodes", &show_tree_nodes);    // Will grow contents size and display highlight over full width
1193b4be Poul Sander 2025-02-03 21:28 4663
            ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
1193b4be Poul Sander 2025-02-03 21:28 4664
            ImGui::Checkbox("Columns", &show_columns);          // Will use contents size
1193b4be Poul Sander 2025-02-03 21:28 4665
            ImGui::Checkbox("Tab bar", &show_tab_bar);          // Will use contents size
1193b4be Poul Sander 2025-02-03 21:28 4666
            ImGui::Checkbox("Child", &show_child);              // Will grow and use contents size
1193b4be Poul Sander 2025-02-03 21:28 4667
            ImGui::Checkbox("Explicit content size", &explicit_content_size);
1193b4be Poul Sander 2025-02-03 21:28 4668
            ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
1193b4be Poul Sander 2025-02-03 21:28 4669
            if (explicit_content_size)
1193b4be Poul Sander 2025-02-03 21:28 4670
            {
1193b4be Poul Sander 2025-02-03 21:28 4671
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4672
                ImGui::SetNextItemWidth(100);
1193b4be Poul Sander 2025-02-03 21:28 4673
                ImGui::DragFloat("##csx", &contents_size_x);
1193b4be Poul Sander 2025-02-03 21:28 4674
                ImVec2 p = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 4675
                ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
1193b4be Poul Sander 2025-02-03 21:28 4676
                ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
1193b4be Poul Sander 2025-02-03 21:28 4677
                ImGui::Dummy(ImVec2(0, 10));
1193b4be Poul Sander 2025-02-03 21:28 4678
            }
1193b4be Poul Sander 2025-02-03 21:28 4679
            ImGui::PopStyleVar(2);
1193b4be Poul Sander 2025-02-03 21:28 4680
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 4681
            if (show_button)
1193b4be Poul Sander 2025-02-03 21:28 4682
            {
1193b4be Poul Sander 2025-02-03 21:28 4683
                ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
1193b4be Poul Sander 2025-02-03 21:28 4684
            }
1193b4be Poul Sander 2025-02-03 21:28 4685
            if (show_tree_nodes)
1193b4be Poul Sander 2025-02-03 21:28 4686
            {
1193b4be Poul Sander 2025-02-03 21:28 4687
                bool open = true;
1193b4be Poul Sander 2025-02-03 21:28 4688
                if (ImGui::TreeNode("this is a tree node"))
1193b4be Poul Sander 2025-02-03 21:28 4689
                {
1193b4be Poul Sander 2025-02-03 21:28 4690
                    if (ImGui::TreeNode("another one of those tree node..."))
1193b4be Poul Sander 2025-02-03 21:28 4691
                    {
1193b4be Poul Sander 2025-02-03 21:28 4692
                        ImGui::Text("Some tree contents");
1193b4be Poul Sander 2025-02-03 21:28 4693
                        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4694
                    }
1193b4be Poul Sander 2025-02-03 21:28 4695
                    ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4696
                }
1193b4be Poul Sander 2025-02-03 21:28 4697
                ImGui::CollapsingHeader("CollapsingHeader", &open);
1193b4be Poul Sander 2025-02-03 21:28 4698
            }
1193b4be Poul Sander 2025-02-03 21:28 4699
            if (show_text_wrapped)
1193b4be Poul Sander 2025-02-03 21:28 4700
            {
1193b4be Poul Sander 2025-02-03 21:28 4701
                ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
1193b4be Poul Sander 2025-02-03 21:28 4702
            }
1193b4be Poul Sander 2025-02-03 21:28 4703
            if (show_columns)
1193b4be Poul Sander 2025-02-03 21:28 4704
            {
1193b4be Poul Sander 2025-02-03 21:28 4705
                ImGui::Text("Tables:");
1193b4be Poul Sander 2025-02-03 21:28 4706
                if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders))
1193b4be Poul Sander 2025-02-03 21:28 4707
                {
1193b4be Poul Sander 2025-02-03 21:28 4708
                    for (int n = 0; n < 4; n++)
1193b4be Poul Sander 2025-02-03 21:28 4709
                    {
1193b4be Poul Sander 2025-02-03 21:28 4710
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 4711
                        ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x);
1193b4be Poul Sander 2025-02-03 21:28 4712
                    }
1193b4be Poul Sander 2025-02-03 21:28 4713
                    ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 4714
                }
1193b4be Poul Sander 2025-02-03 21:28 4715
                ImGui::Text("Columns:");
1193b4be Poul Sander 2025-02-03 21:28 4716
                ImGui::Columns(4);
1193b4be Poul Sander 2025-02-03 21:28 4717
                for (int n = 0; n < 4; n++)
1193b4be Poul Sander 2025-02-03 21:28 4718
                {
1193b4be Poul Sander 2025-02-03 21:28 4719
                    ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
1193b4be Poul Sander 2025-02-03 21:28 4720
                    ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 4721
                }
1193b4be Poul Sander 2025-02-03 21:28 4722
                ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 4723
            }
1193b4be Poul Sander 2025-02-03 21:28 4724
            if (show_tab_bar && ImGui::BeginTabBar("Hello"))
1193b4be Poul Sander 2025-02-03 21:28 4725
            {
1193b4be Poul Sander 2025-02-03 21:28 4726
                if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
1193b4be Poul Sander 2025-02-03 21:28 4727
                if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
1193b4be Poul Sander 2025-02-03 21:28 4728
                if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
1193b4be Poul Sander 2025-02-03 21:28 4729
                if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
1193b4be Poul Sander 2025-02-03 21:28 4730
                ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 4731
            }
1193b4be Poul Sander 2025-02-03 21:28 4732
            if (show_child)
1193b4be Poul Sander 2025-02-03 21:28 4733
            {
1193b4be Poul Sander 2025-02-03 21:28 4734
                ImGui::BeginChild("child", ImVec2(0, 0), ImGuiChildFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 4735
                ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 4736
            }
1193b4be Poul Sander 2025-02-03 21:28 4737
            ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 4738
        }
1193b4be Poul Sander 2025-02-03 21:28 4739
1193b4be Poul Sander 2025-02-03 21:28 4740
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4741
    }
1193b4be Poul Sander 2025-02-03 21:28 4742
1193b4be Poul Sander 2025-02-03 21:28 4743
    IMGUI_DEMO_MARKER("Layout/Text Clipping");
1193b4be Poul Sander 2025-02-03 21:28 4744
    if (ImGui::TreeNode("Text Clipping"))
1193b4be Poul Sander 2025-02-03 21:28 4745
    {
1193b4be Poul Sander 2025-02-03 21:28 4746
        static ImVec2 size(100.0f, 100.0f);
1193b4be Poul Sander 2025-02-03 21:28 4747
        static ImVec2 offset(30.0f, 30.0f);
1193b4be Poul Sander 2025-02-03 21:28 4748
        ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 4749
        ImGui::TextWrapped("(Click and drag to scroll)");
1193b4be Poul Sander 2025-02-03 21:28 4750
1193b4be Poul Sander 2025-02-03 21:28 4751
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 4752
            "(Left) Using ImGui::PushClipRect():\n"
1193b4be Poul Sander 2025-02-03 21:28 4753
            "Will alter ImGui hit-testing logic + ImDrawList rendering.\n"
1193b4be Poul Sander 2025-02-03 21:28 4754
            "(use this if you want your clipping rectangle to affect interactions)\n\n"
1193b4be Poul Sander 2025-02-03 21:28 4755
            "(Center) Using ImDrawList::PushClipRect():\n"
1193b4be Poul Sander 2025-02-03 21:28 4756
            "Will alter ImDrawList rendering only.\n"
1193b4be Poul Sander 2025-02-03 21:28 4757
            "(use this as a shortcut if you are only using ImDrawList calls)\n\n"
1193b4be Poul Sander 2025-02-03 21:28 4758
            "(Right) Using ImDrawList::AddText() with a fine ClipRect:\n"
1193b4be Poul Sander 2025-02-03 21:28 4759
            "Will alter only this specific ImDrawList::AddText() rendering.\n"
1193b4be Poul Sander 2025-02-03 21:28 4760
            "This is often used internally to avoid altering the clipping rectangle and minimize draw calls.");
1193b4be Poul Sander 2025-02-03 21:28 4761
1193b4be Poul Sander 2025-02-03 21:28 4762
        for (int n = 0; n < 3; n++)
1193b4be Poul Sander 2025-02-03 21:28 4763
        {
1193b4be Poul Sander 2025-02-03 21:28 4764
            if (n > 0)
1193b4be Poul Sander 2025-02-03 21:28 4765
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4766
1193b4be Poul Sander 2025-02-03 21:28 4767
            ImGui::PushID(n);
1193b4be Poul Sander 2025-02-03 21:28 4768
            ImGui::InvisibleButton("##canvas", size);
1193b4be Poul Sander 2025-02-03 21:28 4769
            if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left))
1193b4be Poul Sander 2025-02-03 21:28 4770
            {
1193b4be Poul Sander 2025-02-03 21:28 4771
                offset.x += ImGui::GetIO().MouseDelta.x;
1193b4be Poul Sander 2025-02-03 21:28 4772
                offset.y += ImGui::GetIO().MouseDelta.y;
1193b4be Poul Sander 2025-02-03 21:28 4773
            }
1193b4be Poul Sander 2025-02-03 21:28 4774
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 4775
            if (!ImGui::IsItemVisible()) // Skip rendering as ImDrawList elements are not clipped.
1193b4be Poul Sander 2025-02-03 21:28 4776
                continue;
1193b4be Poul Sander 2025-02-03 21:28 4777
1193b4be Poul Sander 2025-02-03 21:28 4778
            const ImVec2 p0 = ImGui::GetItemRectMin();
1193b4be Poul Sander 2025-02-03 21:28 4779
            const ImVec2 p1 = ImGui::GetItemRectMax();
1193b4be Poul Sander 2025-02-03 21:28 4780
            const char* text_str = "Line 1 hello\nLine 2 clip me!";
1193b4be Poul Sander 2025-02-03 21:28 4781
            const ImVec2 text_pos = ImVec2(p0.x + offset.x, p0.y + offset.y);
1193b4be Poul Sander 2025-02-03 21:28 4782
            ImDrawList* draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 4783
            switch (n)
1193b4be Poul Sander 2025-02-03 21:28 4784
            {
1193b4be Poul Sander 2025-02-03 21:28 4785
            case 0:
1193b4be Poul Sander 2025-02-03 21:28 4786
                ImGui::PushClipRect(p0, p1, true);
1193b4be Poul Sander 2025-02-03 21:28 4787
                draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
1193b4be Poul Sander 2025-02-03 21:28 4788
                draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
1193b4be Poul Sander 2025-02-03 21:28 4789
                ImGui::PopClipRect();
1193b4be Poul Sander 2025-02-03 21:28 4790
                break;
1193b4be Poul Sander 2025-02-03 21:28 4791
            case 1:
1193b4be Poul Sander 2025-02-03 21:28 4792
                draw_list->PushClipRect(p0, p1, true);
1193b4be Poul Sander 2025-02-03 21:28 4793
                draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
1193b4be Poul Sander 2025-02-03 21:28 4794
                draw_list->AddText(text_pos, IM_COL32_WHITE, text_str);
1193b4be Poul Sander 2025-02-03 21:28 4795
                draw_list->PopClipRect();
1193b4be Poul Sander 2025-02-03 21:28 4796
                break;
1193b4be Poul Sander 2025-02-03 21:28 4797
            case 2:
1193b4be Poul Sander 2025-02-03 21:28 4798
                ImVec4 clip_rect(p0.x, p0.y, p1.x, p1.y); // AddText() takes a ImVec4* here so let's convert.
1193b4be Poul Sander 2025-02-03 21:28 4799
                draw_list->AddRectFilled(p0, p1, IM_COL32(90, 90, 120, 255));
1193b4be Poul Sander 2025-02-03 21:28 4800
                draw_list->AddText(ImGui::GetFont(), ImGui::GetFontSize(), text_pos, IM_COL32_WHITE, text_str, NULL, 0.0f, &clip_rect);
1193b4be Poul Sander 2025-02-03 21:28 4801
                break;
1193b4be Poul Sander 2025-02-03 21:28 4802
            }
1193b4be Poul Sander 2025-02-03 21:28 4803
        }
1193b4be Poul Sander 2025-02-03 21:28 4804
1193b4be Poul Sander 2025-02-03 21:28 4805
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4806
    }
1193b4be Poul Sander 2025-02-03 21:28 4807
1193b4be Poul Sander 2025-02-03 21:28 4808
    IMGUI_DEMO_MARKER("Layout/Overlap Mode");
1193b4be Poul Sander 2025-02-03 21:28 4809
    if (ImGui::TreeNode("Overlap Mode"))
1193b4be Poul Sander 2025-02-03 21:28 4810
    {
1193b4be Poul Sander 2025-02-03 21:28 4811
        static bool enable_allow_overlap = true;
1193b4be Poul Sander 2025-02-03 21:28 4812
1193b4be Poul Sander 2025-02-03 21:28 4813
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 4814
            "Hit-testing is by default performed in item submission order, which generally is perceived as 'back-to-front'.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 4815
            "By using SetNextItemAllowOverlap() you can notify that an item may be overlapped by another. "
1193b4be Poul Sander 2025-02-03 21:28 4816
            "Doing so alters the hovering logic: items using AllowOverlap mode requires an extra frame to accept hovered state.");
1193b4be Poul Sander 2025-02-03 21:28 4817
        ImGui::Checkbox("Enable AllowOverlap", &enable_allow_overlap);
1193b4be Poul Sander 2025-02-03 21:28 4818
1193b4be Poul Sander 2025-02-03 21:28 4819
        ImVec2 button1_pos = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 4820
        ImVec2 button2_pos = ImVec2(button1_pos.x + 50.0f, button1_pos.y + 50.0f);
1193b4be Poul Sander 2025-02-03 21:28 4821
        if (enable_allow_overlap)
1193b4be Poul Sander 2025-02-03 21:28 4822
            ImGui::SetNextItemAllowOverlap();
1193b4be Poul Sander 2025-02-03 21:28 4823
        ImGui::Button("Button 1", ImVec2(80, 80));
1193b4be Poul Sander 2025-02-03 21:28 4824
        ImGui::SetCursorScreenPos(button2_pos);
1193b4be Poul Sander 2025-02-03 21:28 4825
        ImGui::Button("Button 2", ImVec2(80, 80));
1193b4be Poul Sander 2025-02-03 21:28 4826
1193b4be Poul Sander 2025-02-03 21:28 4827
        // This is typically used with width-spanning items.
1193b4be Poul Sander 2025-02-03 21:28 4828
        // (note that Selectable() has a dedicated flag ImGuiSelectableFlags_AllowOverlap, which is a shortcut
1193b4be Poul Sander 2025-02-03 21:28 4829
        // for using SetNextItemAllowOverlap(). For demo purpose we use SetNextItemAllowOverlap() here.)
1193b4be Poul Sander 2025-02-03 21:28 4830
        if (enable_allow_overlap)
1193b4be Poul Sander 2025-02-03 21:28 4831
            ImGui::SetNextItemAllowOverlap();
1193b4be Poul Sander 2025-02-03 21:28 4832
        ImGui::Selectable("Some Selectable", false);
1193b4be Poul Sander 2025-02-03 21:28 4833
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4834
        ImGui::SmallButton("++");
1193b4be Poul Sander 2025-02-03 21:28 4835
1193b4be Poul Sander 2025-02-03 21:28 4836
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4837
    }
1193b4be Poul Sander 2025-02-03 21:28 4838
}
1193b4be Poul Sander 2025-02-03 21:28 4839
1193b4be Poul Sander 2025-02-03 21:28 4840
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 4841
// [SECTION] ShowDemoWindowPopups()
1193b4be Poul Sander 2025-02-03 21:28 4842
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 4843
1193b4be Poul Sander 2025-02-03 21:28 4844
static void ShowDemoWindowPopups()
1193b4be Poul Sander 2025-02-03 21:28 4845
{
1193b4be Poul Sander 2025-02-03 21:28 4846
    IMGUI_DEMO_MARKER("Popups");
1193b4be Poul Sander 2025-02-03 21:28 4847
    if (!ImGui::CollapsingHeader("Popups & Modal windows"))
1193b4be Poul Sander 2025-02-03 21:28 4848
        return;
1193b4be Poul Sander 2025-02-03 21:28 4849
1193b4be Poul Sander 2025-02-03 21:28 4850
    // The properties of popups windows are:
1193b4be Poul Sander 2025-02-03 21:28 4851
    // - They block normal mouse hovering detection outside them. (*)
1193b4be Poul Sander 2025-02-03 21:28 4852
    // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
1193b4be Poul Sander 2025-02-03 21:28 4853
    // - Their visibility state (~bool) is held internally by Dear ImGui instead of being held by the programmer as
1193b4be Poul Sander 2025-02-03 21:28 4854
    //   we are used to with regular Begin() calls. User can manipulate the visibility state by calling OpenPopup().
1193b4be Poul Sander 2025-02-03 21:28 4855
    // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even
1193b4be Poul Sander 2025-02-03 21:28 4856
    //     when normally blocked by a popup.
1193b4be Poul Sander 2025-02-03 21:28 4857
    // Those three properties are connected. The library needs to hold their visibility state BECAUSE it can close
1193b4be Poul Sander 2025-02-03 21:28 4858
    // popups at any time.
1193b4be Poul Sander 2025-02-03 21:28 4859
1193b4be Poul Sander 2025-02-03 21:28 4860
    // Typical use for regular windows:
1193b4be Poul Sander 2025-02-03 21:28 4861
    //   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();
1193b4be Poul Sander 2025-02-03 21:28 4862
    // Typical use for popups:
1193b4be Poul Sander 2025-02-03 21:28 4863
    //   if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
1193b4be Poul Sander 2025-02-03 21:28 4864
1193b4be Poul Sander 2025-02-03 21:28 4865
    // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
1193b4be Poul Sander 2025-02-03 21:28 4866
    // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
1193b4be Poul Sander 2025-02-03 21:28 4867
1193b4be Poul Sander 2025-02-03 21:28 4868
    IMGUI_DEMO_MARKER("Popups/Popups");
1193b4be Poul Sander 2025-02-03 21:28 4869
    if (ImGui::TreeNode("Popups"))
1193b4be Poul Sander 2025-02-03 21:28 4870
    {
1193b4be Poul Sander 2025-02-03 21:28 4871
        ImGui::TextWrapped(
1193b4be Poul Sander 2025-02-03 21:28 4872
            "When a popup is active, it inhibits interacting with windows that are behind the popup. "
1193b4be Poul Sander 2025-02-03 21:28 4873
            "Clicking outside the popup closes it.");
1193b4be Poul Sander 2025-02-03 21:28 4874
1193b4be Poul Sander 2025-02-03 21:28 4875
        static int selected_fish = -1;
1193b4be Poul Sander 2025-02-03 21:28 4876
        const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
1193b4be Poul Sander 2025-02-03 21:28 4877
        static bool toggles[] = { true, false, false, false, false };
1193b4be Poul Sander 2025-02-03 21:28 4878
1193b4be Poul Sander 2025-02-03 21:28 4879
        // Simple selection popup (if you want to show the current selection inside the Button itself,
1193b4be Poul Sander 2025-02-03 21:28 4880
        // you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
1193b4be Poul Sander 2025-02-03 21:28 4881
        if (ImGui::Button("Select.."))
1193b4be Poul Sander 2025-02-03 21:28 4882
            ImGui::OpenPopup("my_select_popup");
1193b4be Poul Sander 2025-02-03 21:28 4883
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 4884
        ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
1193b4be Poul Sander 2025-02-03 21:28 4885
        if (ImGui::BeginPopup("my_select_popup"))
1193b4be Poul Sander 2025-02-03 21:28 4886
        {
1193b4be Poul Sander 2025-02-03 21:28 4887
            ImGui::SeparatorText("Aquarium");
1193b4be Poul Sander 2025-02-03 21:28 4888
            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1193b4be Poul Sander 2025-02-03 21:28 4889
                if (ImGui::Selectable(names[i]))
1193b4be Poul Sander 2025-02-03 21:28 4890
                    selected_fish = i;
1193b4be Poul Sander 2025-02-03 21:28 4891
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 4892
        }
1193b4be Poul Sander 2025-02-03 21:28 4893
1193b4be Poul Sander 2025-02-03 21:28 4894
        // Showing a menu with toggles
1193b4be Poul Sander 2025-02-03 21:28 4895
        if (ImGui::Button("Toggle.."))
1193b4be Poul Sander 2025-02-03 21:28 4896
            ImGui::OpenPopup("my_toggle_popup");
1193b4be Poul Sander 2025-02-03 21:28 4897
        if (ImGui::BeginPopup("my_toggle_popup"))
1193b4be Poul Sander 2025-02-03 21:28 4898
        {
1193b4be Poul Sander 2025-02-03 21:28 4899
            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1193b4be Poul Sander 2025-02-03 21:28 4900
                ImGui::MenuItem(names[i], "", &toggles[i]);
1193b4be Poul Sander 2025-02-03 21:28 4901
            if (ImGui::BeginMenu("Sub-menu"))
1193b4be Poul Sander 2025-02-03 21:28 4902
            {
1193b4be Poul Sander 2025-02-03 21:28 4903
                ImGui::MenuItem("Click me");
1193b4be Poul Sander 2025-02-03 21:28 4904
                ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 4905
            }
1193b4be Poul Sander 2025-02-03 21:28 4906
1193b4be Poul Sander 2025-02-03 21:28 4907
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 4908
            ImGui::Text("Tooltip here");
1193b4be Poul Sander 2025-02-03 21:28 4909
            ImGui::SetItemTooltip("I am a tooltip over a popup");
1193b4be Poul Sander 2025-02-03 21:28 4910
1193b4be Poul Sander 2025-02-03 21:28 4911
            if (ImGui::Button("Stacked Popup"))
1193b4be Poul Sander 2025-02-03 21:28 4912
                ImGui::OpenPopup("another popup");
1193b4be Poul Sander 2025-02-03 21:28 4913
            if (ImGui::BeginPopup("another popup"))
1193b4be Poul Sander 2025-02-03 21:28 4914
            {
1193b4be Poul Sander 2025-02-03 21:28 4915
                for (int i = 0; i < IM_ARRAYSIZE(names); i++)
1193b4be Poul Sander 2025-02-03 21:28 4916
                    ImGui::MenuItem(names[i], "", &toggles[i]);
1193b4be Poul Sander 2025-02-03 21:28 4917
                if (ImGui::BeginMenu("Sub-menu"))
1193b4be Poul Sander 2025-02-03 21:28 4918
                {
1193b4be Poul Sander 2025-02-03 21:28 4919
                    ImGui::MenuItem("Click me");
1193b4be Poul Sander 2025-02-03 21:28 4920
                    if (ImGui::Button("Stacked Popup"))
1193b4be Poul Sander 2025-02-03 21:28 4921
                        ImGui::OpenPopup("another popup");
1193b4be Poul Sander 2025-02-03 21:28 4922
                    if (ImGui::BeginPopup("another popup"))
1193b4be Poul Sander 2025-02-03 21:28 4923
                    {
1193b4be Poul Sander 2025-02-03 21:28 4924
                        ImGui::Text("I am the last one here.");
1193b4be Poul Sander 2025-02-03 21:28 4925
                        ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 4926
                    }
1193b4be Poul Sander 2025-02-03 21:28 4927
                    ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 4928
                }
1193b4be Poul Sander 2025-02-03 21:28 4929
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 4930
            }
1193b4be Poul Sander 2025-02-03 21:28 4931
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 4932
        }
1193b4be Poul Sander 2025-02-03 21:28 4933
1193b4be Poul Sander 2025-02-03 21:28 4934
        // Call the more complete ShowExampleMenuFile which we use in various places of this demo
1193b4be Poul Sander 2025-02-03 21:28 4935
        if (ImGui::Button("With a menu.."))
1193b4be Poul Sander 2025-02-03 21:28 4936
            ImGui::OpenPopup("my_file_popup");
1193b4be Poul Sander 2025-02-03 21:28 4937
        if (ImGui::BeginPopup("my_file_popup", ImGuiWindowFlags_MenuBar))
1193b4be Poul Sander 2025-02-03 21:28 4938
        {
1193b4be Poul Sander 2025-02-03 21:28 4939
            if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 4940
            {
1193b4be Poul Sander 2025-02-03 21:28 4941
                if (ImGui::BeginMenu("File"))
1193b4be Poul Sander 2025-02-03 21:28 4942
                {
1193b4be Poul Sander 2025-02-03 21:28 4943
                    ShowExampleMenuFile();
1193b4be Poul Sander 2025-02-03 21:28 4944
                    ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 4945
                }
1193b4be Poul Sander 2025-02-03 21:28 4946
                if (ImGui::BeginMenu("Edit"))
1193b4be Poul Sander 2025-02-03 21:28 4947
                {
1193b4be Poul Sander 2025-02-03 21:28 4948
                    ImGui::MenuItem("Dummy");
1193b4be Poul Sander 2025-02-03 21:28 4949
                    ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 4950
                }
1193b4be Poul Sander 2025-02-03 21:28 4951
                ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 4952
            }
1193b4be Poul Sander 2025-02-03 21:28 4953
            ImGui::Text("Hello from popup!");
1193b4be Poul Sander 2025-02-03 21:28 4954
            ImGui::Button("This is a dummy button..");
1193b4be Poul Sander 2025-02-03 21:28 4955
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 4956
        }
1193b4be Poul Sander 2025-02-03 21:28 4957
1193b4be Poul Sander 2025-02-03 21:28 4958
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 4959
    }
1193b4be Poul Sander 2025-02-03 21:28 4960
1193b4be Poul Sander 2025-02-03 21:28 4961
    IMGUI_DEMO_MARKER("Popups/Context menus");
1193b4be Poul Sander 2025-02-03 21:28 4962
    if (ImGui::TreeNode("Context menus"))
1193b4be Poul Sander 2025-02-03 21:28 4963
    {
1193b4be Poul Sander 2025-02-03 21:28 4964
        HelpMarker("\"Context\" functions are simple helpers to associate a Popup to a given Item or Window identifier.");
1193b4be Poul Sander 2025-02-03 21:28 4965
1193b4be Poul Sander 2025-02-03 21:28 4966
        // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
1193b4be Poul Sander 2025-02-03 21:28 4967
        //     if (id == 0)
1193b4be Poul Sander 2025-02-03 21:28 4968
        //         id = GetItemID(); // Use last item id
1193b4be Poul Sander 2025-02-03 21:28 4969
        //     if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
1193b4be Poul Sander 2025-02-03 21:28 4970
        //         OpenPopup(id);
1193b4be Poul Sander 2025-02-03 21:28 4971
        //     return BeginPopup(id);
1193b4be Poul Sander 2025-02-03 21:28 4972
        // For advanced uses you may want to replicate and customize this code.
1193b4be Poul Sander 2025-02-03 21:28 4973
        // See more details in BeginPopupContextItem().
1193b4be Poul Sander 2025-02-03 21:28 4974
1193b4be Poul Sander 2025-02-03 21:28 4975
        // Example 1
1193b4be Poul Sander 2025-02-03 21:28 4976
        // When used after an item that has an ID (e.g. Button), we can skip providing an ID to BeginPopupContextItem(),
1193b4be Poul Sander 2025-02-03 21:28 4977
        // and BeginPopupContextItem() will use the last item ID as the popup ID.
1193b4be Poul Sander 2025-02-03 21:28 4978
        {
1193b4be Poul Sander 2025-02-03 21:28 4979
            const char* names[5] = { "Label1", "Label2", "Label3", "Label4", "Label5" };
1193b4be Poul Sander 2025-02-03 21:28 4980
            static int selected = -1;
1193b4be Poul Sander 2025-02-03 21:28 4981
            for (int n = 0; n < 5; n++)
1193b4be Poul Sander 2025-02-03 21:28 4982
            {
1193b4be Poul Sander 2025-02-03 21:28 4983
                if (ImGui::Selectable(names[n], selected == n))
1193b4be Poul Sander 2025-02-03 21:28 4984
                    selected = n;
1193b4be Poul Sander 2025-02-03 21:28 4985
                if (ImGui::BeginPopupContextItem()) // <-- use last item id as popup id
1193b4be Poul Sander 2025-02-03 21:28 4986
                {
1193b4be Poul Sander 2025-02-03 21:28 4987
                    selected = n;
1193b4be Poul Sander 2025-02-03 21:28 4988
                    ImGui::Text("This a popup for \"%s\"!", names[n]);
1193b4be Poul Sander 2025-02-03 21:28 4989
                    if (ImGui::Button("Close"))
1193b4be Poul Sander 2025-02-03 21:28 4990
                        ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 4991
                    ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 4992
                }
1193b4be Poul Sander 2025-02-03 21:28 4993
                ImGui::SetItemTooltip("Right-click to open popup");
1193b4be Poul Sander 2025-02-03 21:28 4994
            }
1193b4be Poul Sander 2025-02-03 21:28 4995
        }
1193b4be Poul Sander 2025-02-03 21:28 4996
1193b4be Poul Sander 2025-02-03 21:28 4997
        // Example 2
1193b4be Poul Sander 2025-02-03 21:28 4998
        // Popup on a Text() element which doesn't have an identifier: we need to provide an identifier to BeginPopupContextItem().
1193b4be Poul Sander 2025-02-03 21:28 4999
        // Using an explicit identifier is also convenient if you want to activate the popups from different locations.
1193b4be Poul Sander 2025-02-03 21:28 5000
        {
1193b4be Poul Sander 2025-02-03 21:28 5001
            HelpMarker("Text() elements don't have stable identifiers so we need to provide one.");
1193b4be Poul Sander 2025-02-03 21:28 5002
            static float value = 0.5f;
1193b4be Poul Sander 2025-02-03 21:28 5003
            ImGui::Text("Value = %.3f <-- (1) right-click this text", value);
1193b4be Poul Sander 2025-02-03 21:28 5004
            if (ImGui::BeginPopupContextItem("my popup"))
1193b4be Poul Sander 2025-02-03 21:28 5005
            {
1193b4be Poul Sander 2025-02-03 21:28 5006
                if (ImGui::Selectable("Set to zero")) value = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 5007
                if (ImGui::Selectable("Set to PI")) value = 3.1415f;
1193b4be Poul Sander 2025-02-03 21:28 5008
                ImGui::SetNextItemWidth(-FLT_MIN);
1193b4be Poul Sander 2025-02-03 21:28 5009
                ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 5010
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 5011
            }
1193b4be Poul Sander 2025-02-03 21:28 5012
1193b4be Poul Sander 2025-02-03 21:28 5013
            // We can also use OpenPopupOnItemClick() to toggle the visibility of a given popup.
1193b4be Poul Sander 2025-02-03 21:28 5014
            // Here we make it that right-clicking this other text element opens the same popup as above.
1193b4be Poul Sander 2025-02-03 21:28 5015
            // The popup itself will be submitted by the code above.
1193b4be Poul Sander 2025-02-03 21:28 5016
            ImGui::Text("(2) Or right-click this text");
1193b4be Poul Sander 2025-02-03 21:28 5017
            ImGui::OpenPopupOnItemClick("my popup", ImGuiPopupFlags_MouseButtonRight);
1193b4be Poul Sander 2025-02-03 21:28 5018
1193b4be Poul Sander 2025-02-03 21:28 5019
            // Back to square one: manually open the same popup.
1193b4be Poul Sander 2025-02-03 21:28 5020
            if (ImGui::Button("(3) Or click this button"))
1193b4be Poul Sander 2025-02-03 21:28 5021
                ImGui::OpenPopup("my popup");
1193b4be Poul Sander 2025-02-03 21:28 5022
        }
1193b4be Poul Sander 2025-02-03 21:28 5023
1193b4be Poul Sander 2025-02-03 21:28 5024
        // Example 3
1193b4be Poul Sander 2025-02-03 21:28 5025
        // When using BeginPopupContextItem() with an implicit identifier (NULL == use last item ID),
1193b4be Poul Sander 2025-02-03 21:28 5026
        // we need to make sure your item identifier is stable.
1193b4be Poul Sander 2025-02-03 21:28 5027
        // In this example we showcase altering the item label while preserving its identifier, using the ### operator (see FAQ).
1193b4be Poul Sander 2025-02-03 21:28 5028
        {
1193b4be Poul Sander 2025-02-03 21:28 5029
            HelpMarker("Showcase using a popup ID linked to item ID, with the item having a changing label + stable ID using the ### operator.");
1193b4be Poul Sander 2025-02-03 21:28 5030
            static char name[32] = "Label1";
1193b4be Poul Sander 2025-02-03 21:28 5031
            char buf[64];
1193b4be Poul Sander 2025-02-03 21:28 5032
            sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
1193b4be Poul Sander 2025-02-03 21:28 5033
            ImGui::Button(buf);
1193b4be Poul Sander 2025-02-03 21:28 5034
            if (ImGui::BeginPopupContextItem())
1193b4be Poul Sander 2025-02-03 21:28 5035
            {
1193b4be Poul Sander 2025-02-03 21:28 5036
                ImGui::Text("Edit name:");
1193b4be Poul Sander 2025-02-03 21:28 5037
                ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
1193b4be Poul Sander 2025-02-03 21:28 5038
                if (ImGui::Button("Close"))
1193b4be Poul Sander 2025-02-03 21:28 5039
                    ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 5040
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 5041
            }
1193b4be Poul Sander 2025-02-03 21:28 5042
            ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
1193b4be Poul Sander 2025-02-03 21:28 5043
        }
1193b4be Poul Sander 2025-02-03 21:28 5044
1193b4be Poul Sander 2025-02-03 21:28 5045
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5046
    }
1193b4be Poul Sander 2025-02-03 21:28 5047
1193b4be Poul Sander 2025-02-03 21:28 5048
    IMGUI_DEMO_MARKER("Popups/Modals");
1193b4be Poul Sander 2025-02-03 21:28 5049
    if (ImGui::TreeNode("Modals"))
1193b4be Poul Sander 2025-02-03 21:28 5050
    {
1193b4be Poul Sander 2025-02-03 21:28 5051
        ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside.");
1193b4be Poul Sander 2025-02-03 21:28 5052
1193b4be Poul Sander 2025-02-03 21:28 5053
        if (ImGui::Button("Delete.."))
1193b4be Poul Sander 2025-02-03 21:28 5054
            ImGui::OpenPopup("Delete?");
1193b4be Poul Sander 2025-02-03 21:28 5055
1193b4be Poul Sander 2025-02-03 21:28 5056
        // Always center this window when appearing
1193b4be Poul Sander 2025-02-03 21:28 5057
        ImVec2 center = ImGui::GetMainViewport()->GetCenter();
1193b4be Poul Sander 2025-02-03 21:28 5058
        ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
1193b4be Poul Sander 2025-02-03 21:28 5059
1193b4be Poul Sander 2025-02-03 21:28 5060
        if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
1193b4be Poul Sander 2025-02-03 21:28 5061
        {
1193b4be Poul Sander 2025-02-03 21:28 5062
            ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!");
1193b4be Poul Sander 2025-02-03 21:28 5063
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 5064
1193b4be Poul Sander 2025-02-03 21:28 5065
            //static int unused_i = 0;
1193b4be Poul Sander 2025-02-03 21:28 5066
            //ImGui::Combo("Combo", &unused_i, "Delete\0Delete harder\0");
1193b4be Poul Sander 2025-02-03 21:28 5067
1193b4be Poul Sander 2025-02-03 21:28 5068
            static bool dont_ask_me_next_time = false;
1193b4be Poul Sander 2025-02-03 21:28 5069
            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1193b4be Poul Sander 2025-02-03 21:28 5070
            ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
1193b4be Poul Sander 2025-02-03 21:28 5071
            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 5072
1193b4be Poul Sander 2025-02-03 21:28 5073
            if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
1193b4be Poul Sander 2025-02-03 21:28 5074
            ImGui::SetItemDefaultFocus();
1193b4be Poul Sander 2025-02-03 21:28 5075
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5076
            if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
1193b4be Poul Sander 2025-02-03 21:28 5077
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 5078
        }
1193b4be Poul Sander 2025-02-03 21:28 5079
1193b4be Poul Sander 2025-02-03 21:28 5080
        if (ImGui::Button("Stacked modals.."))
1193b4be Poul Sander 2025-02-03 21:28 5081
            ImGui::OpenPopup("Stacked 1");
1193b4be Poul Sander 2025-02-03 21:28 5082
        if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
1193b4be Poul Sander 2025-02-03 21:28 5083
        {
1193b4be Poul Sander 2025-02-03 21:28 5084
            if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 5085
            {
1193b4be Poul Sander 2025-02-03 21:28 5086
                if (ImGui::BeginMenu("File"))
1193b4be Poul Sander 2025-02-03 21:28 5087
                {
1193b4be Poul Sander 2025-02-03 21:28 5088
                    if (ImGui::MenuItem("Some menu item")) {}
1193b4be Poul Sander 2025-02-03 21:28 5089
                    ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 5090
                }
1193b4be Poul Sander 2025-02-03 21:28 5091
                ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 5092
            }
1193b4be Poul Sander 2025-02-03 21:28 5093
            ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
1193b4be Poul Sander 2025-02-03 21:28 5094
1193b4be Poul Sander 2025-02-03 21:28 5095
            // Testing behavior of widgets stacking their own regular popups over the modal.
1193b4be Poul Sander 2025-02-03 21:28 5096
            static int item = 1;
1193b4be Poul Sander 2025-02-03 21:28 5097
            static float color[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
1193b4be Poul Sander 2025-02-03 21:28 5098
            ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
1193b4be Poul Sander 2025-02-03 21:28 5099
            ImGui::ColorEdit4("Color", color);
1193b4be Poul Sander 2025-02-03 21:28 5100
1193b4be Poul Sander 2025-02-03 21:28 5101
            if (ImGui::Button("Add another modal.."))
1193b4be Poul Sander 2025-02-03 21:28 5102
                ImGui::OpenPopup("Stacked 2");
1193b4be Poul Sander 2025-02-03 21:28 5103
1193b4be Poul Sander 2025-02-03 21:28 5104
            // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which
1193b4be Poul Sander 2025-02-03 21:28 5105
            // will close the popup. Note that the visibility state of popups is owned by imgui, so the input value
1193b4be Poul Sander 2025-02-03 21:28 5106
            // of the bool actually doesn't matter here.
1193b4be Poul Sander 2025-02-03 21:28 5107
            bool unused_open = true;
1193b4be Poul Sander 2025-02-03 21:28 5108
            if (ImGui::BeginPopupModal("Stacked 2", &unused_open))
1193b4be Poul Sander 2025-02-03 21:28 5109
            {
1193b4be Poul Sander 2025-02-03 21:28 5110
                ImGui::Text("Hello from Stacked The Second!");
1193b4be Poul Sander 2025-02-03 21:28 5111
                ImGui::ColorEdit4("Color", color); // Allow opening another nested popup
1193b4be Poul Sander 2025-02-03 21:28 5112
                if (ImGui::Button("Close"))
1193b4be Poul Sander 2025-02-03 21:28 5113
                    ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 5114
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 5115
            }
1193b4be Poul Sander 2025-02-03 21:28 5116
1193b4be Poul Sander 2025-02-03 21:28 5117
            if (ImGui::Button("Close"))
1193b4be Poul Sander 2025-02-03 21:28 5118
                ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 5119
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 5120
        }
1193b4be Poul Sander 2025-02-03 21:28 5121
1193b4be Poul Sander 2025-02-03 21:28 5122
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5123
    }
1193b4be Poul Sander 2025-02-03 21:28 5124
1193b4be Poul Sander 2025-02-03 21:28 5125
    IMGUI_DEMO_MARKER("Popups/Menus inside a regular window");
1193b4be Poul Sander 2025-02-03 21:28 5126
    if (ImGui::TreeNode("Menus inside a regular window"))
1193b4be Poul Sander 2025-02-03 21:28 5127
    {
1193b4be Poul Sander 2025-02-03 21:28 5128
        ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
1193b4be Poul Sander 2025-02-03 21:28 5129
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 5130
1193b4be Poul Sander 2025-02-03 21:28 5131
        ImGui::MenuItem("Menu item", "CTRL+M");
1193b4be Poul Sander 2025-02-03 21:28 5132
        if (ImGui::BeginMenu("Menu inside a regular window"))
1193b4be Poul Sander 2025-02-03 21:28 5133
        {
1193b4be Poul Sander 2025-02-03 21:28 5134
            ShowExampleMenuFile();
1193b4be Poul Sander 2025-02-03 21:28 5135
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 5136
        }
1193b4be Poul Sander 2025-02-03 21:28 5137
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 5138
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5139
    }
1193b4be Poul Sander 2025-02-03 21:28 5140
}
1193b4be Poul Sander 2025-02-03 21:28 5141
1193b4be Poul Sander 2025-02-03 21:28 5142
// Dummy data structure that we use for the Table demo.
1193b4be Poul Sander 2025-02-03 21:28 5143
// (pre-C++11 doesn't allow us to instantiate ImVector<MyItem> template if this structure is defined inside the demo function)
1193b4be Poul Sander 2025-02-03 21:28 5144
namespace
1193b4be Poul Sander 2025-02-03 21:28 5145
{
1193b4be Poul Sander 2025-02-03 21:28 5146
// We are passing our own identifier to TableSetupColumn() to facilitate identifying columns in the sorting code.
1193b4be Poul Sander 2025-02-03 21:28 5147
// This identifier will be passed down into ImGuiTableSortSpec::ColumnUserID.
1193b4be Poul Sander 2025-02-03 21:28 5148
// But it is possible to omit the user id parameter of TableSetupColumn() and just use the column index instead! (ImGuiTableSortSpec::ColumnIndex)
1193b4be Poul Sander 2025-02-03 21:28 5149
// If you don't use sorting, you will generally never care about giving column an ID!
1193b4be Poul Sander 2025-02-03 21:28 5150
enum MyItemColumnID
1193b4be Poul Sander 2025-02-03 21:28 5151
{
1193b4be Poul Sander 2025-02-03 21:28 5152
    MyItemColumnID_ID,
1193b4be Poul Sander 2025-02-03 21:28 5153
    MyItemColumnID_Name,
1193b4be Poul Sander 2025-02-03 21:28 5154
    MyItemColumnID_Action,
1193b4be Poul Sander 2025-02-03 21:28 5155
    MyItemColumnID_Quantity,
1193b4be Poul Sander 2025-02-03 21:28 5156
    MyItemColumnID_Description
1193b4be Poul Sander 2025-02-03 21:28 5157
};
1193b4be Poul Sander 2025-02-03 21:28 5158
1193b4be Poul Sander 2025-02-03 21:28 5159
struct MyItem
1193b4be Poul Sander 2025-02-03 21:28 5160
{
1193b4be Poul Sander 2025-02-03 21:28 5161
    int         ID;
1193b4be Poul Sander 2025-02-03 21:28 5162
    const char* Name;
1193b4be Poul Sander 2025-02-03 21:28 5163
    int         Quantity;
1193b4be Poul Sander 2025-02-03 21:28 5164
1193b4be Poul Sander 2025-02-03 21:28 5165
    // We have a problem which is affecting _only this demo_ and should not affect your code:
1193b4be Poul Sander 2025-02-03 21:28 5166
    // As we don't rely on std:: or other third-party library to compile dear imgui, we only have reliable access to qsort(),
1193b4be Poul Sander 2025-02-03 21:28 5167
    // however qsort doesn't allow passing user data to comparing function.
1193b4be Poul Sander 2025-02-03 21:28 5168
    // As a workaround, we are storing the sort specs in a static/global for the comparing function to access.
1193b4be Poul Sander 2025-02-03 21:28 5169
    // In your own use case you would probably pass the sort specs to your sorting/comparing functions directly and not use a global.
1193b4be Poul Sander 2025-02-03 21:28 5170
    // We could technically call ImGui::TableGetSortSpecs() in CompareWithSortSpecs(), but considering that this function is called
1193b4be Poul Sander 2025-02-03 21:28 5171
    // very often by the sorting algorithm it would be a little wasteful.
1193b4be Poul Sander 2025-02-03 21:28 5172
    static const ImGuiTableSortSpecs* s_current_sort_specs;
1193b4be Poul Sander 2025-02-03 21:28 5173
1193b4be Poul Sander 2025-02-03 21:28 5174
    static void SortWithSortSpecs(ImGuiTableSortSpecs* sort_specs, MyItem* items, int items_count)
1193b4be Poul Sander 2025-02-03 21:28 5175
    {
1193b4be Poul Sander 2025-02-03 21:28 5176
        s_current_sort_specs = sort_specs; // Store in variable accessible by the sort function.
1193b4be Poul Sander 2025-02-03 21:28 5177
        if (items_count > 1)
1193b4be Poul Sander 2025-02-03 21:28 5178
            qsort(items, (size_t)items_count, sizeof(items[0]), MyItem::CompareWithSortSpecs);
1193b4be Poul Sander 2025-02-03 21:28 5179
        s_current_sort_specs = NULL;
1193b4be Poul Sander 2025-02-03 21:28 5180
    }
1193b4be Poul Sander 2025-02-03 21:28 5181
1193b4be Poul Sander 2025-02-03 21:28 5182
    // Compare function to be used by qsort()
1193b4be Poul Sander 2025-02-03 21:28 5183
    static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs)
1193b4be Poul Sander 2025-02-03 21:28 5184
    {
1193b4be Poul Sander 2025-02-03 21:28 5185
        const MyItem* a = (const MyItem*)lhs;
1193b4be Poul Sander 2025-02-03 21:28 5186
        const MyItem* b = (const MyItem*)rhs;
1193b4be Poul Sander 2025-02-03 21:28 5187
        for (int n = 0; n < s_current_sort_specs->SpecsCount; n++)
1193b4be Poul Sander 2025-02-03 21:28 5188
        {
1193b4be Poul Sander 2025-02-03 21:28 5189
            // Here we identify columns using the ColumnUserID value that we ourselves passed to TableSetupColumn()
1193b4be Poul Sander 2025-02-03 21:28 5190
            // We could also choose to identify columns based on their index (sort_spec->ColumnIndex), which is simpler!
1193b4be Poul Sander 2025-02-03 21:28 5191
            const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n];
1193b4be Poul Sander 2025-02-03 21:28 5192
            int delta = 0;
1193b4be Poul Sander 2025-02-03 21:28 5193
            switch (sort_spec->ColumnUserID)
1193b4be Poul Sander 2025-02-03 21:28 5194
            {
1193b4be Poul Sander 2025-02-03 21:28 5195
            case MyItemColumnID_ID:             delta = (a->ID - b->ID);                break;
1193b4be Poul Sander 2025-02-03 21:28 5196
            case MyItemColumnID_Name:           delta = (strcmp(a->Name, b->Name));     break;
1193b4be Poul Sander 2025-02-03 21:28 5197
            case MyItemColumnID_Quantity:       delta = (a->Quantity - b->Quantity);    break;
1193b4be Poul Sander 2025-02-03 21:28 5198
            case MyItemColumnID_Description:    delta = (strcmp(a->Name, b->Name));     break;
1193b4be Poul Sander 2025-02-03 21:28 5199
            default: IM_ASSERT(0); break;
1193b4be Poul Sander 2025-02-03 21:28 5200
            }
1193b4be Poul Sander 2025-02-03 21:28 5201
            if (delta > 0)
1193b4be Poul Sander 2025-02-03 21:28 5202
                return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1;
1193b4be Poul Sander 2025-02-03 21:28 5203
            if (delta < 0)
1193b4be Poul Sander 2025-02-03 21:28 5204
                return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1;
1193b4be Poul Sander 2025-02-03 21:28 5205
        }
1193b4be Poul Sander 2025-02-03 21:28 5206
1193b4be Poul Sander 2025-02-03 21:28 5207
        // qsort() is instable so always return a way to differenciate items.
1193b4be Poul Sander 2025-02-03 21:28 5208
        // Your own compare function may want to avoid fallback on implicit sort specs.
1193b4be Poul Sander 2025-02-03 21:28 5209
        // e.g. a Name compare if it wasn't already part of the sort specs.
1193b4be Poul Sander 2025-02-03 21:28 5210
        return (a->ID - b->ID);
1193b4be Poul Sander 2025-02-03 21:28 5211
    }
1193b4be Poul Sander 2025-02-03 21:28 5212
};
1193b4be Poul Sander 2025-02-03 21:28 5213
const ImGuiTableSortSpecs* MyItem::s_current_sort_specs = NULL;
1193b4be Poul Sander 2025-02-03 21:28 5214
}
1193b4be Poul Sander 2025-02-03 21:28 5215
1193b4be Poul Sander 2025-02-03 21:28 5216
// Make the UI compact because there are so many fields
1193b4be Poul Sander 2025-02-03 21:28 5217
static void PushStyleCompact()
1193b4be Poul Sander 2025-02-03 21:28 5218
{
1193b4be Poul Sander 2025-02-03 21:28 5219
    ImGuiStyle& style = ImGui::GetStyle();
1193b4be Poul Sander 2025-02-03 21:28 5220
    ImGui::PushStyleVarY(ImGuiStyleVar_FramePadding, (float)(int)(style.FramePadding.y * 0.60f));
1193b4be Poul Sander 2025-02-03 21:28 5221
    ImGui::PushStyleVarY(ImGuiStyleVar_ItemSpacing, (float)(int)(style.ItemSpacing.y * 0.60f));
1193b4be Poul Sander 2025-02-03 21:28 5222
}
1193b4be Poul Sander 2025-02-03 21:28 5223
1193b4be Poul Sander 2025-02-03 21:28 5224
static void PopStyleCompact()
1193b4be Poul Sander 2025-02-03 21:28 5225
{
1193b4be Poul Sander 2025-02-03 21:28 5226
    ImGui::PopStyleVar(2);
1193b4be Poul Sander 2025-02-03 21:28 5227
}
1193b4be Poul Sander 2025-02-03 21:28 5228
1193b4be Poul Sander 2025-02-03 21:28 5229
// Show a combo box with a choice of sizing policies
1193b4be Poul Sander 2025-02-03 21:28 5230
static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
1193b4be Poul Sander 2025-02-03 21:28 5231
{
1193b4be Poul Sander 2025-02-03 21:28 5232
    struct EnumDesc { ImGuiTableFlags Value; const char* Name; const char* Tooltip; };
1193b4be Poul Sander 2025-02-03 21:28 5233
    static const EnumDesc policies[] =
1193b4be Poul Sander 2025-02-03 21:28 5234
    {
1193b4be Poul Sander 2025-02-03 21:28 5235
        { ImGuiTableFlags_None,               "Default",                            "Use default sizing policy:\n- ImGuiTableFlags_SizingFixedFit if ScrollX is on or if host window has ImGuiWindowFlags_AlwaysAutoResize.\n- ImGuiTableFlags_SizingStretchSame otherwise." },
1193b4be Poul Sander 2025-02-03 21:28 5236
        { ImGuiTableFlags_SizingFixedFit,     "ImGuiTableFlags_SizingFixedFit",     "Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width." },
1193b4be Poul Sander 2025-02-03 21:28 5237
        { ImGuiTableFlags_SizingFixedSame,    "ImGuiTableFlags_SizingFixedSame",    "Columns are all the same width, matching the maximum contents width.\nImplicitly disable ImGuiTableFlags_Resizable and enable ImGuiTableFlags_NoKeepColumnsVisible." },
1193b4be Poul Sander 2025-02-03 21:28 5238
        { ImGuiTableFlags_SizingStretchProp,  "ImGuiTableFlags_SizingStretchProp",  "Columns default to _WidthStretch with weights proportional to their widths." },
1193b4be Poul Sander 2025-02-03 21:28 5239
        { ImGuiTableFlags_SizingStretchSame,  "ImGuiTableFlags_SizingStretchSame",  "Columns default to _WidthStretch with same weights." }
1193b4be Poul Sander 2025-02-03 21:28 5240
    };
1193b4be Poul Sander 2025-02-03 21:28 5241
    int idx;
1193b4be Poul Sander 2025-02-03 21:28 5242
    for (idx = 0; idx < IM_ARRAYSIZE(policies); idx++)
1193b4be Poul Sander 2025-02-03 21:28 5243
        if (policies[idx].Value == (*p_flags & ImGuiTableFlags_SizingMask_))
1193b4be Poul Sander 2025-02-03 21:28 5244
            break;
1193b4be Poul Sander 2025-02-03 21:28 5245
    const char* preview_text = (idx < IM_ARRAYSIZE(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : "";
1193b4be Poul Sander 2025-02-03 21:28 5246
    if (ImGui::BeginCombo("Sizing Policy", preview_text))
1193b4be Poul Sander 2025-02-03 21:28 5247
    {
1193b4be Poul Sander 2025-02-03 21:28 5248
        for (int n = 0; n < IM_ARRAYSIZE(policies); n++)
1193b4be Poul Sander 2025-02-03 21:28 5249
            if (ImGui::Selectable(policies[n].Name, idx == n))
1193b4be Poul Sander 2025-02-03 21:28 5250
                *p_flags = (*p_flags & ~ImGuiTableFlags_SizingMask_) | policies[n].Value;
1193b4be Poul Sander 2025-02-03 21:28 5251
        ImGui::EndCombo();
1193b4be Poul Sander 2025-02-03 21:28 5252
    }
1193b4be Poul Sander 2025-02-03 21:28 5253
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5254
    ImGui::TextDisabled("(?)");
1193b4be Poul Sander 2025-02-03 21:28 5255
    if (ImGui::BeginItemTooltip())
1193b4be Poul Sander 2025-02-03 21:28 5256
    {
1193b4be Poul Sander 2025-02-03 21:28 5257
        ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
1193b4be Poul Sander 2025-02-03 21:28 5258
        for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
1193b4be Poul Sander 2025-02-03 21:28 5259
        {
1193b4be Poul Sander 2025-02-03 21:28 5260
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 5261
            ImGui::Text("%s:", policies[m].Name);
1193b4be Poul Sander 2025-02-03 21:28 5262
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 5263
            ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().IndentSpacing * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 5264
            ImGui::TextUnformatted(policies[m].Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 5265
        }
1193b4be Poul Sander 2025-02-03 21:28 5266
        ImGui::PopTextWrapPos();
1193b4be Poul Sander 2025-02-03 21:28 5267
        ImGui::EndTooltip();
1193b4be Poul Sander 2025-02-03 21:28 5268
    }
1193b4be Poul Sander 2025-02-03 21:28 5269
}
1193b4be Poul Sander 2025-02-03 21:28 5270
1193b4be Poul Sander 2025-02-03 21:28 5271
static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
1193b4be Poul Sander 2025-02-03 21:28 5272
{
1193b4be Poul Sander 2025-02-03 21:28 5273
    ImGui::CheckboxFlags("_Disabled", p_flags, ImGuiTableColumnFlags_Disabled); ImGui::SameLine(); HelpMarker("Master disable flag (also hide from context menu)");
1193b4be Poul Sander 2025-02-03 21:28 5274
    ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide);
1193b4be Poul Sander 2025-02-03 21:28 5275
    ImGui::CheckboxFlags("_DefaultSort", p_flags, ImGuiTableColumnFlags_DefaultSort);
1193b4be Poul Sander 2025-02-03 21:28 5276
    if (ImGui::CheckboxFlags("_WidthStretch", p_flags, ImGuiTableColumnFlags_WidthStretch))
1193b4be Poul Sander 2025-02-03 21:28 5277
        *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch);
1193b4be Poul Sander 2025-02-03 21:28 5278
    if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed))
1193b4be Poul Sander 2025-02-03 21:28 5279
        *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed);
1193b4be Poul Sander 2025-02-03 21:28 5280
    ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize);
1193b4be Poul Sander 2025-02-03 21:28 5281
    ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder);
1193b4be Poul Sander 2025-02-03 21:28 5282
    ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide);
1193b4be Poul Sander 2025-02-03 21:28 5283
    ImGui::CheckboxFlags("_NoClip", p_flags, ImGuiTableColumnFlags_NoClip);
1193b4be Poul Sander 2025-02-03 21:28 5284
    ImGui::CheckboxFlags("_NoSort", p_flags, ImGuiTableColumnFlags_NoSort);
1193b4be Poul Sander 2025-02-03 21:28 5285
    ImGui::CheckboxFlags("_NoSortAscending", p_flags, ImGuiTableColumnFlags_NoSortAscending);
1193b4be Poul Sander 2025-02-03 21:28 5286
    ImGui::CheckboxFlags("_NoSortDescending", p_flags, ImGuiTableColumnFlags_NoSortDescending);
1193b4be Poul Sander 2025-02-03 21:28 5287
    ImGui::CheckboxFlags("_NoHeaderLabel", p_flags, ImGuiTableColumnFlags_NoHeaderLabel);
1193b4be Poul Sander 2025-02-03 21:28 5288
    ImGui::CheckboxFlags("_NoHeaderWidth", p_flags, ImGuiTableColumnFlags_NoHeaderWidth);
1193b4be Poul Sander 2025-02-03 21:28 5289
    ImGui::CheckboxFlags("_PreferSortAscending", p_flags, ImGuiTableColumnFlags_PreferSortAscending);
1193b4be Poul Sander 2025-02-03 21:28 5290
    ImGui::CheckboxFlags("_PreferSortDescending", p_flags, ImGuiTableColumnFlags_PreferSortDescending);
1193b4be Poul Sander 2025-02-03 21:28 5291
    ImGui::CheckboxFlags("_IndentEnable", p_flags, ImGuiTableColumnFlags_IndentEnable); ImGui::SameLine(); HelpMarker("Default for column 0");
1193b4be Poul Sander 2025-02-03 21:28 5292
    ImGui::CheckboxFlags("_IndentDisable", p_flags, ImGuiTableColumnFlags_IndentDisable); ImGui::SameLine(); HelpMarker("Default for column >0");
1193b4be Poul Sander 2025-02-03 21:28 5293
    ImGui::CheckboxFlags("_AngledHeader", p_flags, ImGuiTableColumnFlags_AngledHeader);
1193b4be Poul Sander 2025-02-03 21:28 5294
}
1193b4be Poul Sander 2025-02-03 21:28 5295
1193b4be Poul Sander 2025-02-03 21:28 5296
static void ShowTableColumnsStatusFlags(ImGuiTableColumnFlags flags)
1193b4be Poul Sander 2025-02-03 21:28 5297
{
1193b4be Poul Sander 2025-02-03 21:28 5298
    ImGui::CheckboxFlags("_IsEnabled", &flags, ImGuiTableColumnFlags_IsEnabled);
1193b4be Poul Sander 2025-02-03 21:28 5299
    ImGui::CheckboxFlags("_IsVisible", &flags, ImGuiTableColumnFlags_IsVisible);
1193b4be Poul Sander 2025-02-03 21:28 5300
    ImGui::CheckboxFlags("_IsSorted", &flags, ImGuiTableColumnFlags_IsSorted);
1193b4be Poul Sander 2025-02-03 21:28 5301
    ImGui::CheckboxFlags("_IsHovered", &flags, ImGuiTableColumnFlags_IsHovered);
1193b4be Poul Sander 2025-02-03 21:28 5302
}
1193b4be Poul Sander 2025-02-03 21:28 5303
1193b4be Poul Sander 2025-02-03 21:28 5304
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 5305
// [SECTION] ShowDemoWindowTables()
1193b4be Poul Sander 2025-02-03 21:28 5306
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 5307
1193b4be Poul Sander 2025-02-03 21:28 5308
static void ShowDemoWindowTables()
1193b4be Poul Sander 2025-02-03 21:28 5309
{
1193b4be Poul Sander 2025-02-03 21:28 5310
    //ImGui::SetNextItemOpen(true, ImGuiCond_Once);
1193b4be Poul Sander 2025-02-03 21:28 5311
    IMGUI_DEMO_MARKER("Tables");
1193b4be Poul Sander 2025-02-03 21:28 5312
    if (!ImGui::CollapsingHeader("Tables & Columns"))
1193b4be Poul Sander 2025-02-03 21:28 5313
        return;
1193b4be Poul Sander 2025-02-03 21:28 5314
1193b4be Poul Sander 2025-02-03 21:28 5315
    // Using those as a base value to create width/height that are factor of the size of our font
1193b4be Poul Sander 2025-02-03 21:28 5316
    const float TEXT_BASE_WIDTH = ImGui::CalcTextSize("A").x;
1193b4be Poul Sander 2025-02-03 21:28 5317
    const float TEXT_BASE_HEIGHT = ImGui::GetTextLineHeightWithSpacing();
1193b4be Poul Sander 2025-02-03 21:28 5318
1193b4be Poul Sander 2025-02-03 21:28 5319
    ImGui::PushID("Tables");
1193b4be Poul Sander 2025-02-03 21:28 5320
1193b4be Poul Sander 2025-02-03 21:28 5321
    int open_action = -1;
1193b4be Poul Sander 2025-02-03 21:28 5322
    if (ImGui::Button("Expand all"))
1193b4be Poul Sander 2025-02-03 21:28 5323
        open_action = 1;
1193b4be Poul Sander 2025-02-03 21:28 5324
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5325
    if (ImGui::Button("Collapse all"))
1193b4be Poul Sander 2025-02-03 21:28 5326
        open_action = 0;
1193b4be Poul Sander 2025-02-03 21:28 5327
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5328
1193b4be Poul Sander 2025-02-03 21:28 5329
    // Options
1193b4be Poul Sander 2025-02-03 21:28 5330
    static bool disable_indent = false;
1193b4be Poul Sander 2025-02-03 21:28 5331
    ImGui::Checkbox("Disable tree indentation", &disable_indent);
1193b4be Poul Sander 2025-02-03 21:28 5332
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5333
    HelpMarker("Disable the indenting of tree nodes so demo tables can use the full window width.");
1193b4be Poul Sander 2025-02-03 21:28 5334
    ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 5335
    if (disable_indent)
1193b4be Poul Sander 2025-02-03 21:28 5336
        ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 5337
1193b4be Poul Sander 2025-02-03 21:28 5338
    // About Styling of tables
1193b4be Poul Sander 2025-02-03 21:28 5339
    // Most settings are configured on a per-table basis via the flags passed to BeginTable() and TableSetupColumns APIs.
1193b4be Poul Sander 2025-02-03 21:28 5340
    // There are however a few settings that a shared and part of the ImGuiStyle structure:
1193b4be Poul Sander 2025-02-03 21:28 5341
    //   style.CellPadding                          // Padding within each cell
1193b4be Poul Sander 2025-02-03 21:28 5342
    //   style.Colors[ImGuiCol_TableHeaderBg]       // Table header background
1193b4be Poul Sander 2025-02-03 21:28 5343
    //   style.Colors[ImGuiCol_TableBorderStrong]   // Table outer and header borders
1193b4be Poul Sander 2025-02-03 21:28 5344
    //   style.Colors[ImGuiCol_TableBorderLight]    // Table inner borders
1193b4be Poul Sander 2025-02-03 21:28 5345
    //   style.Colors[ImGuiCol_TableRowBg]          // Table row background when ImGuiTableFlags_RowBg is enabled (even rows)
1193b4be Poul Sander 2025-02-03 21:28 5346
    //   style.Colors[ImGuiCol_TableRowBgAlt]       // Table row background when ImGuiTableFlags_RowBg is enabled (odds rows)
1193b4be Poul Sander 2025-02-03 21:28 5347
1193b4be Poul Sander 2025-02-03 21:28 5348
    // Demos
1193b4be Poul Sander 2025-02-03 21:28 5349
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5350
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5351
    IMGUI_DEMO_MARKER("Tables/Basic");
1193b4be Poul Sander 2025-02-03 21:28 5352
    if (ImGui::TreeNode("Basic"))
1193b4be Poul Sander 2025-02-03 21:28 5353
    {
1193b4be Poul Sander 2025-02-03 21:28 5354
        // Here we will showcase three different ways to output a table.
1193b4be Poul Sander 2025-02-03 21:28 5355
        // They are very simple variations of a same thing!
1193b4be Poul Sander 2025-02-03 21:28 5356
1193b4be Poul Sander 2025-02-03 21:28 5357
        // [Method 1] Using TableNextRow() to create a new row, and TableSetColumnIndex() to select the column.
1193b4be Poul Sander 2025-02-03 21:28 5358
        // In many situations, this is the most flexible and easy to use pattern.
1193b4be Poul Sander 2025-02-03 21:28 5359
        HelpMarker("Using TableNextRow() + calling TableSetColumnIndex() _before_ each cell, in a loop.");
1193b4be Poul Sander 2025-02-03 21:28 5360
        if (ImGui::BeginTable("table1", 3))
1193b4be Poul Sander 2025-02-03 21:28 5361
        {
1193b4be Poul Sander 2025-02-03 21:28 5362
            for (int row = 0; row < 4; row++)
1193b4be Poul Sander 2025-02-03 21:28 5363
            {
1193b4be Poul Sander 2025-02-03 21:28 5364
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5365
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5366
                {
1193b4be Poul Sander 2025-02-03 21:28 5367
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5368
                    ImGui::Text("Row %d Column %d", row, column);
1193b4be Poul Sander 2025-02-03 21:28 5369
                }
1193b4be Poul Sander 2025-02-03 21:28 5370
            }
1193b4be Poul Sander 2025-02-03 21:28 5371
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5372
        }
1193b4be Poul Sander 2025-02-03 21:28 5373
1193b4be Poul Sander 2025-02-03 21:28 5374
        // [Method 2] Using TableNextColumn() called multiple times, instead of using a for loop + TableSetColumnIndex().
1193b4be Poul Sander 2025-02-03 21:28 5375
        // This is generally more convenient when you have code manually submitting the contents of each column.
1193b4be Poul Sander 2025-02-03 21:28 5376
        HelpMarker("Using TableNextRow() + calling TableNextColumn() _before_ each cell, manually.");
1193b4be Poul Sander 2025-02-03 21:28 5377
        if (ImGui::BeginTable("table2", 3))
1193b4be Poul Sander 2025-02-03 21:28 5378
        {
1193b4be Poul Sander 2025-02-03 21:28 5379
            for (int row = 0; row < 4; row++)
1193b4be Poul Sander 2025-02-03 21:28 5380
            {
1193b4be Poul Sander 2025-02-03 21:28 5381
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5382
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 5383
                ImGui::Text("Row %d", row);
1193b4be Poul Sander 2025-02-03 21:28 5384
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 5385
                ImGui::Text("Some contents");
1193b4be Poul Sander 2025-02-03 21:28 5386
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 5387
                ImGui::Text("123.456");
1193b4be Poul Sander 2025-02-03 21:28 5388
            }
1193b4be Poul Sander 2025-02-03 21:28 5389
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5390
        }
1193b4be Poul Sander 2025-02-03 21:28 5391
1193b4be Poul Sander 2025-02-03 21:28 5392
        // [Method 3] We call TableNextColumn() _before_ each cell. We never call TableNextRow(),
1193b4be Poul Sander 2025-02-03 21:28 5393
        // as TableNextColumn() will automatically wrap around and create new rows as needed.
1193b4be Poul Sander 2025-02-03 21:28 5394
        // This is generally more convenient when your cells all contains the same type of data.
1193b4be Poul Sander 2025-02-03 21:28 5395
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5396
            "Only using TableNextColumn(), which tends to be convenient for tables where every cell contains "
1193b4be Poul Sander 2025-02-03 21:28 5397
            "the same type of contents.\n This is also more similar to the old NextColumn() function of the "
1193b4be Poul Sander 2025-02-03 21:28 5398
            "Columns API, and provided to facilitate the Columns->Tables API transition.");
1193b4be Poul Sander 2025-02-03 21:28 5399
        if (ImGui::BeginTable("table3", 3))
1193b4be Poul Sander 2025-02-03 21:28 5400
        {
1193b4be Poul Sander 2025-02-03 21:28 5401
            for (int item = 0; item < 14; item++)
1193b4be Poul Sander 2025-02-03 21:28 5402
            {
1193b4be Poul Sander 2025-02-03 21:28 5403
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 5404
                ImGui::Text("Item %d", item);
1193b4be Poul Sander 2025-02-03 21:28 5405
            }
1193b4be Poul Sander 2025-02-03 21:28 5406
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5407
        }
1193b4be Poul Sander 2025-02-03 21:28 5408
1193b4be Poul Sander 2025-02-03 21:28 5409
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5410
    }
1193b4be Poul Sander 2025-02-03 21:28 5411
1193b4be Poul Sander 2025-02-03 21:28 5412
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5413
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5414
    IMGUI_DEMO_MARKER("Tables/Borders, background");
1193b4be Poul Sander 2025-02-03 21:28 5415
    if (ImGui::TreeNode("Borders, background"))
1193b4be Poul Sander 2025-02-03 21:28 5416
    {
1193b4be Poul Sander 2025-02-03 21:28 5417
        // Expose a few Borders related flags interactively
1193b4be Poul Sander 2025-02-03 21:28 5418
        enum ContentsType { CT_Text, CT_FillButton };
1193b4be Poul Sander 2025-02-03 21:28 5419
        static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
1193b4be Poul Sander 2025-02-03 21:28 5420
        static bool display_headers = false;
1193b4be Poul Sander 2025-02-03 21:28 5421
        static int contents_type = CT_Text;
1193b4be Poul Sander 2025-02-03 21:28 5422
1193b4be Poul Sander 2025-02-03 21:28 5423
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5424
        ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
1193b4be Poul Sander 2025-02-03 21:28 5425
        ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 5426
        ImGui::SameLine(); HelpMarker("ImGuiTableFlags_Borders\n = ImGuiTableFlags_BordersInnerV\n | ImGuiTableFlags_BordersOuterV\n | ImGuiTableFlags_BordersInnerH\n | ImGuiTableFlags_BordersOuterH");
1193b4be Poul Sander 2025-02-03 21:28 5427
        ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 5428
1193b4be Poul Sander 2025-02-03 21:28 5429
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
1193b4be Poul Sander 2025-02-03 21:28 5430
        ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 5431
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
1193b4be Poul Sander 2025-02-03 21:28 5432
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
1193b4be Poul Sander 2025-02-03 21:28 5433
        ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 5434
1193b4be Poul Sander 2025-02-03 21:28 5435
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
1193b4be Poul Sander 2025-02-03 21:28 5436
        ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 5437
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
1193b4be Poul Sander 2025-02-03 21:28 5438
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
1193b4be Poul Sander 2025-02-03 21:28 5439
        ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 5440
1193b4be Poul Sander 2025-02-03 21:28 5441
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags, ImGuiTableFlags_BordersOuter);
1193b4be Poul Sander 2025-02-03 21:28 5442
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags, ImGuiTableFlags_BordersInner);
1193b4be Poul Sander 2025-02-03 21:28 5443
        ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 5444
1193b4be Poul Sander 2025-02-03 21:28 5445
        ImGui::AlignTextToFramePadding(); ImGui::Text("Cell contents:");
1193b4be Poul Sander 2025-02-03 21:28 5446
        ImGui::SameLine(); ImGui::RadioButton("Text", &contents_type, CT_Text);
1193b4be Poul Sander 2025-02-03 21:28 5447
        ImGui::SameLine(); ImGui::RadioButton("FillButton", &contents_type, CT_FillButton);
1193b4be Poul Sander 2025-02-03 21:28 5448
        ImGui::Checkbox("Display headers", &display_headers);
1193b4be Poul Sander 2025-02-03 21:28 5449
        ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appear in Headers");
1193b4be Poul Sander 2025-02-03 21:28 5450
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5451
1193b4be Poul Sander 2025-02-03 21:28 5452
        if (ImGui::BeginTable("table1", 3, flags))
1193b4be Poul Sander 2025-02-03 21:28 5453
        {
1193b4be Poul Sander 2025-02-03 21:28 5454
            // Display headers so we can inspect their interaction with borders
1193b4be Poul Sander 2025-02-03 21:28 5455
            // (Headers are not the main purpose of this section of the demo, so we are not elaborating on them now. See other sections for details)
1193b4be Poul Sander 2025-02-03 21:28 5456
            if (display_headers)
1193b4be Poul Sander 2025-02-03 21:28 5457
            {
1193b4be Poul Sander 2025-02-03 21:28 5458
                ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 5459
                ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 5460
                ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 5461
                ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5462
            }
1193b4be Poul Sander 2025-02-03 21:28 5463
1193b4be Poul Sander 2025-02-03 21:28 5464
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 5465
            {
1193b4be Poul Sander 2025-02-03 21:28 5466
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5467
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5468
                {
1193b4be Poul Sander 2025-02-03 21:28 5469
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5470
                    char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 5471
                    sprintf(buf, "Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5472
                    if (contents_type == CT_Text)
1193b4be Poul Sander 2025-02-03 21:28 5473
                        ImGui::TextUnformatted(buf);
1193b4be Poul Sander 2025-02-03 21:28 5474
                    else if (contents_type == CT_FillButton)
1193b4be Poul Sander 2025-02-03 21:28 5475
                        ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 5476
                }
1193b4be Poul Sander 2025-02-03 21:28 5477
            }
1193b4be Poul Sander 2025-02-03 21:28 5478
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5479
        }
1193b4be Poul Sander 2025-02-03 21:28 5480
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5481
    }
1193b4be Poul Sander 2025-02-03 21:28 5482
1193b4be Poul Sander 2025-02-03 21:28 5483
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5484
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5485
    IMGUI_DEMO_MARKER("Tables/Resizable, stretch");
1193b4be Poul Sander 2025-02-03 21:28 5486
    if (ImGui::TreeNode("Resizable, stretch"))
1193b4be Poul Sander 2025-02-03 21:28 5487
    {
1193b4be Poul Sander 2025-02-03 21:28 5488
        // By default, if we don't enable ScrollX the sizing policy for each column is "Stretch"
1193b4be Poul Sander 2025-02-03 21:28 5489
        // All columns maintain a sizing weight, and they will occupy all available width.
1193b4be Poul Sander 2025-02-03 21:28 5490
        static ImGuiTableFlags flags = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
1193b4be Poul Sander 2025-02-03 21:28 5491
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5492
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 5493
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
1193b4be Poul Sander 2025-02-03 21:28 5494
        ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5495
            "Using the _Resizable flag automatically enables the _BordersInnerV flag as well, "
1193b4be Poul Sander 2025-02-03 21:28 5496
            "this is why the resize borders are still showing when unchecking this.");
1193b4be Poul Sander 2025-02-03 21:28 5497
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5498
1193b4be Poul Sander 2025-02-03 21:28 5499
        if (ImGui::BeginTable("table1", 3, flags))
1193b4be Poul Sander 2025-02-03 21:28 5500
        {
1193b4be Poul Sander 2025-02-03 21:28 5501
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 5502
            {
1193b4be Poul Sander 2025-02-03 21:28 5503
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5504
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5505
                {
1193b4be Poul Sander 2025-02-03 21:28 5506
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5507
                    ImGui::Text("Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5508
                }
1193b4be Poul Sander 2025-02-03 21:28 5509
            }
1193b4be Poul Sander 2025-02-03 21:28 5510
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5511
        }
1193b4be Poul Sander 2025-02-03 21:28 5512
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5513
    }
1193b4be Poul Sander 2025-02-03 21:28 5514
1193b4be Poul Sander 2025-02-03 21:28 5515
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5516
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5517
    IMGUI_DEMO_MARKER("Tables/Resizable, fixed");
1193b4be Poul Sander 2025-02-03 21:28 5518
    if (ImGui::TreeNode("Resizable, fixed"))
1193b4be Poul Sander 2025-02-03 21:28 5519
    {
1193b4be Poul Sander 2025-02-03 21:28 5520
        // Here we use ImGuiTableFlags_SizingFixedFit (even though _ScrollX is not set)
1193b4be Poul Sander 2025-02-03 21:28 5521
        // So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small)
1193b4be Poul Sander 2025-02-03 21:28 5522
        // If there is not enough available width to fit all columns, they will however be resized down.
1193b4be Poul Sander 2025-02-03 21:28 5523
        // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings
1193b4be Poul Sander 2025-02-03 21:28 5524
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5525
            "Using _Resizable + _SizingFixedFit flags.\n"
1193b4be Poul Sander 2025-02-03 21:28 5526
            "Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 5527
            "Double-click a column border to auto-fit the column to its contents.");
1193b4be Poul Sander 2025-02-03 21:28 5528
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5529
        static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
1193b4be Poul Sander 2025-02-03 21:28 5530
        ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
1193b4be Poul Sander 2025-02-03 21:28 5531
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5532
1193b4be Poul Sander 2025-02-03 21:28 5533
        if (ImGui::BeginTable("table1", 3, flags))
1193b4be Poul Sander 2025-02-03 21:28 5534
        {
1193b4be Poul Sander 2025-02-03 21:28 5535
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 5536
            {
1193b4be Poul Sander 2025-02-03 21:28 5537
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5538
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5539
                {
1193b4be Poul Sander 2025-02-03 21:28 5540
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5541
                    ImGui::Text("Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5542
                }
1193b4be Poul Sander 2025-02-03 21:28 5543
            }
1193b4be Poul Sander 2025-02-03 21:28 5544
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5545
        }
1193b4be Poul Sander 2025-02-03 21:28 5546
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5547
    }
1193b4be Poul Sander 2025-02-03 21:28 5548
1193b4be Poul Sander 2025-02-03 21:28 5549
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5550
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5551
    IMGUI_DEMO_MARKER("Tables/Resizable, mixed");
1193b4be Poul Sander 2025-02-03 21:28 5552
    if (ImGui::TreeNode("Resizable, mixed"))
1193b4be Poul Sander 2025-02-03 21:28 5553
    {
1193b4be Poul Sander 2025-02-03 21:28 5554
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5555
            "Using TableSetupColumn() to alter resizing policy on a per-column basis.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 5556
            "When combining Fixed and Stretch columns, generally you only want one, maybe two trailing columns to use _WidthStretch.");
1193b4be Poul Sander 2025-02-03 21:28 5557
        static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
1193b4be Poul Sander 2025-02-03 21:28 5558
1193b4be Poul Sander 2025-02-03 21:28 5559
        if (ImGui::BeginTable("table1", 3, flags))
1193b4be Poul Sander 2025-02-03 21:28 5560
        {
1193b4be Poul Sander 2025-02-03 21:28 5561
            ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
1193b4be Poul Sander 2025-02-03 21:28 5562
            ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
1193b4be Poul Sander 2025-02-03 21:28 5563
            ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthStretch);
1193b4be Poul Sander 2025-02-03 21:28 5564
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5565
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 5566
            {
1193b4be Poul Sander 2025-02-03 21:28 5567
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5568
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5569
                {
1193b4be Poul Sander 2025-02-03 21:28 5570
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5571
                    ImGui::Text("%s %d,%d", (column == 2) ? "Stretch" : "Fixed", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5572
                }
1193b4be Poul Sander 2025-02-03 21:28 5573
            }
1193b4be Poul Sander 2025-02-03 21:28 5574
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5575
        }
1193b4be Poul Sander 2025-02-03 21:28 5576
        if (ImGui::BeginTable("table2", 6, flags))
1193b4be Poul Sander 2025-02-03 21:28 5577
        {
1193b4be Poul Sander 2025-02-03 21:28 5578
            ImGui::TableSetupColumn("AAA", ImGuiTableColumnFlags_WidthFixed);
1193b4be Poul Sander 2025-02-03 21:28 5579
            ImGui::TableSetupColumn("BBB", ImGuiTableColumnFlags_WidthFixed);
1193b4be Poul Sander 2025-02-03 21:28 5580
            ImGui::TableSetupColumn("CCC", ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_DefaultHide);
1193b4be Poul Sander 2025-02-03 21:28 5581
            ImGui::TableSetupColumn("DDD", ImGuiTableColumnFlags_WidthStretch);
1193b4be Poul Sander 2025-02-03 21:28 5582
            ImGui::TableSetupColumn("EEE", ImGuiTableColumnFlags_WidthStretch);
1193b4be Poul Sander 2025-02-03 21:28 5583
            ImGui::TableSetupColumn("FFF", ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_DefaultHide);
1193b4be Poul Sander 2025-02-03 21:28 5584
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5585
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 5586
            {
1193b4be Poul Sander 2025-02-03 21:28 5587
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5588
                for (int column = 0; column < 6; column++)
1193b4be Poul Sander 2025-02-03 21:28 5589
                {
1193b4be Poul Sander 2025-02-03 21:28 5590
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5591
                    ImGui::Text("%s %d,%d", (column >= 3) ? "Stretch" : "Fixed", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5592
                }
1193b4be Poul Sander 2025-02-03 21:28 5593
            }
1193b4be Poul Sander 2025-02-03 21:28 5594
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5595
        }
1193b4be Poul Sander 2025-02-03 21:28 5596
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5597
    }
1193b4be Poul Sander 2025-02-03 21:28 5598
1193b4be Poul Sander 2025-02-03 21:28 5599
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5600
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5601
    IMGUI_DEMO_MARKER("Tables/Reorderable, hideable, with headers");
1193b4be Poul Sander 2025-02-03 21:28 5602
    if (ImGui::TreeNode("Reorderable, hideable, with headers"))
1193b4be Poul Sander 2025-02-03 21:28 5603
    {
1193b4be Poul Sander 2025-02-03 21:28 5604
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5605
            "Click and drag column headers to reorder columns.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 5606
            "Right-click on a header to open a context menu.");
1193b4be Poul Sander 2025-02-03 21:28 5607
        static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV;
1193b4be Poul Sander 2025-02-03 21:28 5608
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5609
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 5610
        ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
1193b4be Poul Sander 2025-02-03 21:28 5611
        ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
1193b4be Poul Sander 2025-02-03 21:28 5612
        ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody);
1193b4be Poul Sander 2025-02-03 21:28 5613
        ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers)");
1193b4be Poul Sander 2025-02-03 21:28 5614
        ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn);
1193b4be Poul Sander 2025-02-03 21:28 5615
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5616
1193b4be Poul Sander 2025-02-03 21:28 5617
        if (ImGui::BeginTable("table1", 3, flags))
1193b4be Poul Sander 2025-02-03 21:28 5618
        {
1193b4be Poul Sander 2025-02-03 21:28 5619
            // Submit columns name with TableSetupColumn() and call TableHeadersRow() to create a row with a header in each column.
1193b4be Poul Sander 2025-02-03 21:28 5620
            // (Later we will show how TableSetupColumn() has other uses, optional flags, sizing weight etc.)
1193b4be Poul Sander 2025-02-03 21:28 5621
            ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 5622
            ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 5623
            ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 5624
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5625
            for (int row = 0; row < 6; row++)
1193b4be Poul Sander 2025-02-03 21:28 5626
            {
1193b4be Poul Sander 2025-02-03 21:28 5627
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5628
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5629
                {
1193b4be Poul Sander 2025-02-03 21:28 5630
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5631
                    ImGui::Text("Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5632
                }
1193b4be Poul Sander 2025-02-03 21:28 5633
            }
1193b4be Poul Sander 2025-02-03 21:28 5634
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5635
        }
1193b4be Poul Sander 2025-02-03 21:28 5636
1193b4be Poul Sander 2025-02-03 21:28 5637
        // Use outer_size.x == 0.0f instead of default to make the table as tight as possible
1193b4be Poul Sander 2025-02-03 21:28 5638
        // (only valid when no scrolling and no stretch column)
1193b4be Poul Sander 2025-02-03 21:28 5639
        if (ImGui::BeginTable("table2", 3, flags | ImGuiTableFlags_SizingFixedFit, ImVec2(0.0f, 0.0f)))
1193b4be Poul Sander 2025-02-03 21:28 5640
        {
1193b4be Poul Sander 2025-02-03 21:28 5641
            ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 5642
            ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 5643
            ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 5644
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5645
            for (int row = 0; row < 6; row++)
1193b4be Poul Sander 2025-02-03 21:28 5646
            {
1193b4be Poul Sander 2025-02-03 21:28 5647
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5648
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5649
                {
1193b4be Poul Sander 2025-02-03 21:28 5650
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5651
                    ImGui::Text("Fixed %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5652
                }
1193b4be Poul Sander 2025-02-03 21:28 5653
            }
1193b4be Poul Sander 2025-02-03 21:28 5654
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5655
        }
1193b4be Poul Sander 2025-02-03 21:28 5656
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5657
    }
1193b4be Poul Sander 2025-02-03 21:28 5658
1193b4be Poul Sander 2025-02-03 21:28 5659
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5660
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5661
    IMGUI_DEMO_MARKER("Tables/Padding");
1193b4be Poul Sander 2025-02-03 21:28 5662
    if (ImGui::TreeNode("Padding"))
1193b4be Poul Sander 2025-02-03 21:28 5663
    {
1193b4be Poul Sander 2025-02-03 21:28 5664
        // First example: showcase use of padding flags and effect of BorderOuterV/BorderInnerV on X padding.
1193b4be Poul Sander 2025-02-03 21:28 5665
        // We don't expose BorderOuterH/BorderInnerH here because they have no effect on X padding.
1193b4be Poul Sander 2025-02-03 21:28 5666
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5667
            "We often want outer padding activated when any using features which makes the edges of a column visible:\n"
1193b4be Poul Sander 2025-02-03 21:28 5668
            "e.g.:\n"
1193b4be Poul Sander 2025-02-03 21:28 5669
            "- BorderOuterV\n"
1193b4be Poul Sander 2025-02-03 21:28 5670
            "- any form of row selection\n"
1193b4be Poul Sander 2025-02-03 21:28 5671
            "Because of this, activating BorderOuterV sets the default to PadOuterX. "
1193b4be Poul Sander 2025-02-03 21:28 5672
            "Using PadOuterX or NoPadOuterX you can override the default.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 5673
            "Actual padding values are using style.CellPadding.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 5674
            "In this demo we don't show horizontal borders to emphasize how they don't affect default horizontal padding.");
1193b4be Poul Sander 2025-02-03 21:28 5675
1193b4be Poul Sander 2025-02-03 21:28 5676
        static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV;
1193b4be Poul Sander 2025-02-03 21:28 5677
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5678
        ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags1, ImGuiTableFlags_PadOuterX);
1193b4be Poul Sander 2025-02-03 21:28 5679
        ImGui::SameLine(); HelpMarker("Enable outer-most padding (default if ImGuiTableFlags_BordersOuterV is set)");
1193b4be Poul Sander 2025-02-03 21:28 5680
        ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags1, ImGuiTableFlags_NoPadOuterX);
1193b4be Poul Sander 2025-02-03 21:28 5681
        ImGui::SameLine(); HelpMarker("Disable outer-most padding (default if ImGuiTableFlags_BordersOuterV is not set)");
1193b4be Poul Sander 2025-02-03 21:28 5682
        ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags1, ImGuiTableFlags_NoPadInnerX);
1193b4be Poul Sander 2025-02-03 21:28 5683
        ImGui::SameLine(); HelpMarker("Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off)");
1193b4be Poul Sander 2025-02-03 21:28 5684
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags1, ImGuiTableFlags_BordersOuterV);
1193b4be Poul Sander 2025-02-03 21:28 5685
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags1, ImGuiTableFlags_BordersInnerV);
1193b4be Poul Sander 2025-02-03 21:28 5686
        static bool show_headers = false;
1193b4be Poul Sander 2025-02-03 21:28 5687
        ImGui::Checkbox("show_headers", &show_headers);
1193b4be Poul Sander 2025-02-03 21:28 5688
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5689
1193b4be Poul Sander 2025-02-03 21:28 5690
        if (ImGui::BeginTable("table_padding", 3, flags1))
1193b4be Poul Sander 2025-02-03 21:28 5691
        {
1193b4be Poul Sander 2025-02-03 21:28 5692
            if (show_headers)
1193b4be Poul Sander 2025-02-03 21:28 5693
            {
1193b4be Poul Sander 2025-02-03 21:28 5694
                ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 5695
                ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 5696
                ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 5697
                ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5698
            }
1193b4be Poul Sander 2025-02-03 21:28 5699
1193b4be Poul Sander 2025-02-03 21:28 5700
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 5701
            {
1193b4be Poul Sander 2025-02-03 21:28 5702
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5703
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5704
                {
1193b4be Poul Sander 2025-02-03 21:28 5705
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5706
                    if (row == 0)
1193b4be Poul Sander 2025-02-03 21:28 5707
                    {
1193b4be Poul Sander 2025-02-03 21:28 5708
                        ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
1193b4be Poul Sander 2025-02-03 21:28 5709
                    }
1193b4be Poul Sander 2025-02-03 21:28 5710
                    else
1193b4be Poul Sander 2025-02-03 21:28 5711
                    {
1193b4be Poul Sander 2025-02-03 21:28 5712
                        char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 5713
                        sprintf(buf, "Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5714
                        ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 5715
                    }
1193b4be Poul Sander 2025-02-03 21:28 5716
                    //if (ImGui::TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered)
1193b4be Poul Sander 2025-02-03 21:28 5717
                    //    ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, IM_COL32(0, 100, 0, 255));
1193b4be Poul Sander 2025-02-03 21:28 5718
                }
1193b4be Poul Sander 2025-02-03 21:28 5719
            }
1193b4be Poul Sander 2025-02-03 21:28 5720
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5721
        }
1193b4be Poul Sander 2025-02-03 21:28 5722
1193b4be Poul Sander 2025-02-03 21:28 5723
        // Second example: set style.CellPadding to (0.0) or a custom value.
1193b4be Poul Sander 2025-02-03 21:28 5724
        // FIXME-TABLE: Vertical border effectively not displayed the same way as horizontal one...
1193b4be Poul Sander 2025-02-03 21:28 5725
        HelpMarker("Setting style.CellPadding to (0,0) or a custom value.");
1193b4be Poul Sander 2025-02-03 21:28 5726
        static ImGuiTableFlags flags2 = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
1193b4be Poul Sander 2025-02-03 21:28 5727
        static ImVec2 cell_padding(0.0f, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 5728
        static bool show_widget_frame_bg = true;
1193b4be Poul Sander 2025-02-03 21:28 5729
1193b4be Poul Sander 2025-02-03 21:28 5730
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5731
        ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags2, ImGuiTableFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 5732
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags2, ImGuiTableFlags_BordersH);
1193b4be Poul Sander 2025-02-03 21:28 5733
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags2, ImGuiTableFlags_BordersV);
1193b4be Poul Sander 2025-02-03 21:28 5734
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags2, ImGuiTableFlags_BordersInner);
1193b4be Poul Sander 2025-02-03 21:28 5735
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags2, ImGuiTableFlags_BordersOuter);
1193b4be Poul Sander 2025-02-03 21:28 5736
        ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags2, ImGuiTableFlags_RowBg);
1193b4be Poul Sander 2025-02-03 21:28 5737
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags2, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 5738
        ImGui::Checkbox("show_widget_frame_bg", &show_widget_frame_bg);
1193b4be Poul Sander 2025-02-03 21:28 5739
        ImGui::SliderFloat2("CellPadding", &cell_padding.x, 0.0f, 10.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 5740
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5741
1193b4be Poul Sander 2025-02-03 21:28 5742
        ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cell_padding);
1193b4be Poul Sander 2025-02-03 21:28 5743
        if (ImGui::BeginTable("table_padding_2", 3, flags2))
1193b4be Poul Sander 2025-02-03 21:28 5744
        {
1193b4be Poul Sander 2025-02-03 21:28 5745
            static char text_bufs[3 * 5][16]; // Mini text storage for 3x5 cells
1193b4be Poul Sander 2025-02-03 21:28 5746
            static bool init = true;
1193b4be Poul Sander 2025-02-03 21:28 5747
            if (!show_widget_frame_bg)
1193b4be Poul Sander 2025-02-03 21:28 5748
                ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);
1193b4be Poul Sander 2025-02-03 21:28 5749
            for (int cell = 0; cell < 3 * 5; cell++)
1193b4be Poul Sander 2025-02-03 21:28 5750
            {
1193b4be Poul Sander 2025-02-03 21:28 5751
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 5752
                if (init)
1193b4be Poul Sander 2025-02-03 21:28 5753
                    strcpy(text_bufs[cell], "edit me");
1193b4be Poul Sander 2025-02-03 21:28 5754
                ImGui::SetNextItemWidth(-FLT_MIN);
1193b4be Poul Sander 2025-02-03 21:28 5755
                ImGui::PushID(cell);
1193b4be Poul Sander 2025-02-03 21:28 5756
                ImGui::InputText("##cell", text_bufs[cell], IM_ARRAYSIZE(text_bufs[cell]));
1193b4be Poul Sander 2025-02-03 21:28 5757
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 5758
            }
1193b4be Poul Sander 2025-02-03 21:28 5759
            if (!show_widget_frame_bg)
1193b4be Poul Sander 2025-02-03 21:28 5760
                ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 5761
            init = false;
1193b4be Poul Sander 2025-02-03 21:28 5762
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5763
        }
1193b4be Poul Sander 2025-02-03 21:28 5764
        ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 5765
1193b4be Poul Sander 2025-02-03 21:28 5766
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5767
    }
1193b4be Poul Sander 2025-02-03 21:28 5768
1193b4be Poul Sander 2025-02-03 21:28 5769
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5770
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5771
    IMGUI_DEMO_MARKER("Tables/Explicit widths");
1193b4be Poul Sander 2025-02-03 21:28 5772
    if (ImGui::TreeNode("Sizing policies"))
1193b4be Poul Sander 2025-02-03 21:28 5773
    {
1193b4be Poul Sander 2025-02-03 21:28 5774
        static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
1193b4be Poul Sander 2025-02-03 21:28 5775
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5776
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 5777
        ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags1, ImGuiTableFlags_NoHostExtendX);
1193b4be Poul Sander 2025-02-03 21:28 5778
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5779
1193b4be Poul Sander 2025-02-03 21:28 5780
        static ImGuiTableFlags sizing_policy_flags[4] = { ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp, ImGuiTableFlags_SizingStretchSame };
1193b4be Poul Sander 2025-02-03 21:28 5781
        for (int table_n = 0; table_n < 4; table_n++)
1193b4be Poul Sander 2025-02-03 21:28 5782
        {
1193b4be Poul Sander 2025-02-03 21:28 5783
            ImGui::PushID(table_n);
1193b4be Poul Sander 2025-02-03 21:28 5784
            ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 30);
1193b4be Poul Sander 2025-02-03 21:28 5785
            EditTableSizingFlags(&sizing_policy_flags[table_n]);
1193b4be Poul Sander 2025-02-03 21:28 5786
1193b4be Poul Sander 2025-02-03 21:28 5787
            // To make it easier to understand the different sizing policy,
1193b4be Poul Sander 2025-02-03 21:28 5788
            // For each policy: we display one table where the columns have equal contents width,
1193b4be Poul Sander 2025-02-03 21:28 5789
            // and one where the columns have different contents width.
1193b4be Poul Sander 2025-02-03 21:28 5790
            if (ImGui::BeginTable("table1", 3, sizing_policy_flags[table_n] | flags1))
1193b4be Poul Sander 2025-02-03 21:28 5791
            {
1193b4be Poul Sander 2025-02-03 21:28 5792
                for (int row = 0; row < 3; row++)
1193b4be Poul Sander 2025-02-03 21:28 5793
                {
1193b4be Poul Sander 2025-02-03 21:28 5794
                    ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5795
                    ImGui::TableNextColumn(); ImGui::Text("Oh dear");
1193b4be Poul Sander 2025-02-03 21:28 5796
                    ImGui::TableNextColumn(); ImGui::Text("Oh dear");
1193b4be Poul Sander 2025-02-03 21:28 5797
                    ImGui::TableNextColumn(); ImGui::Text("Oh dear");
1193b4be Poul Sander 2025-02-03 21:28 5798
                }
1193b4be Poul Sander 2025-02-03 21:28 5799
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5800
            }
1193b4be Poul Sander 2025-02-03 21:28 5801
            if (ImGui::BeginTable("table2", 3, sizing_policy_flags[table_n] | flags1))
1193b4be Poul Sander 2025-02-03 21:28 5802
            {
1193b4be Poul Sander 2025-02-03 21:28 5803
                for (int row = 0; row < 3; row++)
1193b4be Poul Sander 2025-02-03 21:28 5804
                {
1193b4be Poul Sander 2025-02-03 21:28 5805
                    ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5806
                    ImGui::TableNextColumn(); ImGui::Text("AAAA");
1193b4be Poul Sander 2025-02-03 21:28 5807
                    ImGui::TableNextColumn(); ImGui::Text("BBBBBBBB");
1193b4be Poul Sander 2025-02-03 21:28 5808
                    ImGui::TableNextColumn(); ImGui::Text("CCCCCCCCCCCC");
1193b4be Poul Sander 2025-02-03 21:28 5809
                }
1193b4be Poul Sander 2025-02-03 21:28 5810
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5811
            }
1193b4be Poul Sander 2025-02-03 21:28 5812
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 5813
        }
1193b4be Poul Sander 2025-02-03 21:28 5814
1193b4be Poul Sander 2025-02-03 21:28 5815
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 5816
        ImGui::TextUnformatted("Advanced");
1193b4be Poul Sander 2025-02-03 21:28 5817
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5818
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5819
            "This section allows you to interact and see the effect of various sizing policies "
1193b4be Poul Sander 2025-02-03 21:28 5820
            "depending on whether Scroll is enabled and the contents of your columns.");
1193b4be Poul Sander 2025-02-03 21:28 5821
1193b4be Poul Sander 2025-02-03 21:28 5822
        enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText };
1193b4be Poul Sander 2025-02-03 21:28 5823
        static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable;
1193b4be Poul Sander 2025-02-03 21:28 5824
        static int contents_type = CT_ShowWidth;
1193b4be Poul Sander 2025-02-03 21:28 5825
        static int column_count = 3;
1193b4be Poul Sander 2025-02-03 21:28 5826
1193b4be Poul Sander 2025-02-03 21:28 5827
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5828
        ImGui::PushID("Advanced");
1193b4be Poul Sander 2025-02-03 21:28 5829
        ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
1193b4be Poul Sander 2025-02-03 21:28 5830
        EditTableSizingFlags(&flags);
1193b4be Poul Sander 2025-02-03 21:28 5831
        ImGui::Combo("Contents", &contents_type, "Show width\0Short Text\0Long Text\0Button\0Fill Button\0InputText\0");
1193b4be Poul Sander 2025-02-03 21:28 5832
        if (contents_type == CT_FillButton)
1193b4be Poul Sander 2025-02-03 21:28 5833
        {
1193b4be Poul Sander 2025-02-03 21:28 5834
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5835
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5836
                "Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop "
1193b4be Poul Sander 2025-02-03 21:28 5837
                "where contents width can feed into auto-column width can feed into contents width.");
1193b4be Poul Sander 2025-02-03 21:28 5838
        }
1193b4be Poul Sander 2025-02-03 21:28 5839
        ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
1193b4be Poul Sander 2025-02-03 21:28 5840
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 5841
        ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
1193b4be Poul Sander 2025-02-03 21:28 5842
        ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.");
1193b4be Poul Sander 2025-02-03 21:28 5843
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
1193b4be Poul Sander 2025-02-03 21:28 5844
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
1193b4be Poul Sander 2025-02-03 21:28 5845
        ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
1193b4be Poul Sander 2025-02-03 21:28 5846
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 5847
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 5848
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5849
1193b4be Poul Sander 2025-02-03 21:28 5850
        if (ImGui::BeginTable("table2", column_count, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 7)))
1193b4be Poul Sander 2025-02-03 21:28 5851
        {
1193b4be Poul Sander 2025-02-03 21:28 5852
            for (int cell = 0; cell < 10 * column_count; cell++)
1193b4be Poul Sander 2025-02-03 21:28 5853
            {
1193b4be Poul Sander 2025-02-03 21:28 5854
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 5855
                int column = ImGui::TableGetColumnIndex();
1193b4be Poul Sander 2025-02-03 21:28 5856
                int row = ImGui::TableGetRowIndex();
1193b4be Poul Sander 2025-02-03 21:28 5857
1193b4be Poul Sander 2025-02-03 21:28 5858
                ImGui::PushID(cell);
1193b4be Poul Sander 2025-02-03 21:28 5859
                char label[32];
1193b4be Poul Sander 2025-02-03 21:28 5860
                static char text_buf[32] = "";
1193b4be Poul Sander 2025-02-03 21:28 5861
                sprintf(label, "Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5862
                switch (contents_type)
1193b4be Poul Sander 2025-02-03 21:28 5863
                {
1193b4be Poul Sander 2025-02-03 21:28 5864
                case CT_ShortText:  ImGui::TextUnformatted(label); break;
1193b4be Poul Sander 2025-02-03 21:28 5865
                case CT_LongText:   ImGui::Text("Some %s text %d,%d\nOver two lines..", column == 0 ? "long" : "longeeer", column, row); break;
1193b4be Poul Sander 2025-02-03 21:28 5866
                case CT_ShowWidth:  ImGui::Text("W: %.1f", ImGui::GetContentRegionAvail().x); break;
1193b4be Poul Sander 2025-02-03 21:28 5867
                case CT_Button:     ImGui::Button(label); break;
1193b4be Poul Sander 2025-02-03 21:28 5868
                case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
1193b4be Poul Sander 2025-02-03 21:28 5869
                case CT_InputText:  ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
1193b4be Poul Sander 2025-02-03 21:28 5870
                }
1193b4be Poul Sander 2025-02-03 21:28 5871
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 5872
            }
1193b4be Poul Sander 2025-02-03 21:28 5873
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5874
        }
1193b4be Poul Sander 2025-02-03 21:28 5875
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5876
    }
1193b4be Poul Sander 2025-02-03 21:28 5877
1193b4be Poul Sander 2025-02-03 21:28 5878
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5879
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5880
    IMGUI_DEMO_MARKER("Tables/Vertical scrolling, with clipping");
1193b4be Poul Sander 2025-02-03 21:28 5881
    if (ImGui::TreeNode("Vertical scrolling, with clipping"))
1193b4be Poul Sander 2025-02-03 21:28 5882
    {
1193b4be Poul Sander 2025-02-03 21:28 5883
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5884
            "Here we activate ScrollY, which will create a child window container to allow hosting scrollable contents.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 5885
            "We also demonstrate using ImGuiListClipper to virtualize the submission of many items.");
1193b4be Poul Sander 2025-02-03 21:28 5886
        static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
1193b4be Poul Sander 2025-02-03 21:28 5887
1193b4be Poul Sander 2025-02-03 21:28 5888
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5889
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
1193b4be Poul Sander 2025-02-03 21:28 5890
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5891
1193b4be Poul Sander 2025-02-03 21:28 5892
        // When using ScrollX or ScrollY we need to specify a size for our table container!
1193b4be Poul Sander 2025-02-03 21:28 5893
        // Otherwise by default the table will fit all available space, like a BeginChild() call.
1193b4be Poul Sander 2025-02-03 21:28 5894
        ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
1193b4be Poul Sander 2025-02-03 21:28 5895
        if (ImGui::BeginTable("table_scrolly", 3, flags, outer_size))
1193b4be Poul Sander 2025-02-03 21:28 5896
        {
1193b4be Poul Sander 2025-02-03 21:28 5897
            ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
1193b4be Poul Sander 2025-02-03 21:28 5898
            ImGui::TableSetupColumn("One", ImGuiTableColumnFlags_None);
1193b4be Poul Sander 2025-02-03 21:28 5899
            ImGui::TableSetupColumn("Two", ImGuiTableColumnFlags_None);
1193b4be Poul Sander 2025-02-03 21:28 5900
            ImGui::TableSetupColumn("Three", ImGuiTableColumnFlags_None);
1193b4be Poul Sander 2025-02-03 21:28 5901
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5902
1193b4be Poul Sander 2025-02-03 21:28 5903
            // Demonstrate using clipper for large vertical lists
1193b4be Poul Sander 2025-02-03 21:28 5904
            ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 5905
            clipper.Begin(1000);
1193b4be Poul Sander 2025-02-03 21:28 5906
            while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 5907
            {
1193b4be Poul Sander 2025-02-03 21:28 5908
                for (int row = clipper.DisplayStart; row < clipper.DisplayEnd; row++)
1193b4be Poul Sander 2025-02-03 21:28 5909
                {
1193b4be Poul Sander 2025-02-03 21:28 5910
                    ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5911
                    for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 5912
                    {
1193b4be Poul Sander 2025-02-03 21:28 5913
                        ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 5914
                        ImGui::Text("Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5915
                    }
1193b4be Poul Sander 2025-02-03 21:28 5916
                }
1193b4be Poul Sander 2025-02-03 21:28 5917
            }
1193b4be Poul Sander 2025-02-03 21:28 5918
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5919
        }
1193b4be Poul Sander 2025-02-03 21:28 5920
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 5921
    }
1193b4be Poul Sander 2025-02-03 21:28 5922
1193b4be Poul Sander 2025-02-03 21:28 5923
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 5924
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 5925
    IMGUI_DEMO_MARKER("Tables/Horizontal scrolling");
1193b4be Poul Sander 2025-02-03 21:28 5926
    if (ImGui::TreeNode("Horizontal scrolling"))
1193b4be Poul Sander 2025-02-03 21:28 5927
    {
1193b4be Poul Sander 2025-02-03 21:28 5928
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5929
            "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingFixedFit, "
1193b4be Poul Sander 2025-02-03 21:28 5930
            "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 5931
            "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX, "
1193b4be Poul Sander 2025-02-03 21:28 5932
            "because the container window won't automatically extend vertically to fix contents "
1193b4be Poul Sander 2025-02-03 21:28 5933
            "(this may be improved in future versions).");
1193b4be Poul Sander 2025-02-03 21:28 5934
        static ImGuiTableFlags flags = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
1193b4be Poul Sander 2025-02-03 21:28 5935
        static int freeze_cols = 1;
1193b4be Poul Sander 2025-02-03 21:28 5936
        static int freeze_rows = 1;
1193b4be Poul Sander 2025-02-03 21:28 5937
1193b4be Poul Sander 2025-02-03 21:28 5938
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5939
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 5940
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
1193b4be Poul Sander 2025-02-03 21:28 5941
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
1193b4be Poul Sander 2025-02-03 21:28 5942
        ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
1193b4be Poul Sander 2025-02-03 21:28 5943
        ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
1193b4be Poul Sander 2025-02-03 21:28 5944
        ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
1193b4be Poul Sander 2025-02-03 21:28 5945
        ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
1193b4be Poul Sander 2025-02-03 21:28 5946
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5947
1193b4be Poul Sander 2025-02-03 21:28 5948
        // When using ScrollX or ScrollY we need to specify a size for our table container!
1193b4be Poul Sander 2025-02-03 21:28 5949
        // Otherwise by default the table will fit all available space, like a BeginChild() call.
1193b4be Poul Sander 2025-02-03 21:28 5950
        ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 8);
1193b4be Poul Sander 2025-02-03 21:28 5951
        if (ImGui::BeginTable("table_scrollx", 7, flags, outer_size))
1193b4be Poul Sander 2025-02-03 21:28 5952
        {
1193b4be Poul Sander 2025-02-03 21:28 5953
            ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
1193b4be Poul Sander 2025-02-03 21:28 5954
            ImGui::TableSetupColumn("Line #", ImGuiTableColumnFlags_NoHide); // Make the first column not hideable to match our use of TableSetupScrollFreeze()
1193b4be Poul Sander 2025-02-03 21:28 5955
            ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 5956
            ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 5957
            ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 5958
            ImGui::TableSetupColumn("Four");
1193b4be Poul Sander 2025-02-03 21:28 5959
            ImGui::TableSetupColumn("Five");
1193b4be Poul Sander 2025-02-03 21:28 5960
            ImGui::TableSetupColumn("Six");
1193b4be Poul Sander 2025-02-03 21:28 5961
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 5962
            for (int row = 0; row < 20; row++)
1193b4be Poul Sander 2025-02-03 21:28 5963
            {
1193b4be Poul Sander 2025-02-03 21:28 5964
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 5965
                for (int column = 0; column < 7; column++)
1193b4be Poul Sander 2025-02-03 21:28 5966
                {
1193b4be Poul Sander 2025-02-03 21:28 5967
                    // Both TableNextColumn() and TableSetColumnIndex() return true when a column is visible or performing width measurement.
1193b4be Poul Sander 2025-02-03 21:28 5968
                    // Because here we know that:
1193b4be Poul Sander 2025-02-03 21:28 5969
                    // - A) all our columns are contributing the same to row height
1193b4be Poul Sander 2025-02-03 21:28 5970
                    // - B) column 0 is always visible,
1193b4be Poul Sander 2025-02-03 21:28 5971
                    // We only always submit this one column and can skip others.
1193b4be Poul Sander 2025-02-03 21:28 5972
                    // More advanced per-column clipping behaviors may benefit from polling the status flags via TableGetColumnFlags().
1193b4be Poul Sander 2025-02-03 21:28 5973
                    if (!ImGui::TableSetColumnIndex(column) && column > 0)
1193b4be Poul Sander 2025-02-03 21:28 5974
                        continue;
1193b4be Poul Sander 2025-02-03 21:28 5975
                    if (column == 0)
1193b4be Poul Sander 2025-02-03 21:28 5976
                        ImGui::Text("Line %d", row);
1193b4be Poul Sander 2025-02-03 21:28 5977
                    else
1193b4be Poul Sander 2025-02-03 21:28 5978
                        ImGui::Text("Hello world %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 5979
                }
1193b4be Poul Sander 2025-02-03 21:28 5980
            }
1193b4be Poul Sander 2025-02-03 21:28 5981
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 5982
        }
1193b4be Poul Sander 2025-02-03 21:28 5983
1193b4be Poul Sander 2025-02-03 21:28 5984
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 5985
        ImGui::TextUnformatted("Stretch + ScrollX");
1193b4be Poul Sander 2025-02-03 21:28 5986
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 5987
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 5988
            "Showcase using Stretch columns + ScrollX together: "
1193b4be Poul Sander 2025-02-03 21:28 5989
            "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
1193b4be Poul Sander 2025-02-03 21:28 5990
            "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns "
1193b4be Poul Sander 2025-02-03 21:28 5991
            "along with ScrollX doesn't make sense.");
1193b4be Poul Sander 2025-02-03 21:28 5992
        static ImGuiTableFlags flags2 = ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
1193b4be Poul Sander 2025-02-03 21:28 5993
        static float inner_width = 1000.0f;
1193b4be Poul Sander 2025-02-03 21:28 5994
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 5995
        ImGui::PushID("flags3");
1193b4be Poul Sander 2025-02-03 21:28 5996
        ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
1193b4be Poul Sander 2025-02-03 21:28 5997
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX);
1193b4be Poul Sander 2025-02-03 21:28 5998
        ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
1193b4be Poul Sander 2025-02-03 21:28 5999
        ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 6000
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6001
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6002
        if (ImGui::BeginTable("table2", 7, flags2, outer_size, inner_width))
1193b4be Poul Sander 2025-02-03 21:28 6003
        {
1193b4be Poul Sander 2025-02-03 21:28 6004
            for (int cell = 0; cell < 20 * 7; cell++)
1193b4be Poul Sander 2025-02-03 21:28 6005
            {
1193b4be Poul Sander 2025-02-03 21:28 6006
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6007
                ImGui::Text("Hello world %d,%d", ImGui::TableGetColumnIndex(), ImGui::TableGetRowIndex());
1193b4be Poul Sander 2025-02-03 21:28 6008
            }
1193b4be Poul Sander 2025-02-03 21:28 6009
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6010
        }
1193b4be Poul Sander 2025-02-03 21:28 6011
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6012
    }
1193b4be Poul Sander 2025-02-03 21:28 6013
1193b4be Poul Sander 2025-02-03 21:28 6014
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6015
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6016
    IMGUI_DEMO_MARKER("Tables/Columns flags");
1193b4be Poul Sander 2025-02-03 21:28 6017
    if (ImGui::TreeNode("Columns flags"))
1193b4be Poul Sander 2025-02-03 21:28 6018
    {
1193b4be Poul Sander 2025-02-03 21:28 6019
        // Create a first table just to show all the options/flags we want to make visible in our example!
1193b4be Poul Sander 2025-02-03 21:28 6020
        const int column_count = 3;
1193b4be Poul Sander 2025-02-03 21:28 6021
        const char* column_names[column_count] = { "One", "Two", "Three" };
1193b4be Poul Sander 2025-02-03 21:28 6022
        static ImGuiTableColumnFlags column_flags[column_count] = { ImGuiTableColumnFlags_DefaultSort, ImGuiTableColumnFlags_None, ImGuiTableColumnFlags_DefaultHide };
1193b4be Poul Sander 2025-02-03 21:28 6023
        static ImGuiTableColumnFlags column_flags_out[column_count] = { 0, 0, 0 }; // Output from TableGetColumnFlags()
1193b4be Poul Sander 2025-02-03 21:28 6024
1193b4be Poul Sander 2025-02-03 21:28 6025
        if (ImGui::BeginTable("table_columns_flags_checkboxes", column_count, ImGuiTableFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 6026
        {
1193b4be Poul Sander 2025-02-03 21:28 6027
            PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6028
            for (int column = 0; column < column_count; column++)
1193b4be Poul Sander 2025-02-03 21:28 6029
            {
1193b4be Poul Sander 2025-02-03 21:28 6030
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6031
                ImGui::PushID(column);
1193b4be Poul Sander 2025-02-03 21:28 6032
                ImGui::AlignTextToFramePadding(); // FIXME-TABLE: Workaround for wrong text baseline propagation across columns
1193b4be Poul Sander 2025-02-03 21:28 6033
                ImGui::Text("'%s'", column_names[column]);
1193b4be Poul Sander 2025-02-03 21:28 6034
                ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 6035
                ImGui::Text("Input flags:");
1193b4be Poul Sander 2025-02-03 21:28 6036
                EditTableColumnsFlags(&column_flags[column]);
1193b4be Poul Sander 2025-02-03 21:28 6037
                ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 6038
                ImGui::Text("Output flags:");
1193b4be Poul Sander 2025-02-03 21:28 6039
                ImGui::BeginDisabled();
1193b4be Poul Sander 2025-02-03 21:28 6040
                ShowTableColumnsStatusFlags(column_flags_out[column]);
1193b4be Poul Sander 2025-02-03 21:28 6041
                ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 6042
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6043
            }
1193b4be Poul Sander 2025-02-03 21:28 6044
            PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6045
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6046
        }
1193b4be Poul Sander 2025-02-03 21:28 6047
1193b4be Poul Sander 2025-02-03 21:28 6048
        // Create the real table we care about for the example!
1193b4be Poul Sander 2025-02-03 21:28 6049
        // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above,
1193b4be Poul Sander 2025-02-03 21:28 6050
        // otherwise in a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible
1193b4be Poul Sander 2025-02-03 21:28 6051
        // + resizing the parent window down).
1193b4be Poul Sander 2025-02-03 21:28 6052
        const ImGuiTableFlags flags
1193b4be Poul Sander 2025-02-03 21:28 6053
            = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
1193b4be Poul Sander 2025-02-03 21:28 6054
            | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV
1193b4be Poul Sander 2025-02-03 21:28 6055
            | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable;
1193b4be Poul Sander 2025-02-03 21:28 6056
        ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 9);
1193b4be Poul Sander 2025-02-03 21:28 6057
        if (ImGui::BeginTable("table_columns_flags", column_count, flags, outer_size))
1193b4be Poul Sander 2025-02-03 21:28 6058
        {
1193b4be Poul Sander 2025-02-03 21:28 6059
            bool has_angled_header = false;
1193b4be Poul Sander 2025-02-03 21:28 6060
            for (int column = 0; column < column_count; column++)
1193b4be Poul Sander 2025-02-03 21:28 6061
            {
1193b4be Poul Sander 2025-02-03 21:28 6062
                has_angled_header |= (column_flags[column] & ImGuiTableColumnFlags_AngledHeader) != 0;
1193b4be Poul Sander 2025-02-03 21:28 6063
                ImGui::TableSetupColumn(column_names[column], column_flags[column]);
1193b4be Poul Sander 2025-02-03 21:28 6064
            }
1193b4be Poul Sander 2025-02-03 21:28 6065
            if (has_angled_header)
1193b4be Poul Sander 2025-02-03 21:28 6066
                ImGui::TableAngledHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6067
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6068
            for (int column = 0; column < column_count; column++)
1193b4be Poul Sander 2025-02-03 21:28 6069
                column_flags_out[column] = ImGui::TableGetColumnFlags(column);
1193b4be Poul Sander 2025-02-03 21:28 6070
            float indent_step = (float)((int)TEXT_BASE_WIDTH / 2);
1193b4be Poul Sander 2025-02-03 21:28 6071
            for (int row = 0; row < 8; row++)
1193b4be Poul Sander 2025-02-03 21:28 6072
            {
1193b4be Poul Sander 2025-02-03 21:28 6073
                // Add some indentation to demonstrate usage of per-column IndentEnable/IndentDisable flags.
1193b4be Poul Sander 2025-02-03 21:28 6074
                ImGui::Indent(indent_step);
1193b4be Poul Sander 2025-02-03 21:28 6075
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6076
                for (int column = 0; column < column_count; column++)
1193b4be Poul Sander 2025-02-03 21:28 6077
                {
1193b4be Poul Sander 2025-02-03 21:28 6078
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6079
                    ImGui::Text("%s %s", (column == 0) ? "Indented" : "Hello", ImGui::TableGetColumnName(column));
1193b4be Poul Sander 2025-02-03 21:28 6080
                }
1193b4be Poul Sander 2025-02-03 21:28 6081
            }
1193b4be Poul Sander 2025-02-03 21:28 6082
            ImGui::Unindent(indent_step * 8.0f);
1193b4be Poul Sander 2025-02-03 21:28 6083
1193b4be Poul Sander 2025-02-03 21:28 6084
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6085
        }
1193b4be Poul Sander 2025-02-03 21:28 6086
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6087
    }
1193b4be Poul Sander 2025-02-03 21:28 6088
1193b4be Poul Sander 2025-02-03 21:28 6089
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6090
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6091
    IMGUI_DEMO_MARKER("Tables/Columns widths");
1193b4be Poul Sander 2025-02-03 21:28 6092
    if (ImGui::TreeNode("Columns widths"))
1193b4be Poul Sander 2025-02-03 21:28 6093
    {
1193b4be Poul Sander 2025-02-03 21:28 6094
        HelpMarker("Using TableSetupColumn() to setup default width.");
1193b4be Poul Sander 2025-02-03 21:28 6095
1193b4be Poul Sander 2025-02-03 21:28 6096
        static ImGuiTableFlags flags1 = ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBodyUntilResize;
1193b4be Poul Sander 2025-02-03 21:28 6097
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6098
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 6099
        ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags1, ImGuiTableFlags_NoBordersInBodyUntilResize);
1193b4be Poul Sander 2025-02-03 21:28 6100
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6101
        if (ImGui::BeginTable("table1", 3, flags1))
1193b4be Poul Sander 2025-02-03 21:28 6102
        {
1193b4be Poul Sander 2025-02-03 21:28 6103
            // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed.
1193b4be Poul Sander 2025-02-03 21:28 6104
            ImGui::TableSetupColumn("one", ImGuiTableColumnFlags_WidthFixed, 100.0f); // Default to 100.0f
1193b4be Poul Sander 2025-02-03 21:28 6105
            ImGui::TableSetupColumn("two", ImGuiTableColumnFlags_WidthFixed, 200.0f); // Default to 200.0f
1193b4be Poul Sander 2025-02-03 21:28 6106
            ImGui::TableSetupColumn("three", ImGuiTableColumnFlags_WidthFixed);       // Default to auto
1193b4be Poul Sander 2025-02-03 21:28 6107
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6108
            for (int row = 0; row < 4; row++)
1193b4be Poul Sander 2025-02-03 21:28 6109
            {
1193b4be Poul Sander 2025-02-03 21:28 6110
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6111
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 6112
                {
1193b4be Poul Sander 2025-02-03 21:28 6113
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6114
                    if (row == 0)
1193b4be Poul Sander 2025-02-03 21:28 6115
                        ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
1193b4be Poul Sander 2025-02-03 21:28 6116
                    else
1193b4be Poul Sander 2025-02-03 21:28 6117
                        ImGui::Text("Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6118
                }
1193b4be Poul Sander 2025-02-03 21:28 6119
            }
1193b4be Poul Sander 2025-02-03 21:28 6120
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6121
        }
1193b4be Poul Sander 2025-02-03 21:28 6122
1193b4be Poul Sander 2025-02-03 21:28 6123
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 6124
            "Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, "
1193b4be Poul Sander 2025-02-03 21:28 6125
            "fixed columns with set width may still be shrunk down if there's not enough space in the host.");
1193b4be Poul Sander 2025-02-03 21:28 6126
1193b4be Poul Sander 2025-02-03 21:28 6127
        static ImGuiTableFlags flags2 = ImGuiTableFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 6128
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6129
        ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags2, ImGuiTableFlags_NoKeepColumnsVisible);
1193b4be Poul Sander 2025-02-03 21:28 6130
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags2, ImGuiTableFlags_BordersInnerV);
1193b4be Poul Sander 2025-02-03 21:28 6131
        ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags2, ImGuiTableFlags_BordersOuterV);
1193b4be Poul Sander 2025-02-03 21:28 6132
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6133
        if (ImGui::BeginTable("table2", 4, flags2))
1193b4be Poul Sander 2025-02-03 21:28 6134
        {
1193b4be Poul Sander 2025-02-03 21:28 6135
            // We could also set ImGuiTableFlags_SizingFixedFit on the table and then all columns
1193b4be Poul Sander 2025-02-03 21:28 6136
            // will default to ImGuiTableColumnFlags_WidthFixed.
1193b4be Poul Sander 2025-02-03 21:28 6137
            ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f);
1193b4be Poul Sander 2025-02-03 21:28 6138
            ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
1193b4be Poul Sander 2025-02-03 21:28 6139
            ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f);
1193b4be Poul Sander 2025-02-03 21:28 6140
            ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
1193b4be Poul Sander 2025-02-03 21:28 6141
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 6142
            {
1193b4be Poul Sander 2025-02-03 21:28 6143
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6144
                for (int column = 0; column < 4; column++)
1193b4be Poul Sander 2025-02-03 21:28 6145
                {
1193b4be Poul Sander 2025-02-03 21:28 6146
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6147
                    if (row == 0)
1193b4be Poul Sander 2025-02-03 21:28 6148
                        ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x);
1193b4be Poul Sander 2025-02-03 21:28 6149
                    else
1193b4be Poul Sander 2025-02-03 21:28 6150
                        ImGui::Text("Hello %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6151
                }
1193b4be Poul Sander 2025-02-03 21:28 6152
            }
1193b4be Poul Sander 2025-02-03 21:28 6153
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6154
        }
1193b4be Poul Sander 2025-02-03 21:28 6155
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6156
    }
1193b4be Poul Sander 2025-02-03 21:28 6157
1193b4be Poul Sander 2025-02-03 21:28 6158
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6159
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6160
    IMGUI_DEMO_MARKER("Tables/Nested tables");
1193b4be Poul Sander 2025-02-03 21:28 6161
    if (ImGui::TreeNode("Nested tables"))
1193b4be Poul Sander 2025-02-03 21:28 6162
    {
1193b4be Poul Sander 2025-02-03 21:28 6163
        HelpMarker("This demonstrates embedding a table into another table cell.");
1193b4be Poul Sander 2025-02-03 21:28 6164
1193b4be Poul Sander 2025-02-03 21:28 6165
        if (ImGui::BeginTable("table_nested1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
1193b4be Poul Sander 2025-02-03 21:28 6166
        {
1193b4be Poul Sander 2025-02-03 21:28 6167
            ImGui::TableSetupColumn("A0");
1193b4be Poul Sander 2025-02-03 21:28 6168
            ImGui::TableSetupColumn("A1");
1193b4be Poul Sander 2025-02-03 21:28 6169
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6170
1193b4be Poul Sander 2025-02-03 21:28 6171
            ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6172
            ImGui::Text("A0 Row 0");
1193b4be Poul Sander 2025-02-03 21:28 6173
            {
1193b4be Poul Sander 2025-02-03 21:28 6174
                float rows_height = TEXT_BASE_HEIGHT * 2;
1193b4be Poul Sander 2025-02-03 21:28 6175
                if (ImGui::BeginTable("table_nested2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
1193b4be Poul Sander 2025-02-03 21:28 6176
                {
1193b4be Poul Sander 2025-02-03 21:28 6177
                    ImGui::TableSetupColumn("B0");
1193b4be Poul Sander 2025-02-03 21:28 6178
                    ImGui::TableSetupColumn("B1");
1193b4be Poul Sander 2025-02-03 21:28 6179
                    ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6180
1193b4be Poul Sander 2025-02-03 21:28 6181
                    ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
1193b4be Poul Sander 2025-02-03 21:28 6182
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6183
                    ImGui::Text("B0 Row 0");
1193b4be Poul Sander 2025-02-03 21:28 6184
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6185
                    ImGui::Text("B1 Row 0");
1193b4be Poul Sander 2025-02-03 21:28 6186
                    ImGui::TableNextRow(ImGuiTableRowFlags_None, rows_height);
1193b4be Poul Sander 2025-02-03 21:28 6187
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6188
                    ImGui::Text("B0 Row 1");
1193b4be Poul Sander 2025-02-03 21:28 6189
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6190
                    ImGui::Text("B1 Row 1");
1193b4be Poul Sander 2025-02-03 21:28 6191
1193b4be Poul Sander 2025-02-03 21:28 6192
                    ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6193
                }
1193b4be Poul Sander 2025-02-03 21:28 6194
            }
1193b4be Poul Sander 2025-02-03 21:28 6195
            ImGui::TableNextColumn(); ImGui::Text("A1 Row 0");
1193b4be Poul Sander 2025-02-03 21:28 6196
            ImGui::TableNextColumn(); ImGui::Text("A0 Row 1");
1193b4be Poul Sander 2025-02-03 21:28 6197
            ImGui::TableNextColumn(); ImGui::Text("A1 Row 1");
1193b4be Poul Sander 2025-02-03 21:28 6198
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6199
        }
1193b4be Poul Sander 2025-02-03 21:28 6200
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6201
    }
1193b4be Poul Sander 2025-02-03 21:28 6202
1193b4be Poul Sander 2025-02-03 21:28 6203
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6204
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6205
    IMGUI_DEMO_MARKER("Tables/Row height");
1193b4be Poul Sander 2025-02-03 21:28 6206
    if (ImGui::TreeNode("Row height"))
1193b4be Poul Sander 2025-02-03 21:28 6207
    {
1193b4be Poul Sander 2025-02-03 21:28 6208
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 6209
            "You can pass a 'min_row_height' to TableNextRow().\n\nRows are padded with 'style.CellPadding.y' on top and bottom, "
1193b4be Poul Sander 2025-02-03 21:28 6210
            "so effectively the minimum row height will always be >= 'style.CellPadding.y * 2.0f'.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 6211
            "We cannot honor a _maximum_ row height as that would require a unique clipping rectangle per row.");
1193b4be Poul Sander 2025-02-03 21:28 6212
        if (ImGui::BeginTable("table_row_height", 1, ImGuiTableFlags_Borders))
1193b4be Poul Sander 2025-02-03 21:28 6213
        {
1193b4be Poul Sander 2025-02-03 21:28 6214
            for (int row = 0; row < 8; row++)
1193b4be Poul Sander 2025-02-03 21:28 6215
            {
1193b4be Poul Sander 2025-02-03 21:28 6216
                float min_row_height = (float)(int)(TEXT_BASE_HEIGHT * 0.30f * row);
1193b4be Poul Sander 2025-02-03 21:28 6217
                ImGui::TableNextRow(ImGuiTableRowFlags_None, min_row_height);
1193b4be Poul Sander 2025-02-03 21:28 6218
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6219
                ImGui::Text("min_row_height = %.2f", min_row_height);
1193b4be Poul Sander 2025-02-03 21:28 6220
            }
1193b4be Poul Sander 2025-02-03 21:28 6221
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6222
        }
1193b4be Poul Sander 2025-02-03 21:28 6223
1193b4be Poul Sander 2025-02-03 21:28 6224
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 6225
            "Showcase using SameLine(0,0) to share Current Line Height between cells.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 6226
            "Please note that Tables Row Height is not the same thing as Current Line Height, "
1193b4be Poul Sander 2025-02-03 21:28 6227
            "as a table cell may contains multiple lines.");
1193b4be Poul Sander 2025-02-03 21:28 6228
        if (ImGui::BeginTable("table_share_lineheight", 2, ImGuiTableFlags_Borders))
1193b4be Poul Sander 2025-02-03 21:28 6229
        {
1193b4be Poul Sander 2025-02-03 21:28 6230
            ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6231
            ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6232
            ImGui::ColorButton("##1", ImVec4(0.13f, 0.26f, 0.40f, 1.0f), ImGuiColorEditFlags_None, ImVec2(40, 40));
1193b4be Poul Sander 2025-02-03 21:28 6233
            ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6234
            ImGui::Text("Line 1");
1193b4be Poul Sander 2025-02-03 21:28 6235
            ImGui::Text("Line 2");
1193b4be Poul Sander 2025-02-03 21:28 6236
1193b4be Poul Sander 2025-02-03 21:28 6237
            ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6238
            ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6239
            ImGui::ColorButton("##2", ImVec4(0.13f, 0.26f, 0.40f, 1.0f), ImGuiColorEditFlags_None, ImVec2(40, 40));
1193b4be Poul Sander 2025-02-03 21:28 6240
            ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6241
            ImGui::SameLine(0.0f, 0.0f); // Reuse line height from previous column
1193b4be Poul Sander 2025-02-03 21:28 6242
            ImGui::Text("Line 1, with SameLine(0,0)");
1193b4be Poul Sander 2025-02-03 21:28 6243
            ImGui::Text("Line 2");
1193b4be Poul Sander 2025-02-03 21:28 6244
1193b4be Poul Sander 2025-02-03 21:28 6245
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6246
        }
1193b4be Poul Sander 2025-02-03 21:28 6247
1193b4be Poul Sander 2025-02-03 21:28 6248
        HelpMarker("Showcase altering CellPadding.y between rows. Note that CellPadding.x is locked for the entire table.");
1193b4be Poul Sander 2025-02-03 21:28 6249
        if (ImGui::BeginTable("table_changing_cellpadding_y", 1, ImGuiTableFlags_Borders))
1193b4be Poul Sander 2025-02-03 21:28 6250
        {
1193b4be Poul Sander 2025-02-03 21:28 6251
            ImGuiStyle& style = ImGui::GetStyle();
1193b4be Poul Sander 2025-02-03 21:28 6252
            for (int row = 0; row < 8; row++)
1193b4be Poul Sander 2025-02-03 21:28 6253
            {
1193b4be Poul Sander 2025-02-03 21:28 6254
                if ((row % 3) == 2)
1193b4be Poul Sander 2025-02-03 21:28 6255
                    ImGui::PushStyleVarY(ImGuiStyleVar_CellPadding, 20.0f);
1193b4be Poul Sander 2025-02-03 21:28 6256
                ImGui::TableNextRow(ImGuiTableRowFlags_None);
1193b4be Poul Sander 2025-02-03 21:28 6257
                ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6258
                ImGui::Text("CellPadding.y = %.2f", style.CellPadding.y);
1193b4be Poul Sander 2025-02-03 21:28 6259
                if ((row % 3) == 2)
1193b4be Poul Sander 2025-02-03 21:28 6260
                    ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 6261
            }
1193b4be Poul Sander 2025-02-03 21:28 6262
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6263
        }
1193b4be Poul Sander 2025-02-03 21:28 6264
1193b4be Poul Sander 2025-02-03 21:28 6265
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6266
    }
1193b4be Poul Sander 2025-02-03 21:28 6267
1193b4be Poul Sander 2025-02-03 21:28 6268
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6269
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6270
    IMGUI_DEMO_MARKER("Tables/Outer size");
1193b4be Poul Sander 2025-02-03 21:28 6271
    if (ImGui::TreeNode("Outer size"))
1193b4be Poul Sander 2025-02-03 21:28 6272
    {
1193b4be Poul Sander 2025-02-03 21:28 6273
        // Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY
1193b4be Poul Sander 2025-02-03 21:28 6274
        // Important to that note how the two flags have slightly different behaviors!
1193b4be Poul Sander 2025-02-03 21:28 6275
        ImGui::Text("Using NoHostExtendX and NoHostExtendY:");
1193b4be Poul Sander 2025-02-03 21:28 6276
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6277
        static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX;
1193b4be Poul Sander 2025-02-03 21:28 6278
        ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
1193b4be Poul Sander 2025-02-03 21:28 6279
        ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used.");
1193b4be Poul Sander 2025-02-03 21:28 6280
        ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
1193b4be Poul Sander 2025-02-03 21:28 6281
        ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.");
1193b4be Poul Sander 2025-02-03 21:28 6282
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6283
1193b4be Poul Sander 2025-02-03 21:28 6284
        ImVec2 outer_size = ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f);
1193b4be Poul Sander 2025-02-03 21:28 6285
        if (ImGui::BeginTable("table1", 3, flags, outer_size))
1193b4be Poul Sander 2025-02-03 21:28 6286
        {
1193b4be Poul Sander 2025-02-03 21:28 6287
            for (int row = 0; row < 10; row++)
1193b4be Poul Sander 2025-02-03 21:28 6288
            {
1193b4be Poul Sander 2025-02-03 21:28 6289
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6290
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 6291
                {
1193b4be Poul Sander 2025-02-03 21:28 6292
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6293
                    ImGui::Text("Cell %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6294
                }
1193b4be Poul Sander 2025-02-03 21:28 6295
            }
1193b4be Poul Sander 2025-02-03 21:28 6296
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6297
        }
1193b4be Poul Sander 2025-02-03 21:28 6298
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 6299
        ImGui::Text("Hello!");
1193b4be Poul Sander 2025-02-03 21:28 6300
1193b4be Poul Sander 2025-02-03 21:28 6301
        ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 6302
1193b4be Poul Sander 2025-02-03 21:28 6303
        ImGui::Text("Using explicit size:");
1193b4be Poul Sander 2025-02-03 21:28 6304
        if (ImGui::BeginTable("table2", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
1193b4be Poul Sander 2025-02-03 21:28 6305
        {
1193b4be Poul Sander 2025-02-03 21:28 6306
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 6307
            {
1193b4be Poul Sander 2025-02-03 21:28 6308
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6309
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 6310
                {
1193b4be Poul Sander 2025-02-03 21:28 6311
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6312
                    ImGui::Text("Cell %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6313
                }
1193b4be Poul Sander 2025-02-03 21:28 6314
            }
1193b4be Poul Sander 2025-02-03 21:28 6315
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6316
        }
1193b4be Poul Sander 2025-02-03 21:28 6317
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 6318
        if (ImGui::BeginTable("table3", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f)))
1193b4be Poul Sander 2025-02-03 21:28 6319
        {
1193b4be Poul Sander 2025-02-03 21:28 6320
            for (int row = 0; row < 3; row++)
1193b4be Poul Sander 2025-02-03 21:28 6321
            {
1193b4be Poul Sander 2025-02-03 21:28 6322
                ImGui::TableNextRow(0, TEXT_BASE_HEIGHT * 1.5f);
1193b4be Poul Sander 2025-02-03 21:28 6323
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 6324
                {
1193b4be Poul Sander 2025-02-03 21:28 6325
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6326
                    ImGui::Text("Cell %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6327
                }
1193b4be Poul Sander 2025-02-03 21:28 6328
            }
1193b4be Poul Sander 2025-02-03 21:28 6329
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6330
        }
1193b4be Poul Sander 2025-02-03 21:28 6331
1193b4be Poul Sander 2025-02-03 21:28 6332
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6333
    }
1193b4be Poul Sander 2025-02-03 21:28 6334
1193b4be Poul Sander 2025-02-03 21:28 6335
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6336
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6337
    IMGUI_DEMO_MARKER("Tables/Background color");
1193b4be Poul Sander 2025-02-03 21:28 6338
    if (ImGui::TreeNode("Background color"))
1193b4be Poul Sander 2025-02-03 21:28 6339
    {
1193b4be Poul Sander 2025-02-03 21:28 6340
        static ImGuiTableFlags flags = ImGuiTableFlags_RowBg;
1193b4be Poul Sander 2025-02-03 21:28 6341
        static int row_bg_type = 1;
1193b4be Poul Sander 2025-02-03 21:28 6342
        static int row_bg_target = 1;
1193b4be Poul Sander 2025-02-03 21:28 6343
        static int cell_bg_type = 1;
1193b4be Poul Sander 2025-02-03 21:28 6344
1193b4be Poul Sander 2025-02-03 21:28 6345
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6346
        ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags, ImGuiTableFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 6347
        ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
1193b4be Poul Sander 2025-02-03 21:28 6348
        ImGui::SameLine(); HelpMarker("ImGuiTableFlags_RowBg automatically sets RowBg0 to alternative colors pulled from the Style.");
1193b4be Poul Sander 2025-02-03 21:28 6349
        ImGui::Combo("row bg type", (int*)&row_bg_type, "None\0Red\0Gradient\0");
1193b4be Poul Sander 2025-02-03 21:28 6350
        ImGui::Combo("row bg target", (int*)&row_bg_target, "RowBg0\0RowBg1\0"); ImGui::SameLine(); HelpMarker("Target RowBg0 to override the alternating odd/even colors,\nTarget RowBg1 to blend with them.");
1193b4be Poul Sander 2025-02-03 21:28 6351
        ImGui::Combo("cell bg type", (int*)&cell_bg_type, "None\0Blue\0"); ImGui::SameLine(); HelpMarker("We are colorizing cells to B1->C2 here.");
1193b4be Poul Sander 2025-02-03 21:28 6352
        IM_ASSERT(row_bg_type >= 0 && row_bg_type <= 2);
1193b4be Poul Sander 2025-02-03 21:28 6353
        IM_ASSERT(row_bg_target >= 0 && row_bg_target <= 1);
1193b4be Poul Sander 2025-02-03 21:28 6354
        IM_ASSERT(cell_bg_type >= 0 && cell_bg_type <= 1);
1193b4be Poul Sander 2025-02-03 21:28 6355
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6356
1193b4be Poul Sander 2025-02-03 21:28 6357
        if (ImGui::BeginTable("table1", 5, flags))
1193b4be Poul Sander 2025-02-03 21:28 6358
        {
1193b4be Poul Sander 2025-02-03 21:28 6359
            for (int row = 0; row < 6; row++)
1193b4be Poul Sander 2025-02-03 21:28 6360
            {
1193b4be Poul Sander 2025-02-03 21:28 6361
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6362
1193b4be Poul Sander 2025-02-03 21:28 6363
                // Demonstrate setting a row background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBgX, ...)'
1193b4be Poul Sander 2025-02-03 21:28 6364
                // We use a transparent color so we can see the one behind in case our target is RowBg1 and RowBg0 was already targeted by the ImGuiTableFlags_RowBg flag.
1193b4be Poul Sander 2025-02-03 21:28 6365
                if (row_bg_type != 0)
1193b4be Poul Sander 2025-02-03 21:28 6366
                {
1193b4be Poul Sander 2025-02-03 21:28 6367
                    ImU32 row_bg_color = ImGui::GetColorU32(row_bg_type == 1 ? ImVec4(0.7f, 0.3f, 0.3f, 0.65f) : ImVec4(0.2f + row * 0.1f, 0.2f, 0.2f, 0.65f)); // Flat or Gradient?
1193b4be Poul Sander 2025-02-03 21:28 6368
                    ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0 + row_bg_target, row_bg_color);
1193b4be Poul Sander 2025-02-03 21:28 6369
                }
1193b4be Poul Sander 2025-02-03 21:28 6370
1193b4be Poul Sander 2025-02-03 21:28 6371
                // Fill cells
1193b4be Poul Sander 2025-02-03 21:28 6372
                for (int column = 0; column < 5; column++)
1193b4be Poul Sander 2025-02-03 21:28 6373
                {
1193b4be Poul Sander 2025-02-03 21:28 6374
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6375
                    ImGui::Text("%c%c", 'A' + row, '0' + column);
1193b4be Poul Sander 2025-02-03 21:28 6376
1193b4be Poul Sander 2025-02-03 21:28 6377
                    // Change background of Cells B1->C2
1193b4be Poul Sander 2025-02-03 21:28 6378
                    // Demonstrate setting a cell background color with 'ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ...)'
1193b4be Poul Sander 2025-02-03 21:28 6379
                    // (the CellBg color will be blended over the RowBg and ColumnBg colors)
1193b4be Poul Sander 2025-02-03 21:28 6380
                    // We can also pass a column number as a third parameter to TableSetBgColor() and do this outside the column loop.
1193b4be Poul Sander 2025-02-03 21:28 6381
                    if (row >= 1 && row <= 2 && column >= 1 && column <= 2 && cell_bg_type == 1)
1193b4be Poul Sander 2025-02-03 21:28 6382
                    {
1193b4be Poul Sander 2025-02-03 21:28 6383
                        ImU32 cell_bg_color = ImGui::GetColorU32(ImVec4(0.3f, 0.3f, 0.7f, 0.65f));
1193b4be Poul Sander 2025-02-03 21:28 6384
                        ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, cell_bg_color);
1193b4be Poul Sander 2025-02-03 21:28 6385
                    }
1193b4be Poul Sander 2025-02-03 21:28 6386
                }
1193b4be Poul Sander 2025-02-03 21:28 6387
            }
1193b4be Poul Sander 2025-02-03 21:28 6388
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6389
        }
1193b4be Poul Sander 2025-02-03 21:28 6390
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6391
    }
1193b4be Poul Sander 2025-02-03 21:28 6392
1193b4be Poul Sander 2025-02-03 21:28 6393
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6394
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6395
    IMGUI_DEMO_MARKER("Tables/Tree view");
1193b4be Poul Sander 2025-02-03 21:28 6396
    if (ImGui::TreeNode("Tree view"))
1193b4be Poul Sander 2025-02-03 21:28 6397
    {
1193b4be Poul Sander 2025-02-03 21:28 6398
        static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
1193b4be Poul Sander 2025-02-03 21:28 6399
1193b4be Poul Sander 2025-02-03 21:28 6400
        static ImGuiTreeNodeFlags tree_node_flags = ImGuiTreeNodeFlags_SpanAllColumns;
1193b4be Poul Sander 2025-02-03 21:28 6401
        ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanFullWidth",  &tree_node_flags, ImGuiTreeNodeFlags_SpanFullWidth);
1193b4be Poul Sander 2025-02-03 21:28 6402
        ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanTextWidth",  &tree_node_flags, ImGuiTreeNodeFlags_SpanTextWidth);
1193b4be Poul Sander 2025-02-03 21:28 6403
        ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAllColumns", &tree_node_flags, ImGuiTreeNodeFlags_SpanAllColumns);
1193b4be Poul Sander 2025-02-03 21:28 6404
1193b4be Poul Sander 2025-02-03 21:28 6405
        HelpMarker("See \"Columns flags\" section to configure how indentation is applied to individual columns.");
1193b4be Poul Sander 2025-02-03 21:28 6406
        if (ImGui::BeginTable("3ways", 3, flags))
1193b4be Poul Sander 2025-02-03 21:28 6407
        {
1193b4be Poul Sander 2025-02-03 21:28 6408
            // The first column will use the default _WidthStretch when ScrollX is Off and _WidthFixed when ScrollX is On
1193b4be Poul Sander 2025-02-03 21:28 6409
            ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide);
1193b4be Poul Sander 2025-02-03 21:28 6410
            ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f);
1193b4be Poul Sander 2025-02-03 21:28 6411
            ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 18.0f);
1193b4be Poul Sander 2025-02-03 21:28 6412
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6413
1193b4be Poul Sander 2025-02-03 21:28 6414
            // Simple storage to output a dummy file-system.
1193b4be Poul Sander 2025-02-03 21:28 6415
            struct MyTreeNode
1193b4be Poul Sander 2025-02-03 21:28 6416
            {
1193b4be Poul Sander 2025-02-03 21:28 6417
                const char*     Name;
1193b4be Poul Sander 2025-02-03 21:28 6418
                const char*     Type;
1193b4be Poul Sander 2025-02-03 21:28 6419
                int             Size;
1193b4be Poul Sander 2025-02-03 21:28 6420
                int             ChildIdx;
1193b4be Poul Sander 2025-02-03 21:28 6421
                int             ChildCount;
1193b4be Poul Sander 2025-02-03 21:28 6422
                static void DisplayNode(const MyTreeNode* node, const MyTreeNode* all_nodes)
1193b4be Poul Sander 2025-02-03 21:28 6423
                {
1193b4be Poul Sander 2025-02-03 21:28 6424
                    ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6425
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6426
                    const bool is_folder = (node->ChildCount > 0);
1193b4be Poul Sander 2025-02-03 21:28 6427
                    if (is_folder)
1193b4be Poul Sander 2025-02-03 21:28 6428
                    {
1193b4be Poul Sander 2025-02-03 21:28 6429
                        bool open = ImGui::TreeNodeEx(node->Name, tree_node_flags);
1193b4be Poul Sander 2025-02-03 21:28 6430
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6431
                        ImGui::TextDisabled("--");
1193b4be Poul Sander 2025-02-03 21:28 6432
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6433
                        ImGui::TextUnformatted(node->Type);
1193b4be Poul Sander 2025-02-03 21:28 6434
                        if (open)
1193b4be Poul Sander 2025-02-03 21:28 6435
                        {
1193b4be Poul Sander 2025-02-03 21:28 6436
                            for (int child_n = 0; child_n < node->ChildCount; child_n++)
1193b4be Poul Sander 2025-02-03 21:28 6437
                                DisplayNode(&all_nodes[node->ChildIdx + child_n], all_nodes);
1193b4be Poul Sander 2025-02-03 21:28 6438
                            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6439
                        }
1193b4be Poul Sander 2025-02-03 21:28 6440
                    }
1193b4be Poul Sander 2025-02-03 21:28 6441
                    else
1193b4be Poul Sander 2025-02-03 21:28 6442
                    {
1193b4be Poul Sander 2025-02-03 21:28 6443
                        ImGui::TreeNodeEx(node->Name, tree_node_flags | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet | ImGuiTreeNodeFlags_NoTreePushOnOpen);
1193b4be Poul Sander 2025-02-03 21:28 6444
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6445
                        ImGui::Text("%d", node->Size);
1193b4be Poul Sander 2025-02-03 21:28 6446
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6447
                        ImGui::TextUnformatted(node->Type);
1193b4be Poul Sander 2025-02-03 21:28 6448
                    }
1193b4be Poul Sander 2025-02-03 21:28 6449
                }
1193b4be Poul Sander 2025-02-03 21:28 6450
            };
1193b4be Poul Sander 2025-02-03 21:28 6451
            static const MyTreeNode nodes[] =
1193b4be Poul Sander 2025-02-03 21:28 6452
            {
1193b4be Poul Sander 2025-02-03 21:28 6453
                { "Root",                         "Folder",       -1,       1, 3    }, // 0
1193b4be Poul Sander 2025-02-03 21:28 6454
                { "Music",                        "Folder",       -1,       4, 2    }, // 1
1193b4be Poul Sander 2025-02-03 21:28 6455
                { "Textures",                     "Folder",       -1,       6, 3    }, // 2
1193b4be Poul Sander 2025-02-03 21:28 6456
                { "desktop.ini",                  "System file",  1024,    -1,-1    }, // 3
1193b4be Poul Sander 2025-02-03 21:28 6457
                { "File1_a.wav",                  "Audio file",   123000,  -1,-1    }, // 4
1193b4be Poul Sander 2025-02-03 21:28 6458
                { "File1_b.wav",                  "Audio file",   456000,  -1,-1    }, // 5
1193b4be Poul Sander 2025-02-03 21:28 6459
                { "Image001.png",                 "Image file",   203128,  -1,-1    }, // 6
1193b4be Poul Sander 2025-02-03 21:28 6460
                { "Copy of Image001.png",         "Image file",   203256,  -1,-1    }, // 7
1193b4be Poul Sander 2025-02-03 21:28 6461
                { "Copy of Image001 (Final2).png","Image file",   203512,  -1,-1    }, // 8
1193b4be Poul Sander 2025-02-03 21:28 6462
            };
1193b4be Poul Sander 2025-02-03 21:28 6463
1193b4be Poul Sander 2025-02-03 21:28 6464
            MyTreeNode::DisplayNode(&nodes[0], nodes);
1193b4be Poul Sander 2025-02-03 21:28 6465
1193b4be Poul Sander 2025-02-03 21:28 6466
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6467
        }
1193b4be Poul Sander 2025-02-03 21:28 6468
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6469
    }
1193b4be Poul Sander 2025-02-03 21:28 6470
1193b4be Poul Sander 2025-02-03 21:28 6471
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6472
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6473
    IMGUI_DEMO_MARKER("Tables/Item width");
1193b4be Poul Sander 2025-02-03 21:28 6474
    if (ImGui::TreeNode("Item width"))
1193b4be Poul Sander 2025-02-03 21:28 6475
    {
1193b4be Poul Sander 2025-02-03 21:28 6476
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 6477
            "Showcase using PushItemWidth() and how it is preserved on a per-column basis.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 6478
            "Note that on auto-resizing non-resizable fixed columns, querying the content width for "
1193b4be Poul Sander 2025-02-03 21:28 6479
            "e.g. right-alignment doesn't make sense.");
1193b4be Poul Sander 2025-02-03 21:28 6480
        if (ImGui::BeginTable("table_item_width", 3, ImGuiTableFlags_Borders))
1193b4be Poul Sander 2025-02-03 21:28 6481
        {
1193b4be Poul Sander 2025-02-03 21:28 6482
            ImGui::TableSetupColumn("small");
1193b4be Poul Sander 2025-02-03 21:28 6483
            ImGui::TableSetupColumn("half");
1193b4be Poul Sander 2025-02-03 21:28 6484
            ImGui::TableSetupColumn("right-align");
1193b4be Poul Sander 2025-02-03 21:28 6485
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6486
1193b4be Poul Sander 2025-02-03 21:28 6487
            for (int row = 0; row < 3; row++)
1193b4be Poul Sander 2025-02-03 21:28 6488
            {
1193b4be Poul Sander 2025-02-03 21:28 6489
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6490
                if (row == 0)
1193b4be Poul Sander 2025-02-03 21:28 6491
                {
1193b4be Poul Sander 2025-02-03 21:28 6492
                    // Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient)
1193b4be Poul Sander 2025-02-03 21:28 6493
                    ImGui::TableSetColumnIndex(0);
1193b4be Poul Sander 2025-02-03 21:28 6494
                    ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small
1193b4be Poul Sander 2025-02-03 21:28 6495
                    ImGui::TableSetColumnIndex(1);
1193b4be Poul Sander 2025-02-03 21:28 6496
                    ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 6497
                    ImGui::TableSetColumnIndex(2);
1193b4be Poul Sander 2025-02-03 21:28 6498
                    ImGui::PushItemWidth(-FLT_MIN); // Right-aligned
1193b4be Poul Sander 2025-02-03 21:28 6499
                }
1193b4be Poul Sander 2025-02-03 21:28 6500
1193b4be Poul Sander 2025-02-03 21:28 6501
                // Draw our contents
1193b4be Poul Sander 2025-02-03 21:28 6502
                static float dummy_f = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 6503
                ImGui::PushID(row);
1193b4be Poul Sander 2025-02-03 21:28 6504
                ImGui::TableSetColumnIndex(0);
1193b4be Poul Sander 2025-02-03 21:28 6505
                ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 6506
                ImGui::TableSetColumnIndex(1);
1193b4be Poul Sander 2025-02-03 21:28 6507
                ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 6508
                ImGui::TableSetColumnIndex(2);
1193b4be Poul Sander 2025-02-03 21:28 6509
                ImGui::SliderFloat("##float2", &dummy_f, 0.0f, 1.0f); // No visible label since right-aligned
1193b4be Poul Sander 2025-02-03 21:28 6510
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6511
            }
1193b4be Poul Sander 2025-02-03 21:28 6512
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6513
        }
1193b4be Poul Sander 2025-02-03 21:28 6514
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6515
    }
1193b4be Poul Sander 2025-02-03 21:28 6516
1193b4be Poul Sander 2025-02-03 21:28 6517
    // Demonstrate using TableHeader() calls instead of TableHeadersRow()
1193b4be Poul Sander 2025-02-03 21:28 6518
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6519
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6520
    IMGUI_DEMO_MARKER("Tables/Custom headers");
1193b4be Poul Sander 2025-02-03 21:28 6521
    if (ImGui::TreeNode("Custom headers"))
1193b4be Poul Sander 2025-02-03 21:28 6522
    {
1193b4be Poul Sander 2025-02-03 21:28 6523
        const int COLUMNS_COUNT = 3;
1193b4be Poul Sander 2025-02-03 21:28 6524
        if (ImGui::BeginTable("table_custom_headers", COLUMNS_COUNT, ImGuiTableFlags_Borders | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
1193b4be Poul Sander 2025-02-03 21:28 6525
        {
1193b4be Poul Sander 2025-02-03 21:28 6526
            ImGui::TableSetupColumn("Apricot");
1193b4be Poul Sander 2025-02-03 21:28 6527
            ImGui::TableSetupColumn("Banana");
1193b4be Poul Sander 2025-02-03 21:28 6528
            ImGui::TableSetupColumn("Cherry");
1193b4be Poul Sander 2025-02-03 21:28 6529
1193b4be Poul Sander 2025-02-03 21:28 6530
            // Dummy entire-column selection storage
1193b4be Poul Sander 2025-02-03 21:28 6531
            // FIXME: It would be nice to actually demonstrate full-featured selection using those checkbox.
1193b4be Poul Sander 2025-02-03 21:28 6532
            static bool column_selected[3] = {};
1193b4be Poul Sander 2025-02-03 21:28 6533
1193b4be Poul Sander 2025-02-03 21:28 6534
            // Instead of calling TableHeadersRow() we'll submit custom headers ourselves.
1193b4be Poul Sander 2025-02-03 21:28 6535
            // (A different approach is also possible:
1193b4be Poul Sander 2025-02-03 21:28 6536
            //    - Specify ImGuiTableColumnFlags_NoHeaderLabel in some TableSetupColumn() call.
1193b4be Poul Sander 2025-02-03 21:28 6537
            //    - Call TableHeadersRow() normally. This will submit TableHeader() with no name.
1193b4be Poul Sander 2025-02-03 21:28 6538
            //    - Then call TableSetColumnIndex() to position yourself in the column and submit your stuff e.g. Checkbox().)
1193b4be Poul Sander 2025-02-03 21:28 6539
            ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
1193b4be Poul Sander 2025-02-03 21:28 6540
            for (int column = 0; column < COLUMNS_COUNT; column++)
1193b4be Poul Sander 2025-02-03 21:28 6541
            {
1193b4be Poul Sander 2025-02-03 21:28 6542
                ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6543
                const char* column_name = ImGui::TableGetColumnName(column); // Retrieve name passed to TableSetupColumn()
1193b4be Poul Sander 2025-02-03 21:28 6544
                ImGui::PushID(column);
1193b4be Poul Sander 2025-02-03 21:28 6545
                ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
1193b4be Poul Sander 2025-02-03 21:28 6546
                ImGui::Checkbox("##checkall", &column_selected[column]);
1193b4be Poul Sander 2025-02-03 21:28 6547
                ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 6548
                ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 6549
                ImGui::TableHeader(column_name);
1193b4be Poul Sander 2025-02-03 21:28 6550
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6551
            }
1193b4be Poul Sander 2025-02-03 21:28 6552
1193b4be Poul Sander 2025-02-03 21:28 6553
            // Submit table contents
1193b4be Poul Sander 2025-02-03 21:28 6554
            for (int row = 0; row < 5; row++)
1193b4be Poul Sander 2025-02-03 21:28 6555
            {
1193b4be Poul Sander 2025-02-03 21:28 6556
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6557
                for (int column = 0; column < 3; column++)
1193b4be Poul Sander 2025-02-03 21:28 6558
                {
1193b4be Poul Sander 2025-02-03 21:28 6559
                    char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 6560
                    sprintf(buf, "Cell %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6561
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6562
                    ImGui::Selectable(buf, column_selected[column]);
1193b4be Poul Sander 2025-02-03 21:28 6563
                }
1193b4be Poul Sander 2025-02-03 21:28 6564
            }
1193b4be Poul Sander 2025-02-03 21:28 6565
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6566
        }
1193b4be Poul Sander 2025-02-03 21:28 6567
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6568
    }
1193b4be Poul Sander 2025-02-03 21:28 6569
1193b4be Poul Sander 2025-02-03 21:28 6570
    // Demonstrate using ImGuiTableColumnFlags_AngledHeader flag to create angled headers
1193b4be Poul Sander 2025-02-03 21:28 6571
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6572
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6573
    IMGUI_DEMO_MARKER("Tables/Angled headers");
1193b4be Poul Sander 2025-02-03 21:28 6574
    if (ImGui::TreeNode("Angled headers"))
1193b4be Poul Sander 2025-02-03 21:28 6575
    {
1193b4be Poul Sander 2025-02-03 21:28 6576
        const char* column_names[] = { "Track", "cabasa", "ride", "smash", "tom-hi", "tom-mid", "tom-low", "hihat-o", "hihat-c", "snare-s", "snare-c", "clap", "rim", "kick" };
1193b4be Poul Sander 2025-02-03 21:28 6577
        const int columns_count = IM_ARRAYSIZE(column_names);
1193b4be Poul Sander 2025-02-03 21:28 6578
        const int rows_count = 12;
1193b4be Poul Sander 2025-02-03 21:28 6579
1193b4be Poul Sander 2025-02-03 21:28 6580
        static ImGuiTableFlags table_flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersInnerH | ImGuiTableFlags_Hideable | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_HighlightHoveredColumn;
1193b4be Poul Sander 2025-02-03 21:28 6581
        static ImGuiTableColumnFlags column_flags = ImGuiTableColumnFlags_AngledHeader | ImGuiTableColumnFlags_WidthFixed;
1193b4be Poul Sander 2025-02-03 21:28 6582
        static bool bools[columns_count * rows_count] = {}; // Dummy storage selection storage
1193b4be Poul Sander 2025-02-03 21:28 6583
        static int frozen_cols = 1;
1193b4be Poul Sander 2025-02-03 21:28 6584
        static int frozen_rows = 2;
1193b4be Poul Sander 2025-02-03 21:28 6585
        ImGui::CheckboxFlags("_ScrollX", &table_flags, ImGuiTableFlags_ScrollX);
1193b4be Poul Sander 2025-02-03 21:28 6586
        ImGui::CheckboxFlags("_ScrollY", &table_flags, ImGuiTableFlags_ScrollY);
1193b4be Poul Sander 2025-02-03 21:28 6587
        ImGui::CheckboxFlags("_Resizable", &table_flags, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 6588
        ImGui::CheckboxFlags("_Sortable", &table_flags, ImGuiTableFlags_Sortable);
1193b4be Poul Sander 2025-02-03 21:28 6589
        ImGui::CheckboxFlags("_NoBordersInBody", &table_flags, ImGuiTableFlags_NoBordersInBody);
1193b4be Poul Sander 2025-02-03 21:28 6590
        ImGui::CheckboxFlags("_HighlightHoveredColumn", &table_flags, ImGuiTableFlags_HighlightHoveredColumn);
1193b4be Poul Sander 2025-02-03 21:28 6591
        ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 6592
        ImGui::SliderInt("Frozen columns", &frozen_cols, 0, 2);
1193b4be Poul Sander 2025-02-03 21:28 6593
        ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 6594
        ImGui::SliderInt("Frozen rows", &frozen_rows, 0, 2);
1193b4be Poul Sander 2025-02-03 21:28 6595
        ImGui::CheckboxFlags("Disable header contributing to column width", &column_flags, ImGuiTableColumnFlags_NoHeaderWidth);
1193b4be Poul Sander 2025-02-03 21:28 6596
1193b4be Poul Sander 2025-02-03 21:28 6597
        if (ImGui::TreeNode("Style settings"))
1193b4be Poul Sander 2025-02-03 21:28 6598
        {
1193b4be Poul Sander 2025-02-03 21:28 6599
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 6600
            HelpMarker("Giving access to some ImGuiStyle value in this demo for convenience.");
1193b4be Poul Sander 2025-02-03 21:28 6601
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 6602
            ImGui::SliderAngle("style.TableAngledHeadersAngle", &ImGui::GetStyle().TableAngledHeadersAngle, -50.0f, +50.0f);
1193b4be Poul Sander 2025-02-03 21:28 6603
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 6604
            ImGui::SliderFloat2("style.TableAngledHeadersTextAlign", (float*)&ImGui::GetStyle().TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
1193b4be Poul Sander 2025-02-03 21:28 6605
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6606
        }
1193b4be Poul Sander 2025-02-03 21:28 6607
1193b4be Poul Sander 2025-02-03 21:28 6608
        if (ImGui::BeginTable("table_angled_headers", columns_count, table_flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 12)))
1193b4be Poul Sander 2025-02-03 21:28 6609
        {
1193b4be Poul Sander 2025-02-03 21:28 6610
            ImGui::TableSetupColumn(column_names[0], ImGuiTableColumnFlags_NoHide | ImGuiTableColumnFlags_NoReorder);
1193b4be Poul Sander 2025-02-03 21:28 6611
            for (int n = 1; n < columns_count; n++)
1193b4be Poul Sander 2025-02-03 21:28 6612
                ImGui::TableSetupColumn(column_names[n], column_flags);
1193b4be Poul Sander 2025-02-03 21:28 6613
            ImGui::TableSetupScrollFreeze(frozen_cols, frozen_rows);
1193b4be Poul Sander 2025-02-03 21:28 6614
1193b4be Poul Sander 2025-02-03 21:28 6615
            ImGui::TableAngledHeadersRow(); // Draw angled headers for all columns with the ImGuiTableColumnFlags_AngledHeader flag.
1193b4be Poul Sander 2025-02-03 21:28 6616
            ImGui::TableHeadersRow();       // Draw remaining headers and allow access to context-menu and other functions.
1193b4be Poul Sander 2025-02-03 21:28 6617
            for (int row = 0; row < rows_count; row++)
1193b4be Poul Sander 2025-02-03 21:28 6618
            {
1193b4be Poul Sander 2025-02-03 21:28 6619
                ImGui::PushID(row);
1193b4be Poul Sander 2025-02-03 21:28 6620
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6621
                ImGui::TableSetColumnIndex(0);
1193b4be Poul Sander 2025-02-03 21:28 6622
                ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 6623
                ImGui::Text("Track %d", row);
1193b4be Poul Sander 2025-02-03 21:28 6624
                for (int column = 1; column < columns_count; column++)
1193b4be Poul Sander 2025-02-03 21:28 6625
                    if (ImGui::TableSetColumnIndex(column))
1193b4be Poul Sander 2025-02-03 21:28 6626
                    {
1193b4be Poul Sander 2025-02-03 21:28 6627
                        ImGui::PushID(column);
1193b4be Poul Sander 2025-02-03 21:28 6628
                        ImGui::Checkbox("", &bools[row * columns_count + column]);
1193b4be Poul Sander 2025-02-03 21:28 6629
                        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6630
                    }
1193b4be Poul Sander 2025-02-03 21:28 6631
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6632
            }
1193b4be Poul Sander 2025-02-03 21:28 6633
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6634
        }
1193b4be Poul Sander 2025-02-03 21:28 6635
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6636
    }
1193b4be Poul Sander 2025-02-03 21:28 6637
1193b4be Poul Sander 2025-02-03 21:28 6638
    // Demonstrate creating custom context menus inside columns,
1193b4be Poul Sander 2025-02-03 21:28 6639
    // while playing it nice with context menus provided by TableHeadersRow()/TableHeader()
1193b4be Poul Sander 2025-02-03 21:28 6640
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6641
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6642
    IMGUI_DEMO_MARKER("Tables/Context menus");
1193b4be Poul Sander 2025-02-03 21:28 6643
    if (ImGui::TreeNode("Context menus"))
1193b4be Poul Sander 2025-02-03 21:28 6644
    {
1193b4be Poul Sander 2025-02-03 21:28 6645
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 6646
            "By default, right-clicking over a TableHeadersRow()/TableHeader() line will open the default context-menu.\n"
1193b4be Poul Sander 2025-02-03 21:28 6647
            "Using ImGuiTableFlags_ContextMenuInBody we also allow right-clicking over columns body.");
1193b4be Poul Sander 2025-02-03 21:28 6648
        static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody;
1193b4be Poul Sander 2025-02-03 21:28 6649
1193b4be Poul Sander 2025-02-03 21:28 6650
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6651
        ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags1, ImGuiTableFlags_ContextMenuInBody);
1193b4be Poul Sander 2025-02-03 21:28 6652
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6653
1193b4be Poul Sander 2025-02-03 21:28 6654
        // Context Menus: first example
1193b4be Poul Sander 2025-02-03 21:28 6655
        // [1.1] Right-click on the TableHeadersRow() line to open the default table context menu.
1193b4be Poul Sander 2025-02-03 21:28 6656
        // [1.2] Right-click in columns also open the default table context menu (if ImGuiTableFlags_ContextMenuInBody is set)
1193b4be Poul Sander 2025-02-03 21:28 6657
        const int COLUMNS_COUNT = 3;
1193b4be Poul Sander 2025-02-03 21:28 6658
        if (ImGui::BeginTable("table_context_menu", COLUMNS_COUNT, flags1))
1193b4be Poul Sander 2025-02-03 21:28 6659
        {
1193b4be Poul Sander 2025-02-03 21:28 6660
            ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 6661
            ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 6662
            ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 6663
1193b4be Poul Sander 2025-02-03 21:28 6664
            // [1.1]] Right-click on the TableHeadersRow() line to open the default table context menu.
1193b4be Poul Sander 2025-02-03 21:28 6665
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6666
1193b4be Poul Sander 2025-02-03 21:28 6667
            // Submit dummy contents
1193b4be Poul Sander 2025-02-03 21:28 6668
            for (int row = 0; row < 4; row++)
1193b4be Poul Sander 2025-02-03 21:28 6669
            {
1193b4be Poul Sander 2025-02-03 21:28 6670
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6671
                for (int column = 0; column < COLUMNS_COUNT; column++)
1193b4be Poul Sander 2025-02-03 21:28 6672
                {
1193b4be Poul Sander 2025-02-03 21:28 6673
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6674
                    ImGui::Text("Cell %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6675
                }
1193b4be Poul Sander 2025-02-03 21:28 6676
            }
1193b4be Poul Sander 2025-02-03 21:28 6677
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6678
        }
1193b4be Poul Sander 2025-02-03 21:28 6679
1193b4be Poul Sander 2025-02-03 21:28 6680
        // Context Menus: second example
1193b4be Poul Sander 2025-02-03 21:28 6681
        // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
1193b4be Poul Sander 2025-02-03 21:28 6682
        // [2.2] Right-click on the ".." to open a custom popup
1193b4be Poul Sander 2025-02-03 21:28 6683
        // [2.3] Right-click in columns to open another custom popup
1193b4be Poul Sander 2025-02-03 21:28 6684
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 6685
            "Demonstrate mixing table context menu (over header), item context button (over button) "
1193b4be Poul Sander 2025-02-03 21:28 6686
            "and custom per-colunm context menu (over column body).");
1193b4be Poul Sander 2025-02-03 21:28 6687
        ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders;
1193b4be Poul Sander 2025-02-03 21:28 6688
        if (ImGui::BeginTable("table_context_menu_2", COLUMNS_COUNT, flags2))
1193b4be Poul Sander 2025-02-03 21:28 6689
        {
1193b4be Poul Sander 2025-02-03 21:28 6690
            ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 6691
            ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 6692
            ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 6693
1193b4be Poul Sander 2025-02-03 21:28 6694
            // [2.1] Right-click on the TableHeadersRow() line to open the default table context menu.
1193b4be Poul Sander 2025-02-03 21:28 6695
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6696
            for (int row = 0; row < 4; row++)
1193b4be Poul Sander 2025-02-03 21:28 6697
            {
1193b4be Poul Sander 2025-02-03 21:28 6698
                ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6699
                for (int column = 0; column < COLUMNS_COUNT; column++)
1193b4be Poul Sander 2025-02-03 21:28 6700
                {
1193b4be Poul Sander 2025-02-03 21:28 6701
                    // Submit dummy contents
1193b4be Poul Sander 2025-02-03 21:28 6702
                    ImGui::TableSetColumnIndex(column);
1193b4be Poul Sander 2025-02-03 21:28 6703
                    ImGui::Text("Cell %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6704
                    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 6705
1193b4be Poul Sander 2025-02-03 21:28 6706
                    // [2.2] Right-click on the ".." to open a custom popup
1193b4be Poul Sander 2025-02-03 21:28 6707
                    ImGui::PushID(row * COLUMNS_COUNT + column);
1193b4be Poul Sander 2025-02-03 21:28 6708
                    ImGui::SmallButton("..");
1193b4be Poul Sander 2025-02-03 21:28 6709
                    if (ImGui::BeginPopupContextItem())
1193b4be Poul Sander 2025-02-03 21:28 6710
                    {
1193b4be Poul Sander 2025-02-03 21:28 6711
                        ImGui::Text("This is the popup for Button(\"..\") in Cell %d,%d", column, row);
1193b4be Poul Sander 2025-02-03 21:28 6712
                        if (ImGui::Button("Close"))
1193b4be Poul Sander 2025-02-03 21:28 6713
                            ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 6714
                        ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 6715
                    }
1193b4be Poul Sander 2025-02-03 21:28 6716
                    ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6717
                }
1193b4be Poul Sander 2025-02-03 21:28 6718
            }
1193b4be Poul Sander 2025-02-03 21:28 6719
1193b4be Poul Sander 2025-02-03 21:28 6720
            // [2.3] Right-click anywhere in columns to open another custom popup
1193b4be Poul Sander 2025-02-03 21:28 6721
            // (instead of testing for !IsAnyItemHovered() we could also call OpenPopup() with ImGuiPopupFlags_NoOpenOverExistingPopup
1193b4be Poul Sander 2025-02-03 21:28 6722
            // to manage popup priority as the popups triggers, here "are we hovering a column" are overlapping)
1193b4be Poul Sander 2025-02-03 21:28 6723
            int hovered_column = -1;
1193b4be Poul Sander 2025-02-03 21:28 6724
            for (int column = 0; column < COLUMNS_COUNT + 1; column++)
1193b4be Poul Sander 2025-02-03 21:28 6725
            {
1193b4be Poul Sander 2025-02-03 21:28 6726
                ImGui::PushID(column);
1193b4be Poul Sander 2025-02-03 21:28 6727
                if (ImGui::TableGetColumnFlags(column) & ImGuiTableColumnFlags_IsHovered)
1193b4be Poul Sander 2025-02-03 21:28 6728
                    hovered_column = column;
1193b4be Poul Sander 2025-02-03 21:28 6729
                if (hovered_column == column && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(1))
1193b4be Poul Sander 2025-02-03 21:28 6730
                    ImGui::OpenPopup("MyPopup");
1193b4be Poul Sander 2025-02-03 21:28 6731
                if (ImGui::BeginPopup("MyPopup"))
1193b4be Poul Sander 2025-02-03 21:28 6732
                {
1193b4be Poul Sander 2025-02-03 21:28 6733
                    if (column == COLUMNS_COUNT)
1193b4be Poul Sander 2025-02-03 21:28 6734
                        ImGui::Text("This is a custom popup for unused space after the last column.");
1193b4be Poul Sander 2025-02-03 21:28 6735
                    else
1193b4be Poul Sander 2025-02-03 21:28 6736
                        ImGui::Text("This is a custom popup for Column %d", column);
1193b4be Poul Sander 2025-02-03 21:28 6737
                    if (ImGui::Button("Close"))
1193b4be Poul Sander 2025-02-03 21:28 6738
                        ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 6739
                    ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 6740
                }
1193b4be Poul Sander 2025-02-03 21:28 6741
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6742
            }
1193b4be Poul Sander 2025-02-03 21:28 6743
1193b4be Poul Sander 2025-02-03 21:28 6744
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6745
            ImGui::Text("Hovered column: %d", hovered_column);
1193b4be Poul Sander 2025-02-03 21:28 6746
        }
1193b4be Poul Sander 2025-02-03 21:28 6747
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6748
    }
1193b4be Poul Sander 2025-02-03 21:28 6749
1193b4be Poul Sander 2025-02-03 21:28 6750
    // Demonstrate creating multiple tables with the same ID
1193b4be Poul Sander 2025-02-03 21:28 6751
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6752
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6753
    IMGUI_DEMO_MARKER("Tables/Synced instances");
1193b4be Poul Sander 2025-02-03 21:28 6754
    if (ImGui::TreeNode("Synced instances"))
1193b4be Poul Sander 2025-02-03 21:28 6755
    {
1193b4be Poul Sander 2025-02-03 21:28 6756
        HelpMarker("Multiple tables with the same identifier will share their settings, width, visibility, order etc.");
1193b4be Poul Sander 2025-02-03 21:28 6757
1193b4be Poul Sander 2025-02-03 21:28 6758
        static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoSavedSettings;
1193b4be Poul Sander 2025-02-03 21:28 6759
        ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 6760
        ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
1193b4be Poul Sander 2025-02-03 21:28 6761
        ImGui::CheckboxFlags("ImGuiTableFlags_SizingFixedFit", &flags, ImGuiTableFlags_SizingFixedFit);
1193b4be Poul Sander 2025-02-03 21:28 6762
        ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn);
1193b4be Poul Sander 2025-02-03 21:28 6763
        for (int n = 0; n < 3; n++)
1193b4be Poul Sander 2025-02-03 21:28 6764
        {
1193b4be Poul Sander 2025-02-03 21:28 6765
            char buf[32];
1193b4be Poul Sander 2025-02-03 21:28 6766
            sprintf(buf, "Synced Table %d", n);
1193b4be Poul Sander 2025-02-03 21:28 6767
            bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen);
1193b4be Poul Sander 2025-02-03 21:28 6768
            if (open && ImGui::BeginTable("Table", 3, flags, ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 5)))
1193b4be Poul Sander 2025-02-03 21:28 6769
            {
1193b4be Poul Sander 2025-02-03 21:28 6770
                ImGui::TableSetupColumn("One");
1193b4be Poul Sander 2025-02-03 21:28 6771
                ImGui::TableSetupColumn("Two");
1193b4be Poul Sander 2025-02-03 21:28 6772
                ImGui::TableSetupColumn("Three");
1193b4be Poul Sander 2025-02-03 21:28 6773
                ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6774
                const int cell_count = (n == 1) ? 27 : 9; // Make second table have a scrollbar to verify that additional decoration is not affecting column positions.
1193b4be Poul Sander 2025-02-03 21:28 6775
                for (int cell = 0; cell < cell_count; cell++)
1193b4be Poul Sander 2025-02-03 21:28 6776
                {
1193b4be Poul Sander 2025-02-03 21:28 6777
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6778
                    ImGui::Text("this cell %d", cell);
1193b4be Poul Sander 2025-02-03 21:28 6779
                }
1193b4be Poul Sander 2025-02-03 21:28 6780
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6781
            }
1193b4be Poul Sander 2025-02-03 21:28 6782
        }
1193b4be Poul Sander 2025-02-03 21:28 6783
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6784
    }
1193b4be Poul Sander 2025-02-03 21:28 6785
1193b4be Poul Sander 2025-02-03 21:28 6786
    // Demonstrate using Sorting facilities
1193b4be Poul Sander 2025-02-03 21:28 6787
    // This is a simplified version of the "Advanced" example, where we mostly focus on the code necessary to handle sorting.
1193b4be Poul Sander 2025-02-03 21:28 6788
    // Note that the "Advanced" example also showcase manually triggering a sort (e.g. if item quantities have been modified)
1193b4be Poul Sander 2025-02-03 21:28 6789
    static const char* template_items_names[] =
1193b4be Poul Sander 2025-02-03 21:28 6790
    {
1193b4be Poul Sander 2025-02-03 21:28 6791
        "Banana", "Apple", "Cherry", "Watermelon", "Grapefruit", "Strawberry", "Mango",
1193b4be Poul Sander 2025-02-03 21:28 6792
        "Kiwi", "Orange", "Pineapple", "Blueberry", "Plum", "Coconut", "Pear", "Apricot"
1193b4be Poul Sander 2025-02-03 21:28 6793
    };
1193b4be Poul Sander 2025-02-03 21:28 6794
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6795
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6796
    IMGUI_DEMO_MARKER("Tables/Sorting");
1193b4be Poul Sander 2025-02-03 21:28 6797
    if (ImGui::TreeNode("Sorting"))
1193b4be Poul Sander 2025-02-03 21:28 6798
    {
1193b4be Poul Sander 2025-02-03 21:28 6799
        // Create item list
1193b4be Poul Sander 2025-02-03 21:28 6800
        static ImVector<MyItem> items;
1193b4be Poul Sander 2025-02-03 21:28 6801
        if (items.Size == 0)
1193b4be Poul Sander 2025-02-03 21:28 6802
        {
1193b4be Poul Sander 2025-02-03 21:28 6803
            items.resize(50, MyItem());
1193b4be Poul Sander 2025-02-03 21:28 6804
            for (int n = 0; n < items.Size; n++)
1193b4be Poul Sander 2025-02-03 21:28 6805
            {
1193b4be Poul Sander 2025-02-03 21:28 6806
                const int template_n = n % IM_ARRAYSIZE(template_items_names);
1193b4be Poul Sander 2025-02-03 21:28 6807
                MyItem& item = items[n];
1193b4be Poul Sander 2025-02-03 21:28 6808
                item.ID = n;
1193b4be Poul Sander 2025-02-03 21:28 6809
                item.Name = template_items_names[template_n];
1193b4be Poul Sander 2025-02-03 21:28 6810
                item.Quantity = (n * n - n) % 20; // Assign default quantities
1193b4be Poul Sander 2025-02-03 21:28 6811
            }
1193b4be Poul Sander 2025-02-03 21:28 6812
        }
1193b4be Poul Sander 2025-02-03 21:28 6813
1193b4be Poul Sander 2025-02-03 21:28 6814
        // Options
1193b4be Poul Sander 2025-02-03 21:28 6815
        static ImGuiTableFlags flags =
1193b4be Poul Sander 2025-02-03 21:28 6816
            ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
1193b4be Poul Sander 2025-02-03 21:28 6817
            | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody
1193b4be Poul Sander 2025-02-03 21:28 6818
            | ImGuiTableFlags_ScrollY;
1193b4be Poul Sander 2025-02-03 21:28 6819
        PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6820
        ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
1193b4be Poul Sander 2025-02-03 21:28 6821
        ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
1193b4be Poul Sander 2025-02-03 21:28 6822
        ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
1193b4be Poul Sander 2025-02-03 21:28 6823
        ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
1193b4be Poul Sander 2025-02-03 21:28 6824
        PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6825
1193b4be Poul Sander 2025-02-03 21:28 6826
        if (ImGui::BeginTable("table_sorting", 4, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 15), 0.0f))
1193b4be Poul Sander 2025-02-03 21:28 6827
        {
1193b4be Poul Sander 2025-02-03 21:28 6828
            // Declare columns
1193b4be Poul Sander 2025-02-03 21:28 6829
            // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
1193b4be Poul Sander 2025-02-03 21:28 6830
            // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
1193b4be Poul Sander 2025-02-03 21:28 6831
            // Demonstrate using a mixture of flags among available sort-related flags:
1193b4be Poul Sander 2025-02-03 21:28 6832
            // - ImGuiTableColumnFlags_DefaultSort
1193b4be Poul Sander 2025-02-03 21:28 6833
            // - ImGuiTableColumnFlags_NoSort / ImGuiTableColumnFlags_NoSortAscending / ImGuiTableColumnFlags_NoSortDescending
1193b4be Poul Sander 2025-02-03 21:28 6834
            // - ImGuiTableColumnFlags_PreferSortAscending / ImGuiTableColumnFlags_PreferSortDescending
1193b4be Poul Sander 2025-02-03 21:28 6835
            ImGui::TableSetupColumn("ID",       ImGuiTableColumnFlags_DefaultSort          | ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_ID);
1193b4be Poul Sander 2025-02-03 21:28 6836
            ImGui::TableSetupColumn("Name",                                                  ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_Name);
1193b4be Poul Sander 2025-02-03 21:28 6837
            ImGui::TableSetupColumn("Action",   ImGuiTableColumnFlags_NoSort               | ImGuiTableColumnFlags_WidthFixed,   0.0f, MyItemColumnID_Action);
1193b4be Poul Sander 2025-02-03 21:28 6838
            ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Quantity);
1193b4be Poul Sander 2025-02-03 21:28 6839
            ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible
1193b4be Poul Sander 2025-02-03 21:28 6840
            ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 6841
1193b4be Poul Sander 2025-02-03 21:28 6842
            // Sort our data if sort specs have been changed!
1193b4be Poul Sander 2025-02-03 21:28 6843
            if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs())
1193b4be Poul Sander 2025-02-03 21:28 6844
                if (sort_specs->SpecsDirty)
1193b4be Poul Sander 2025-02-03 21:28 6845
                {
1193b4be Poul Sander 2025-02-03 21:28 6846
                    MyItem::SortWithSortSpecs(sort_specs, items.Data, items.Size);
1193b4be Poul Sander 2025-02-03 21:28 6847
                    sort_specs->SpecsDirty = false;
1193b4be Poul Sander 2025-02-03 21:28 6848
                }
1193b4be Poul Sander 2025-02-03 21:28 6849
1193b4be Poul Sander 2025-02-03 21:28 6850
            // Demonstrate using clipper for large vertical lists
1193b4be Poul Sander 2025-02-03 21:28 6851
            ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 6852
            clipper.Begin(items.Size);
1193b4be Poul Sander 2025-02-03 21:28 6853
            while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 6854
                for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
1193b4be Poul Sander 2025-02-03 21:28 6855
                {
1193b4be Poul Sander 2025-02-03 21:28 6856
                    // Display a data item
1193b4be Poul Sander 2025-02-03 21:28 6857
                    MyItem* item = &items[row_n];
1193b4be Poul Sander 2025-02-03 21:28 6858
                    ImGui::PushID(item->ID);
1193b4be Poul Sander 2025-02-03 21:28 6859
                    ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 6860
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6861
                    ImGui::Text("%04d", item->ID);
1193b4be Poul Sander 2025-02-03 21:28 6862
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6863
                    ImGui::TextUnformatted(item->Name);
1193b4be Poul Sander 2025-02-03 21:28 6864
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6865
                    ImGui::SmallButton("None");
1193b4be Poul Sander 2025-02-03 21:28 6866
                    ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 6867
                    ImGui::Text("%d", item->Quantity);
1193b4be Poul Sander 2025-02-03 21:28 6868
                    ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 6869
                }
1193b4be Poul Sander 2025-02-03 21:28 6870
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 6871
        }
1193b4be Poul Sander 2025-02-03 21:28 6872
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6873
    }
1193b4be Poul Sander 2025-02-03 21:28 6874
1193b4be Poul Sander 2025-02-03 21:28 6875
    // In this example we'll expose most table flags and settings.
1193b4be Poul Sander 2025-02-03 21:28 6876
    // For specific flags and settings refer to the corresponding section for more detailed explanation.
1193b4be Poul Sander 2025-02-03 21:28 6877
    // This section is mostly useful to experiment with combining certain flags or settings with each others.
1193b4be Poul Sander 2025-02-03 21:28 6878
    //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // [DEBUG]
1193b4be Poul Sander 2025-02-03 21:28 6879
    if (open_action != -1)
1193b4be Poul Sander 2025-02-03 21:28 6880
        ImGui::SetNextItemOpen(open_action != 0);
1193b4be Poul Sander 2025-02-03 21:28 6881
    IMGUI_DEMO_MARKER("Tables/Advanced");
1193b4be Poul Sander 2025-02-03 21:28 6882
    if (ImGui::TreeNode("Advanced"))
1193b4be Poul Sander 2025-02-03 21:28 6883
    {
1193b4be Poul Sander 2025-02-03 21:28 6884
        static ImGuiTableFlags flags =
1193b4be Poul Sander 2025-02-03 21:28 6885
            ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable
1193b4be Poul Sander 2025-02-03 21:28 6886
            | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
1193b4be Poul Sander 2025-02-03 21:28 6887
            | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody
1193b4be Poul Sander 2025-02-03 21:28 6888
            | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
1193b4be Poul Sander 2025-02-03 21:28 6889
            | ImGuiTableFlags_SizingFixedFit;
1193b4be Poul Sander 2025-02-03 21:28 6890
        static ImGuiTableColumnFlags columns_base_flags = ImGuiTableColumnFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 6891
1193b4be Poul Sander 2025-02-03 21:28 6892
        enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow };
1193b4be Poul Sander 2025-02-03 21:28 6893
        static int contents_type = CT_SelectableSpanRow;
1193b4be Poul Sander 2025-02-03 21:28 6894
        const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable", "Selectable (span row)" };
1193b4be Poul Sander 2025-02-03 21:28 6895
        static int freeze_cols = 1;
1193b4be Poul Sander 2025-02-03 21:28 6896
        static int freeze_rows = 1;
1193b4be Poul Sander 2025-02-03 21:28 6897
        static int items_count = IM_ARRAYSIZE(template_items_names) * 2;
1193b4be Poul Sander 2025-02-03 21:28 6898
        static ImVec2 outer_size_value = ImVec2(0.0f, TEXT_BASE_HEIGHT * 12);
1193b4be Poul Sander 2025-02-03 21:28 6899
        static float row_min_height = 0.0f; // Auto
1193b4be Poul Sander 2025-02-03 21:28 6900
        static float inner_width_with_scroll = 0.0f; // Auto-extend
1193b4be Poul Sander 2025-02-03 21:28 6901
        static bool outer_size_enabled = true;
1193b4be Poul Sander 2025-02-03 21:28 6902
        static bool show_headers = true;
1193b4be Poul Sander 2025-02-03 21:28 6903
        static bool show_wrapped_text = false;
1193b4be Poul Sander 2025-02-03 21:28 6904
        //static ImGuiTextFilter filter;
1193b4be Poul Sander 2025-02-03 21:28 6905
        //ImGui::SetNextItemOpen(true, ImGuiCond_Once); // FIXME-TABLE: Enabling this results in initial clipped first pass on table which tend to affect column sizing
1193b4be Poul Sander 2025-02-03 21:28 6906
        if (ImGui::TreeNode("Options"))
1193b4be Poul Sander 2025-02-03 21:28 6907
        {
1193b4be Poul Sander 2025-02-03 21:28 6908
            // Make the UI compact because there are so many fields
1193b4be Poul Sander 2025-02-03 21:28 6909
            PushStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 6910
            ImGui::PushItemWidth(TEXT_BASE_WIDTH * 28.0f);
1193b4be Poul Sander 2025-02-03 21:28 6911
1193b4be Poul Sander 2025-02-03 21:28 6912
            if (ImGui::TreeNodeEx("Features:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6913
            {
1193b4be Poul Sander 2025-02-03 21:28 6914
                ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
1193b4be Poul Sander 2025-02-03 21:28 6915
                ImGui::CheckboxFlags("ImGuiTableFlags_Reorderable", &flags, ImGuiTableFlags_Reorderable);
1193b4be Poul Sander 2025-02-03 21:28 6916
                ImGui::CheckboxFlags("ImGuiTableFlags_Hideable", &flags, ImGuiTableFlags_Hideable);
1193b4be Poul Sander 2025-02-03 21:28 6917
                ImGui::CheckboxFlags("ImGuiTableFlags_Sortable", &flags, ImGuiTableFlags_Sortable);
1193b4be Poul Sander 2025-02-03 21:28 6918
                ImGui::CheckboxFlags("ImGuiTableFlags_NoSavedSettings", &flags, ImGuiTableFlags_NoSavedSettings);
1193b4be Poul Sander 2025-02-03 21:28 6919
                ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags, ImGuiTableFlags_ContextMenuInBody);
1193b4be Poul Sander 2025-02-03 21:28 6920
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6921
            }
1193b4be Poul Sander 2025-02-03 21:28 6922
1193b4be Poul Sander 2025-02-03 21:28 6923
            if (ImGui::TreeNodeEx("Decorations:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6924
            {
1193b4be Poul Sander 2025-02-03 21:28 6925
                ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg);
1193b4be Poul Sander 2025-02-03 21:28 6926
                ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV);
1193b4be Poul Sander 2025-02-03 21:28 6927
                ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
1193b4be Poul Sander 2025-02-03 21:28 6928
                ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
1193b4be Poul Sander 2025-02-03 21:28 6929
                ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH);
1193b4be Poul Sander 2025-02-03 21:28 6930
                ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
1193b4be Poul Sander 2025-02-03 21:28 6931
                ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
1193b4be Poul Sander 2025-02-03 21:28 6932
                ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBody", &flags, ImGuiTableFlags_NoBordersInBody); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body (borders will always appear in Headers");
1193b4be Poul Sander 2025-02-03 21:28 6933
                ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags, ImGuiTableFlags_NoBordersInBodyUntilResize); ImGui::SameLine(); HelpMarker("Disable vertical borders in columns Body until hovered for resize (borders will always appear in Headers)");
1193b4be Poul Sander 2025-02-03 21:28 6934
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6935
            }
1193b4be Poul Sander 2025-02-03 21:28 6936
1193b4be Poul Sander 2025-02-03 21:28 6937
            if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6938
            {
1193b4be Poul Sander 2025-02-03 21:28 6939
                EditTableSizingFlags(&flags);
1193b4be Poul Sander 2025-02-03 21:28 6940
                ImGui::SameLine(); HelpMarker("In the Advanced demo we override the policy of each column so those table-wide settings have less effect that typical.");
1193b4be Poul Sander 2025-02-03 21:28 6941
                ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX);
1193b4be Poul Sander 2025-02-03 21:28 6942
                ImGui::SameLine(); HelpMarker("Make outer width auto-fit to columns, overriding outer_size.x value.\n\nOnly available when ScrollX/ScrollY are disabled and Stretch columns are not used.");
1193b4be Poul Sander 2025-02-03 21:28 6943
                ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
1193b4be Poul Sander 2025-02-03 21:28 6944
                ImGui::SameLine(); HelpMarker("Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit).\n\nOnly available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.");
1193b4be Poul Sander 2025-02-03 21:28 6945
                ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible);
1193b4be Poul Sander 2025-02-03 21:28 6946
                ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled.");
1193b4be Poul Sander 2025-02-03 21:28 6947
                ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
1193b4be Poul Sander 2025-02-03 21:28 6948
                ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.");
1193b4be Poul Sander 2025-02-03 21:28 6949
                ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
1193b4be Poul Sander 2025-02-03 21:28 6950
                ImGui::SameLine(); HelpMarker("Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with ScrollFreeze options.");
1193b4be Poul Sander 2025-02-03 21:28 6951
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6952
            }
1193b4be Poul Sander 2025-02-03 21:28 6953
1193b4be Poul Sander 2025-02-03 21:28 6954
            if (ImGui::TreeNodeEx("Padding:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6955
            {
1193b4be Poul Sander 2025-02-03 21:28 6956
                ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags, ImGuiTableFlags_PadOuterX);
1193b4be Poul Sander 2025-02-03 21:28 6957
                ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags, ImGuiTableFlags_NoPadOuterX);
1193b4be Poul Sander 2025-02-03 21:28 6958
                ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags, ImGuiTableFlags_NoPadInnerX);
1193b4be Poul Sander 2025-02-03 21:28 6959
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6960
            }
1193b4be Poul Sander 2025-02-03 21:28 6961
1193b4be Poul Sander 2025-02-03 21:28 6962
            if (ImGui::TreeNodeEx("Scrolling:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6963
            {
1193b4be Poul Sander 2025-02-03 21:28 6964
                ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
1193b4be Poul Sander 2025-02-03 21:28 6965
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 6966
                ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
1193b4be Poul Sander 2025-02-03 21:28 6967
                ImGui::DragInt("freeze_cols", &freeze_cols, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
1193b4be Poul Sander 2025-02-03 21:28 6968
                ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
1193b4be Poul Sander 2025-02-03 21:28 6969
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 6970
                ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
1193b4be Poul Sander 2025-02-03 21:28 6971
                ImGui::DragInt("freeze_rows", &freeze_rows, 0.2f, 0, 9, NULL, ImGuiSliderFlags_NoInput);
1193b4be Poul Sander 2025-02-03 21:28 6972
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6973
            }
1193b4be Poul Sander 2025-02-03 21:28 6974
1193b4be Poul Sander 2025-02-03 21:28 6975
            if (ImGui::TreeNodeEx("Sorting:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6976
            {
1193b4be Poul Sander 2025-02-03 21:28 6977
                ImGui::CheckboxFlags("ImGuiTableFlags_SortMulti", &flags, ImGuiTableFlags_SortMulti);
1193b4be Poul Sander 2025-02-03 21:28 6978
                ImGui::SameLine(); HelpMarker("When sorting is enabled: hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).");
1193b4be Poul Sander 2025-02-03 21:28 6979
                ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate);
1193b4be Poul Sander 2025-02-03 21:28 6980
                ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).");
1193b4be Poul Sander 2025-02-03 21:28 6981
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6982
            }
1193b4be Poul Sander 2025-02-03 21:28 6983
1193b4be Poul Sander 2025-02-03 21:28 6984
            if (ImGui::TreeNodeEx("Headers:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6985
            {
1193b4be Poul Sander 2025-02-03 21:28 6986
                ImGui::Checkbox("show_headers", &show_headers);
1193b4be Poul Sander 2025-02-03 21:28 6987
                ImGui::CheckboxFlags("ImGuiTableFlags_HighlightHoveredColumn", &flags, ImGuiTableFlags_HighlightHoveredColumn);
1193b4be Poul Sander 2025-02-03 21:28 6988
                ImGui::CheckboxFlags("ImGuiTableColumnFlags_AngledHeader", &columns_base_flags, ImGuiTableColumnFlags_AngledHeader);
1193b4be Poul Sander 2025-02-03 21:28 6989
                ImGui::SameLine(); HelpMarker("Enable AngledHeader on all columns. Best enabled on selected narrow columns (see \"Angled headers\" section of the demo).");
1193b4be Poul Sander 2025-02-03 21:28 6990
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 6991
            }
1193b4be Poul Sander 2025-02-03 21:28 6992
1193b4be Poul Sander 2025-02-03 21:28 6993
            if (ImGui::TreeNodeEx("Other:", ImGuiTreeNodeFlags_DefaultOpen))
1193b4be Poul Sander 2025-02-03 21:28 6994
            {
1193b4be Poul Sander 2025-02-03 21:28 6995
                ImGui::Checkbox("show_wrapped_text", &show_wrapped_text);
1193b4be Poul Sander 2025-02-03 21:28 6996
1193b4be Poul Sander 2025-02-03 21:28 6997
                ImGui::DragFloat2("##OuterSize", &outer_size_value.x);
1193b4be Poul Sander 2025-02-03 21:28 6998
                ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 6999
                ImGui::Checkbox("outer_size", &outer_size_enabled);
1193b4be Poul Sander 2025-02-03 21:28 7000
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7001
                HelpMarker("If scrolling is disabled (ScrollX and ScrollY not set):\n"
1193b4be Poul Sander 2025-02-03 21:28 7002
                    "- The table is output directly in the parent window.\n"
1193b4be Poul Sander 2025-02-03 21:28 7003
                    "- OuterSize.x < 0.0f will right-align the table.\n"
1193b4be Poul Sander 2025-02-03 21:28 7004
                    "- OuterSize.x = 0.0f will narrow fit the table unless there are any Stretch columns.\n"
1193b4be Poul Sander 2025-02-03 21:28 7005
                    "- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set).");
1193b4be Poul Sander 2025-02-03 21:28 7006
1193b4be Poul Sander 2025-02-03 21:28 7007
                // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling.
1193b4be Poul Sander 2025-02-03 21:28 7008
                // To facilitate toying with this demo we will actually pass 0.0f to the BeginTable() when ScrollX is disabled.
1193b4be Poul Sander 2025-02-03 21:28 7009
                ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX);
1193b4be Poul Sander 2025-02-03 21:28 7010
1193b4be Poul Sander 2025-02-03 21:28 7011
                ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX);
1193b4be Poul Sander 2025-02-03 21:28 7012
                ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
1193b4be Poul Sander 2025-02-03 21:28 7013
1193b4be Poul Sander 2025-02-03 21:28 7014
                ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999);
1193b4be Poul Sander 2025-02-03 21:28 7015
                ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names));
1193b4be Poul Sander 2025-02-03 21:28 7016
                //filter.Draw("filter");
1193b4be Poul Sander 2025-02-03 21:28 7017
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7018
            }
1193b4be Poul Sander 2025-02-03 21:28 7019
1193b4be Poul Sander 2025-02-03 21:28 7020
            ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 7021
            PopStyleCompact();
1193b4be Poul Sander 2025-02-03 21:28 7022
            ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 7023
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7024
        }
1193b4be Poul Sander 2025-02-03 21:28 7025
1193b4be Poul Sander 2025-02-03 21:28 7026
        // Update item list if we changed the number of items
1193b4be Poul Sander 2025-02-03 21:28 7027
        static ImVector<MyItem> items;
1193b4be Poul Sander 2025-02-03 21:28 7028
        static ImVector<int> selection;
1193b4be Poul Sander 2025-02-03 21:28 7029
        static bool items_need_sort = false;
1193b4be Poul Sander 2025-02-03 21:28 7030
        if (items.Size != items_count)
1193b4be Poul Sander 2025-02-03 21:28 7031
        {
1193b4be Poul Sander 2025-02-03 21:28 7032
            items.resize(items_count, MyItem());
1193b4be Poul Sander 2025-02-03 21:28 7033
            for (int n = 0; n < items_count; n++)
1193b4be Poul Sander 2025-02-03 21:28 7034
            {
1193b4be Poul Sander 2025-02-03 21:28 7035
                const int template_n = n % IM_ARRAYSIZE(template_items_names);
1193b4be Poul Sander 2025-02-03 21:28 7036
                MyItem& item = items[n];
1193b4be Poul Sander 2025-02-03 21:28 7037
                item.ID = n;
1193b4be Poul Sander 2025-02-03 21:28 7038
                item.Name = template_items_names[template_n];
1193b4be Poul Sander 2025-02-03 21:28 7039
                item.Quantity = (template_n == 3) ? 10 : (template_n == 4) ? 20 : 0; // Assign default quantities
1193b4be Poul Sander 2025-02-03 21:28 7040
            }
1193b4be Poul Sander 2025-02-03 21:28 7041
        }
1193b4be Poul Sander 2025-02-03 21:28 7042
1193b4be Poul Sander 2025-02-03 21:28 7043
        const ImDrawList* parent_draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 7044
        const int parent_draw_list_draw_cmd_count = parent_draw_list->CmdBuffer.Size;
1193b4be Poul Sander 2025-02-03 21:28 7045
        ImVec2 table_scroll_cur, table_scroll_max; // For debug display
1193b4be Poul Sander 2025-02-03 21:28 7046
        const ImDrawList* table_draw_list = NULL;  // "
1193b4be Poul Sander 2025-02-03 21:28 7047
1193b4be Poul Sander 2025-02-03 21:28 7048
        // Submit table
1193b4be Poul Sander 2025-02-03 21:28 7049
        const float inner_width_to_use = (flags & ImGuiTableFlags_ScrollX) ? inner_width_with_scroll : 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 7050
        if (ImGui::BeginTable("table_advanced", 6, flags, outer_size_enabled ? outer_size_value : ImVec2(0, 0), inner_width_to_use))
1193b4be Poul Sander 2025-02-03 21:28 7051
        {
1193b4be Poul Sander 2025-02-03 21:28 7052
            // Declare columns
1193b4be Poul Sander 2025-02-03 21:28 7053
            // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications.
1193b4be Poul Sander 2025-02-03 21:28 7054
            // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index!
1193b4be Poul Sander 2025-02-03 21:28 7055
            ImGui::TableSetupColumn("ID",           columns_base_flags | ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, 0.0f, MyItemColumnID_ID);
1193b4be Poul Sander 2025-02-03 21:28 7056
            ImGui::TableSetupColumn("Name",         columns_base_flags | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name);
1193b4be Poul Sander 2025-02-03 21:28 7057
            ImGui::TableSetupColumn("Action",       columns_base_flags | ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action);
1193b4be Poul Sander 2025-02-03 21:28 7058
            ImGui::TableSetupColumn("Quantity",     columns_base_flags | ImGuiTableColumnFlags_PreferSortDescending, 0.0f, MyItemColumnID_Quantity);
1193b4be Poul Sander 2025-02-03 21:28 7059
            ImGui::TableSetupColumn("Description",  columns_base_flags | ((flags & ImGuiTableFlags_NoHostExtendX) ? 0 : ImGuiTableColumnFlags_WidthStretch), 0.0f, MyItemColumnID_Description);
1193b4be Poul Sander 2025-02-03 21:28 7060
            ImGui::TableSetupColumn("Hidden",       columns_base_flags |  ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort);
1193b4be Poul Sander 2025-02-03 21:28 7061
            ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
1193b4be Poul Sander 2025-02-03 21:28 7062
1193b4be Poul Sander 2025-02-03 21:28 7063
            // Sort our data if sort specs have been changed!
1193b4be Poul Sander 2025-02-03 21:28 7064
            ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs();
1193b4be Poul Sander 2025-02-03 21:28 7065
            if (sort_specs && sort_specs->SpecsDirty)
1193b4be Poul Sander 2025-02-03 21:28 7066
                items_need_sort = true;
1193b4be Poul Sander 2025-02-03 21:28 7067
            if (sort_specs && items_need_sort && items.Size > 1)
1193b4be Poul Sander 2025-02-03 21:28 7068
            {
1193b4be Poul Sander 2025-02-03 21:28 7069
                MyItem::SortWithSortSpecs(sort_specs, items.Data, items.Size);
1193b4be Poul Sander 2025-02-03 21:28 7070
                sort_specs->SpecsDirty = false;
1193b4be Poul Sander 2025-02-03 21:28 7071
            }
1193b4be Poul Sander 2025-02-03 21:28 7072
            items_need_sort = false;
1193b4be Poul Sander 2025-02-03 21:28 7073
1193b4be Poul Sander 2025-02-03 21:28 7074
            // Take note of whether we are currently sorting based on the Quantity field,
1193b4be Poul Sander 2025-02-03 21:28 7075
            // we will use this to trigger sorting when we know the data of this column has been modified.
1193b4be Poul Sander 2025-02-03 21:28 7076
            const bool sorts_specs_using_quantity = (ImGui::TableGetColumnFlags(3) & ImGuiTableColumnFlags_IsSorted) != 0;
1193b4be Poul Sander 2025-02-03 21:28 7077
1193b4be Poul Sander 2025-02-03 21:28 7078
            // Show headers
1193b4be Poul Sander 2025-02-03 21:28 7079
            if (show_headers && (columns_base_flags & ImGuiTableColumnFlags_AngledHeader) != 0)
1193b4be Poul Sander 2025-02-03 21:28 7080
                ImGui::TableAngledHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 7081
            if (show_headers)
1193b4be Poul Sander 2025-02-03 21:28 7082
                ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 7083
1193b4be Poul Sander 2025-02-03 21:28 7084
            // Show data
1193b4be Poul Sander 2025-02-03 21:28 7085
            // FIXME-TABLE FIXME-NAV: How we can get decent up/down even though we have the buttons here?
1193b4be Poul Sander 2025-02-03 21:28 7086
#if 1
1193b4be Poul Sander 2025-02-03 21:28 7087
            // Demonstrate using clipper for large vertical lists
1193b4be Poul Sander 2025-02-03 21:28 7088
            ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 7089
            clipper.Begin(items.Size);
1193b4be Poul Sander 2025-02-03 21:28 7090
            while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 7091
            {
1193b4be Poul Sander 2025-02-03 21:28 7092
                for (int row_n = clipper.DisplayStart; row_n < clipper.DisplayEnd; row_n++)
1193b4be Poul Sander 2025-02-03 21:28 7093
#else
1193b4be Poul Sander 2025-02-03 21:28 7094
            // Without clipper
1193b4be Poul Sander 2025-02-03 21:28 7095
            {
1193b4be Poul Sander 2025-02-03 21:28 7096
                for (int row_n = 0; row_n < items.Size; row_n++)
1193b4be Poul Sander 2025-02-03 21:28 7097
#endif
1193b4be Poul Sander 2025-02-03 21:28 7098
                {
1193b4be Poul Sander 2025-02-03 21:28 7099
                    MyItem* item = &items[row_n];
1193b4be Poul Sander 2025-02-03 21:28 7100
                    //if (!filter.PassFilter(item->Name))
1193b4be Poul Sander 2025-02-03 21:28 7101
                    //    continue;
1193b4be Poul Sander 2025-02-03 21:28 7102
1193b4be Poul Sander 2025-02-03 21:28 7103
                    const bool item_is_selected = selection.contains(item->ID);
1193b4be Poul Sander 2025-02-03 21:28 7104
                    ImGui::PushID(item->ID);
1193b4be Poul Sander 2025-02-03 21:28 7105
                    ImGui::TableNextRow(ImGuiTableRowFlags_None, row_min_height);
1193b4be Poul Sander 2025-02-03 21:28 7106
1193b4be Poul Sander 2025-02-03 21:28 7107
                    // For the demo purpose we can select among different type of items submitted in the first column
1193b4be Poul Sander 2025-02-03 21:28 7108
                    ImGui::TableSetColumnIndex(0);
1193b4be Poul Sander 2025-02-03 21:28 7109
                    char label[32];
1193b4be Poul Sander 2025-02-03 21:28 7110
                    sprintf(label, "%04d", item->ID);
1193b4be Poul Sander 2025-02-03 21:28 7111
                    if (contents_type == CT_Text)
1193b4be Poul Sander 2025-02-03 21:28 7112
                        ImGui::TextUnformatted(label);
1193b4be Poul Sander 2025-02-03 21:28 7113
                    else if (contents_type == CT_Button)
1193b4be Poul Sander 2025-02-03 21:28 7114
                        ImGui::Button(label);
1193b4be Poul Sander 2025-02-03 21:28 7115
                    else if (contents_type == CT_SmallButton)
1193b4be Poul Sander 2025-02-03 21:28 7116
                        ImGui::SmallButton(label);
1193b4be Poul Sander 2025-02-03 21:28 7117
                    else if (contents_type == CT_FillButton)
1193b4be Poul Sander 2025-02-03 21:28 7118
                        ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 7119
                    else if (contents_type == CT_Selectable || contents_type == CT_SelectableSpanRow)
1193b4be Poul Sander 2025-02-03 21:28 7120
                    {
1193b4be Poul Sander 2025-02-03 21:28 7121
                        ImGuiSelectableFlags selectable_flags = (contents_type == CT_SelectableSpanRow) ? ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowOverlap : ImGuiSelectableFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 7122
                        if (ImGui::Selectable(label, item_is_selected, selectable_flags, ImVec2(0, row_min_height)))
1193b4be Poul Sander 2025-02-03 21:28 7123
                        {
1193b4be Poul Sander 2025-02-03 21:28 7124
                            if (ImGui::GetIO().KeyCtrl)
1193b4be Poul Sander 2025-02-03 21:28 7125
                            {
1193b4be Poul Sander 2025-02-03 21:28 7126
                                if (item_is_selected)
1193b4be Poul Sander 2025-02-03 21:28 7127
                                    selection.find_erase_unsorted(item->ID);
1193b4be Poul Sander 2025-02-03 21:28 7128
                                else
1193b4be Poul Sander 2025-02-03 21:28 7129
                                    selection.push_back(item->ID);
1193b4be Poul Sander 2025-02-03 21:28 7130
                            }
1193b4be Poul Sander 2025-02-03 21:28 7131
                            else
1193b4be Poul Sander 2025-02-03 21:28 7132
                            {
1193b4be Poul Sander 2025-02-03 21:28 7133
                                selection.clear();
1193b4be Poul Sander 2025-02-03 21:28 7134
                                selection.push_back(item->ID);
1193b4be Poul Sander 2025-02-03 21:28 7135
                            }
1193b4be Poul Sander 2025-02-03 21:28 7136
                        }
1193b4be Poul Sander 2025-02-03 21:28 7137
                    }
1193b4be Poul Sander 2025-02-03 21:28 7138
1193b4be Poul Sander 2025-02-03 21:28 7139
                    if (ImGui::TableSetColumnIndex(1))
1193b4be Poul Sander 2025-02-03 21:28 7140
                        ImGui::TextUnformatted(item->Name);
1193b4be Poul Sander 2025-02-03 21:28 7141
1193b4be Poul Sander 2025-02-03 21:28 7142
                    // Here we demonstrate marking our data set as needing to be sorted again if we modified a quantity,
1193b4be Poul Sander 2025-02-03 21:28 7143
                    // and we are currently sorting on the column showing the Quantity.
1193b4be Poul Sander 2025-02-03 21:28 7144
                    // To avoid triggering a sort while holding the button, we only trigger it when the button has been released.
1193b4be Poul Sander 2025-02-03 21:28 7145
                    // You will probably need some extra logic if you want to automatically sort when a specific entry changes.
1193b4be Poul Sander 2025-02-03 21:28 7146
                    if (ImGui::TableSetColumnIndex(2))
1193b4be Poul Sander 2025-02-03 21:28 7147
                    {
1193b4be Poul Sander 2025-02-03 21:28 7148
                        if (ImGui::SmallButton("Chop")) { item->Quantity += 1; }
1193b4be Poul Sander 2025-02-03 21:28 7149
                        if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
1193b4be Poul Sander 2025-02-03 21:28 7150
                        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7151
                        if (ImGui::SmallButton("Eat")) { item->Quantity -= 1; }
1193b4be Poul Sander 2025-02-03 21:28 7152
                        if (sorts_specs_using_quantity && ImGui::IsItemDeactivated()) { items_need_sort = true; }
1193b4be Poul Sander 2025-02-03 21:28 7153
                    }
1193b4be Poul Sander 2025-02-03 21:28 7154
1193b4be Poul Sander 2025-02-03 21:28 7155
                    if (ImGui::TableSetColumnIndex(3))
1193b4be Poul Sander 2025-02-03 21:28 7156
                        ImGui::Text("%d", item->Quantity);
1193b4be Poul Sander 2025-02-03 21:28 7157
1193b4be Poul Sander 2025-02-03 21:28 7158
                    ImGui::TableSetColumnIndex(4);
1193b4be Poul Sander 2025-02-03 21:28 7159
                    if (show_wrapped_text)
1193b4be Poul Sander 2025-02-03 21:28 7160
                        ImGui::TextWrapped("Lorem ipsum dolor sit amet");
1193b4be Poul Sander 2025-02-03 21:28 7161
                    else
1193b4be Poul Sander 2025-02-03 21:28 7162
                        ImGui::Text("Lorem ipsum dolor sit amet");
1193b4be Poul Sander 2025-02-03 21:28 7163
1193b4be Poul Sander 2025-02-03 21:28 7164
                    if (ImGui::TableSetColumnIndex(5))
1193b4be Poul Sander 2025-02-03 21:28 7165
                        ImGui::Text("1234");
1193b4be Poul Sander 2025-02-03 21:28 7166
1193b4be Poul Sander 2025-02-03 21:28 7167
                    ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 7168
                }
1193b4be Poul Sander 2025-02-03 21:28 7169
            }
1193b4be Poul Sander 2025-02-03 21:28 7170
1193b4be Poul Sander 2025-02-03 21:28 7171
            // Store some info to display debug details below
1193b4be Poul Sander 2025-02-03 21:28 7172
            table_scroll_cur = ImVec2(ImGui::GetScrollX(), ImGui::GetScrollY());
1193b4be Poul Sander 2025-02-03 21:28 7173
            table_scroll_max = ImVec2(ImGui::GetScrollMaxX(), ImGui::GetScrollMaxY());
1193b4be Poul Sander 2025-02-03 21:28 7174
            table_draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 7175
            ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 7176
        }
1193b4be Poul Sander 2025-02-03 21:28 7177
        static bool show_debug_details = false;
1193b4be Poul Sander 2025-02-03 21:28 7178
        ImGui::Checkbox("Debug details", &show_debug_details);
1193b4be Poul Sander 2025-02-03 21:28 7179
        if (show_debug_details && table_draw_list)
1193b4be Poul Sander 2025-02-03 21:28 7180
        {
1193b4be Poul Sander 2025-02-03 21:28 7181
            ImGui::SameLine(0.0f, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 7182
            const int table_draw_list_draw_cmd_count = table_draw_list->CmdBuffer.Size;
1193b4be Poul Sander 2025-02-03 21:28 7183
            if (table_draw_list == parent_draw_list)
1193b4be Poul Sander 2025-02-03 21:28 7184
                ImGui::Text(": DrawCmd: +%d (in same window)",
1193b4be Poul Sander 2025-02-03 21:28 7185
                    table_draw_list_draw_cmd_count - parent_draw_list_draw_cmd_count);
1193b4be Poul Sander 2025-02-03 21:28 7186
            else
1193b4be Poul Sander 2025-02-03 21:28 7187
                ImGui::Text(": DrawCmd: +%d (in child window), Scroll: (%.f/%.f) (%.f/%.f)",
1193b4be Poul Sander 2025-02-03 21:28 7188
                    table_draw_list_draw_cmd_count - 1, table_scroll_cur.x, table_scroll_max.x, table_scroll_cur.y, table_scroll_max.y);
1193b4be Poul Sander 2025-02-03 21:28 7189
        }
1193b4be Poul Sander 2025-02-03 21:28 7190
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7191
    }
1193b4be Poul Sander 2025-02-03 21:28 7192
1193b4be Poul Sander 2025-02-03 21:28 7193
    ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 7194
1193b4be Poul Sander 2025-02-03 21:28 7195
    ShowDemoWindowColumns();
1193b4be Poul Sander 2025-02-03 21:28 7196
1193b4be Poul Sander 2025-02-03 21:28 7197
    if (disable_indent)
1193b4be Poul Sander 2025-02-03 21:28 7198
        ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 7199
}
1193b4be Poul Sander 2025-02-03 21:28 7200
1193b4be Poul Sander 2025-02-03 21:28 7201
// Demonstrate old/legacy Columns API!
1193b4be Poul Sander 2025-02-03 21:28 7202
// [2020: Columns are under-featured and not maintained. Prefer using the more flexible and powerful BeginTable() API!]
1193b4be Poul Sander 2025-02-03 21:28 7203
static void ShowDemoWindowColumns()
1193b4be Poul Sander 2025-02-03 21:28 7204
{
1193b4be Poul Sander 2025-02-03 21:28 7205
    IMGUI_DEMO_MARKER("Columns (legacy API)");
1193b4be Poul Sander 2025-02-03 21:28 7206
    bool open = ImGui::TreeNode("Legacy Columns API");
1193b4be Poul Sander 2025-02-03 21:28 7207
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7208
    HelpMarker("Columns() is an old API! Prefer using the more flexible and powerful BeginTable() API!");
1193b4be Poul Sander 2025-02-03 21:28 7209
    if (!open)
1193b4be Poul Sander 2025-02-03 21:28 7210
        return;
1193b4be Poul Sander 2025-02-03 21:28 7211
1193b4be Poul Sander 2025-02-03 21:28 7212
    // Basic columns
1193b4be Poul Sander 2025-02-03 21:28 7213
    IMGUI_DEMO_MARKER("Columns (legacy API)/Basic");
1193b4be Poul Sander 2025-02-03 21:28 7214
    if (ImGui::TreeNode("Basic"))
1193b4be Poul Sander 2025-02-03 21:28 7215
    {
1193b4be Poul Sander 2025-02-03 21:28 7216
        ImGui::Text("Without border:");
1193b4be Poul Sander 2025-02-03 21:28 7217
        ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
1193b4be Poul Sander 2025-02-03 21:28 7218
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7219
        for (int n = 0; n < 14; n++)
1193b4be Poul Sander 2025-02-03 21:28 7220
        {
1193b4be Poul Sander 2025-02-03 21:28 7221
            char label[32];
1193b4be Poul Sander 2025-02-03 21:28 7222
            sprintf(label, "Item %d", n);
1193b4be Poul Sander 2025-02-03 21:28 7223
            if (ImGui::Selectable(label)) {}
1193b4be Poul Sander 2025-02-03 21:28 7224
            //if (ImGui::Button(label, ImVec2(-FLT_MIN,0.0f))) {}
1193b4be Poul Sander 2025-02-03 21:28 7225
            ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7226
        }
1193b4be Poul Sander 2025-02-03 21:28 7227
        ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 7228
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7229
1193b4be Poul Sander 2025-02-03 21:28 7230
        ImGui::Text("With border:");
1193b4be Poul Sander 2025-02-03 21:28 7231
        ImGui::Columns(4, "mycolumns"); // 4-ways, with border
1193b4be Poul Sander 2025-02-03 21:28 7232
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7233
        ImGui::Text("ID"); ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7234
        ImGui::Text("Name"); ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7235
        ImGui::Text("Path"); ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7236
        ImGui::Text("Hovered"); ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7237
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7238
        const char* names[3] = { "One", "Two", "Three" };
1193b4be Poul Sander 2025-02-03 21:28 7239
        const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
1193b4be Poul Sander 2025-02-03 21:28 7240
        static int selected = -1;
1193b4be Poul Sander 2025-02-03 21:28 7241
        for (int i = 0; i < 3; i++)
1193b4be Poul Sander 2025-02-03 21:28 7242
        {
1193b4be Poul Sander 2025-02-03 21:28 7243
            char label[32];
1193b4be Poul Sander 2025-02-03 21:28 7244
            sprintf(label, "%04d", i);
1193b4be Poul Sander 2025-02-03 21:28 7245
            if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
1193b4be Poul Sander 2025-02-03 21:28 7246
                selected = i;
1193b4be Poul Sander 2025-02-03 21:28 7247
            bool hovered = ImGui::IsItemHovered();
1193b4be Poul Sander 2025-02-03 21:28 7248
            ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7249
            ImGui::Text(names[i]); ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7250
            ImGui::Text(paths[i]); ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7251
            ImGui::Text("%d", hovered); ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7252
        }
1193b4be Poul Sander 2025-02-03 21:28 7253
        ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 7254
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7255
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7256
    }
1193b4be Poul Sander 2025-02-03 21:28 7257
1193b4be Poul Sander 2025-02-03 21:28 7258
    IMGUI_DEMO_MARKER("Columns (legacy API)/Borders");
1193b4be Poul Sander 2025-02-03 21:28 7259
    if (ImGui::TreeNode("Borders"))
1193b4be Poul Sander 2025-02-03 21:28 7260
    {
1193b4be Poul Sander 2025-02-03 21:28 7261
        // NB: Future columns API should allow automatic horizontal borders.
1193b4be Poul Sander 2025-02-03 21:28 7262
        static bool h_borders = true;
1193b4be Poul Sander 2025-02-03 21:28 7263
        static bool v_borders = true;
1193b4be Poul Sander 2025-02-03 21:28 7264
        static int columns_count = 4;
1193b4be Poul Sander 2025-02-03 21:28 7265
        const int lines_count = 3;
1193b4be Poul Sander 2025-02-03 21:28 7266
        ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 7267
        ImGui::DragInt("##columns_count", &columns_count, 0.1f, 2, 10, "%d columns");
1193b4be Poul Sander 2025-02-03 21:28 7268
        if (columns_count < 2)
1193b4be Poul Sander 2025-02-03 21:28 7269
            columns_count = 2;
1193b4be Poul Sander 2025-02-03 21:28 7270
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7271
        ImGui::Checkbox("horizontal", &h_borders);
1193b4be Poul Sander 2025-02-03 21:28 7272
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7273
        ImGui::Checkbox("vertical", &v_borders);
1193b4be Poul Sander 2025-02-03 21:28 7274
        ImGui::Columns(columns_count, NULL, v_borders);
1193b4be Poul Sander 2025-02-03 21:28 7275
        for (int i = 0; i < columns_count * lines_count; i++)
1193b4be Poul Sander 2025-02-03 21:28 7276
        {
1193b4be Poul Sander 2025-02-03 21:28 7277
            if (h_borders && ImGui::GetColumnIndex() == 0)
1193b4be Poul Sander 2025-02-03 21:28 7278
                ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7279
            ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 7280
            ImGui::Text("%c%c%c", 'a' + i, 'a' + i, 'a' + i);
1193b4be Poul Sander 2025-02-03 21:28 7281
            ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
1193b4be Poul Sander 2025-02-03 21:28 7282
            ImGui::Text("Avail %.2f", ImGui::GetContentRegionAvail().x);
1193b4be Poul Sander 2025-02-03 21:28 7283
            ImGui::Text("Offset %.2f", ImGui::GetColumnOffset());
1193b4be Poul Sander 2025-02-03 21:28 7284
            ImGui::Text("Long text that is likely to clip");
1193b4be Poul Sander 2025-02-03 21:28 7285
            ImGui::Button("Button", ImVec2(-FLT_MIN, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 7286
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 7287
            ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7288
        }
1193b4be Poul Sander 2025-02-03 21:28 7289
        ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 7290
        if (h_borders)
1193b4be Poul Sander 2025-02-03 21:28 7291
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7292
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7293
    }
1193b4be Poul Sander 2025-02-03 21:28 7294
1193b4be Poul Sander 2025-02-03 21:28 7295
    // Create multiple items in a same cell before switching to next column
1193b4be Poul Sander 2025-02-03 21:28 7296
    IMGUI_DEMO_MARKER("Columns (legacy API)/Mixed items");
1193b4be Poul Sander 2025-02-03 21:28 7297
    if (ImGui::TreeNode("Mixed items"))
1193b4be Poul Sander 2025-02-03 21:28 7298
    {
1193b4be Poul Sander 2025-02-03 21:28 7299
        ImGui::Columns(3, "mixed");
1193b4be Poul Sander 2025-02-03 21:28 7300
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7301
1193b4be Poul Sander 2025-02-03 21:28 7302
        ImGui::Text("Hello");
1193b4be Poul Sander 2025-02-03 21:28 7303
        ImGui::Button("Banana");
1193b4be Poul Sander 2025-02-03 21:28 7304
        ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7305
1193b4be Poul Sander 2025-02-03 21:28 7306
        ImGui::Text("ImGui");
1193b4be Poul Sander 2025-02-03 21:28 7307
        ImGui::Button("Apple");
1193b4be Poul Sander 2025-02-03 21:28 7308
        static float foo = 1.0f;
1193b4be Poul Sander 2025-02-03 21:28 7309
        ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
1193b4be Poul Sander 2025-02-03 21:28 7310
        ImGui::Text("An extra line here.");
1193b4be Poul Sander 2025-02-03 21:28 7311
        ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7312
1193b4be Poul Sander 2025-02-03 21:28 7313
        ImGui::Text("Sailor");
1193b4be Poul Sander 2025-02-03 21:28 7314
        ImGui::Button("Corniflower");
1193b4be Poul Sander 2025-02-03 21:28 7315
        static float bar = 1.0f;
1193b4be Poul Sander 2025-02-03 21:28 7316
        ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
1193b4be Poul Sander 2025-02-03 21:28 7317
        ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7318
1193b4be Poul Sander 2025-02-03 21:28 7319
        if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7320
        if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7321
        if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7322
        ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 7323
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7324
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7325
    }
1193b4be Poul Sander 2025-02-03 21:28 7326
1193b4be Poul Sander 2025-02-03 21:28 7327
    // Word wrapping
1193b4be Poul Sander 2025-02-03 21:28 7328
    IMGUI_DEMO_MARKER("Columns (legacy API)/Word-wrapping");
1193b4be Poul Sander 2025-02-03 21:28 7329
    if (ImGui::TreeNode("Word-wrapping"))
1193b4be Poul Sander 2025-02-03 21:28 7330
    {
1193b4be Poul Sander 2025-02-03 21:28 7331
        ImGui::Columns(2, "word-wrapping");
1193b4be Poul Sander 2025-02-03 21:28 7332
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7333
        ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
1193b4be Poul Sander 2025-02-03 21:28 7334
        ImGui::TextWrapped("Hello Left");
1193b4be Poul Sander 2025-02-03 21:28 7335
        ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7336
        ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
1193b4be Poul Sander 2025-02-03 21:28 7337
        ImGui::TextWrapped("Hello Right");
1193b4be Poul Sander 2025-02-03 21:28 7338
        ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 7339
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7340
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7341
    }
1193b4be Poul Sander 2025-02-03 21:28 7342
1193b4be Poul Sander 2025-02-03 21:28 7343
    IMGUI_DEMO_MARKER("Columns (legacy API)/Horizontal Scrolling");
1193b4be Poul Sander 2025-02-03 21:28 7344
    if (ImGui::TreeNode("Horizontal Scrolling"))
1193b4be Poul Sander 2025-02-03 21:28 7345
    {
1193b4be Poul Sander 2025-02-03 21:28 7346
        ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 7347
        ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f);
1193b4be Poul Sander 2025-02-03 21:28 7348
        ImGui::BeginChild("##ScrollingRegion", child_size, ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar);
1193b4be Poul Sander 2025-02-03 21:28 7349
        ImGui::Columns(10);
1193b4be Poul Sander 2025-02-03 21:28 7350
1193b4be Poul Sander 2025-02-03 21:28 7351
        // Also demonstrate using clipper for large vertical lists
1193b4be Poul Sander 2025-02-03 21:28 7352
        int ITEMS_COUNT = 2000;
1193b4be Poul Sander 2025-02-03 21:28 7353
        ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 7354
        clipper.Begin(ITEMS_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 7355
        while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 7356
        {
1193b4be Poul Sander 2025-02-03 21:28 7357
            for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
1193b4be Poul Sander 2025-02-03 21:28 7358
                for (int j = 0; j < 10; j++)
1193b4be Poul Sander 2025-02-03 21:28 7359
                {
1193b4be Poul Sander 2025-02-03 21:28 7360
                    ImGui::Text("Line %d Column %d...", i, j);
1193b4be Poul Sander 2025-02-03 21:28 7361
                    ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7362
                }
1193b4be Poul Sander 2025-02-03 21:28 7363
        }
1193b4be Poul Sander 2025-02-03 21:28 7364
        ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 7365
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 7366
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7367
    }
1193b4be Poul Sander 2025-02-03 21:28 7368
1193b4be Poul Sander 2025-02-03 21:28 7369
    IMGUI_DEMO_MARKER("Columns (legacy API)/Tree");
1193b4be Poul Sander 2025-02-03 21:28 7370
    if (ImGui::TreeNode("Tree"))
1193b4be Poul Sander 2025-02-03 21:28 7371
    {
1193b4be Poul Sander 2025-02-03 21:28 7372
        ImGui::Columns(2, "tree", true);
1193b4be Poul Sander 2025-02-03 21:28 7373
        for (int x = 0; x < 3; x++)
1193b4be Poul Sander 2025-02-03 21:28 7374
        {
1193b4be Poul Sander 2025-02-03 21:28 7375
            bool open1 = ImGui::TreeNode((void*)(intptr_t)x, "Node%d", x);
1193b4be Poul Sander 2025-02-03 21:28 7376
            ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7377
            ImGui::Text("Node contents");
1193b4be Poul Sander 2025-02-03 21:28 7378
            ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7379
            if (open1)
1193b4be Poul Sander 2025-02-03 21:28 7380
            {
1193b4be Poul Sander 2025-02-03 21:28 7381
                for (int y = 0; y < 3; y++)
1193b4be Poul Sander 2025-02-03 21:28 7382
                {
1193b4be Poul Sander 2025-02-03 21:28 7383
                    bool open2 = ImGui::TreeNode((void*)(intptr_t)y, "Node%d.%d", x, y);
1193b4be Poul Sander 2025-02-03 21:28 7384
                    ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7385
                    ImGui::Text("Node contents");
1193b4be Poul Sander 2025-02-03 21:28 7386
                    if (open2)
1193b4be Poul Sander 2025-02-03 21:28 7387
                    {
1193b4be Poul Sander 2025-02-03 21:28 7388
                        ImGui::Text("Even more contents");
1193b4be Poul Sander 2025-02-03 21:28 7389
                        if (ImGui::TreeNode("Tree in column"))
1193b4be Poul Sander 2025-02-03 21:28 7390
                        {
1193b4be Poul Sander 2025-02-03 21:28 7391
                            ImGui::Text("The quick brown fox jumps over the lazy dog");
1193b4be Poul Sander 2025-02-03 21:28 7392
                            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7393
                        }
1193b4be Poul Sander 2025-02-03 21:28 7394
                    }
1193b4be Poul Sander 2025-02-03 21:28 7395
                    ImGui::NextColumn();
1193b4be Poul Sander 2025-02-03 21:28 7396
                    if (open2)
1193b4be Poul Sander 2025-02-03 21:28 7397
                        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7398
                }
1193b4be Poul Sander 2025-02-03 21:28 7399
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7400
            }
1193b4be Poul Sander 2025-02-03 21:28 7401
        }
1193b4be Poul Sander 2025-02-03 21:28 7402
        ImGui::Columns(1);
1193b4be Poul Sander 2025-02-03 21:28 7403
        ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7404
    }
1193b4be Poul Sander 2025-02-03 21:28 7405
1193b4be Poul Sander 2025-02-03 21:28 7406
    ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7407
}
1193b4be Poul Sander 2025-02-03 21:28 7408
1193b4be Poul Sander 2025-02-03 21:28 7409
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 7410
// [SECTION] ShowDemoWindowInputs()
1193b4be Poul Sander 2025-02-03 21:28 7411
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 7412
1193b4be Poul Sander 2025-02-03 21:28 7413
static void ShowDemoWindowInputs()
1193b4be Poul Sander 2025-02-03 21:28 7414
{
1193b4be Poul Sander 2025-02-03 21:28 7415
    IMGUI_DEMO_MARKER("Inputs & Focus");
1193b4be Poul Sander 2025-02-03 21:28 7416
    if (ImGui::CollapsingHeader("Inputs & Focus"))
1193b4be Poul Sander 2025-02-03 21:28 7417
    {
1193b4be Poul Sander 2025-02-03 21:28 7418
        ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 7419
1193b4be Poul Sander 2025-02-03 21:28 7420
        // Display inputs submitted to ImGuiIO
1193b4be Poul Sander 2025-02-03 21:28 7421
        IMGUI_DEMO_MARKER("Inputs & Focus/Inputs");
1193b4be Poul Sander 2025-02-03 21:28 7422
        ImGui::SetNextItemOpen(true, ImGuiCond_Once);
1193b4be Poul Sander 2025-02-03 21:28 7423
        bool inputs_opened = ImGui::TreeNode("Inputs");
1193b4be Poul Sander 2025-02-03 21:28 7424
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7425
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 7426
            "This is a simplified view. See more detailed input state:\n"
1193b4be Poul Sander 2025-02-03 21:28 7427
            "- in 'Tools->Metrics/Debugger->Inputs'.\n"
1193b4be Poul Sander 2025-02-03 21:28 7428
            "- in 'Tools->Debug Log->IO'.");
1193b4be Poul Sander 2025-02-03 21:28 7429
        if (inputs_opened)
1193b4be Poul Sander 2025-02-03 21:28 7430
        {
1193b4be Poul Sander 2025-02-03 21:28 7431
            if (ImGui::IsMousePosValid())
1193b4be Poul Sander 2025-02-03 21:28 7432
                ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
1193b4be Poul Sander 2025-02-03 21:28 7433
            else
1193b4be Poul Sander 2025-02-03 21:28 7434
                ImGui::Text("Mouse pos: <INVALID>");
1193b4be Poul Sander 2025-02-03 21:28 7435
            ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
1193b4be Poul Sander 2025-02-03 21:28 7436
            ImGui::Text("Mouse down:");
1193b4be Poul Sander 2025-02-03 21:28 7437
            for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDown(i)) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
1193b4be Poul Sander 2025-02-03 21:28 7438
            ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
1193b4be Poul Sander 2025-02-03 21:28 7439
1193b4be Poul Sander 2025-02-03 21:28 7440
            // We iterate both legacy native range and named ImGuiKey ranges. This is a little unusual/odd but this allows
1193b4be Poul Sander 2025-02-03 21:28 7441
            // displaying the data for old/new backends.
1193b4be Poul Sander 2025-02-03 21:28 7442
            // User code should never have to go through such hoops!
1193b4be Poul Sander 2025-02-03 21:28 7443
            // You can generally iterate between ImGuiKey_NamedKey_BEGIN and ImGuiKey_NamedKey_END.
1193b4be Poul Sander 2025-02-03 21:28 7444
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
1193b4be Poul Sander 2025-02-03 21:28 7445
            struct funcs { static bool IsLegacyNativeDupe(ImGuiKey) { return false; } };
1193b4be Poul Sander 2025-02-03 21:28 7446
            ImGuiKey start_key = ImGuiKey_NamedKey_BEGIN;
1193b4be Poul Sander 2025-02-03 21:28 7447
#else
1193b4be Poul Sander 2025-02-03 21:28 7448
            struct funcs { static bool IsLegacyNativeDupe(ImGuiKey key) { return key >= 0 && key < 512 && ImGui::GetIO().KeyMap[key] != -1; } }; // Hide Native<>ImGuiKey duplicates when both exists in the array
1193b4be Poul Sander 2025-02-03 21:28 7449
            ImGuiKey start_key = (ImGuiKey)0;
1193b4be Poul Sander 2025-02-03 21:28 7450
#endif
1193b4be Poul Sander 2025-02-03 21:28 7451
            ImGui::Text("Keys down:");         for (ImGuiKey key = start_key; key < ImGuiKey_NamedKey_END; key = (ImGuiKey)(key + 1)) { if (funcs::IsLegacyNativeDupe(key) || !ImGui::IsKeyDown(key)) continue; ImGui::SameLine(); ImGui::Text((key < ImGuiKey_NamedKey_BEGIN) ? "\"%s\"" : "\"%s\" %d", ImGui::GetKeyName(key), key); }
1193b4be Poul Sander 2025-02-03 21:28 7452
            ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
1193b4be Poul Sander 2025-02-03 21:28 7453
            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.
1193b4be Poul Sander 2025-02-03 21:28 7454
1193b4be Poul Sander 2025-02-03 21:28 7455
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7456
        }
1193b4be Poul Sander 2025-02-03 21:28 7457
1193b4be Poul Sander 2025-02-03 21:28 7458
        // Display ImGuiIO output flags
1193b4be Poul Sander 2025-02-03 21:28 7459
        IMGUI_DEMO_MARKER("Inputs & Focus/Outputs");
1193b4be Poul Sander 2025-02-03 21:28 7460
        ImGui::SetNextItemOpen(true, ImGuiCond_Once);
1193b4be Poul Sander 2025-02-03 21:28 7461
        bool outputs_opened = ImGui::TreeNode("Outputs");
1193b4be Poul Sander 2025-02-03 21:28 7462
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7463
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 7464
            "The value of io.WantCaptureMouse and io.WantCaptureKeyboard are normally set by Dear ImGui "
1193b4be Poul Sander 2025-02-03 21:28 7465
            "to instruct your application of how to route inputs. Typically, when a value is true, it means "
1193b4be Poul Sander 2025-02-03 21:28 7466
            "Dear ImGui wants the corresponding inputs and we expect the underlying application to ignore them.\n\n"
1193b4be Poul Sander 2025-02-03 21:28 7467
            "The most typical case is: when hovering a window, Dear ImGui set io.WantCaptureMouse to true, "
1193b4be Poul Sander 2025-02-03 21:28 7468
            "and underlying application should ignore mouse inputs (in practice there are many and more subtle "
1193b4be Poul Sander 2025-02-03 21:28 7469
            "rules leading to how those flags are set).");
1193b4be Poul Sander 2025-02-03 21:28 7470
        if (outputs_opened)
1193b4be Poul Sander 2025-02-03 21:28 7471
        {
1193b4be Poul Sander 2025-02-03 21:28 7472
            ImGui::Text("io.WantCaptureMouse: %d", io.WantCaptureMouse);
1193b4be Poul Sander 2025-02-03 21:28 7473
            ImGui::Text("io.WantCaptureMouseUnlessPopupClose: %d", io.WantCaptureMouseUnlessPopupClose);
1193b4be Poul Sander 2025-02-03 21:28 7474
            ImGui::Text("io.WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
1193b4be Poul Sander 2025-02-03 21:28 7475
            ImGui::Text("io.WantTextInput: %d", io.WantTextInput);
1193b4be Poul Sander 2025-02-03 21:28 7476
            ImGui::Text("io.WantSetMousePos: %d", io.WantSetMousePos);
1193b4be Poul Sander 2025-02-03 21:28 7477
            ImGui::Text("io.NavActive: %d, io.NavVisible: %d", io.NavActive, io.NavVisible);
1193b4be Poul Sander 2025-02-03 21:28 7478
1193b4be Poul Sander 2025-02-03 21:28 7479
            IMGUI_DEMO_MARKER("Inputs & Focus/Outputs/WantCapture override");
1193b4be Poul Sander 2025-02-03 21:28 7480
            if (ImGui::TreeNode("WantCapture override"))
1193b4be Poul Sander 2025-02-03 21:28 7481
            {
1193b4be Poul Sander 2025-02-03 21:28 7482
                HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 7483
                    "Hovering the colored canvas will override io.WantCaptureXXX fields.\n"
1193b4be Poul Sander 2025-02-03 21:28 7484
                    "Notice how normally (when set to none), the value of io.WantCaptureKeyboard would be false when hovering "
1193b4be Poul Sander 2025-02-03 21:28 7485
                    "and true when clicking.");
1193b4be Poul Sander 2025-02-03 21:28 7486
                static int capture_override_mouse = -1;
1193b4be Poul Sander 2025-02-03 21:28 7487
                static int capture_override_keyboard = -1;
1193b4be Poul Sander 2025-02-03 21:28 7488
                const char* capture_override_desc[] = { "None", "Set to false", "Set to true" };
1193b4be Poul Sander 2025-02-03 21:28 7489
                ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
1193b4be Poul Sander 2025-02-03 21:28 7490
                ImGui::SliderInt("SetNextFrameWantCaptureMouse() on hover", &capture_override_mouse, -1, +1, capture_override_desc[capture_override_mouse + 1], ImGuiSliderFlags_AlwaysClamp);
1193b4be Poul Sander 2025-02-03 21:28 7491
                ImGui::SetNextItemWidth(ImGui::GetFontSize() * 15);
1193b4be Poul Sander 2025-02-03 21:28 7492
                ImGui::SliderInt("SetNextFrameWantCaptureKeyboard() on hover", &capture_override_keyboard, -1, +1, capture_override_desc[capture_override_keyboard + 1], ImGuiSliderFlags_AlwaysClamp);
1193b4be Poul Sander 2025-02-03 21:28 7493
1193b4be Poul Sander 2025-02-03 21:28 7494
                ImGui::ColorButton("##panel", ImVec4(0.7f, 0.1f, 0.7f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, ImVec2(128.0f, 96.0f)); // Dummy item
1193b4be Poul Sander 2025-02-03 21:28 7495
                if (ImGui::IsItemHovered() && capture_override_mouse != -1)
1193b4be Poul Sander 2025-02-03 21:28 7496
                    ImGui::SetNextFrameWantCaptureMouse(capture_override_mouse == 1);
1193b4be Poul Sander 2025-02-03 21:28 7497
                if (ImGui::IsItemHovered() && capture_override_keyboard != -1)
1193b4be Poul Sander 2025-02-03 21:28 7498
                    ImGui::SetNextFrameWantCaptureKeyboard(capture_override_keyboard == 1);
1193b4be Poul Sander 2025-02-03 21:28 7499
1193b4be Poul Sander 2025-02-03 21:28 7500
                ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7501
            }
1193b4be Poul Sander 2025-02-03 21:28 7502
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7503
        }
1193b4be Poul Sander 2025-02-03 21:28 7504
1193b4be Poul Sander 2025-02-03 21:28 7505
        // Demonstrate using Shortcut() and Routing Policies.
1193b4be Poul Sander 2025-02-03 21:28 7506
        // The general flow is:
1193b4be Poul Sander 2025-02-03 21:28 7507
        // - Code interested in a chord (e.g. "Ctrl+A") declares their intent.
1193b4be Poul Sander 2025-02-03 21:28 7508
        // - Multiple locations may be interested in same chord! Routing helps find a winner.
1193b4be Poul Sander 2025-02-03 21:28 7509
        // - Every frame, we resolve all claims and assign one owner if the modifiers are matching.
1193b4be Poul Sander 2025-02-03 21:28 7510
        // - The lower-level function is 'bool SetShortcutRouting()', returns true when caller got the route.
1193b4be Poul Sander 2025-02-03 21:28 7511
        // - Most of the times, SetShortcutRouting() is not called directly. User mostly calls Shortcut() with routing flags.
1193b4be Poul Sander 2025-02-03 21:28 7512
        // - If you call Shortcut() WITHOUT any routing option, it uses ImGuiInputFlags_RouteFocused.
1193b4be Poul Sander 2025-02-03 21:28 7513
        // TL;DR: Most uses will simply be:
1193b4be Poul Sander 2025-02-03 21:28 7514
        // - Shortcut(ImGuiMod_Ctrl | ImGuiKey_A); // Use ImGuiInputFlags_RouteFocused policy.
1193b4be Poul Sander 2025-02-03 21:28 7515
        IMGUI_DEMO_MARKER("Inputs & Focus/Shortcuts");
1193b4be Poul Sander 2025-02-03 21:28 7516
        if (ImGui::TreeNode("Shortcuts"))
1193b4be Poul Sander 2025-02-03 21:28 7517
        {
1193b4be Poul Sander 2025-02-03 21:28 7518
            static ImGuiInputFlags route_options = ImGuiInputFlags_Repeat;
1193b4be Poul Sander 2025-02-03 21:28 7519
            static ImGuiInputFlags route_type = ImGuiInputFlags_RouteFocused;
1193b4be Poul Sander 2025-02-03 21:28 7520
            ImGui::CheckboxFlags("ImGuiInputFlags_Repeat", &route_options, ImGuiInputFlags_Repeat);
1193b4be Poul Sander 2025-02-03 21:28 7521
            ImGui::RadioButton("ImGuiInputFlags_RouteActive", &route_type, ImGuiInputFlags_RouteActive);
1193b4be Poul Sander 2025-02-03 21:28 7522
            ImGui::RadioButton("ImGuiInputFlags_RouteFocused (default)", &route_type, ImGuiInputFlags_RouteFocused);
1193b4be Poul Sander 2025-02-03 21:28 7523
            ImGui::RadioButton("ImGuiInputFlags_RouteGlobal", &route_type, ImGuiInputFlags_RouteGlobal);
1193b4be Poul Sander 2025-02-03 21:28 7524
            ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 7525
            ImGui::BeginDisabled(route_type != ImGuiInputFlags_RouteGlobal);
1193b4be Poul Sander 2025-02-03 21:28 7526
            ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverFocused", &route_options, ImGuiInputFlags_RouteOverFocused);
1193b4be Poul Sander 2025-02-03 21:28 7527
            ImGui::CheckboxFlags("ImGuiInputFlags_RouteOverActive", &route_options, ImGuiInputFlags_RouteOverActive);
1193b4be Poul Sander 2025-02-03 21:28 7528
            ImGui::CheckboxFlags("ImGuiInputFlags_RouteUnlessBgFocused", &route_options, ImGuiInputFlags_RouteUnlessBgFocused);
1193b4be Poul Sander 2025-02-03 21:28 7529
            ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 7530
            ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 7531
            ImGui::RadioButton("ImGuiInputFlags_RouteAlways", &route_type, ImGuiInputFlags_RouteAlways);
1193b4be Poul Sander 2025-02-03 21:28 7532
            ImGuiInputFlags flags = route_type | route_options; // Merged flags
1193b4be Poul Sander 2025-02-03 21:28 7533
            if (route_type != ImGuiInputFlags_RouteGlobal)
1193b4be Poul Sander 2025-02-03 21:28 7534
                flags &= ~(ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused);
1193b4be Poul Sander 2025-02-03 21:28 7535
1193b4be Poul Sander 2025-02-03 21:28 7536
            ImGui::SeparatorText("Using SetNextItemShortcut()");
1193b4be Poul Sander 2025-02-03 21:28 7537
            ImGui::Text("Ctrl+S");
1193b4be Poul Sander 2025-02-03 21:28 7538
            ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, flags | ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 7539
            ImGui::Button("Save");
1193b4be Poul Sander 2025-02-03 21:28 7540
            ImGui::Text("Alt+F");
1193b4be Poul Sander 2025-02-03 21:28 7541
            ImGui::SetNextItemShortcut(ImGuiMod_Alt | ImGuiKey_F, flags | ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 7542
            static float f = 0.5f;
1193b4be Poul Sander 2025-02-03 21:28 7543
            ImGui::SliderFloat("Factor", &f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 7544
1193b4be Poul Sander 2025-02-03 21:28 7545
            ImGui::SeparatorText("Using Shortcut()");
1193b4be Poul Sander 2025-02-03 21:28 7546
            const float line_height = ImGui::GetTextLineHeightWithSpacing();
1193b4be Poul Sander 2025-02-03 21:28 7547
            const ImGuiKeyChord key_chord = ImGuiMod_Ctrl | ImGuiKey_A;
1193b4be Poul Sander 2025-02-03 21:28 7548
1193b4be Poul Sander 2025-02-03 21:28 7549
            ImGui::Text("Ctrl+A");
1193b4be Poul Sander 2025-02-03 21:28 7550
            ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
1193b4be Poul Sander 2025-02-03 21:28 7551
1193b4be Poul Sander 2025-02-03 21:28 7552
            ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(1.0f, 0.0f, 1.0f, 0.1f));
1193b4be Poul Sander 2025-02-03 21:28 7553
1193b4be Poul Sander 2025-02-03 21:28 7554
            ImGui::BeginChild("WindowA", ImVec2(-FLT_MIN, line_height * 14), true);
1193b4be Poul Sander 2025-02-03 21:28 7555
            ImGui::Text("Press CTRL+A and see who receives it!");
1193b4be Poul Sander 2025-02-03 21:28 7556
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7557
1193b4be Poul Sander 2025-02-03 21:28 7558
            // 1: Window polling for CTRL+A
1193b4be Poul Sander 2025-02-03 21:28 7559
            ImGui::Text("(in WindowA)");
1193b4be Poul Sander 2025-02-03 21:28 7560
            ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
1193b4be Poul Sander 2025-02-03 21:28 7561
1193b4be Poul Sander 2025-02-03 21:28 7562
            // 2: InputText also polling for CTRL+A: it always uses _RouteFocused internally (gets priority when active)
1193b4be Poul Sander 2025-02-03 21:28 7563
            // (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
1193b4be Poul Sander 2025-02-03 21:28 7564
            //char str[16] = "Press CTRL+A";
1193b4be Poul Sander 2025-02-03 21:28 7565
            //ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 7566
            //ImGui::InputText("InputTextB", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
1193b4be Poul Sander 2025-02-03 21:28 7567
            //ImGuiID item_id = ImGui::GetItemID();
1193b4be Poul Sander 2025-02-03 21:28 7568
            //ImGui::SameLine(); HelpMarker("Internal widgets always use _RouteFocused");
1193b4be Poul Sander 2025-02-03 21:28 7569
            //ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, item_id) ? "PRESSED" : "...");
1193b4be Poul Sander 2025-02-03 21:28 7570
1193b4be Poul Sander 2025-02-03 21:28 7571
            // 3: Dummy child is not claiming the route: focusing them shouldn't steal route away from WindowA
1193b4be Poul Sander 2025-02-03 21:28 7572
            ImGui::BeginChild("ChildD", ImVec2(-FLT_MIN, line_height * 4), true);
1193b4be Poul Sander 2025-02-03 21:28 7573
            ImGui::Text("(in ChildD: not using same Shortcut)");
1193b4be Poul Sander 2025-02-03 21:28 7574
            ImGui::Text("IsWindowFocused: %d", ImGui::IsWindowFocused());
1193b4be Poul Sander 2025-02-03 21:28 7575
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 7576
1193b4be Poul Sander 2025-02-03 21:28 7577
            // 4: Child window polling for CTRL+A. It is deeper than WindowA and gets priority when focused.
1193b4be Poul Sander 2025-02-03 21:28 7578
            ImGui::BeginChild("ChildE", ImVec2(-FLT_MIN, line_height * 4), true);
1193b4be Poul Sander 2025-02-03 21:28 7579
            ImGui::Text("(in ChildE: using same Shortcut)");
1193b4be Poul Sander 2025-02-03 21:28 7580
            ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
1193b4be Poul Sander 2025-02-03 21:28 7581
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 7582
1193b4be Poul Sander 2025-02-03 21:28 7583
            // 5: In a popup
1193b4be Poul Sander 2025-02-03 21:28 7584
            if (ImGui::Button("Open Popup"))
1193b4be Poul Sander 2025-02-03 21:28 7585
                ImGui::OpenPopup("PopupF");
1193b4be Poul Sander 2025-02-03 21:28 7586
            if (ImGui::BeginPopup("PopupF"))
1193b4be Poul Sander 2025-02-03 21:28 7587
            {
1193b4be Poul Sander 2025-02-03 21:28 7588
                ImGui::Text("(in PopupF)");
1193b4be Poul Sander 2025-02-03 21:28 7589
                ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags) ? "PRESSED" : "...");
1193b4be Poul Sander 2025-02-03 21:28 7590
                // (Commmented because the owner-aware version of Shortcut() is still in imgui_internal.h)
1193b4be Poul Sander 2025-02-03 21:28 7591
                //ImGui::InputText("InputTextG", str, IM_ARRAYSIZE(str), ImGuiInputTextFlags_ReadOnly);
1193b4be Poul Sander 2025-02-03 21:28 7592
                //ImGui::Text("IsWindowFocused: %d, Shortcut: %s", ImGui::IsWindowFocused(), ImGui::Shortcut(key_chord, flags, ImGui::GetItemID()) ? "PRESSED" : "...");
1193b4be Poul Sander 2025-02-03 21:28 7593
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 7594
            }
1193b4be Poul Sander 2025-02-03 21:28 7595
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 7596
            ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 7597
1193b4be Poul Sander 2025-02-03 21:28 7598
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7599
        }
1193b4be Poul Sander 2025-02-03 21:28 7600
1193b4be Poul Sander 2025-02-03 21:28 7601
        // Display mouse cursors
1193b4be Poul Sander 2025-02-03 21:28 7602
        IMGUI_DEMO_MARKER("Inputs & Focus/Mouse Cursors");
1193b4be Poul Sander 2025-02-03 21:28 7603
        if (ImGui::TreeNode("Mouse Cursors"))
1193b4be Poul Sander 2025-02-03 21:28 7604
        {
1193b4be Poul Sander 2025-02-03 21:28 7605
            const char* mouse_cursors_names[] = { "Arrow", "TextInput", "ResizeAll", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand", "NotAllowed" };
1193b4be Poul Sander 2025-02-03 21:28 7606
            IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
1193b4be Poul Sander 2025-02-03 21:28 7607
1193b4be Poul Sander 2025-02-03 21:28 7608
            ImGuiMouseCursor current = ImGui::GetMouseCursor();
1193b4be Poul Sander 2025-02-03 21:28 7609
            const char* cursor_name = (current >= ImGuiMouseCursor_Arrow) && (current < ImGuiMouseCursor_COUNT) ? mouse_cursors_names[current] : "N/A";
1193b4be Poul Sander 2025-02-03 21:28 7610
            ImGui::Text("Current mouse cursor = %d: %s", current, cursor_name);
1193b4be Poul Sander 2025-02-03 21:28 7611
            ImGui::BeginDisabled(true);
1193b4be Poul Sander 2025-02-03 21:28 7612
            ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", &io.BackendFlags, ImGuiBackendFlags_HasMouseCursors);
1193b4be Poul Sander 2025-02-03 21:28 7613
            ImGui::EndDisabled();
1193b4be Poul Sander 2025-02-03 21:28 7614
1193b4be Poul Sander 2025-02-03 21:28 7615
            ImGui::Text("Hover to see mouse cursors:");
1193b4be Poul Sander 2025-02-03 21:28 7616
            ImGui::SameLine(); HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 7617
                "Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. "
1193b4be Poul Sander 2025-02-03 21:28 7618
                "If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, "
1193b4be Poul Sander 2025-02-03 21:28 7619
                "otherwise your backend needs to handle it.");
1193b4be Poul Sander 2025-02-03 21:28 7620
            for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
1193b4be Poul Sander 2025-02-03 21:28 7621
            {
1193b4be Poul Sander 2025-02-03 21:28 7622
                char label[32];
1193b4be Poul Sander 2025-02-03 21:28 7623
                sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
1193b4be Poul Sander 2025-02-03 21:28 7624
                ImGui::Bullet(); ImGui::Selectable(label, false);
1193b4be Poul Sander 2025-02-03 21:28 7625
                if (ImGui::IsItemHovered())
1193b4be Poul Sander 2025-02-03 21:28 7626
                    ImGui::SetMouseCursor(i);
1193b4be Poul Sander 2025-02-03 21:28 7627
            }
1193b4be Poul Sander 2025-02-03 21:28 7628
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7629
        }
1193b4be Poul Sander 2025-02-03 21:28 7630
1193b4be Poul Sander 2025-02-03 21:28 7631
        IMGUI_DEMO_MARKER("Inputs & Focus/Tabbing");
1193b4be Poul Sander 2025-02-03 21:28 7632
        if (ImGui::TreeNode("Tabbing"))
1193b4be Poul Sander 2025-02-03 21:28 7633
        {
1193b4be Poul Sander 2025-02-03 21:28 7634
            ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
1193b4be Poul Sander 2025-02-03 21:28 7635
            static char buf[32] = "hello";
1193b4be Poul Sander 2025-02-03 21:28 7636
            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7637
            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7638
            ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7639
            ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true);
1193b4be Poul Sander 2025-02-03 21:28 7640
            ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7641
            ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
1193b4be Poul Sander 2025-02-03 21:28 7642
            ImGui::PopItemFlag();
1193b4be Poul Sander 2025-02-03 21:28 7643
            ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7644
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7645
        }
1193b4be Poul Sander 2025-02-03 21:28 7646
1193b4be Poul Sander 2025-02-03 21:28 7647
        IMGUI_DEMO_MARKER("Inputs & Focus/Focus from code");
1193b4be Poul Sander 2025-02-03 21:28 7648
        if (ImGui::TreeNode("Focus from code"))
1193b4be Poul Sander 2025-02-03 21:28 7649
        {
1193b4be Poul Sander 2025-02-03 21:28 7650
            bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7651
            bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7652
            bool focus_3 = ImGui::Button("Focus on 3");
1193b4be Poul Sander 2025-02-03 21:28 7653
            int has_focus = 0;
1193b4be Poul Sander 2025-02-03 21:28 7654
            static char buf[128] = "click on a button to set focus";
1193b4be Poul Sander 2025-02-03 21:28 7655
1193b4be Poul Sander 2025-02-03 21:28 7656
            if (focus_1) ImGui::SetKeyboardFocusHere();
1193b4be Poul Sander 2025-02-03 21:28 7657
            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7658
            if (ImGui::IsItemActive()) has_focus = 1;
1193b4be Poul Sander 2025-02-03 21:28 7659
1193b4be Poul Sander 2025-02-03 21:28 7660
            if (focus_2) ImGui::SetKeyboardFocusHere();
1193b4be Poul Sander 2025-02-03 21:28 7661
            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7662
            if (ImGui::IsItemActive()) has_focus = 2;
1193b4be Poul Sander 2025-02-03 21:28 7663
1193b4be Poul Sander 2025-02-03 21:28 7664
            ImGui::PushItemFlag(ImGuiItemFlags_NoTabStop, true);
1193b4be Poul Sander 2025-02-03 21:28 7665
            if (focus_3) ImGui::SetKeyboardFocusHere();
1193b4be Poul Sander 2025-02-03 21:28 7666
            ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
1193b4be Poul Sander 2025-02-03 21:28 7667
            if (ImGui::IsItemActive()) has_focus = 3;
1193b4be Poul Sander 2025-02-03 21:28 7668
            ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
1193b4be Poul Sander 2025-02-03 21:28 7669
            ImGui::PopItemFlag();
1193b4be Poul Sander 2025-02-03 21:28 7670
1193b4be Poul Sander 2025-02-03 21:28 7671
            if (has_focus)
1193b4be Poul Sander 2025-02-03 21:28 7672
                ImGui::Text("Item with focus: %d", has_focus);
1193b4be Poul Sander 2025-02-03 21:28 7673
            else
1193b4be Poul Sander 2025-02-03 21:28 7674
                ImGui::Text("Item with focus: <none>");
1193b4be Poul Sander 2025-02-03 21:28 7675
1193b4be Poul Sander 2025-02-03 21:28 7676
            // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
1193b4be Poul Sander 2025-02-03 21:28 7677
            static float f3[3] = { 0.0f, 0.0f, 0.0f };
1193b4be Poul Sander 2025-02-03 21:28 7678
            int focus_ahead = -1;
1193b4be Poul Sander 2025-02-03 21:28 7679
            if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7680
            if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7681
            if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
1193b4be Poul Sander 2025-02-03 21:28 7682
            if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
1193b4be Poul Sander 2025-02-03 21:28 7683
            ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 7684
1193b4be Poul Sander 2025-02-03 21:28 7685
            ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
1193b4be Poul Sander 2025-02-03 21:28 7686
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7687
        }
1193b4be Poul Sander 2025-02-03 21:28 7688
1193b4be Poul Sander 2025-02-03 21:28 7689
        IMGUI_DEMO_MARKER("Inputs & Focus/Dragging");
1193b4be Poul Sander 2025-02-03 21:28 7690
        if (ImGui::TreeNode("Dragging"))
1193b4be Poul Sander 2025-02-03 21:28 7691
        {
1193b4be Poul Sander 2025-02-03 21:28 7692
            ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
1193b4be Poul Sander 2025-02-03 21:28 7693
            for (int button = 0; button < 3; button++)
1193b4be Poul Sander 2025-02-03 21:28 7694
            {
1193b4be Poul Sander 2025-02-03 21:28 7695
                ImGui::Text("IsMouseDragging(%d):", button);
1193b4be Poul Sander 2025-02-03 21:28 7696
                ImGui::Text("  w/ default threshold: %d,", ImGui::IsMouseDragging(button));
1193b4be Poul Sander 2025-02-03 21:28 7697
                ImGui::Text("  w/ zero threshold: %d,", ImGui::IsMouseDragging(button, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 7698
                ImGui::Text("  w/ large threshold: %d,", ImGui::IsMouseDragging(button, 20.0f));
1193b4be Poul Sander 2025-02-03 21:28 7699
            }
1193b4be Poul Sander 2025-02-03 21:28 7700
1193b4be Poul Sander 2025-02-03 21:28 7701
            ImGui::Button("Drag Me");
1193b4be Poul Sander 2025-02-03 21:28 7702
            if (ImGui::IsItemActive())
1193b4be Poul Sander 2025-02-03 21:28 7703
                ImGui::GetForegroundDrawList()->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); // Draw a line between the button and the mouse cursor
1193b4be Poul Sander 2025-02-03 21:28 7704
1193b4be Poul Sander 2025-02-03 21:28 7705
            // Drag operations gets "unlocked" when the mouse has moved past a certain threshold
1193b4be Poul Sander 2025-02-03 21:28 7706
            // (the default threshold is stored in io.MouseDragThreshold). You can request a lower or higher
1193b4be Poul Sander 2025-02-03 21:28 7707
            // threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta().
1193b4be Poul Sander 2025-02-03 21:28 7708
            ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 7709
            ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
1193b4be Poul Sander 2025-02-03 21:28 7710
            ImVec2 mouse_delta = io.MouseDelta;
1193b4be Poul Sander 2025-02-03 21:28 7711
            ImGui::Text("GetMouseDragDelta(0):");
1193b4be Poul Sander 2025-02-03 21:28 7712
            ImGui::Text("  w/ default threshold: (%.1f, %.1f)", value_with_lock_threshold.x, value_with_lock_threshold.y);
1193b4be Poul Sander 2025-02-03 21:28 7713
            ImGui::Text("  w/ zero threshold: (%.1f, %.1f)", value_raw.x, value_raw.y);
1193b4be Poul Sander 2025-02-03 21:28 7714
            ImGui::Text("io.MouseDelta: (%.1f, %.1f)", mouse_delta.x, mouse_delta.y);
1193b4be Poul Sander 2025-02-03 21:28 7715
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 7716
        }
1193b4be Poul Sander 2025-02-03 21:28 7717
    }
1193b4be Poul Sander 2025-02-03 21:28 7718
}
1193b4be Poul Sander 2025-02-03 21:28 7719
1193b4be Poul Sander 2025-02-03 21:28 7720
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 7721
// [SECTION] About Window / ShowAboutWindow()
1193b4be Poul Sander 2025-02-03 21:28 7722
// Access from Dear ImGui Demo -> Tools -> About
1193b4be Poul Sander 2025-02-03 21:28 7723
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 7724
1193b4be Poul Sander 2025-02-03 21:28 7725
void ImGui::ShowAboutWindow(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 7726
{
1193b4be Poul Sander 2025-02-03 21:28 7727
    if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
1193b4be Poul Sander 2025-02-03 21:28 7728
    {
1193b4be Poul Sander 2025-02-03 21:28 7729
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 7730
        return;
1193b4be Poul Sander 2025-02-03 21:28 7731
    }
1193b4be Poul Sander 2025-02-03 21:28 7732
    IMGUI_DEMO_MARKER("Tools/About Dear ImGui");
1193b4be Poul Sander 2025-02-03 21:28 7733
    ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
1193b4be Poul Sander 2025-02-03 21:28 7734
1193b4be Poul Sander 2025-02-03 21:28 7735
    ImGui::TextLinkOpenURL("Homepage", "https://github.com/ocornut/imgui");
1193b4be Poul Sander 2025-02-03 21:28 7736
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7737
    ImGui::TextLinkOpenURL("FAQ", "https://github.com/ocornut/imgui/blob/master/docs/FAQ.md");
1193b4be Poul Sander 2025-02-03 21:28 7738
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7739
    ImGui::TextLinkOpenURL("Wiki", "https://github.com/ocornut/imgui/wiki");
1193b4be Poul Sander 2025-02-03 21:28 7740
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7741
    ImGui::TextLinkOpenURL("Releases", "https://github.com/ocornut/imgui/releases");
1193b4be Poul Sander 2025-02-03 21:28 7742
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7743
    ImGui::TextLinkOpenURL("Funding", "https://github.com/ocornut/imgui/wiki/Funding");
1193b4be Poul Sander 2025-02-03 21:28 7744
1193b4be Poul Sander 2025-02-03 21:28 7745
    ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7746
    ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
1193b4be Poul Sander 2025-02-03 21:28 7747
    ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
1193b4be Poul Sander 2025-02-03 21:28 7748
    ImGui::Text("If your company uses this, please consider funding the project.");
1193b4be Poul Sander 2025-02-03 21:28 7749
1193b4be Poul Sander 2025-02-03 21:28 7750
    static bool show_config_info = false;
1193b4be Poul Sander 2025-02-03 21:28 7751
    ImGui::Checkbox("Config/Build Information", &show_config_info);
1193b4be Poul Sander 2025-02-03 21:28 7752
    if (show_config_info)
1193b4be Poul Sander 2025-02-03 21:28 7753
    {
1193b4be Poul Sander 2025-02-03 21:28 7754
        ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 7755
        ImGuiStyle& style = ImGui::GetStyle();
1193b4be Poul Sander 2025-02-03 21:28 7756
1193b4be Poul Sander 2025-02-03 21:28 7757
        bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
1193b4be Poul Sander 2025-02-03 21:28 7758
        ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18);
1193b4be Poul Sander 2025-02-03 21:28 7759
        ImGui::BeginChild(ImGui::GetID("cfg_infos"), child_size, ImGuiChildFlags_FrameStyle);
1193b4be Poul Sander 2025-02-03 21:28 7760
        if (copy_to_clipboard)
1193b4be Poul Sander 2025-02-03 21:28 7761
        {
1193b4be Poul Sander 2025-02-03 21:28 7762
            ImGui::LogToClipboard();
1193b4be Poul Sander 2025-02-03 21:28 7763
            ImGui::LogText("```\n"); // Back quotes will make text appears without formatting when pasting on GitHub
1193b4be Poul Sander 2025-02-03 21:28 7764
        }
1193b4be Poul Sander 2025-02-03 21:28 7765
1193b4be Poul Sander 2025-02-03 21:28 7766
        ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
1193b4be Poul Sander 2025-02-03 21:28 7767
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7768
        ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
1193b4be Poul Sander 2025-02-03 21:28 7769
        ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
1193b4be Poul Sander 2025-02-03 21:28 7770
#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7771
        ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7772
#endif
1193b4be Poul Sander 2025-02-03 21:28 7773
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO
1193b4be Poul Sander 2025-02-03 21:28 7774
        ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_KEYIO");
1193b4be Poul Sander 2025-02-03 21:28 7775
#endif
1193b4be Poul Sander 2025-02-03 21:28 7776
#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7777
        ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7778
#endif
1193b4be Poul Sander 2025-02-03 21:28 7779
#ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7780
        ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7781
#endif
1193b4be Poul Sander 2025-02-03 21:28 7782
#ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7783
        ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7784
#endif
1193b4be Poul Sander 2025-02-03 21:28 7785
#ifdef IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7786
        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7787
#endif
1193b4be Poul Sander 2025-02-03 21:28 7788
#ifdef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7789
        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7790
#endif
1193b4be Poul Sander 2025-02-03 21:28 7791
#ifdef IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7792
        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7793
#endif
1193b4be Poul Sander 2025-02-03 21:28 7794
#ifdef IMGUI_DISABLE_FILE_FUNCTIONS
1193b4be Poul Sander 2025-02-03 21:28 7795
        ImGui::Text("define: IMGUI_DISABLE_FILE_FUNCTIONS");
1193b4be Poul Sander 2025-02-03 21:28 7796
#endif
1193b4be Poul Sander 2025-02-03 21:28 7797
#ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
1193b4be Poul Sander 2025-02-03 21:28 7798
        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
1193b4be Poul Sander 2025-02-03 21:28 7799
#endif
1193b4be Poul Sander 2025-02-03 21:28 7800
#ifdef IMGUI_USE_BGRA_PACKED_COLOR
1193b4be Poul Sander 2025-02-03 21:28 7801
        ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
1193b4be Poul Sander 2025-02-03 21:28 7802
#endif
1193b4be Poul Sander 2025-02-03 21:28 7803
#ifdef _WIN32
1193b4be Poul Sander 2025-02-03 21:28 7804
        ImGui::Text("define: _WIN32");
1193b4be Poul Sander 2025-02-03 21:28 7805
#endif
1193b4be Poul Sander 2025-02-03 21:28 7806
#ifdef _WIN64
1193b4be Poul Sander 2025-02-03 21:28 7807
        ImGui::Text("define: _WIN64");
1193b4be Poul Sander 2025-02-03 21:28 7808
#endif
1193b4be Poul Sander 2025-02-03 21:28 7809
#ifdef __linux__
1193b4be Poul Sander 2025-02-03 21:28 7810
        ImGui::Text("define: __linux__");
1193b4be Poul Sander 2025-02-03 21:28 7811
#endif
1193b4be Poul Sander 2025-02-03 21:28 7812
#ifdef __APPLE__
1193b4be Poul Sander 2025-02-03 21:28 7813
        ImGui::Text("define: __APPLE__");
1193b4be Poul Sander 2025-02-03 21:28 7814
#endif
1193b4be Poul Sander 2025-02-03 21:28 7815
#ifdef _MSC_VER
1193b4be Poul Sander 2025-02-03 21:28 7816
        ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
1193b4be Poul Sander 2025-02-03 21:28 7817
#endif
1193b4be Poul Sander 2025-02-03 21:28 7818
#ifdef _MSVC_LANG
1193b4be Poul Sander 2025-02-03 21:28 7819
        ImGui::Text("define: _MSVC_LANG=%d", (int)_MSVC_LANG);
1193b4be Poul Sander 2025-02-03 21:28 7820
#endif
1193b4be Poul Sander 2025-02-03 21:28 7821
#ifdef __MINGW32__
1193b4be Poul Sander 2025-02-03 21:28 7822
        ImGui::Text("define: __MINGW32__");
1193b4be Poul Sander 2025-02-03 21:28 7823
#endif
1193b4be Poul Sander 2025-02-03 21:28 7824
#ifdef __MINGW64__
1193b4be Poul Sander 2025-02-03 21:28 7825
        ImGui::Text("define: __MINGW64__");
1193b4be Poul Sander 2025-02-03 21:28 7826
#endif
1193b4be Poul Sander 2025-02-03 21:28 7827
#ifdef __GNUC__
1193b4be Poul Sander 2025-02-03 21:28 7828
        ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
1193b4be Poul Sander 2025-02-03 21:28 7829
#endif
1193b4be Poul Sander 2025-02-03 21:28 7830
#ifdef __clang_version__
1193b4be Poul Sander 2025-02-03 21:28 7831
        ImGui::Text("define: __clang_version__=%s", __clang_version__);
1193b4be Poul Sander 2025-02-03 21:28 7832
#endif
1193b4be Poul Sander 2025-02-03 21:28 7833
#ifdef __EMSCRIPTEN__
1193b4be Poul Sander 2025-02-03 21:28 7834
        ImGui::Text("define: __EMSCRIPTEN__");
1193b4be Poul Sander 2025-02-03 21:28 7835
        ImGui::Text("Emscripten: %d.%d.%d", __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__);
1193b4be Poul Sander 2025-02-03 21:28 7836
#endif
1193b4be Poul Sander 2025-02-03 21:28 7837
#ifdef IMGUI_HAS_VIEWPORT
1193b4be Poul Sander 2025-02-03 21:28 7838
        ImGui::Text("define: IMGUI_HAS_VIEWPORT");
1193b4be Poul Sander 2025-02-03 21:28 7839
#endif
1193b4be Poul Sander 2025-02-03 21:28 7840
#ifdef IMGUI_HAS_DOCK
1193b4be Poul Sander 2025-02-03 21:28 7841
        ImGui::Text("define: IMGUI_HAS_DOCK");
1193b4be Poul Sander 2025-02-03 21:28 7842
#endif
1193b4be Poul Sander 2025-02-03 21:28 7843
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7844
        ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
1193b4be Poul Sander 2025-02-03 21:28 7845
        ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
1193b4be Poul Sander 2025-02-03 21:28 7846
        ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
1193b4be Poul Sander 2025-02-03 21:28 7847
        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)        ImGui::Text(" NavEnableKeyboard");
1193b4be Poul Sander 2025-02-03 21:28 7848
        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
1193b4be Poul Sander 2025-02-03 21:28 7849
        if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
1193b4be Poul Sander 2025-02-03 21:28 7850
        if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
1193b4be Poul Sander 2025-02-03 21:28 7851
        if (io.ConfigFlags & ImGuiConfigFlags_NoKeyboard)               ImGui::Text(" NoKeyboard");
1193b4be Poul Sander 2025-02-03 21:28 7852
        if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)            ImGui::Text(" DockingEnable");
1193b4be Poul Sander 2025-02-03 21:28 7853
        if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)          ImGui::Text(" ViewportsEnable");
1193b4be Poul Sander 2025-02-03 21:28 7854
        if (io.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleViewports)  ImGui::Text(" DpiEnableScaleViewports");
1193b4be Poul Sander 2025-02-03 21:28 7855
        if (io.ConfigFlags & ImGuiConfigFlags_DpiEnableScaleFonts)      ImGui::Text(" DpiEnableScaleFonts");
1193b4be Poul Sander 2025-02-03 21:28 7856
        if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
1193b4be Poul Sander 2025-02-03 21:28 7857
        if (io.ConfigViewportsNoAutoMerge)                              ImGui::Text("io.ConfigViewportsNoAutoMerge");
1193b4be Poul Sander 2025-02-03 21:28 7858
        if (io.ConfigViewportsNoTaskBarIcon)                            ImGui::Text("io.ConfigViewportsNoTaskBarIcon");
1193b4be Poul Sander 2025-02-03 21:28 7859
        if (io.ConfigViewportsNoDecoration)                             ImGui::Text("io.ConfigViewportsNoDecoration");
1193b4be Poul Sander 2025-02-03 21:28 7860
        if (io.ConfigViewportsNoDefaultParent)                          ImGui::Text("io.ConfigViewportsNoDefaultParent");
1193b4be Poul Sander 2025-02-03 21:28 7861
        if (io.ConfigDockingNoSplit)                                    ImGui::Text("io.ConfigDockingNoSplit");
1193b4be Poul Sander 2025-02-03 21:28 7862
        if (io.ConfigDockingWithShift)                                  ImGui::Text("io.ConfigDockingWithShift");
1193b4be Poul Sander 2025-02-03 21:28 7863
        if (io.ConfigDockingAlwaysTabBar)                               ImGui::Text("io.ConfigDockingAlwaysTabBar");
1193b4be Poul Sander 2025-02-03 21:28 7864
        if (io.ConfigDockingTransparentPayload)                         ImGui::Text("io.ConfigDockingTransparentPayload");
1193b4be Poul Sander 2025-02-03 21:28 7865
        if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
1193b4be Poul Sander 2025-02-03 21:28 7866
        if (io.ConfigNavMoveSetMousePos)                                ImGui::Text("io.ConfigNavMoveSetMousePos");
1193b4be Poul Sander 2025-02-03 21:28 7867
        if (io.ConfigNavCaptureKeyboard)                                ImGui::Text("io.ConfigNavCaptureKeyboard");
1193b4be Poul Sander 2025-02-03 21:28 7868
        if (io.ConfigInputTextCursorBlink)                              ImGui::Text("io.ConfigInputTextCursorBlink");
1193b4be Poul Sander 2025-02-03 21:28 7869
        if (io.ConfigWindowsResizeFromEdges)                            ImGui::Text("io.ConfigWindowsResizeFromEdges");
1193b4be Poul Sander 2025-02-03 21:28 7870
        if (io.ConfigWindowsMoveFromTitleBarOnly)                       ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
1193b4be Poul Sander 2025-02-03 21:28 7871
        if (io.ConfigMemoryCompactTimer >= 0.0f)                        ImGui::Text("io.ConfigMemoryCompactTimer = %.1f", io.ConfigMemoryCompactTimer);
1193b4be Poul Sander 2025-02-03 21:28 7872
        ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
1193b4be Poul Sander 2025-02-03 21:28 7873
        if (io.BackendFlags & ImGuiBackendFlags_HasGamepad)             ImGui::Text(" HasGamepad");
1193b4be Poul Sander 2025-02-03 21:28 7874
        if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)        ImGui::Text(" HasMouseCursors");
1193b4be Poul Sander 2025-02-03 21:28 7875
        if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)         ImGui::Text(" HasSetMousePos");
1193b4be Poul Sander 2025-02-03 21:28 7876
        if (io.BackendFlags & ImGuiBackendFlags_PlatformHasViewports)   ImGui::Text(" PlatformHasViewports");
1193b4be Poul Sander 2025-02-03 21:28 7877
        if (io.BackendFlags & ImGuiBackendFlags_HasMouseHoveredViewport)ImGui::Text(" HasMouseHoveredViewport");
1193b4be Poul Sander 2025-02-03 21:28 7878
        if (io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset)   ImGui::Text(" RendererHasVtxOffset");
1193b4be Poul Sander 2025-02-03 21:28 7879
        if (io.BackendFlags & ImGuiBackendFlags_RendererHasViewports)   ImGui::Text(" RendererHasViewports");
1193b4be Poul Sander 2025-02-03 21:28 7880
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7881
        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);
1193b4be Poul Sander 2025-02-03 21:28 7882
        ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
1193b4be Poul Sander 2025-02-03 21:28 7883
        ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
1193b4be Poul Sander 2025-02-03 21:28 7884
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 7885
        ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
1193b4be Poul Sander 2025-02-03 21:28 7886
        ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
1193b4be Poul Sander 2025-02-03 21:28 7887
        ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
1193b4be Poul Sander 2025-02-03 21:28 7888
        ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
1193b4be Poul Sander 2025-02-03 21:28 7889
        ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
1193b4be Poul Sander 2025-02-03 21:28 7890
        ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
1193b4be Poul Sander 2025-02-03 21:28 7891
        ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
1193b4be Poul Sander 2025-02-03 21:28 7892
1193b4be Poul Sander 2025-02-03 21:28 7893
        if (copy_to_clipboard)
1193b4be Poul Sander 2025-02-03 21:28 7894
        {
1193b4be Poul Sander 2025-02-03 21:28 7895
            ImGui::LogText("\n```\n");
1193b4be Poul Sander 2025-02-03 21:28 7896
            ImGui::LogFinish();
1193b4be Poul Sander 2025-02-03 21:28 7897
        }
1193b4be Poul Sander 2025-02-03 21:28 7898
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 7899
    }
1193b4be Poul Sander 2025-02-03 21:28 7900
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 7901
}
1193b4be Poul Sander 2025-02-03 21:28 7902
1193b4be Poul Sander 2025-02-03 21:28 7903
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 7904
// [SECTION] Style Editor / ShowStyleEditor()
1193b4be Poul Sander 2025-02-03 21:28 7905
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 7906
// - ShowFontSelector()
1193b4be Poul Sander 2025-02-03 21:28 7907
// - ShowStyleSelector()
1193b4be Poul Sander 2025-02-03 21:28 7908
// - ShowStyleEditor()
1193b4be Poul Sander 2025-02-03 21:28 7909
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 7910
1193b4be Poul Sander 2025-02-03 21:28 7911
// Forward declare ShowFontAtlas() which isn't worth putting in public API yet
1193b4be Poul Sander 2025-02-03 21:28 7912
namespace ImGui { IMGUI_API void ShowFontAtlas(ImFontAtlas* atlas); }
1193b4be Poul Sander 2025-02-03 21:28 7913
1193b4be Poul Sander 2025-02-03 21:28 7914
// Demo helper function to select among loaded fonts.
1193b4be Poul Sander 2025-02-03 21:28 7915
// Here we use the regular BeginCombo()/EndCombo() api which is the more flexible one.
1193b4be Poul Sander 2025-02-03 21:28 7916
void ImGui::ShowFontSelector(const char* label)
1193b4be Poul Sander 2025-02-03 21:28 7917
{
1193b4be Poul Sander 2025-02-03 21:28 7918
    ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 7919
    ImFont* font_current = ImGui::GetFont();
1193b4be Poul Sander 2025-02-03 21:28 7920
    if (ImGui::BeginCombo(label, font_current->GetDebugName()))
1193b4be Poul Sander 2025-02-03 21:28 7921
    {
1193b4be Poul Sander 2025-02-03 21:28 7922
        for (ImFont* font : io.Fonts->Fonts)
1193b4be Poul Sander 2025-02-03 21:28 7923
        {
1193b4be Poul Sander 2025-02-03 21:28 7924
            ImGui::PushID((void*)font);
1193b4be Poul Sander 2025-02-03 21:28 7925
            if (ImGui::Selectable(font->GetDebugName(), font == font_current))
1193b4be Poul Sander 2025-02-03 21:28 7926
                io.FontDefault = font;
1193b4be Poul Sander 2025-02-03 21:28 7927
            ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 7928
        }
1193b4be Poul Sander 2025-02-03 21:28 7929
        ImGui::EndCombo();
1193b4be Poul Sander 2025-02-03 21:28 7930
    }
1193b4be Poul Sander 2025-02-03 21:28 7931
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7932
    HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 7933
        "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
1193b4be Poul Sander 2025-02-03 21:28 7934
        "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
1193b4be Poul Sander 2025-02-03 21:28 7935
        "- Read FAQ and docs/FONTS.md for more details.\n"
1193b4be Poul Sander 2025-02-03 21:28 7936
        "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
1193b4be Poul Sander 2025-02-03 21:28 7937
}
1193b4be Poul Sander 2025-02-03 21:28 7938
1193b4be Poul Sander 2025-02-03 21:28 7939
// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
1193b4be Poul Sander 2025-02-03 21:28 7940
// Here we use the simplified Combo() api that packs items into a single literal string.
1193b4be Poul Sander 2025-02-03 21:28 7941
// Useful for quick combo boxes where the choices are known locally.
1193b4be Poul Sander 2025-02-03 21:28 7942
bool ImGui::ShowStyleSelector(const char* label)
1193b4be Poul Sander 2025-02-03 21:28 7943
{
1193b4be Poul Sander 2025-02-03 21:28 7944
    static int style_idx = -1;
1193b4be Poul Sander 2025-02-03 21:28 7945
    if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0"))
1193b4be Poul Sander 2025-02-03 21:28 7946
    {
1193b4be Poul Sander 2025-02-03 21:28 7947
        switch (style_idx)
1193b4be Poul Sander 2025-02-03 21:28 7948
        {
1193b4be Poul Sander 2025-02-03 21:28 7949
        case 0: ImGui::StyleColorsDark(); break;
1193b4be Poul Sander 2025-02-03 21:28 7950
        case 1: ImGui::StyleColorsLight(); break;
1193b4be Poul Sander 2025-02-03 21:28 7951
        case 2: ImGui::StyleColorsClassic(); break;
1193b4be Poul Sander 2025-02-03 21:28 7952
        }
1193b4be Poul Sander 2025-02-03 21:28 7953
        return true;
1193b4be Poul Sander 2025-02-03 21:28 7954
    }
1193b4be Poul Sander 2025-02-03 21:28 7955
    return false;
1193b4be Poul Sander 2025-02-03 21:28 7956
}
1193b4be Poul Sander 2025-02-03 21:28 7957
1193b4be Poul Sander 2025-02-03 21:28 7958
void ImGui::ShowStyleEditor(ImGuiStyle* ref)
1193b4be Poul Sander 2025-02-03 21:28 7959
{
1193b4be Poul Sander 2025-02-03 21:28 7960
    IMGUI_DEMO_MARKER("Tools/Style Editor");
1193b4be Poul Sander 2025-02-03 21:28 7961
    // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
1193b4be Poul Sander 2025-02-03 21:28 7962
    // (without a reference style pointer, we will use one compared locally as a reference)
1193b4be Poul Sander 2025-02-03 21:28 7963
    ImGuiStyle& style = ImGui::GetStyle();
1193b4be Poul Sander 2025-02-03 21:28 7964
    static ImGuiStyle ref_saved_style;
1193b4be Poul Sander 2025-02-03 21:28 7965
1193b4be Poul Sander 2025-02-03 21:28 7966
    // Default to using internal storage as reference
1193b4be Poul Sander 2025-02-03 21:28 7967
    static bool init = true;
1193b4be Poul Sander 2025-02-03 21:28 7968
    if (init && ref == NULL)
1193b4be Poul Sander 2025-02-03 21:28 7969
        ref_saved_style = style;
1193b4be Poul Sander 2025-02-03 21:28 7970
    init = false;
1193b4be Poul Sander 2025-02-03 21:28 7971
    if (ref == NULL)
1193b4be Poul Sander 2025-02-03 21:28 7972
        ref = &ref_saved_style;
1193b4be Poul Sander 2025-02-03 21:28 7973
1193b4be Poul Sander 2025-02-03 21:28 7974
    ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
1193b4be Poul Sander 2025-02-03 21:28 7975
1193b4be Poul Sander 2025-02-03 21:28 7976
    if (ImGui::ShowStyleSelector("Colors##Selector"))
1193b4be Poul Sander 2025-02-03 21:28 7977
        ref_saved_style = style;
1193b4be Poul Sander 2025-02-03 21:28 7978
    ImGui::ShowFontSelector("Fonts##Selector");
1193b4be Poul Sander 2025-02-03 21:28 7979
1193b4be Poul Sander 2025-02-03 21:28 7980
    // Simplified Settings (expose floating-pointer border sizes as boolean representing 0.0f or 1.0f)
1193b4be Poul Sander 2025-02-03 21:28 7981
    if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
1193b4be Poul Sander 2025-02-03 21:28 7982
        style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
1193b4be Poul Sander 2025-02-03 21:28 7983
    { bool border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &border)) { style.WindowBorderSize = border ? 1.0f : 0.0f; } }
1193b4be Poul Sander 2025-02-03 21:28 7984
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7985
    { bool border = (style.FrameBorderSize > 0.0f);  if (ImGui::Checkbox("FrameBorder",  &border)) { style.FrameBorderSize  = border ? 1.0f : 0.0f; } }
1193b4be Poul Sander 2025-02-03 21:28 7986
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7987
    { bool border = (style.PopupBorderSize > 0.0f);  if (ImGui::Checkbox("PopupBorder",  &border)) { style.PopupBorderSize  = border ? 1.0f : 0.0f; } }
1193b4be Poul Sander 2025-02-03 21:28 7988
1193b4be Poul Sander 2025-02-03 21:28 7989
    // Save/Revert button
1193b4be Poul Sander 2025-02-03 21:28 7990
    if (ImGui::Button("Save Ref"))
1193b4be Poul Sander 2025-02-03 21:28 7991
        *ref = ref_saved_style = style;
1193b4be Poul Sander 2025-02-03 21:28 7992
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7993
    if (ImGui::Button("Revert Ref"))
1193b4be Poul Sander 2025-02-03 21:28 7994
        style = *ref;
1193b4be Poul Sander 2025-02-03 21:28 7995
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 7996
    HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 7997
        "Save/Revert in local non-persistent storage. Default Colors definition are not affected. "
1193b4be Poul Sander 2025-02-03 21:28 7998
        "Use \"Export\" below to save them somewhere.");
1193b4be Poul Sander 2025-02-03 21:28 7999
1193b4be Poul Sander 2025-02-03 21:28 8000
    ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8001
1193b4be Poul Sander 2025-02-03 21:28 8002
    if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 8003
    {
1193b4be Poul Sander 2025-02-03 21:28 8004
        if (ImGui::BeginTabItem("Sizes"))
1193b4be Poul Sander 2025-02-03 21:28 8005
        {
1193b4be Poul Sander 2025-02-03 21:28 8006
            ImGui::SeparatorText("Main");
1193b4be Poul Sander 2025-02-03 21:28 8007
            ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8008
            ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8009
            ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8010
            ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8011
            ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8012
            ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8013
            ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8014
            ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8015
1193b4be Poul Sander 2025-02-03 21:28 8016
            ImGui::SeparatorText("Borders");
1193b4be Poul Sander 2025-02-03 21:28 8017
            ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8018
            ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8019
            ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8020
            ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8021
            ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8022
            ImGui::SliderFloat("TabBarBorderSize", &style.TabBarBorderSize, 0.0f, 2.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8023
            ImGui::SliderFloat("TabBarOverlineSize", &style.TabBarOverlineSize, 0.0f, 2.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8024
            ImGui::SameLine(); HelpMarker("Overline is only drawn over the selected tab when ImGuiTabBarFlags_DrawSelectedOverline is set.");
1193b4be Poul Sander 2025-02-03 21:28 8025
1193b4be Poul Sander 2025-02-03 21:28 8026
            ImGui::SeparatorText("Rounding");
1193b4be Poul Sander 2025-02-03 21:28 8027
            ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8028
            ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8029
            ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8030
            ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8031
            ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8032
            ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8033
            ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8034
1193b4be Poul Sander 2025-02-03 21:28 8035
            ImGui::SeparatorText("Tables");
1193b4be Poul Sander 2025-02-03 21:28 8036
            ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f, 20.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8037
            ImGui::SliderAngle("TableAngledHeadersAngle", &style.TableAngledHeadersAngle, -50.0f, +50.0f);
1193b4be Poul Sander 2025-02-03 21:28 8038
            ImGui::SliderFloat2("TableAngledHeadersTextAlign", (float*)&style.TableAngledHeadersTextAlign, 0.0f, 1.0f, "%.2f");
1193b4be Poul Sander 2025-02-03 21:28 8039
1193b4be Poul Sander 2025-02-03 21:28 8040
            ImGui::SeparatorText("Widgets");
1193b4be Poul Sander 2025-02-03 21:28 8041
            ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
1193b4be Poul Sander 2025-02-03 21:28 8042
            int window_menu_button_position = style.WindowMenuButtonPosition + 1;
1193b4be Poul Sander 2025-02-03 21:28 8043
            if (ImGui::Combo("WindowMenuButtonPosition", (int*)&window_menu_button_position, "None\0Left\0Right\0"))
1193b4be Poul Sander 2025-02-03 21:28 8044
                style.WindowMenuButtonPosition = (ImGuiDir)(window_menu_button_position - 1);
1193b4be Poul Sander 2025-02-03 21:28 8045
            ImGui::Combo("ColorButtonPosition", (int*)&style.ColorButtonPosition, "Left\0Right\0");
1193b4be Poul Sander 2025-02-03 21:28 8046
            ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f");
1193b4be Poul Sander 2025-02-03 21:28 8047
            ImGui::SameLine(); HelpMarker("Alignment applies when a button is larger than its text content.");
1193b4be Poul Sander 2025-02-03 21:28 8048
            ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f");
1193b4be Poul Sander 2025-02-03 21:28 8049
            ImGui::SameLine(); HelpMarker("Alignment applies when a selectable is larger than its text content.");
1193b4be Poul Sander 2025-02-03 21:28 8050
            ImGui::SliderFloat("SeparatorTextBorderSize", &style.SeparatorTextBorderSize, 0.0f, 10.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8051
            ImGui::SliderFloat2("SeparatorTextAlign", (float*)&style.SeparatorTextAlign, 0.0f, 1.0f, "%.2f");
1193b4be Poul Sander 2025-02-03 21:28 8052
            ImGui::SliderFloat2("SeparatorTextPadding", (float*)&style.SeparatorTextPadding, 0.0f, 40.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8053
            ImGui::SliderFloat("LogSliderDeadzone", &style.LogSliderDeadzone, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8054
1193b4be Poul Sander 2025-02-03 21:28 8055
            ImGui::SeparatorText("Docking");
1193b4be Poul Sander 2025-02-03 21:28 8056
            ImGui::SliderFloat("DockingSplitterSize", &style.DockingSeparatorSize, 0.0f, 12.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 8057
1193b4be Poul Sander 2025-02-03 21:28 8058
            ImGui::SeparatorText("Tooltips");
1193b4be Poul Sander 2025-02-03 21:28 8059
            for (int n = 0; n < 2; n++)
1193b4be Poul Sander 2025-02-03 21:28 8060
                if (ImGui::TreeNodeEx(n == 0 ? "HoverFlagsForTooltipMouse" : "HoverFlagsForTooltipNav"))
1193b4be Poul Sander 2025-02-03 21:28 8061
                {
1193b4be Poul Sander 2025-02-03 21:28 8062
                    ImGuiHoveredFlags* p = (n == 0) ? &style.HoverFlagsForTooltipMouse : &style.HoverFlagsForTooltipNav;
1193b4be Poul Sander 2025-02-03 21:28 8063
                    ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNone", p, ImGuiHoveredFlags_DelayNone);
1193b4be Poul Sander 2025-02-03 21:28 8064
                    ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayShort", p, ImGuiHoveredFlags_DelayShort);
1193b4be Poul Sander 2025-02-03 21:28 8065
                    ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNormal", p, ImGuiHoveredFlags_DelayNormal);
1193b4be Poul Sander 2025-02-03 21:28 8066
                    ImGui::CheckboxFlags("ImGuiHoveredFlags_Stationary", p, ImGuiHoveredFlags_Stationary);
1193b4be Poul Sander 2025-02-03 21:28 8067
                    ImGui::CheckboxFlags("ImGuiHoveredFlags_NoSharedDelay", p, ImGuiHoveredFlags_NoSharedDelay);
1193b4be Poul Sander 2025-02-03 21:28 8068
                    ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 8069
                }
1193b4be Poul Sander 2025-02-03 21:28 8070
1193b4be Poul Sander 2025-02-03 21:28 8071
            ImGui::SeparatorText("Misc");
1193b4be Poul Sander 2025-02-03 21:28 8072
            ImGui::SliderFloat2("DisplayWindowPadding", (float*)&style.DisplayWindowPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Apply to regular windows: amount which we enforce to keep visible when moving near edges of your screen.");
1193b4be Poul Sander 2025-02-03 21:28 8073
            ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f"); ImGui::SameLine(); HelpMarker("Apply to every windows, menus, popups, tooltips: amount where we avoid displaying contents. Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
1193b4be Poul Sander 2025-02-03 21:28 8074
1193b4be Poul Sander 2025-02-03 21:28 8075
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 8076
        }
1193b4be Poul Sander 2025-02-03 21:28 8077
1193b4be Poul Sander 2025-02-03 21:28 8078
        if (ImGui::BeginTabItem("Colors"))
1193b4be Poul Sander 2025-02-03 21:28 8079
        {
1193b4be Poul Sander 2025-02-03 21:28 8080
            static int output_dest = 0;
1193b4be Poul Sander 2025-02-03 21:28 8081
            static bool output_only_modified = true;
1193b4be Poul Sander 2025-02-03 21:28 8082
            if (ImGui::Button("Export"))
1193b4be Poul Sander 2025-02-03 21:28 8083
            {
1193b4be Poul Sander 2025-02-03 21:28 8084
                if (output_dest == 0)
1193b4be Poul Sander 2025-02-03 21:28 8085
                    ImGui::LogToClipboard();
1193b4be Poul Sander 2025-02-03 21:28 8086
                else
1193b4be Poul Sander 2025-02-03 21:28 8087
                    ImGui::LogToTTY();
1193b4be Poul Sander 2025-02-03 21:28 8088
                ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
1193b4be Poul Sander 2025-02-03 21:28 8089
                for (int i = 0; i < ImGuiCol_COUNT; i++)
1193b4be Poul Sander 2025-02-03 21:28 8090
                {
1193b4be Poul Sander 2025-02-03 21:28 8091
                    const ImVec4& col = style.Colors[i];
1193b4be Poul Sander 2025-02-03 21:28 8092
                    const char* name = ImGui::GetStyleColorName(i);
1193b4be Poul Sander 2025-02-03 21:28 8093
                    if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
1193b4be Poul Sander 2025-02-03 21:28 8094
                        ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE,
1193b4be Poul Sander 2025-02-03 21:28 8095
                            name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
1193b4be Poul Sander 2025-02-03 21:28 8096
                }
1193b4be Poul Sander 2025-02-03 21:28 8097
                ImGui::LogFinish();
1193b4be Poul Sander 2025-02-03 21:28 8098
            }
1193b4be Poul Sander 2025-02-03 21:28 8099
            ImGui::SameLine(); ImGui::SetNextItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
1193b4be Poul Sander 2025-02-03 21:28 8100
            ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
1193b4be Poul Sander 2025-02-03 21:28 8101
1193b4be Poul Sander 2025-02-03 21:28 8102
            static ImGuiTextFilter filter;
1193b4be Poul Sander 2025-02-03 21:28 8103
            filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
1193b4be Poul Sander 2025-02-03 21:28 8104
1193b4be Poul Sander 2025-02-03 21:28 8105
            static ImGuiColorEditFlags alpha_flags = 0;
1193b4be Poul Sander 2025-02-03 21:28 8106
            if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None))             { alpha_flags = ImGuiColorEditFlags_None; } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8107
            if (ImGui::RadioButton("Alpha",  alpha_flags == ImGuiColorEditFlags_AlphaPreview))     { alpha_flags = ImGuiColorEditFlags_AlphaPreview; } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8108
            if (ImGui::RadioButton("Both",   alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8109
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 8110
                "In the color list:\n"
1193b4be Poul Sander 2025-02-03 21:28 8111
                "Left-click on color square to open color picker,\n"
1193b4be Poul Sander 2025-02-03 21:28 8112
                "Right-click to open edit options menu.");
1193b4be Poul Sander 2025-02-03 21:28 8113
1193b4be Poul Sander 2025-02-03 21:28 8114
            ImGui::SetNextWindowSizeConstraints(ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 10), ImVec2(FLT_MAX, FLT_MAX));
1193b4be Poul Sander 2025-02-03 21:28 8115
            ImGui::BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar);
1193b4be Poul Sander 2025-02-03 21:28 8116
            ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
1193b4be Poul Sander 2025-02-03 21:28 8117
            for (int i = 0; i < ImGuiCol_COUNT; i++)
1193b4be Poul Sander 2025-02-03 21:28 8118
            {
1193b4be Poul Sander 2025-02-03 21:28 8119
                const char* name = ImGui::GetStyleColorName(i);
1193b4be Poul Sander 2025-02-03 21:28 8120
                if (!filter.PassFilter(name))
1193b4be Poul Sander 2025-02-03 21:28 8121
                    continue;
1193b4be Poul Sander 2025-02-03 21:28 8122
                ImGui::PushID(i);
1193b4be Poul Sander 2025-02-03 21:28 8123
#ifndef IMGUI_DISABLE_DEBUG_TOOLS
1193b4be Poul Sander 2025-02-03 21:28 8124
                if (ImGui::Button("?"))
1193b4be Poul Sander 2025-02-03 21:28 8125
                    ImGui::DebugFlashStyleColor((ImGuiCol)i);
1193b4be Poul Sander 2025-02-03 21:28 8126
                ImGui::SetItemTooltip("Flash given color to identify places where it is used.");
1193b4be Poul Sander 2025-02-03 21:28 8127
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8128
#endif
1193b4be Poul Sander 2025-02-03 21:28 8129
                ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
1193b4be Poul Sander 2025-02-03 21:28 8130
                if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
1193b4be Poul Sander 2025-02-03 21:28 8131
                {
1193b4be Poul Sander 2025-02-03 21:28 8132
                    // Tips: in a real user application, you may want to merge and use an icon font into the main font,
1193b4be Poul Sander 2025-02-03 21:28 8133
                    // so instead of "Save"/"Revert" you'd use icons!
1193b4be Poul Sander 2025-02-03 21:28 8134
                    // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
1193b4be Poul Sander 2025-02-03 21:28 8135
                    ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
1193b4be Poul Sander 2025-02-03 21:28 8136
                    ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
1193b4be Poul Sander 2025-02-03 21:28 8137
                }
1193b4be Poul Sander 2025-02-03 21:28 8138
                ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 8139
                ImGui::TextUnformatted(name);
1193b4be Poul Sander 2025-02-03 21:28 8140
                ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 8141
            }
1193b4be Poul Sander 2025-02-03 21:28 8142
            ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 8143
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 8144
1193b4be Poul Sander 2025-02-03 21:28 8145
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 8146
        }
1193b4be Poul Sander 2025-02-03 21:28 8147
1193b4be Poul Sander 2025-02-03 21:28 8148
        if (ImGui::BeginTabItem("Fonts"))
1193b4be Poul Sander 2025-02-03 21:28 8149
        {
1193b4be Poul Sander 2025-02-03 21:28 8150
            ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 8151
            ImFontAtlas* atlas = io.Fonts;
1193b4be Poul Sander 2025-02-03 21:28 8152
            HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
1193b4be Poul Sander 2025-02-03 21:28 8153
            ImGui::ShowFontAtlas(atlas);
1193b4be Poul Sander 2025-02-03 21:28 8154
1193b4be Poul Sander 2025-02-03 21:28 8155
            // Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
1193b4be Poul Sander 2025-02-03 21:28 8156
            // (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
1193b4be Poul Sander 2025-02-03 21:28 8157
            const float MIN_SCALE = 0.3f;
1193b4be Poul Sander 2025-02-03 21:28 8158
            const float MAX_SCALE = 2.0f;
1193b4be Poul Sander 2025-02-03 21:28 8159
            HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 8160
                "Those are old settings provided for convenience.\n"
1193b4be Poul Sander 2025-02-03 21:28 8161
                "However, the _correct_ way of scaling your UI is currently to reload your font at the designed size, "
1193b4be Poul Sander 2025-02-03 21:28 8162
                "rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n"
1193b4be Poul Sander 2025-02-03 21:28 8163
                "Using those settings here will give you poor quality results.");
1193b4be Poul Sander 2025-02-03 21:28 8164
            static float window_scale = 1.0f;
1193b4be Poul Sander 2025-02-03 21:28 8165
            ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 8166
            if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
1193b4be Poul Sander 2025-02-03 21:28 8167
                ImGui::SetWindowFontScale(window_scale);
1193b4be Poul Sander 2025-02-03 21:28 8168
            ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything
1193b4be Poul Sander 2025-02-03 21:28 8169
            ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 8170
1193b4be Poul Sander 2025-02-03 21:28 8171
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 8172
        }
1193b4be Poul Sander 2025-02-03 21:28 8173
1193b4be Poul Sander 2025-02-03 21:28 8174
        if (ImGui::BeginTabItem("Rendering"))
1193b4be Poul Sander 2025-02-03 21:28 8175
        {
1193b4be Poul Sander 2025-02-03 21:28 8176
            ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines);
1193b4be Poul Sander 2025-02-03 21:28 8177
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8178
            HelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
1193b4be Poul Sander 2025-02-03 21:28 8179
1193b4be Poul Sander 2025-02-03 21:28 8180
            ImGui::Checkbox("Anti-aliased lines use texture", &style.AntiAliasedLinesUseTex);
1193b4be Poul Sander 2025-02-03 21:28 8181
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8182
            HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
1193b4be Poul Sander 2025-02-03 21:28 8183
1193b4be Poul Sander 2025-02-03 21:28 8184
            ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
1193b4be Poul Sander 2025-02-03 21:28 8185
            ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
1193b4be Poul Sander 2025-02-03 21:28 8186
            ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
1193b4be Poul Sander 2025-02-03 21:28 8187
            if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
1193b4be Poul Sander 2025-02-03 21:28 8188
1193b4be Poul Sander 2025-02-03 21:28 8189
            // When editing the "Circle Segment Max Error" value, draw a preview of its effect on auto-tessellated circles.
1193b4be Poul Sander 2025-02-03 21:28 8190
            ImGui::DragFloat("Circle Tessellation Max Error", &style.CircleTessellationMaxError , 0.005f, 0.10f, 5.0f, "%.2f", ImGuiSliderFlags_AlwaysClamp);
1193b4be Poul Sander 2025-02-03 21:28 8191
            const bool show_samples = ImGui::IsItemActive();
1193b4be Poul Sander 2025-02-03 21:28 8192
            if (show_samples)
1193b4be Poul Sander 2025-02-03 21:28 8193
                ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
1193b4be Poul Sander 2025-02-03 21:28 8194
            if (show_samples && ImGui::BeginTooltip())
1193b4be Poul Sander 2025-02-03 21:28 8195
            {
1193b4be Poul Sander 2025-02-03 21:28 8196
                ImGui::TextUnformatted("(R = radius, N = approx number of segments)");
1193b4be Poul Sander 2025-02-03 21:28 8197
                ImGui::Spacing();
1193b4be Poul Sander 2025-02-03 21:28 8198
                ImDrawList* draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 8199
                const float min_widget_width = ImGui::CalcTextSize("R: MMM\nN: MMM").x;
1193b4be Poul Sander 2025-02-03 21:28 8200
                for (int n = 0; n < 8; n++)
1193b4be Poul Sander 2025-02-03 21:28 8201
                {
1193b4be Poul Sander 2025-02-03 21:28 8202
                    const float RAD_MIN = 5.0f;
1193b4be Poul Sander 2025-02-03 21:28 8203
                    const float RAD_MAX = 70.0f;
1193b4be Poul Sander 2025-02-03 21:28 8204
                    const float rad = RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 8205
1193b4be Poul Sander 2025-02-03 21:28 8206
                    ImGui::BeginGroup();
1193b4be Poul Sander 2025-02-03 21:28 8207
1193b4be Poul Sander 2025-02-03 21:28 8208
                    // N is not always exact here due to how PathArcTo() function work internally
1193b4be Poul Sander 2025-02-03 21:28 8209
                    ImGui::Text("R: %.f\nN: %d", rad, draw_list->_CalcCircleAutoSegmentCount(rad));
1193b4be Poul Sander 2025-02-03 21:28 8210
1193b4be Poul Sander 2025-02-03 21:28 8211
                    const float canvas_width = IM_MAX(min_widget_width, rad * 2.0f);
1193b4be Poul Sander 2025-02-03 21:28 8212
                    const float offset_x     = floorf(canvas_width * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 8213
                    const float offset_y     = floorf(RAD_MAX);
1193b4be Poul Sander 2025-02-03 21:28 8214
1193b4be Poul Sander 2025-02-03 21:28 8215
                    const ImVec2 p1 = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 8216
                    draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
1193b4be Poul Sander 2025-02-03 21:28 8217
                    ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
1193b4be Poul Sander 2025-02-03 21:28 8218
1193b4be Poul Sander 2025-02-03 21:28 8219
                    /*
1193b4be Poul Sander 2025-02-03 21:28 8220
                    const ImVec2 p2 = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 8221
                    draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y), rad, ImGui::GetColorU32(ImGuiCol_Text));
1193b4be Poul Sander 2025-02-03 21:28 8222
                    ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
1193b4be Poul Sander 2025-02-03 21:28 8223
                    */
1193b4be Poul Sander 2025-02-03 21:28 8224
1193b4be Poul Sander 2025-02-03 21:28 8225
                    ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 8226
                    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8227
                }
1193b4be Poul Sander 2025-02-03 21:28 8228
                ImGui::EndTooltip();
1193b4be Poul Sander 2025-02-03 21:28 8229
            }
1193b4be Poul Sander 2025-02-03 21:28 8230
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8231
            HelpMarker("When drawing circle primitives with \"num_segments == 0\" tesselation will be calculated automatically.");
1193b4be Poul Sander 2025-02-03 21:28 8232
1193b4be Poul Sander 2025-02-03 21:28 8233
            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.
1193b4be Poul Sander 2025-02-03 21:28 8234
            ImGui::DragFloat("Disabled Alpha", &style.DisabledAlpha, 0.005f, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); HelpMarker("Additional alpha multiplier for disabled items (multiply over current value of Alpha).");
1193b4be Poul Sander 2025-02-03 21:28 8235
            ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 8236
1193b4be Poul Sander 2025-02-03 21:28 8237
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 8238
        }
1193b4be Poul Sander 2025-02-03 21:28 8239
1193b4be Poul Sander 2025-02-03 21:28 8240
        ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 8241
    }
1193b4be Poul Sander 2025-02-03 21:28 8242
1193b4be Poul Sander 2025-02-03 21:28 8243
    ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 8244
}
1193b4be Poul Sander 2025-02-03 21:28 8245
1193b4be Poul Sander 2025-02-03 21:28 8246
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8247
// [SECTION] User Guide / ShowUserGuide()
1193b4be Poul Sander 2025-02-03 21:28 8248
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8249
1193b4be Poul Sander 2025-02-03 21:28 8250
void ImGui::ShowUserGuide()
1193b4be Poul Sander 2025-02-03 21:28 8251
{
1193b4be Poul Sander 2025-02-03 21:28 8252
    ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 8253
    ImGui::BulletText("Double-click on title bar to collapse window.");
1193b4be Poul Sander 2025-02-03 21:28 8254
    ImGui::BulletText(
1193b4be Poul Sander 2025-02-03 21:28 8255
        "Click and drag on lower corner to resize window\n"
1193b4be Poul Sander 2025-02-03 21:28 8256
        "(double-click to auto fit window to its contents).");
1193b4be Poul Sander 2025-02-03 21:28 8257
    ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
1193b4be Poul Sander 2025-02-03 21:28 8258
    ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
1193b4be Poul Sander 2025-02-03 21:28 8259
    ImGui::BulletText("CTRL+Tab to select a window.");
1193b4be Poul Sander 2025-02-03 21:28 8260
    if (io.FontAllowUserScaling)
1193b4be Poul Sander 2025-02-03 21:28 8261
        ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
1193b4be Poul Sander 2025-02-03 21:28 8262
    ImGui::BulletText("While inputing text:\n");
1193b4be Poul Sander 2025-02-03 21:28 8263
    ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 8264
    ImGui::BulletText("CTRL+Left/Right to word jump.");
1193b4be Poul Sander 2025-02-03 21:28 8265
    ImGui::BulletText("CTRL+A or double-click to select all.");
1193b4be Poul Sander 2025-02-03 21:28 8266
    ImGui::BulletText("CTRL+X/C/V to use clipboard cut/copy/paste.");
1193b4be Poul Sander 2025-02-03 21:28 8267
    ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
1193b4be Poul Sander 2025-02-03 21:28 8268
    ImGui::BulletText("ESCAPE to revert.");
1193b4be Poul Sander 2025-02-03 21:28 8269
    ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 8270
    ImGui::BulletText("With keyboard navigation enabled:");
1193b4be Poul Sander 2025-02-03 21:28 8271
    ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 8272
    ImGui::BulletText("Arrow keys to navigate.");
1193b4be Poul Sander 2025-02-03 21:28 8273
    ImGui::BulletText("Space to activate a widget.");
1193b4be Poul Sander 2025-02-03 21:28 8274
    ImGui::BulletText("Return to input text into a widget.");
1193b4be Poul Sander 2025-02-03 21:28 8275
    ImGui::BulletText("Escape to deactivate a widget, close popup, exit child window.");
1193b4be Poul Sander 2025-02-03 21:28 8276
    ImGui::BulletText("Alt to jump to the menu layer of a window.");
1193b4be Poul Sander 2025-02-03 21:28 8277
    ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 8278
}
1193b4be Poul Sander 2025-02-03 21:28 8279
1193b4be Poul Sander 2025-02-03 21:28 8280
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8281
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
1193b4be Poul Sander 2025-02-03 21:28 8282
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8283
// - ShowExampleAppMainMenuBar()
1193b4be Poul Sander 2025-02-03 21:28 8284
// - ShowExampleMenuFile()
1193b4be Poul Sander 2025-02-03 21:28 8285
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8286
1193b4be Poul Sander 2025-02-03 21:28 8287
// Demonstrate creating a "main" fullscreen menu bar and populating it.
1193b4be Poul Sander 2025-02-03 21:28 8288
// Note the difference between BeginMainMenuBar() and BeginMenuBar():
1193b4be Poul Sander 2025-02-03 21:28 8289
// - BeginMenuBar() = menu-bar inside current window (which needs the ImGuiWindowFlags_MenuBar flag!)
1193b4be Poul Sander 2025-02-03 21:28 8290
// - BeginMainMenuBar() = helper to create menu-bar-sized window at the top of the main viewport + call BeginMenuBar() into it.
1193b4be Poul Sander 2025-02-03 21:28 8291
static void ShowExampleAppMainMenuBar()
1193b4be Poul Sander 2025-02-03 21:28 8292
{
1193b4be Poul Sander 2025-02-03 21:28 8293
    if (ImGui::BeginMainMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 8294
    {
1193b4be Poul Sander 2025-02-03 21:28 8295
        if (ImGui::BeginMenu("File"))
1193b4be Poul Sander 2025-02-03 21:28 8296
        {
1193b4be Poul Sander 2025-02-03 21:28 8297
            ShowExampleMenuFile();
1193b4be Poul Sander 2025-02-03 21:28 8298
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8299
        }
1193b4be Poul Sander 2025-02-03 21:28 8300
        if (ImGui::BeginMenu("Edit"))
1193b4be Poul Sander 2025-02-03 21:28 8301
        {
1193b4be Poul Sander 2025-02-03 21:28 8302
            if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
1193b4be Poul Sander 2025-02-03 21:28 8303
            if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
1193b4be Poul Sander 2025-02-03 21:28 8304
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8305
            if (ImGui::MenuItem("Cut", "CTRL+X")) {}
1193b4be Poul Sander 2025-02-03 21:28 8306
            if (ImGui::MenuItem("Copy", "CTRL+C")) {}
1193b4be Poul Sander 2025-02-03 21:28 8307
            if (ImGui::MenuItem("Paste", "CTRL+V")) {}
1193b4be Poul Sander 2025-02-03 21:28 8308
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8309
        }
1193b4be Poul Sander 2025-02-03 21:28 8310
        ImGui::EndMainMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 8311
    }
1193b4be Poul Sander 2025-02-03 21:28 8312
}
1193b4be Poul Sander 2025-02-03 21:28 8313
1193b4be Poul Sander 2025-02-03 21:28 8314
// Note that shortcuts are currently provided for display only
1193b4be Poul Sander 2025-02-03 21:28 8315
// (future version will add explicit flags to BeginMenu() to request processing shortcuts)
1193b4be Poul Sander 2025-02-03 21:28 8316
static void ShowExampleMenuFile()
1193b4be Poul Sander 2025-02-03 21:28 8317
{
1193b4be Poul Sander 2025-02-03 21:28 8318
    IMGUI_DEMO_MARKER("Examples/Menu");
1193b4be Poul Sander 2025-02-03 21:28 8319
    ImGui::MenuItem("(demo menu)", NULL, false, false);
1193b4be Poul Sander 2025-02-03 21:28 8320
    if (ImGui::MenuItem("New")) {}
1193b4be Poul Sander 2025-02-03 21:28 8321
    if (ImGui::MenuItem("Open", "Ctrl+O")) {}
1193b4be Poul Sander 2025-02-03 21:28 8322
    if (ImGui::BeginMenu("Open Recent"))
1193b4be Poul Sander 2025-02-03 21:28 8323
    {
1193b4be Poul Sander 2025-02-03 21:28 8324
        ImGui::MenuItem("fish_hat.c");
1193b4be Poul Sander 2025-02-03 21:28 8325
        ImGui::MenuItem("fish_hat.inl");
1193b4be Poul Sander 2025-02-03 21:28 8326
        ImGui::MenuItem("fish_hat.h");
1193b4be Poul Sander 2025-02-03 21:28 8327
        if (ImGui::BeginMenu("More.."))
1193b4be Poul Sander 2025-02-03 21:28 8328
        {
1193b4be Poul Sander 2025-02-03 21:28 8329
            ImGui::MenuItem("Hello");
1193b4be Poul Sander 2025-02-03 21:28 8330
            ImGui::MenuItem("Sailor");
1193b4be Poul Sander 2025-02-03 21:28 8331
            if (ImGui::BeginMenu("Recurse.."))
1193b4be Poul Sander 2025-02-03 21:28 8332
            {
1193b4be Poul Sander 2025-02-03 21:28 8333
                ShowExampleMenuFile();
1193b4be Poul Sander 2025-02-03 21:28 8334
                ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8335
            }
1193b4be Poul Sander 2025-02-03 21:28 8336
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8337
        }
1193b4be Poul Sander 2025-02-03 21:28 8338
        ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8339
    }
1193b4be Poul Sander 2025-02-03 21:28 8340
    if (ImGui::MenuItem("Save", "Ctrl+S")) {}
1193b4be Poul Sander 2025-02-03 21:28 8341
    if (ImGui::MenuItem("Save As..")) {}
1193b4be Poul Sander 2025-02-03 21:28 8342
1193b4be Poul Sander 2025-02-03 21:28 8343
    ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8344
    IMGUI_DEMO_MARKER("Examples/Menu/Options");
1193b4be Poul Sander 2025-02-03 21:28 8345
    if (ImGui::BeginMenu("Options"))
1193b4be Poul Sander 2025-02-03 21:28 8346
    {
1193b4be Poul Sander 2025-02-03 21:28 8347
        static bool enabled = true;
1193b4be Poul Sander 2025-02-03 21:28 8348
        ImGui::MenuItem("Enabled", "", &enabled);
1193b4be Poul Sander 2025-02-03 21:28 8349
        ImGui::BeginChild("child", ImVec2(0, 60), ImGuiChildFlags_Borders);
1193b4be Poul Sander 2025-02-03 21:28 8350
        for (int i = 0; i < 10; i++)
1193b4be Poul Sander 2025-02-03 21:28 8351
            ImGui::Text("Scrolling Text %d", i);
1193b4be Poul Sander 2025-02-03 21:28 8352
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 8353
        static float f = 0.5f;
1193b4be Poul Sander 2025-02-03 21:28 8354
        static int n = 0;
1193b4be Poul Sander 2025-02-03 21:28 8355
        ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 8356
        ImGui::InputFloat("Input", &f, 0.1f);
1193b4be Poul Sander 2025-02-03 21:28 8357
        ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
1193b4be Poul Sander 2025-02-03 21:28 8358
        ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8359
    }
1193b4be Poul Sander 2025-02-03 21:28 8360
1193b4be Poul Sander 2025-02-03 21:28 8361
    IMGUI_DEMO_MARKER("Examples/Menu/Colors");
1193b4be Poul Sander 2025-02-03 21:28 8362
    if (ImGui::BeginMenu("Colors"))
1193b4be Poul Sander 2025-02-03 21:28 8363
    {
1193b4be Poul Sander 2025-02-03 21:28 8364
        float sz = ImGui::GetTextLineHeight();
1193b4be Poul Sander 2025-02-03 21:28 8365
        for (int i = 0; i < ImGuiCol_COUNT; i++)
1193b4be Poul Sander 2025-02-03 21:28 8366
        {
1193b4be Poul Sander 2025-02-03 21:28 8367
            const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
1193b4be Poul Sander 2025-02-03 21:28 8368
            ImVec2 p = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 8369
            ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + sz, p.y + sz), ImGui::GetColorU32((ImGuiCol)i));
1193b4be Poul Sander 2025-02-03 21:28 8370
            ImGui::Dummy(ImVec2(sz, sz));
1193b4be Poul Sander 2025-02-03 21:28 8371
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8372
            ImGui::MenuItem(name);
1193b4be Poul Sander 2025-02-03 21:28 8373
        }
1193b4be Poul Sander 2025-02-03 21:28 8374
        ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8375
    }
1193b4be Poul Sander 2025-02-03 21:28 8376
1193b4be Poul Sander 2025-02-03 21:28 8377
    // Here we demonstrate appending again to the "Options" menu (which we already created above)
1193b4be Poul Sander 2025-02-03 21:28 8378
    // Of course in this demo it is a little bit silly that this function calls BeginMenu("Options") twice.
1193b4be Poul Sander 2025-02-03 21:28 8379
    // In a real code-base using it would make senses to use this feature from very different code locations.
1193b4be Poul Sander 2025-02-03 21:28 8380
    if (ImGui::BeginMenu("Options")) // <-- Append!
1193b4be Poul Sander 2025-02-03 21:28 8381
    {
1193b4be Poul Sander 2025-02-03 21:28 8382
        IMGUI_DEMO_MARKER("Examples/Menu/Append to an existing menu");
1193b4be Poul Sander 2025-02-03 21:28 8383
        static bool b = true;
1193b4be Poul Sander 2025-02-03 21:28 8384
        ImGui::Checkbox("SomeOption", &b);
1193b4be Poul Sander 2025-02-03 21:28 8385
        ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8386
    }
1193b4be Poul Sander 2025-02-03 21:28 8387
1193b4be Poul Sander 2025-02-03 21:28 8388
    if (ImGui::BeginMenu("Disabled", false)) // Disabled
1193b4be Poul Sander 2025-02-03 21:28 8389
    {
1193b4be Poul Sander 2025-02-03 21:28 8390
        IM_ASSERT(0);
1193b4be Poul Sander 2025-02-03 21:28 8391
    }
1193b4be Poul Sander 2025-02-03 21:28 8392
    if (ImGui::MenuItem("Checked", NULL, true)) {}
1193b4be Poul Sander 2025-02-03 21:28 8393
    ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8394
    if (ImGui::MenuItem("Quit", "Alt+F4")) {}
1193b4be Poul Sander 2025-02-03 21:28 8395
}
1193b4be Poul Sander 2025-02-03 21:28 8396
1193b4be Poul Sander 2025-02-03 21:28 8397
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8398
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
1193b4be Poul Sander 2025-02-03 21:28 8399
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8400
1193b4be Poul Sander 2025-02-03 21:28 8401
// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
1193b4be Poul Sander 2025-02-03 21:28 8402
// For the console example, we are using a more C++ like approach of declaring a class to hold both data and functions.
1193b4be Poul Sander 2025-02-03 21:28 8403
struct ExampleAppConsole
1193b4be Poul Sander 2025-02-03 21:28 8404
{
1193b4be Poul Sander 2025-02-03 21:28 8405
    char                  InputBuf[256];
1193b4be Poul Sander 2025-02-03 21:28 8406
    ImVector<char*>       Items;
1193b4be Poul Sander 2025-02-03 21:28 8407
    ImVector<const char*> Commands;
1193b4be Poul Sander 2025-02-03 21:28 8408
    ImVector<char*>       History;
1193b4be Poul Sander 2025-02-03 21:28 8409
    int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
1193b4be Poul Sander 2025-02-03 21:28 8410
    ImGuiTextFilter       Filter;
1193b4be Poul Sander 2025-02-03 21:28 8411
    bool                  AutoScroll;
1193b4be Poul Sander 2025-02-03 21:28 8412
    bool                  ScrollToBottom;
1193b4be Poul Sander 2025-02-03 21:28 8413
1193b4be Poul Sander 2025-02-03 21:28 8414
    ExampleAppConsole()
1193b4be Poul Sander 2025-02-03 21:28 8415
    {
1193b4be Poul Sander 2025-02-03 21:28 8416
        IMGUI_DEMO_MARKER("Examples/Console");
1193b4be Poul Sander 2025-02-03 21:28 8417
        ClearLog();
1193b4be Poul Sander 2025-02-03 21:28 8418
        memset(InputBuf, 0, sizeof(InputBuf));
1193b4be Poul Sander 2025-02-03 21:28 8419
        HistoryPos = -1;
1193b4be Poul Sander 2025-02-03 21:28 8420
1193b4be Poul Sander 2025-02-03 21:28 8421
        // "CLASSIFY" is here to provide the test case where "C"+[tab] completes to "CL" and display multiple matches.
1193b4be Poul Sander 2025-02-03 21:28 8422
        Commands.push_back("HELP");
1193b4be Poul Sander 2025-02-03 21:28 8423
        Commands.push_back("HISTORY");
1193b4be Poul Sander 2025-02-03 21:28 8424
        Commands.push_back("CLEAR");
1193b4be Poul Sander 2025-02-03 21:28 8425
        Commands.push_back("CLASSIFY");
1193b4be Poul Sander 2025-02-03 21:28 8426
        AutoScroll = true;
1193b4be Poul Sander 2025-02-03 21:28 8427
        ScrollToBottom = false;
1193b4be Poul Sander 2025-02-03 21:28 8428
        AddLog("Welcome to Dear ImGui!");
1193b4be Poul Sander 2025-02-03 21:28 8429
    }
1193b4be Poul Sander 2025-02-03 21:28 8430
    ~ExampleAppConsole()
1193b4be Poul Sander 2025-02-03 21:28 8431
    {
1193b4be Poul Sander 2025-02-03 21:28 8432
        ClearLog();
1193b4be Poul Sander 2025-02-03 21:28 8433
        for (int i = 0; i < History.Size; i++)
1193b4be Poul Sander 2025-02-03 21:28 8434
            ImGui::MemFree(History[i]);
1193b4be Poul Sander 2025-02-03 21:28 8435
    }
1193b4be Poul Sander 2025-02-03 21:28 8436
1193b4be Poul Sander 2025-02-03 21:28 8437
    // Portable helpers
1193b4be Poul Sander 2025-02-03 21:28 8438
    static int   Stricmp(const char* s1, const char* s2)         { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
1193b4be Poul Sander 2025-02-03 21:28 8439
    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; }
1193b4be Poul Sander 2025-02-03 21:28 8440
    static char* Strdup(const char* s)                           { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = ImGui::MemAlloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
1193b4be Poul Sander 2025-02-03 21:28 8441
    static void  Strtrim(char* s)                                { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
1193b4be Poul Sander 2025-02-03 21:28 8442
1193b4be Poul Sander 2025-02-03 21:28 8443
    void    ClearLog()
1193b4be Poul Sander 2025-02-03 21:28 8444
    {
1193b4be Poul Sander 2025-02-03 21:28 8445
        for (int i = 0; i < Items.Size; i++)
1193b4be Poul Sander 2025-02-03 21:28 8446
            ImGui::MemFree(Items[i]);
1193b4be Poul Sander 2025-02-03 21:28 8447
        Items.clear();
1193b4be Poul Sander 2025-02-03 21:28 8448
    }
1193b4be Poul Sander 2025-02-03 21:28 8449
1193b4be Poul Sander 2025-02-03 21:28 8450
    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
1193b4be Poul Sander 2025-02-03 21:28 8451
    {
1193b4be Poul Sander 2025-02-03 21:28 8452
        // FIXME-OPT
1193b4be Poul Sander 2025-02-03 21:28 8453
        char buf[1024];
1193b4be Poul Sander 2025-02-03 21:28 8454
        va_list args;
1193b4be Poul Sander 2025-02-03 21:28 8455
        va_start(args, fmt);
1193b4be Poul Sander 2025-02-03 21:28 8456
        vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
1193b4be Poul Sander 2025-02-03 21:28 8457
        buf[IM_ARRAYSIZE(buf)-1] = 0;
1193b4be Poul Sander 2025-02-03 21:28 8458
        va_end(args);
1193b4be Poul Sander 2025-02-03 21:28 8459
        Items.push_back(Strdup(buf));
1193b4be Poul Sander 2025-02-03 21:28 8460
    }
1193b4be Poul Sander 2025-02-03 21:28 8461
1193b4be Poul Sander 2025-02-03 21:28 8462
    void    Draw(const char* title, bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 8463
    {
1193b4be Poul Sander 2025-02-03 21:28 8464
        ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 8465
        if (!ImGui::Begin(title, p_open))
1193b4be Poul Sander 2025-02-03 21:28 8466
        {
1193b4be Poul Sander 2025-02-03 21:28 8467
            ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 8468
            return;
1193b4be Poul Sander 2025-02-03 21:28 8469
        }
1193b4be Poul Sander 2025-02-03 21:28 8470
1193b4be Poul Sander 2025-02-03 21:28 8471
        // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar.
1193b4be Poul Sander 2025-02-03 21:28 8472
        // So e.g. IsItemHovered() will return true when hovering the title bar.
1193b4be Poul Sander 2025-02-03 21:28 8473
        // Here we create a context menu only available from the title bar.
1193b4be Poul Sander 2025-02-03 21:28 8474
        if (ImGui::BeginPopupContextItem())
1193b4be Poul Sander 2025-02-03 21:28 8475
        {
1193b4be Poul Sander 2025-02-03 21:28 8476
            if (ImGui::MenuItem("Close Console"))
1193b4be Poul Sander 2025-02-03 21:28 8477
                *p_open = false;
1193b4be Poul Sander 2025-02-03 21:28 8478
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 8479
        }
1193b4be Poul Sander 2025-02-03 21:28 8480
1193b4be Poul Sander 2025-02-03 21:28 8481
        ImGui::TextWrapped(
1193b4be Poul Sander 2025-02-03 21:28 8482
            "This example implements a console with basic coloring, completion (TAB key) and history (Up/Down keys). A more elaborate "
1193b4be Poul Sander 2025-02-03 21:28 8483
            "implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
1193b4be Poul Sander 2025-02-03 21:28 8484
        ImGui::TextWrapped("Enter 'HELP' for help.");
1193b4be Poul Sander 2025-02-03 21:28 8485
1193b4be Poul Sander 2025-02-03 21:28 8486
        // TODO: display items starting from the bottom
1193b4be Poul Sander 2025-02-03 21:28 8487
1193b4be Poul Sander 2025-02-03 21:28 8488
        if (ImGui::SmallButton("Add Debug Text"))  { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); }
1193b4be Poul Sander 2025-02-03 21:28 8489
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8490
        if (ImGui::SmallButton("Add Debug Error")) { AddLog("[error] something went wrong"); }
1193b4be Poul Sander 2025-02-03 21:28 8491
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8492
        if (ImGui::SmallButton("Clear"))           { ClearLog(); }
1193b4be Poul Sander 2025-02-03 21:28 8493
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8494
        bool copy_to_clipboard = ImGui::SmallButton("Copy");
1193b4be Poul Sander 2025-02-03 21:28 8495
        //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
1193b4be Poul Sander 2025-02-03 21:28 8496
1193b4be Poul Sander 2025-02-03 21:28 8497
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8498
1193b4be Poul Sander 2025-02-03 21:28 8499
        // Options menu
1193b4be Poul Sander 2025-02-03 21:28 8500
        if (ImGui::BeginPopup("Options"))
1193b4be Poul Sander 2025-02-03 21:28 8501
        {
1193b4be Poul Sander 2025-02-03 21:28 8502
            ImGui::Checkbox("Auto-scroll", &AutoScroll);
1193b4be Poul Sander 2025-02-03 21:28 8503
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 8504
        }
1193b4be Poul Sander 2025-02-03 21:28 8505
1193b4be Poul Sander 2025-02-03 21:28 8506
        // Options, Filter
1193b4be Poul Sander 2025-02-03 21:28 8507
        ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_O, ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 8508
        if (ImGui::Button("Options"))
1193b4be Poul Sander 2025-02-03 21:28 8509
            ImGui::OpenPopup("Options");
1193b4be Poul Sander 2025-02-03 21:28 8510
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8511
        Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
1193b4be Poul Sander 2025-02-03 21:28 8512
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8513
1193b4be Poul Sander 2025-02-03 21:28 8514
        // Reserve enough left-over height for 1 separator + 1 input text
1193b4be Poul Sander 2025-02-03 21:28 8515
        const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
1193b4be Poul Sander 2025-02-03 21:28 8516
        if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_HorizontalScrollbar))
1193b4be Poul Sander 2025-02-03 21:28 8517
        {
1193b4be Poul Sander 2025-02-03 21:28 8518
            if (ImGui::BeginPopupContextWindow())
1193b4be Poul Sander 2025-02-03 21:28 8519
            {
1193b4be Poul Sander 2025-02-03 21:28 8520
                if (ImGui::Selectable("Clear")) ClearLog();
1193b4be Poul Sander 2025-02-03 21:28 8521
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 8522
            }
1193b4be Poul Sander 2025-02-03 21:28 8523
1193b4be Poul Sander 2025-02-03 21:28 8524
            // Display every line as a separate entry so we can change their color or add custom widgets.
1193b4be Poul Sander 2025-02-03 21:28 8525
            // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
1193b4be Poul Sander 2025-02-03 21:28 8526
            // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
1193b4be Poul Sander 2025-02-03 21:28 8527
            // to only process visible items. The clipper will automatically measure the height of your first item and then
1193b4be Poul Sander 2025-02-03 21:28 8528
            // "seek" to display only items in the visible area.
1193b4be Poul Sander 2025-02-03 21:28 8529
            // To use the clipper we can replace your standard loop:
1193b4be Poul Sander 2025-02-03 21:28 8530
            //      for (int i = 0; i < Items.Size; i++)
1193b4be Poul Sander 2025-02-03 21:28 8531
            //   With:
1193b4be Poul Sander 2025-02-03 21:28 8532
            //      ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 8533
            //      clipper.Begin(Items.Size);
1193b4be Poul Sander 2025-02-03 21:28 8534
            //      while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 8535
            //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
1193b4be Poul Sander 2025-02-03 21:28 8536
            // - That your items are evenly spaced (same height)
1193b4be Poul Sander 2025-02-03 21:28 8537
            // - That you have cheap random access to your elements (you can access them given their index,
1193b4be Poul Sander 2025-02-03 21:28 8538
            //   without processing all the ones before)
1193b4be Poul Sander 2025-02-03 21:28 8539
            // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
1193b4be Poul Sander 2025-02-03 21:28 8540
            // We would need random-access on the post-filtered list.
1193b4be Poul Sander 2025-02-03 21:28 8541
            // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
1193b4be Poul Sander 2025-02-03 21:28 8542
            // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
1193b4be Poul Sander 2025-02-03 21:28 8543
            // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
1193b4be Poul Sander 2025-02-03 21:28 8544
            // to improve this example code!
1193b4be Poul Sander 2025-02-03 21:28 8545
            // If your items are of variable height:
1193b4be Poul Sander 2025-02-03 21:28 8546
            // - Split them into same height items would be simpler and facilitate random-seeking into your list.
1193b4be Poul Sander 2025-02-03 21:28 8547
            // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
1193b4be Poul Sander 2025-02-03 21:28 8548
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
1193b4be Poul Sander 2025-02-03 21:28 8549
            if (copy_to_clipboard)
1193b4be Poul Sander 2025-02-03 21:28 8550
                ImGui::LogToClipboard();
1193b4be Poul Sander 2025-02-03 21:28 8551
            for (const char* item : Items)
1193b4be Poul Sander 2025-02-03 21:28 8552
            {
1193b4be Poul Sander 2025-02-03 21:28 8553
                if (!Filter.PassFilter(item))
1193b4be Poul Sander 2025-02-03 21:28 8554
                    continue;
1193b4be Poul Sander 2025-02-03 21:28 8555
1193b4be Poul Sander 2025-02-03 21:28 8556
                // Normally you would store more information in your item than just a string.
1193b4be Poul Sander 2025-02-03 21:28 8557
                // (e.g. make Items[] an array of structure, store color/type etc.)
1193b4be Poul Sander 2025-02-03 21:28 8558
                ImVec4 color;
1193b4be Poul Sander 2025-02-03 21:28 8559
                bool has_color = false;
1193b4be Poul Sander 2025-02-03 21:28 8560
                if (strstr(item, "[error]")) { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
1193b4be Poul Sander 2025-02-03 21:28 8561
                else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
1193b4be Poul Sander 2025-02-03 21:28 8562
                if (has_color)
1193b4be Poul Sander 2025-02-03 21:28 8563
                    ImGui::PushStyleColor(ImGuiCol_Text, color);
1193b4be Poul Sander 2025-02-03 21:28 8564
                ImGui::TextUnformatted(item);
1193b4be Poul Sander 2025-02-03 21:28 8565
                if (has_color)
1193b4be Poul Sander 2025-02-03 21:28 8566
                    ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 8567
            }
1193b4be Poul Sander 2025-02-03 21:28 8568
            if (copy_to_clipboard)
1193b4be Poul Sander 2025-02-03 21:28 8569
                ImGui::LogFinish();
1193b4be Poul Sander 2025-02-03 21:28 8570
1193b4be Poul Sander 2025-02-03 21:28 8571
            // Keep up at the bottom of the scroll region if we were already at the bottom at the beginning of the frame.
1193b4be Poul Sander 2025-02-03 21:28 8572
            // Using a scrollbar or mouse-wheel will take away from the bottom edge.
1193b4be Poul Sander 2025-02-03 21:28 8573
            if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
1193b4be Poul Sander 2025-02-03 21:28 8574
                ImGui::SetScrollHereY(1.0f);
1193b4be Poul Sander 2025-02-03 21:28 8575
            ScrollToBottom = false;
1193b4be Poul Sander 2025-02-03 21:28 8576
1193b4be Poul Sander 2025-02-03 21:28 8577
            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 8578
        }
1193b4be Poul Sander 2025-02-03 21:28 8579
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 8580
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8581
1193b4be Poul Sander 2025-02-03 21:28 8582
        // Command-line
1193b4be Poul Sander 2025-02-03 21:28 8583
        bool reclaim_focus = false;
1193b4be Poul Sander 2025-02-03 21:28 8584
        ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_EscapeClearsAll | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory;
1193b4be Poul Sander 2025-02-03 21:28 8585
        if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
1193b4be Poul Sander 2025-02-03 21:28 8586
        {
1193b4be Poul Sander 2025-02-03 21:28 8587
            char* s = InputBuf;
1193b4be Poul Sander 2025-02-03 21:28 8588
            Strtrim(s);
1193b4be Poul Sander 2025-02-03 21:28 8589
            if (s[0])
1193b4be Poul Sander 2025-02-03 21:28 8590
                ExecCommand(s);
1193b4be Poul Sander 2025-02-03 21:28 8591
            strcpy(s, "");
1193b4be Poul Sander 2025-02-03 21:28 8592
            reclaim_focus = true;
1193b4be Poul Sander 2025-02-03 21:28 8593
        }
1193b4be Poul Sander 2025-02-03 21:28 8594
1193b4be Poul Sander 2025-02-03 21:28 8595
        // Auto-focus on window apparition
1193b4be Poul Sander 2025-02-03 21:28 8596
        ImGui::SetItemDefaultFocus();
1193b4be Poul Sander 2025-02-03 21:28 8597
        if (reclaim_focus)
1193b4be Poul Sander 2025-02-03 21:28 8598
            ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
1193b4be Poul Sander 2025-02-03 21:28 8599
1193b4be Poul Sander 2025-02-03 21:28 8600
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 8601
    }
1193b4be Poul Sander 2025-02-03 21:28 8602
1193b4be Poul Sander 2025-02-03 21:28 8603
    void    ExecCommand(const char* command_line)
1193b4be Poul Sander 2025-02-03 21:28 8604
    {
1193b4be Poul Sander 2025-02-03 21:28 8605
        AddLog("# %s\n", command_line);
1193b4be Poul Sander 2025-02-03 21:28 8606
1193b4be Poul Sander 2025-02-03 21:28 8607
        // Insert into history. First find match and delete it so it can be pushed to the back.
1193b4be Poul Sander 2025-02-03 21:28 8608
        // This isn't trying to be smart or optimal.
1193b4be Poul Sander 2025-02-03 21:28 8609
        HistoryPos = -1;
1193b4be Poul Sander 2025-02-03 21:28 8610
        for (int i = History.Size - 1; i >= 0; i--)
1193b4be Poul Sander 2025-02-03 21:28 8611
            if (Stricmp(History[i], command_line) == 0)
1193b4be Poul Sander 2025-02-03 21:28 8612
            {
1193b4be Poul Sander 2025-02-03 21:28 8613
                ImGui::MemFree(History[i]);
1193b4be Poul Sander 2025-02-03 21:28 8614
                History.erase(History.begin() + i);
1193b4be Poul Sander 2025-02-03 21:28 8615
                break;
1193b4be Poul Sander 2025-02-03 21:28 8616
            }
1193b4be Poul Sander 2025-02-03 21:28 8617
        History.push_back(Strdup(command_line));
1193b4be Poul Sander 2025-02-03 21:28 8618
1193b4be Poul Sander 2025-02-03 21:28 8619
        // Process command
1193b4be Poul Sander 2025-02-03 21:28 8620
        if (Stricmp(command_line, "CLEAR") == 0)
1193b4be Poul Sander 2025-02-03 21:28 8621
        {
1193b4be Poul Sander 2025-02-03 21:28 8622
            ClearLog();
1193b4be Poul Sander 2025-02-03 21:28 8623
        }
1193b4be Poul Sander 2025-02-03 21:28 8624
        else if (Stricmp(command_line, "HELP") == 0)
1193b4be Poul Sander 2025-02-03 21:28 8625
        {
1193b4be Poul Sander 2025-02-03 21:28 8626
            AddLog("Commands:");
1193b4be Poul Sander 2025-02-03 21:28 8627
            for (int i = 0; i < Commands.Size; i++)
1193b4be Poul Sander 2025-02-03 21:28 8628
                AddLog("- %s", Commands[i]);
1193b4be Poul Sander 2025-02-03 21:28 8629
        }
1193b4be Poul Sander 2025-02-03 21:28 8630
        else if (Stricmp(command_line, "HISTORY") == 0)
1193b4be Poul Sander 2025-02-03 21:28 8631
        {
1193b4be Poul Sander 2025-02-03 21:28 8632
            int first = History.Size - 10;
1193b4be Poul Sander 2025-02-03 21:28 8633
            for (int i = first > 0 ? first : 0; i < History.Size; i++)
1193b4be Poul Sander 2025-02-03 21:28 8634
                AddLog("%3d: %s\n", i, History[i]);
1193b4be Poul Sander 2025-02-03 21:28 8635
        }
1193b4be Poul Sander 2025-02-03 21:28 8636
        else
1193b4be Poul Sander 2025-02-03 21:28 8637
        {
1193b4be Poul Sander 2025-02-03 21:28 8638
            AddLog("Unknown command: '%s'\n", command_line);
1193b4be Poul Sander 2025-02-03 21:28 8639
        }
1193b4be Poul Sander 2025-02-03 21:28 8640
1193b4be Poul Sander 2025-02-03 21:28 8641
        // On command input, we scroll to bottom even if AutoScroll==false
1193b4be Poul Sander 2025-02-03 21:28 8642
        ScrollToBottom = true;
1193b4be Poul Sander 2025-02-03 21:28 8643
    }
1193b4be Poul Sander 2025-02-03 21:28 8644
1193b4be Poul Sander 2025-02-03 21:28 8645
    // In C++11 you'd be better off using lambdas for this sort of forwarding callbacks
1193b4be Poul Sander 2025-02-03 21:28 8646
    static int TextEditCallbackStub(ImGuiInputTextCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 8647
    {
1193b4be Poul Sander 2025-02-03 21:28 8648
        ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
1193b4be Poul Sander 2025-02-03 21:28 8649
        return console->TextEditCallback(data);
1193b4be Poul Sander 2025-02-03 21:28 8650
    }
1193b4be Poul Sander 2025-02-03 21:28 8651
1193b4be Poul Sander 2025-02-03 21:28 8652
    int     TextEditCallback(ImGuiInputTextCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 8653
    {
1193b4be Poul Sander 2025-02-03 21:28 8654
        //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
1193b4be Poul Sander 2025-02-03 21:28 8655
        switch (data->EventFlag)
1193b4be Poul Sander 2025-02-03 21:28 8656
        {
1193b4be Poul Sander 2025-02-03 21:28 8657
        case ImGuiInputTextFlags_CallbackCompletion:
1193b4be Poul Sander 2025-02-03 21:28 8658
            {
1193b4be Poul Sander 2025-02-03 21:28 8659
                // Example of TEXT COMPLETION
1193b4be Poul Sander 2025-02-03 21:28 8660
1193b4be Poul Sander 2025-02-03 21:28 8661
                // Locate beginning of current word
1193b4be Poul Sander 2025-02-03 21:28 8662
                const char* word_end = data->Buf + data->CursorPos;
1193b4be Poul Sander 2025-02-03 21:28 8663
                const char* word_start = word_end;
1193b4be Poul Sander 2025-02-03 21:28 8664
                while (word_start > data->Buf)
1193b4be Poul Sander 2025-02-03 21:28 8665
                {
1193b4be Poul Sander 2025-02-03 21:28 8666
                    const char c = word_start[-1];
1193b4be Poul Sander 2025-02-03 21:28 8667
                    if (c == ' ' || c == '\t' || c == ',' || c == ';')
1193b4be Poul Sander 2025-02-03 21:28 8668
                        break;
1193b4be Poul Sander 2025-02-03 21:28 8669
                    word_start--;
1193b4be Poul Sander 2025-02-03 21:28 8670
                }
1193b4be Poul Sander 2025-02-03 21:28 8671
1193b4be Poul Sander 2025-02-03 21:28 8672
                // Build a list of candidates
1193b4be Poul Sander 2025-02-03 21:28 8673
                ImVector<const char*> candidates;
1193b4be Poul Sander 2025-02-03 21:28 8674
                for (int i = 0; i < Commands.Size; i++)
1193b4be Poul Sander 2025-02-03 21:28 8675
                    if (Strnicmp(Commands[i], word_start, (int)(word_end - word_start)) == 0)
1193b4be Poul Sander 2025-02-03 21:28 8676
                        candidates.push_back(Commands[i]);
1193b4be Poul Sander 2025-02-03 21:28 8677
1193b4be Poul Sander 2025-02-03 21:28 8678
                if (candidates.Size == 0)
1193b4be Poul Sander 2025-02-03 21:28 8679
                {
1193b4be Poul Sander 2025-02-03 21:28 8680
                    // No match
1193b4be Poul Sander 2025-02-03 21:28 8681
                    AddLog("No match for \"%.*s\"!\n", (int)(word_end - word_start), word_start);
1193b4be Poul Sander 2025-02-03 21:28 8682
                }
1193b4be Poul Sander 2025-02-03 21:28 8683
                else if (candidates.Size == 1)
1193b4be Poul Sander 2025-02-03 21:28 8684
                {
1193b4be Poul Sander 2025-02-03 21:28 8685
                    // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing.
1193b4be Poul Sander 2025-02-03 21:28 8686
                    data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
1193b4be Poul Sander 2025-02-03 21:28 8687
                    data->InsertChars(data->CursorPos, candidates[0]);
1193b4be Poul Sander 2025-02-03 21:28 8688
                    data->InsertChars(data->CursorPos, " ");
1193b4be Poul Sander 2025-02-03 21:28 8689
                }
1193b4be Poul Sander 2025-02-03 21:28 8690
                else
1193b4be Poul Sander 2025-02-03 21:28 8691
                {
1193b4be Poul Sander 2025-02-03 21:28 8692
                    // Multiple matches. Complete as much as we can..
1193b4be Poul Sander 2025-02-03 21:28 8693
                    // So inputing "C"+Tab will complete to "CL" then display "CLEAR" and "CLASSIFY" as matches.
1193b4be Poul Sander 2025-02-03 21:28 8694
                    int match_len = (int)(word_end - word_start);
1193b4be Poul Sander 2025-02-03 21:28 8695
                    for (;;)
1193b4be Poul Sander 2025-02-03 21:28 8696
                    {
1193b4be Poul Sander 2025-02-03 21:28 8697
                        int c = 0;
1193b4be Poul Sander 2025-02-03 21:28 8698
                        bool all_candidates_matches = true;
1193b4be Poul Sander 2025-02-03 21:28 8699
                        for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
1193b4be Poul Sander 2025-02-03 21:28 8700
                            if (i == 0)
1193b4be Poul Sander 2025-02-03 21:28 8701
                                c = toupper(candidates[i][match_len]);
1193b4be Poul Sander 2025-02-03 21:28 8702
                            else if (c == 0 || c != toupper(candidates[i][match_len]))
1193b4be Poul Sander 2025-02-03 21:28 8703
                                all_candidates_matches = false;
1193b4be Poul Sander 2025-02-03 21:28 8704
                        if (!all_candidates_matches)
1193b4be Poul Sander 2025-02-03 21:28 8705
                            break;
1193b4be Poul Sander 2025-02-03 21:28 8706
                        match_len++;
1193b4be Poul Sander 2025-02-03 21:28 8707
                    }
1193b4be Poul Sander 2025-02-03 21:28 8708
1193b4be Poul Sander 2025-02-03 21:28 8709
                    if (match_len > 0)
1193b4be Poul Sander 2025-02-03 21:28 8710
                    {
1193b4be Poul Sander 2025-02-03 21:28 8711
                        data->DeleteChars((int)(word_start - data->Buf), (int)(word_end - word_start));
1193b4be Poul Sander 2025-02-03 21:28 8712
                        data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
1193b4be Poul Sander 2025-02-03 21:28 8713
                    }
1193b4be Poul Sander 2025-02-03 21:28 8714
1193b4be Poul Sander 2025-02-03 21:28 8715
                    // List matches
1193b4be Poul Sander 2025-02-03 21:28 8716
                    AddLog("Possible matches:\n");
1193b4be Poul Sander 2025-02-03 21:28 8717
                    for (int i = 0; i < candidates.Size; i++)
1193b4be Poul Sander 2025-02-03 21:28 8718
                        AddLog("- %s\n", candidates[i]);
1193b4be Poul Sander 2025-02-03 21:28 8719
                }
1193b4be Poul Sander 2025-02-03 21:28 8720
1193b4be Poul Sander 2025-02-03 21:28 8721
                break;
1193b4be Poul Sander 2025-02-03 21:28 8722
            }
1193b4be Poul Sander 2025-02-03 21:28 8723
        case ImGuiInputTextFlags_CallbackHistory:
1193b4be Poul Sander 2025-02-03 21:28 8724
            {
1193b4be Poul Sander 2025-02-03 21:28 8725
                // Example of HISTORY
1193b4be Poul Sander 2025-02-03 21:28 8726
                const int prev_history_pos = HistoryPos;
1193b4be Poul Sander 2025-02-03 21:28 8727
                if (data->EventKey == ImGuiKey_UpArrow)
1193b4be Poul Sander 2025-02-03 21:28 8728
                {
1193b4be Poul Sander 2025-02-03 21:28 8729
                    if (HistoryPos == -1)
1193b4be Poul Sander 2025-02-03 21:28 8730
                        HistoryPos = History.Size - 1;
1193b4be Poul Sander 2025-02-03 21:28 8731
                    else if (HistoryPos > 0)
1193b4be Poul Sander 2025-02-03 21:28 8732
                        HistoryPos--;
1193b4be Poul Sander 2025-02-03 21:28 8733
                }
1193b4be Poul Sander 2025-02-03 21:28 8734
                else if (data->EventKey == ImGuiKey_DownArrow)
1193b4be Poul Sander 2025-02-03 21:28 8735
                {
1193b4be Poul Sander 2025-02-03 21:28 8736
                    if (HistoryPos != -1)
1193b4be Poul Sander 2025-02-03 21:28 8737
                        if (++HistoryPos >= History.Size)
1193b4be Poul Sander 2025-02-03 21:28 8738
                            HistoryPos = -1;
1193b4be Poul Sander 2025-02-03 21:28 8739
                }
1193b4be Poul Sander 2025-02-03 21:28 8740
1193b4be Poul Sander 2025-02-03 21:28 8741
                // A better implementation would preserve the data on the current input line along with cursor position.
1193b4be Poul Sander 2025-02-03 21:28 8742
                if (prev_history_pos != HistoryPos)
1193b4be Poul Sander 2025-02-03 21:28 8743
                {
1193b4be Poul Sander 2025-02-03 21:28 8744
                    const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
1193b4be Poul Sander 2025-02-03 21:28 8745
                    data->DeleteChars(0, data->BufTextLen);
1193b4be Poul Sander 2025-02-03 21:28 8746
                    data->InsertChars(0, history_str);
1193b4be Poul Sander 2025-02-03 21:28 8747
                }
1193b4be Poul Sander 2025-02-03 21:28 8748
            }
1193b4be Poul Sander 2025-02-03 21:28 8749
        }
1193b4be Poul Sander 2025-02-03 21:28 8750
        return 0;
1193b4be Poul Sander 2025-02-03 21:28 8751
    }
1193b4be Poul Sander 2025-02-03 21:28 8752
};
1193b4be Poul Sander 2025-02-03 21:28 8753
1193b4be Poul Sander 2025-02-03 21:28 8754
static void ShowExampleAppConsole(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 8755
{
1193b4be Poul Sander 2025-02-03 21:28 8756
    static ExampleAppConsole console;
1193b4be Poul Sander 2025-02-03 21:28 8757
    console.Draw("Example: Console", p_open);
1193b4be Poul Sander 2025-02-03 21:28 8758
}
1193b4be Poul Sander 2025-02-03 21:28 8759
1193b4be Poul Sander 2025-02-03 21:28 8760
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8761
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
1193b4be Poul Sander 2025-02-03 21:28 8762
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8763
1193b4be Poul Sander 2025-02-03 21:28 8764
// Usage:
1193b4be Poul Sander 2025-02-03 21:28 8765
//  static ExampleAppLog my_log;
1193b4be Poul Sander 2025-02-03 21:28 8766
//  my_log.AddLog("Hello %d world\n", 123);
1193b4be Poul Sander 2025-02-03 21:28 8767
//  my_log.Draw("title");
1193b4be Poul Sander 2025-02-03 21:28 8768
struct ExampleAppLog
1193b4be Poul Sander 2025-02-03 21:28 8769
{
1193b4be Poul Sander 2025-02-03 21:28 8770
    ImGuiTextBuffer     Buf;
1193b4be Poul Sander 2025-02-03 21:28 8771
    ImGuiTextFilter     Filter;
1193b4be Poul Sander 2025-02-03 21:28 8772
    ImVector<int>       LineOffsets; // Index to lines offset. We maintain this with AddLog() calls.
1193b4be Poul Sander 2025-02-03 21:28 8773
    bool                AutoScroll;  // Keep scrolling if already at the bottom.
1193b4be Poul Sander 2025-02-03 21:28 8774
1193b4be Poul Sander 2025-02-03 21:28 8775
    ExampleAppLog()
1193b4be Poul Sander 2025-02-03 21:28 8776
    {
1193b4be Poul Sander 2025-02-03 21:28 8777
        AutoScroll = true;
1193b4be Poul Sander 2025-02-03 21:28 8778
        Clear();
1193b4be Poul Sander 2025-02-03 21:28 8779
    }
1193b4be Poul Sander 2025-02-03 21:28 8780
1193b4be Poul Sander 2025-02-03 21:28 8781
    void    Clear()
1193b4be Poul Sander 2025-02-03 21:28 8782
    {
1193b4be Poul Sander 2025-02-03 21:28 8783
        Buf.clear();
1193b4be Poul Sander 2025-02-03 21:28 8784
        LineOffsets.clear();
1193b4be Poul Sander 2025-02-03 21:28 8785
        LineOffsets.push_back(0);
1193b4be Poul Sander 2025-02-03 21:28 8786
    }
1193b4be Poul Sander 2025-02-03 21:28 8787
1193b4be Poul Sander 2025-02-03 21:28 8788
    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
1193b4be Poul Sander 2025-02-03 21:28 8789
    {
1193b4be Poul Sander 2025-02-03 21:28 8790
        int old_size = Buf.size();
1193b4be Poul Sander 2025-02-03 21:28 8791
        va_list args;
1193b4be Poul Sander 2025-02-03 21:28 8792
        va_start(args, fmt);
1193b4be Poul Sander 2025-02-03 21:28 8793
        Buf.appendfv(fmt, args);
1193b4be Poul Sander 2025-02-03 21:28 8794
        va_end(args);
1193b4be Poul Sander 2025-02-03 21:28 8795
        for (int new_size = Buf.size(); old_size < new_size; old_size++)
1193b4be Poul Sander 2025-02-03 21:28 8796
            if (Buf[old_size] == '\n')
1193b4be Poul Sander 2025-02-03 21:28 8797
                LineOffsets.push_back(old_size + 1);
1193b4be Poul Sander 2025-02-03 21:28 8798
    }
1193b4be Poul Sander 2025-02-03 21:28 8799
1193b4be Poul Sander 2025-02-03 21:28 8800
    void    Draw(const char* title, bool* p_open = NULL)
1193b4be Poul Sander 2025-02-03 21:28 8801
    {
1193b4be Poul Sander 2025-02-03 21:28 8802
        if (!ImGui::Begin(title, p_open))
1193b4be Poul Sander 2025-02-03 21:28 8803
        {
1193b4be Poul Sander 2025-02-03 21:28 8804
            ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 8805
            return;
1193b4be Poul Sander 2025-02-03 21:28 8806
        }
1193b4be Poul Sander 2025-02-03 21:28 8807
1193b4be Poul Sander 2025-02-03 21:28 8808
        // Options menu
1193b4be Poul Sander 2025-02-03 21:28 8809
        if (ImGui::BeginPopup("Options"))
1193b4be Poul Sander 2025-02-03 21:28 8810
        {
1193b4be Poul Sander 2025-02-03 21:28 8811
            ImGui::Checkbox("Auto-scroll", &AutoScroll);
1193b4be Poul Sander 2025-02-03 21:28 8812
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 8813
        }
1193b4be Poul Sander 2025-02-03 21:28 8814
1193b4be Poul Sander 2025-02-03 21:28 8815
        // Main window
1193b4be Poul Sander 2025-02-03 21:28 8816
        if (ImGui::Button("Options"))
1193b4be Poul Sander 2025-02-03 21:28 8817
            ImGui::OpenPopup("Options");
1193b4be Poul Sander 2025-02-03 21:28 8818
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8819
        bool clear = ImGui::Button("Clear");
1193b4be Poul Sander 2025-02-03 21:28 8820
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8821
        bool copy = ImGui::Button("Copy");
1193b4be Poul Sander 2025-02-03 21:28 8822
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8823
        Filter.Draw("Filter", -100.0f);
1193b4be Poul Sander 2025-02-03 21:28 8824
1193b4be Poul Sander 2025-02-03 21:28 8825
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8826
1193b4be Poul Sander 2025-02-03 21:28 8827
        if (ImGui::BeginChild("scrolling", ImVec2(0, 0), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar))
1193b4be Poul Sander 2025-02-03 21:28 8828
        {
1193b4be Poul Sander 2025-02-03 21:28 8829
            if (clear)
1193b4be Poul Sander 2025-02-03 21:28 8830
                Clear();
1193b4be Poul Sander 2025-02-03 21:28 8831
            if (copy)
1193b4be Poul Sander 2025-02-03 21:28 8832
                ImGui::LogToClipboard();
1193b4be Poul Sander 2025-02-03 21:28 8833
1193b4be Poul Sander 2025-02-03 21:28 8834
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
1193b4be Poul Sander 2025-02-03 21:28 8835
            const char* buf = Buf.begin();
1193b4be Poul Sander 2025-02-03 21:28 8836
            const char* buf_end = Buf.end();
1193b4be Poul Sander 2025-02-03 21:28 8837
            if (Filter.IsActive())
1193b4be Poul Sander 2025-02-03 21:28 8838
            {
1193b4be Poul Sander 2025-02-03 21:28 8839
                // In this example we don't use the clipper when Filter is enabled.
1193b4be Poul Sander 2025-02-03 21:28 8840
                // This is because we don't have random access to the result of our filter.
1193b4be Poul Sander 2025-02-03 21:28 8841
                // A real application processing logs with ten of thousands of entries may want to store the result of
1193b4be Poul Sander 2025-02-03 21:28 8842
                // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
1193b4be Poul Sander 2025-02-03 21:28 8843
                for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
1193b4be Poul Sander 2025-02-03 21:28 8844
                {
1193b4be Poul Sander 2025-02-03 21:28 8845
                    const char* line_start = buf + LineOffsets[line_no];
1193b4be Poul Sander 2025-02-03 21:28 8846
                    const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
1193b4be Poul Sander 2025-02-03 21:28 8847
                    if (Filter.PassFilter(line_start, line_end))
1193b4be Poul Sander 2025-02-03 21:28 8848
                        ImGui::TextUnformatted(line_start, line_end);
1193b4be Poul Sander 2025-02-03 21:28 8849
                }
1193b4be Poul Sander 2025-02-03 21:28 8850
            }
1193b4be Poul Sander 2025-02-03 21:28 8851
            else
1193b4be Poul Sander 2025-02-03 21:28 8852
            {
1193b4be Poul Sander 2025-02-03 21:28 8853
                // The simplest and easy way to display the entire buffer:
1193b4be Poul Sander 2025-02-03 21:28 8854
                //   ImGui::TextUnformatted(buf_begin, buf_end);
1193b4be Poul Sander 2025-02-03 21:28 8855
                // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
1193b4be Poul Sander 2025-02-03 21:28 8856
                // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
1193b4be Poul Sander 2025-02-03 21:28 8857
                // within the visible area.
1193b4be Poul Sander 2025-02-03 21:28 8858
                // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
1193b4be Poul Sander 2025-02-03 21:28 8859
                // on your side is recommended. Using ImGuiListClipper requires
1193b4be Poul Sander 2025-02-03 21:28 8860
                // - A) random access into your data
1193b4be Poul Sander 2025-02-03 21:28 8861
                // - B) items all being the  same height,
1193b4be Poul Sander 2025-02-03 21:28 8862
                // both of which we can handle since we have an array pointing to the beginning of each line of text.
1193b4be Poul Sander 2025-02-03 21:28 8863
                // When using the filter (in the block of code above) we don't have random access into the data to display
1193b4be Poul Sander 2025-02-03 21:28 8864
                // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
1193b4be Poul Sander 2025-02-03 21:28 8865
                // it possible (and would be recommended if you want to search through tens of thousands of entries).
1193b4be Poul Sander 2025-02-03 21:28 8866
                ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 8867
                clipper.Begin(LineOffsets.Size);
1193b4be Poul Sander 2025-02-03 21:28 8868
                while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 8869
                {
1193b4be Poul Sander 2025-02-03 21:28 8870
                    for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
1193b4be Poul Sander 2025-02-03 21:28 8871
                    {
1193b4be Poul Sander 2025-02-03 21:28 8872
                        const char* line_start = buf + LineOffsets[line_no];
1193b4be Poul Sander 2025-02-03 21:28 8873
                        const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
1193b4be Poul Sander 2025-02-03 21:28 8874
                        ImGui::TextUnformatted(line_start, line_end);
1193b4be Poul Sander 2025-02-03 21:28 8875
                    }
1193b4be Poul Sander 2025-02-03 21:28 8876
                }
1193b4be Poul Sander 2025-02-03 21:28 8877
                clipper.End();
1193b4be Poul Sander 2025-02-03 21:28 8878
            }
1193b4be Poul Sander 2025-02-03 21:28 8879
            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 8880
1193b4be Poul Sander 2025-02-03 21:28 8881
            // Keep up at the bottom of the scroll region if we were already at the bottom at the beginning of the frame.
1193b4be Poul Sander 2025-02-03 21:28 8882
            // Using a scrollbar or mouse-wheel will take away from the bottom edge.
1193b4be Poul Sander 2025-02-03 21:28 8883
            if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
1193b4be Poul Sander 2025-02-03 21:28 8884
                ImGui::SetScrollHereY(1.0f);
1193b4be Poul Sander 2025-02-03 21:28 8885
        }
1193b4be Poul Sander 2025-02-03 21:28 8886
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 8887
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 8888
    }
1193b4be Poul Sander 2025-02-03 21:28 8889
};
1193b4be Poul Sander 2025-02-03 21:28 8890
1193b4be Poul Sander 2025-02-03 21:28 8891
// Demonstrate creating a simple log window with basic filtering.
1193b4be Poul Sander 2025-02-03 21:28 8892
static void ShowExampleAppLog(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 8893
{
1193b4be Poul Sander 2025-02-03 21:28 8894
    static ExampleAppLog log;
1193b4be Poul Sander 2025-02-03 21:28 8895
1193b4be Poul Sander 2025-02-03 21:28 8896
    // For the demo: add a debug button _BEFORE_ the normal log window contents
1193b4be Poul Sander 2025-02-03 21:28 8897
    // We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
1193b4be Poul Sander 2025-02-03 21:28 8898
    // Most of the contents of the window will be added by the log.Draw() call.
1193b4be Poul Sander 2025-02-03 21:28 8899
    ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 8900
    ImGui::Begin("Example: Log", p_open);
1193b4be Poul Sander 2025-02-03 21:28 8901
    IMGUI_DEMO_MARKER("Examples/Log");
1193b4be Poul Sander 2025-02-03 21:28 8902
    if (ImGui::SmallButton("[Debug] Add 5 entries"))
1193b4be Poul Sander 2025-02-03 21:28 8903
    {
1193b4be Poul Sander 2025-02-03 21:28 8904
        static int counter = 0;
1193b4be Poul Sander 2025-02-03 21:28 8905
        const char* categories[3] = { "info", "warn", "error" };
1193b4be Poul Sander 2025-02-03 21:28 8906
        const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
1193b4be Poul Sander 2025-02-03 21:28 8907
        for (int n = 0; n < 5; n++)
1193b4be Poul Sander 2025-02-03 21:28 8908
        {
1193b4be Poul Sander 2025-02-03 21:28 8909
            const char* category = categories[counter % IM_ARRAYSIZE(categories)];
1193b4be Poul Sander 2025-02-03 21:28 8910
            const char* word = words[counter % IM_ARRAYSIZE(words)];
1193b4be Poul Sander 2025-02-03 21:28 8911
            log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
1193b4be Poul Sander 2025-02-03 21:28 8912
                ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
1193b4be Poul Sander 2025-02-03 21:28 8913
            counter++;
1193b4be Poul Sander 2025-02-03 21:28 8914
        }
1193b4be Poul Sander 2025-02-03 21:28 8915
    }
1193b4be Poul Sander 2025-02-03 21:28 8916
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 8917
1193b4be Poul Sander 2025-02-03 21:28 8918
    // Actually call in the regular Log helper (which will Begin() into the same window as we just did)
1193b4be Poul Sander 2025-02-03 21:28 8919
    log.Draw("Example: Log", p_open);
1193b4be Poul Sander 2025-02-03 21:28 8920
}
1193b4be Poul Sander 2025-02-03 21:28 8921
1193b4be Poul Sander 2025-02-03 21:28 8922
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8923
// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
1193b4be Poul Sander 2025-02-03 21:28 8924
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8925
1193b4be Poul Sander 2025-02-03 21:28 8926
// Demonstrate create a window with multiple child windows.
1193b4be Poul Sander 2025-02-03 21:28 8927
static void ShowExampleAppLayout(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 8928
{
1193b4be Poul Sander 2025-02-03 21:28 8929
    ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 8930
    if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
1193b4be Poul Sander 2025-02-03 21:28 8931
    {
1193b4be Poul Sander 2025-02-03 21:28 8932
        IMGUI_DEMO_MARKER("Examples/Simple layout");
1193b4be Poul Sander 2025-02-03 21:28 8933
        if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 8934
        {
1193b4be Poul Sander 2025-02-03 21:28 8935
            if (ImGui::BeginMenu("File"))
1193b4be Poul Sander 2025-02-03 21:28 8936
            {
1193b4be Poul Sander 2025-02-03 21:28 8937
                if (ImGui::MenuItem("Close", "Ctrl+W")) { *p_open = false; }
1193b4be Poul Sander 2025-02-03 21:28 8938
                ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 8939
            }
1193b4be Poul Sander 2025-02-03 21:28 8940
            ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 8941
        }
1193b4be Poul Sander 2025-02-03 21:28 8942
1193b4be Poul Sander 2025-02-03 21:28 8943
        // Left
1193b4be Poul Sander 2025-02-03 21:28 8944
        static int selected = 0;
1193b4be Poul Sander 2025-02-03 21:28 8945
        {
1193b4be Poul Sander 2025-02-03 21:28 8946
            ImGui::BeginChild("left pane", ImVec2(150, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_ResizeX);
1193b4be Poul Sander 2025-02-03 21:28 8947
            for (int i = 0; i < 100; i++)
1193b4be Poul Sander 2025-02-03 21:28 8948
            {
1193b4be Poul Sander 2025-02-03 21:28 8949
                // FIXME: Good candidate to use ImGuiSelectableFlags_SelectOnNav
1193b4be Poul Sander 2025-02-03 21:28 8950
                char label[128];
1193b4be Poul Sander 2025-02-03 21:28 8951
                sprintf(label, "MyObject %d", i);
1193b4be Poul Sander 2025-02-03 21:28 8952
                if (ImGui::Selectable(label, selected == i))
1193b4be Poul Sander 2025-02-03 21:28 8953
                    selected = i;
1193b4be Poul Sander 2025-02-03 21:28 8954
            }
1193b4be Poul Sander 2025-02-03 21:28 8955
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 8956
        }
1193b4be Poul Sander 2025-02-03 21:28 8957
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8958
1193b4be Poul Sander 2025-02-03 21:28 8959
        // Right
1193b4be Poul Sander 2025-02-03 21:28 8960
        {
1193b4be Poul Sander 2025-02-03 21:28 8961
            ImGui::BeginGroup();
1193b4be Poul Sander 2025-02-03 21:28 8962
            ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
1193b4be Poul Sander 2025-02-03 21:28 8963
            ImGui::Text("MyObject: %d", selected);
1193b4be Poul Sander 2025-02-03 21:28 8964
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 8965
            if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
1193b4be Poul Sander 2025-02-03 21:28 8966
            {
1193b4be Poul Sander 2025-02-03 21:28 8967
                if (ImGui::BeginTabItem("Description"))
1193b4be Poul Sander 2025-02-03 21:28 8968
                {
1193b4be Poul Sander 2025-02-03 21:28 8969
                    ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
1193b4be Poul Sander 2025-02-03 21:28 8970
                    ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 8971
                }
1193b4be Poul Sander 2025-02-03 21:28 8972
                if (ImGui::BeginTabItem("Details"))
1193b4be Poul Sander 2025-02-03 21:28 8973
                {
1193b4be Poul Sander 2025-02-03 21:28 8974
                    ImGui::Text("ID: 0123456789");
1193b4be Poul Sander 2025-02-03 21:28 8975
                    ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 8976
                }
1193b4be Poul Sander 2025-02-03 21:28 8977
                ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 8978
            }
1193b4be Poul Sander 2025-02-03 21:28 8979
            ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 8980
            if (ImGui::Button("Revert")) {}
1193b4be Poul Sander 2025-02-03 21:28 8981
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 8982
            if (ImGui::Button("Save")) {}
1193b4be Poul Sander 2025-02-03 21:28 8983
            ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 8984
        }
1193b4be Poul Sander 2025-02-03 21:28 8985
    }
1193b4be Poul Sander 2025-02-03 21:28 8986
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 8987
}
1193b4be Poul Sander 2025-02-03 21:28 8988
1193b4be Poul Sander 2025-02-03 21:28 8989
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8990
// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
1193b4be Poul Sander 2025-02-03 21:28 8991
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8992
// Some of the interactions are a bit lack-luster:
1193b4be Poul Sander 2025-02-03 21:28 8993
// - We would want pressing validating or leaving the filter to somehow restore focus.
1193b4be Poul Sander 2025-02-03 21:28 8994
// - We may want more advanced filtering (child nodes) and clipper support: both will need extra work.
1193b4be Poul Sander 2025-02-03 21:28 8995
// - We would want to customize some keyboard interactions to easily keyboard navigate between the tree and the properties.
1193b4be Poul Sander 2025-02-03 21:28 8996
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 8997
1193b4be Poul Sander 2025-02-03 21:28 8998
struct ExampleAppPropertyEditor
1193b4be Poul Sander 2025-02-03 21:28 8999
{
1193b4be Poul Sander 2025-02-03 21:28 9000
    ImGuiTextFilter     Filter;
1193b4be Poul Sander 2025-02-03 21:28 9001
    ExampleTreeNode*    VisibleNode = NULL;
1193b4be Poul Sander 2025-02-03 21:28 9002
1193b4be Poul Sander 2025-02-03 21:28 9003
    void Draw(ExampleTreeNode* root_node)
1193b4be Poul Sander 2025-02-03 21:28 9004
    {
1193b4be Poul Sander 2025-02-03 21:28 9005
        // Left side: draw tree
1193b4be Poul Sander 2025-02-03 21:28 9006
        // - Currently using a table to benefit from RowBg feature
1193b4be Poul Sander 2025-02-03 21:28 9007
        if (ImGui::BeginChild("##tree", ImVec2(300, 0), ImGuiChildFlags_ResizeX | ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened))
1193b4be Poul Sander 2025-02-03 21:28 9008
        {
1193b4be Poul Sander 2025-02-03 21:28 9009
            ImGui::SetNextItemWidth(-FLT_MIN);
1193b4be Poul Sander 2025-02-03 21:28 9010
            ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 9011
            ImGui::PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true);
1193b4be Poul Sander 2025-02-03 21:28 9012
            if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_ARRAYSIZE(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll))
1193b4be Poul Sander 2025-02-03 21:28 9013
                Filter.Build();
1193b4be Poul Sander 2025-02-03 21:28 9014
            ImGui::PopItemFlag();
1193b4be Poul Sander 2025-02-03 21:28 9015
1193b4be Poul Sander 2025-02-03 21:28 9016
            if (ImGui::BeginTable("##bg", 1, ImGuiTableFlags_RowBg))
1193b4be Poul Sander 2025-02-03 21:28 9017
            {
1193b4be Poul Sander 2025-02-03 21:28 9018
                for (ExampleTreeNode* node : root_node->Childs)
1193b4be Poul Sander 2025-02-03 21:28 9019
                    if (Filter.PassFilter(node->Name)) // Filter root node
1193b4be Poul Sander 2025-02-03 21:28 9020
                        DrawTreeNode(node);
1193b4be Poul Sander 2025-02-03 21:28 9021
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 9022
            }
1193b4be Poul Sander 2025-02-03 21:28 9023
        }
1193b4be Poul Sander 2025-02-03 21:28 9024
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 9025
1193b4be Poul Sander 2025-02-03 21:28 9026
        // Right side: draw properties
1193b4be Poul Sander 2025-02-03 21:28 9027
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9028
1193b4be Poul Sander 2025-02-03 21:28 9029
        ImGui::BeginGroup(); // Lock X position
1193b4be Poul Sander 2025-02-03 21:28 9030
        if (ExampleTreeNode* node = VisibleNode)
1193b4be Poul Sander 2025-02-03 21:28 9031
        {
1193b4be Poul Sander 2025-02-03 21:28 9032
            ImGui::Text("%s", node->Name);
1193b4be Poul Sander 2025-02-03 21:28 9033
            ImGui::TextDisabled("UID: 0x%08X", node->UID);
1193b4be Poul Sander 2025-02-03 21:28 9034
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 9035
            if (ImGui::BeginTable("##properties", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY))
1193b4be Poul Sander 2025-02-03 21:28 9036
            {
1193b4be Poul Sander 2025-02-03 21:28 9037
                ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
1193b4be Poul Sander 2025-02-03 21:28 9038
                ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch, 2.0f); // Default twice larger
1193b4be Poul Sander 2025-02-03 21:28 9039
                if (node->HasData)
1193b4be Poul Sander 2025-02-03 21:28 9040
                {
1193b4be Poul Sander 2025-02-03 21:28 9041
                    // In a typical application, the structure description would be derived from a data-driven system.
1193b4be Poul Sander 2025-02-03 21:28 9042
                    // - We try to mimic this with our ExampleMemberInfo structure and the ExampleTreeNodeMemberInfos[] array.
1193b4be Poul Sander 2025-02-03 21:28 9043
                    // - Limits and some details are hard-coded to simplify the demo.
1193b4be Poul Sander 2025-02-03 21:28 9044
                    for (const ExampleMemberInfo& field_desc : ExampleTreeNodeMemberInfos)
1193b4be Poul Sander 2025-02-03 21:28 9045
                    {
1193b4be Poul Sander 2025-02-03 21:28 9046
                        ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 9047
                        ImGui::PushID(field_desc.Name);
1193b4be Poul Sander 2025-02-03 21:28 9048
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 9049
                        ImGui::AlignTextToFramePadding();
1193b4be Poul Sander 2025-02-03 21:28 9050
                        ImGui::TextUnformatted(field_desc.Name);
1193b4be Poul Sander 2025-02-03 21:28 9051
                        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 9052
                        void* field_ptr = (void*)(((unsigned char*)node) + field_desc.Offset);
1193b4be Poul Sander 2025-02-03 21:28 9053
                        switch (field_desc.DataType)
1193b4be Poul Sander 2025-02-03 21:28 9054
                        {
1193b4be Poul Sander 2025-02-03 21:28 9055
                        case ImGuiDataType_Bool:
1193b4be Poul Sander 2025-02-03 21:28 9056
                        {
1193b4be Poul Sander 2025-02-03 21:28 9057
                            IM_ASSERT(field_desc.DataCount == 1);
1193b4be Poul Sander 2025-02-03 21:28 9058
                            ImGui::Checkbox("##Editor", (bool*)field_ptr);
1193b4be Poul Sander 2025-02-03 21:28 9059
                            break;
1193b4be Poul Sander 2025-02-03 21:28 9060
                        }
1193b4be Poul Sander 2025-02-03 21:28 9061
                        case ImGuiDataType_S32:
1193b4be Poul Sander 2025-02-03 21:28 9062
                        {
1193b4be Poul Sander 2025-02-03 21:28 9063
                            int v_min = INT_MIN, v_max = INT_MAX;
1193b4be Poul Sander 2025-02-03 21:28 9064
                            ImGui::SetNextItemWidth(-FLT_MIN);
1193b4be Poul Sander 2025-02-03 21:28 9065
                            ImGui::DragScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, 1.0f, &v_min, &v_max);
1193b4be Poul Sander 2025-02-03 21:28 9066
                            break;
1193b4be Poul Sander 2025-02-03 21:28 9067
                        }
1193b4be Poul Sander 2025-02-03 21:28 9068
                        case ImGuiDataType_Float:
1193b4be Poul Sander 2025-02-03 21:28 9069
                        {
1193b4be Poul Sander 2025-02-03 21:28 9070
                            float v_min = 0.0f, v_max = 1.0f;
1193b4be Poul Sander 2025-02-03 21:28 9071
                            ImGui::SetNextItemWidth(-FLT_MIN);
1193b4be Poul Sander 2025-02-03 21:28 9072
                            ImGui::SliderScalarN("##Editor", field_desc.DataType, field_ptr, field_desc.DataCount, &v_min, &v_max);
1193b4be Poul Sander 2025-02-03 21:28 9073
                            break;
1193b4be Poul Sander 2025-02-03 21:28 9074
                        }
1193b4be Poul Sander 2025-02-03 21:28 9075
                        }
1193b4be Poul Sander 2025-02-03 21:28 9076
                        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 9077
                    }
1193b4be Poul Sander 2025-02-03 21:28 9078
                }
1193b4be Poul Sander 2025-02-03 21:28 9079
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 9080
            }
1193b4be Poul Sander 2025-02-03 21:28 9081
        }
1193b4be Poul Sander 2025-02-03 21:28 9082
        ImGui::EndGroup();
1193b4be Poul Sander 2025-02-03 21:28 9083
    }
1193b4be Poul Sander 2025-02-03 21:28 9084
1193b4be Poul Sander 2025-02-03 21:28 9085
    void DrawTreeNode(ExampleTreeNode* node)
1193b4be Poul Sander 2025-02-03 21:28 9086
    {
1193b4be Poul Sander 2025-02-03 21:28 9087
        ImGui::TableNextRow();
1193b4be Poul Sander 2025-02-03 21:28 9088
        ImGui::TableNextColumn();
1193b4be Poul Sander 2025-02-03 21:28 9089
        ImGui::PushID(node->UID);
1193b4be Poul Sander 2025-02-03 21:28 9090
        ImGuiTreeNodeFlags tree_flags = ImGuiTreeNodeFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 9091
        tree_flags |= ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;    // Standard opening mode as we are likely to want to add selection afterwards
1193b4be Poul Sander 2025-02-03 21:28 9092
        tree_flags |= ImGuiTreeNodeFlags_NavLeftJumpsBackHere;                                  // Left arrow support
1193b4be Poul Sander 2025-02-03 21:28 9093
        if (node == VisibleNode)
1193b4be Poul Sander 2025-02-03 21:28 9094
            tree_flags |= ImGuiTreeNodeFlags_Selected;
1193b4be Poul Sander 2025-02-03 21:28 9095
        if (node->Childs.Size == 0)
1193b4be Poul Sander 2025-02-03 21:28 9096
            tree_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_Bullet;
1193b4be Poul Sander 2025-02-03 21:28 9097
        if (node->DataMyBool == false)
1193b4be Poul Sander 2025-02-03 21:28 9098
            ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_TextDisabled]);
1193b4be Poul Sander 2025-02-03 21:28 9099
        bool node_open = ImGui::TreeNodeEx("", tree_flags, "%s", node->Name);
1193b4be Poul Sander 2025-02-03 21:28 9100
        if (node->DataMyBool == false)
1193b4be Poul Sander 2025-02-03 21:28 9101
            ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 9102
        if (ImGui::IsItemFocused())
1193b4be Poul Sander 2025-02-03 21:28 9103
            VisibleNode = node;
1193b4be Poul Sander 2025-02-03 21:28 9104
        if (node_open)
1193b4be Poul Sander 2025-02-03 21:28 9105
        {
1193b4be Poul Sander 2025-02-03 21:28 9106
            for (ExampleTreeNode* child : node->Childs)
1193b4be Poul Sander 2025-02-03 21:28 9107
                DrawTreeNode(child);
1193b4be Poul Sander 2025-02-03 21:28 9108
            ImGui::TreePop();
1193b4be Poul Sander 2025-02-03 21:28 9109
        }
1193b4be Poul Sander 2025-02-03 21:28 9110
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 9111
    }
1193b4be Poul Sander 2025-02-03 21:28 9112
};
1193b4be Poul Sander 2025-02-03 21:28 9113
1193b4be Poul Sander 2025-02-03 21:28 9114
// Demonstrate creating a simple property editor.
1193b4be Poul Sander 2025-02-03 21:28 9115
static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data)
1193b4be Poul Sander 2025-02-03 21:28 9116
{
1193b4be Poul Sander 2025-02-03 21:28 9117
    ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 9118
    if (!ImGui::Begin("Example: Property editor", p_open))
1193b4be Poul Sander 2025-02-03 21:28 9119
    {
1193b4be Poul Sander 2025-02-03 21:28 9120
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9121
        return;
1193b4be Poul Sander 2025-02-03 21:28 9122
    }
1193b4be Poul Sander 2025-02-03 21:28 9123
1193b4be Poul Sander 2025-02-03 21:28 9124
    IMGUI_DEMO_MARKER("Examples/Property Editor");
1193b4be Poul Sander 2025-02-03 21:28 9125
    static ExampleAppPropertyEditor property_editor;
1193b4be Poul Sander 2025-02-03 21:28 9126
    if (demo_data->DemoTree == NULL)
1193b4be Poul Sander 2025-02-03 21:28 9127
        demo_data->DemoTree = ExampleTree_CreateDemoTree();
1193b4be Poul Sander 2025-02-03 21:28 9128
    property_editor.Draw(demo_data->DemoTree);
1193b4be Poul Sander 2025-02-03 21:28 9129
1193b4be Poul Sander 2025-02-03 21:28 9130
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9131
}
1193b4be Poul Sander 2025-02-03 21:28 9132
1193b4be Poul Sander 2025-02-03 21:28 9133
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9134
// [SECTION] Example App: Long Text / ShowExampleAppLongText()
1193b4be Poul Sander 2025-02-03 21:28 9135
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9136
1193b4be Poul Sander 2025-02-03 21:28 9137
// Demonstrate/test rendering huge amount of text, and the incidence of clipping.
1193b4be Poul Sander 2025-02-03 21:28 9138
static void ShowExampleAppLongText(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 9139
{
1193b4be Poul Sander 2025-02-03 21:28 9140
    ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 9141
    if (!ImGui::Begin("Example: Long text display", p_open))
1193b4be Poul Sander 2025-02-03 21:28 9142
    {
1193b4be Poul Sander 2025-02-03 21:28 9143
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9144
        return;
1193b4be Poul Sander 2025-02-03 21:28 9145
    }
1193b4be Poul Sander 2025-02-03 21:28 9146
    IMGUI_DEMO_MARKER("Examples/Long text display");
1193b4be Poul Sander 2025-02-03 21:28 9147
1193b4be Poul Sander 2025-02-03 21:28 9148
    static int test_type = 0;
1193b4be Poul Sander 2025-02-03 21:28 9149
    static ImGuiTextBuffer log;
1193b4be Poul Sander 2025-02-03 21:28 9150
    static int lines = 0;
1193b4be Poul Sander 2025-02-03 21:28 9151
    ImGui::Text("Printing unusually long amount of text.");
1193b4be Poul Sander 2025-02-03 21:28 9152
    ImGui::Combo("Test type", &test_type,
1193b4be Poul Sander 2025-02-03 21:28 9153
        "Single call to TextUnformatted()\0"
1193b4be Poul Sander 2025-02-03 21:28 9154
        "Multiple calls to Text(), clipped\0"
1193b4be Poul Sander 2025-02-03 21:28 9155
        "Multiple calls to Text(), not clipped (slow)\0");
1193b4be Poul Sander 2025-02-03 21:28 9156
    ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
1193b4be Poul Sander 2025-02-03 21:28 9157
    if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
1193b4be Poul Sander 2025-02-03 21:28 9158
    ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9159
    if (ImGui::Button("Add 1000 lines"))
1193b4be Poul Sander 2025-02-03 21:28 9160
    {
1193b4be Poul Sander 2025-02-03 21:28 9161
        for (int i = 0; i < 1000; i++)
1193b4be Poul Sander 2025-02-03 21:28 9162
            log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
1193b4be Poul Sander 2025-02-03 21:28 9163
        lines += 1000;
1193b4be Poul Sander 2025-02-03 21:28 9164
    }
1193b4be Poul Sander 2025-02-03 21:28 9165
    ImGui::BeginChild("Log");
1193b4be Poul Sander 2025-02-03 21:28 9166
    switch (test_type)
1193b4be Poul Sander 2025-02-03 21:28 9167
    {
1193b4be Poul Sander 2025-02-03 21:28 9168
    case 0:
1193b4be Poul Sander 2025-02-03 21:28 9169
        // Single call to TextUnformatted() with a big buffer
1193b4be Poul Sander 2025-02-03 21:28 9170
        ImGui::TextUnformatted(log.begin(), log.end());
1193b4be Poul Sander 2025-02-03 21:28 9171
        break;
1193b4be Poul Sander 2025-02-03 21:28 9172
    case 1:
1193b4be Poul Sander 2025-02-03 21:28 9173
        {
1193b4be Poul Sander 2025-02-03 21:28 9174
            // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
1193b4be Poul Sander 2025-02-03 21:28 9175
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
1193b4be Poul Sander 2025-02-03 21:28 9176
            ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 9177
            clipper.Begin(lines);
1193b4be Poul Sander 2025-02-03 21:28 9178
            while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 9179
                for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
1193b4be Poul Sander 2025-02-03 21:28 9180
                    ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
1193b4be Poul Sander 2025-02-03 21:28 9181
            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 9182
            break;
1193b4be Poul Sander 2025-02-03 21:28 9183
        }
1193b4be Poul Sander 2025-02-03 21:28 9184
    case 2:
1193b4be Poul Sander 2025-02-03 21:28 9185
        // Multiple calls to Text(), not clipped (slow)
1193b4be Poul Sander 2025-02-03 21:28 9186
        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
1193b4be Poul Sander 2025-02-03 21:28 9187
        for (int i = 0; i < lines; i++)
1193b4be Poul Sander 2025-02-03 21:28 9188
            ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
1193b4be Poul Sander 2025-02-03 21:28 9189
        ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 9190
        break;
1193b4be Poul Sander 2025-02-03 21:28 9191
    }
1193b4be Poul Sander 2025-02-03 21:28 9192
    ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 9193
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9194
}
1193b4be Poul Sander 2025-02-03 21:28 9195
1193b4be Poul Sander 2025-02-03 21:28 9196
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9197
// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
1193b4be Poul Sander 2025-02-03 21:28 9198
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9199
1193b4be Poul Sander 2025-02-03 21:28 9200
// Demonstrate creating a window which gets auto-resized according to its content.
1193b4be Poul Sander 2025-02-03 21:28 9201
static void ShowExampleAppAutoResize(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 9202
{
1193b4be Poul Sander 2025-02-03 21:28 9203
    if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
1193b4be Poul Sander 2025-02-03 21:28 9204
    {
1193b4be Poul Sander 2025-02-03 21:28 9205
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9206
        return;
1193b4be Poul Sander 2025-02-03 21:28 9207
    }
1193b4be Poul Sander 2025-02-03 21:28 9208
    IMGUI_DEMO_MARKER("Examples/Auto-resizing window");
1193b4be Poul Sander 2025-02-03 21:28 9209
1193b4be Poul Sander 2025-02-03 21:28 9210
    static int lines = 10;
1193b4be Poul Sander 2025-02-03 21:28 9211
    ImGui::TextUnformatted(
1193b4be Poul Sander 2025-02-03 21:28 9212
        "Window will resize every-frame to the size of its content.\n"
1193b4be Poul Sander 2025-02-03 21:28 9213
        "Note that you probably don't want to query the window size to\n"
1193b4be Poul Sander 2025-02-03 21:28 9214
        "output your content because that would create a feedback loop.");
1193b4be Poul Sander 2025-02-03 21:28 9215
    ImGui::SliderInt("Number of lines", &lines, 1, 20);
1193b4be Poul Sander 2025-02-03 21:28 9216
    for (int i = 0; i < lines; i++)
1193b4be Poul Sander 2025-02-03 21:28 9217
        ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
1193b4be Poul Sander 2025-02-03 21:28 9218
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9219
}
1193b4be Poul Sander 2025-02-03 21:28 9220
1193b4be Poul Sander 2025-02-03 21:28 9221
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9222
// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
1193b4be Poul Sander 2025-02-03 21:28 9223
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9224
1193b4be Poul Sander 2025-02-03 21:28 9225
// Demonstrate creating a window with custom resize constraints.
1193b4be Poul Sander 2025-02-03 21:28 9226
// Note that size constraints currently don't work on a docked window (when in 'docking' branch)
1193b4be Poul Sander 2025-02-03 21:28 9227
static void ShowExampleAppConstrainedResize(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 9228
{
1193b4be Poul Sander 2025-02-03 21:28 9229
    struct CustomConstraints
1193b4be Poul Sander 2025-02-03 21:28 9230
    {
1193b4be Poul Sander 2025-02-03 21:28 9231
        // Helper functions to demonstrate programmatic constraints
1193b4be Poul Sander 2025-02-03 21:28 9232
        // FIXME: This doesn't take account of decoration size (e.g. title bar), library should make this easier.
1193b4be Poul Sander 2025-02-03 21:28 9233
        // FIXME: None of the three demos works consistently when resizing from borders.
1193b4be Poul Sander 2025-02-03 21:28 9234
        static void AspectRatio(ImGuiSizeCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 9235
        {
1193b4be Poul Sander 2025-02-03 21:28 9236
            float aspect_ratio = *(float*)data->UserData;
1193b4be Poul Sander 2025-02-03 21:28 9237
            data->DesiredSize.y = (float)(int)(data->DesiredSize.x / aspect_ratio);
1193b4be Poul Sander 2025-02-03 21:28 9238
        }
1193b4be Poul Sander 2025-02-03 21:28 9239
        static void Square(ImGuiSizeCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 9240
        {
1193b4be Poul Sander 2025-02-03 21:28 9241
            data->DesiredSize.x = data->DesiredSize.y = IM_MAX(data->DesiredSize.x, data->DesiredSize.y);
1193b4be Poul Sander 2025-02-03 21:28 9242
        }
1193b4be Poul Sander 2025-02-03 21:28 9243
        static void Step(ImGuiSizeCallbackData* data)
1193b4be Poul Sander 2025-02-03 21:28 9244
        {
1193b4be Poul Sander 2025-02-03 21:28 9245
            float step = *(float*)data->UserData;
1193b4be Poul Sander 2025-02-03 21:28 9246
            data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step);
1193b4be Poul Sander 2025-02-03 21:28 9247
        }
1193b4be Poul Sander 2025-02-03 21:28 9248
    };
1193b4be Poul Sander 2025-02-03 21:28 9249
1193b4be Poul Sander 2025-02-03 21:28 9250
    const char* test_desc[] =
1193b4be Poul Sander 2025-02-03 21:28 9251
    {
1193b4be Poul Sander 2025-02-03 21:28 9252
        "Between 100x100 and 500x500",
1193b4be Poul Sander 2025-02-03 21:28 9253
        "At least 100x100",
1193b4be Poul Sander 2025-02-03 21:28 9254
        "Resize vertical + lock current width",
1193b4be Poul Sander 2025-02-03 21:28 9255
        "Resize horizontal + lock current height",
1193b4be Poul Sander 2025-02-03 21:28 9256
        "Width Between 400 and 500",
1193b4be Poul Sander 2025-02-03 21:28 9257
        "Height at least 400",
1193b4be Poul Sander 2025-02-03 21:28 9258
        "Custom: Aspect Ratio 16:9",
1193b4be Poul Sander 2025-02-03 21:28 9259
        "Custom: Always Square",
1193b4be Poul Sander 2025-02-03 21:28 9260
        "Custom: Fixed Steps (100)",
1193b4be Poul Sander 2025-02-03 21:28 9261
    };
1193b4be Poul Sander 2025-02-03 21:28 9262
1193b4be Poul Sander 2025-02-03 21:28 9263
    // Options
1193b4be Poul Sander 2025-02-03 21:28 9264
    static bool auto_resize = false;
1193b4be Poul Sander 2025-02-03 21:28 9265
    static bool window_padding = true;
1193b4be Poul Sander 2025-02-03 21:28 9266
    static int type = 6; // Aspect Ratio
1193b4be Poul Sander 2025-02-03 21:28 9267
    static int display_lines = 10;
1193b4be Poul Sander 2025-02-03 21:28 9268
1193b4be Poul Sander 2025-02-03 21:28 9269
    // Submit constraint
1193b4be Poul Sander 2025-02-03 21:28 9270
    float aspect_ratio = 16.0f / 9.0f;
1193b4be Poul Sander 2025-02-03 21:28 9271
    float fixed_step = 100.0f;
1193b4be Poul Sander 2025-02-03 21:28 9272
    if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(500, 500));         // Between 100x100 and 500x500
1193b4be Poul Sander 2025-02-03 21:28 9273
    if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
1193b4be Poul Sander 2025-02-03 21:28 9274
    if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Resize vertical + lock current width
1193b4be Poul Sander 2025-02-03 21:28 9275
    if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Resize horizontal + lock current height
1193b4be Poul Sander 2025-02-03 21:28 9276
    if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width Between and 400 and 500
1193b4be Poul Sander 2025-02-03 21:28 9277
    if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, FLT_MAX));      // Height at least 400
1193b4be Poul Sander 2025-02-03 21:28 9278
    if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::AspectRatio, (void*)&aspect_ratio);   // Aspect ratio
1193b4be Poul Sander 2025-02-03 21:28 9279
    if (type == 7) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);                              // Always Square
1193b4be Poul Sander 2025-02-03 21:28 9280
    if (type == 8) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)&fixed_step);            // Fixed Step
1193b4be Poul Sander 2025-02-03 21:28 9281
1193b4be Poul Sander 2025-02-03 21:28 9282
    // Submit window
1193b4be Poul Sander 2025-02-03 21:28 9283
    if (!window_padding)
1193b4be Poul Sander 2025-02-03 21:28 9284
        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 9285
    const ImGuiWindowFlags window_flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
1193b4be Poul Sander 2025-02-03 21:28 9286
    const bool window_open = ImGui::Begin("Example: Constrained Resize", p_open, window_flags);
1193b4be Poul Sander 2025-02-03 21:28 9287
    if (!window_padding)
1193b4be Poul Sander 2025-02-03 21:28 9288
        ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 9289
    if (window_open)
1193b4be Poul Sander 2025-02-03 21:28 9290
    {
1193b4be Poul Sander 2025-02-03 21:28 9291
        IMGUI_DEMO_MARKER("Examples/Constrained Resizing window");
1193b4be Poul Sander 2025-02-03 21:28 9292
        if (ImGui::GetIO().KeyShift)
1193b4be Poul Sander 2025-02-03 21:28 9293
        {
1193b4be Poul Sander 2025-02-03 21:28 9294
            // Display a dummy viewport (in your real app you would likely use ImageButton() to display a texture.
1193b4be Poul Sander 2025-02-03 21:28 9295
            ImVec2 avail_size = ImGui::GetContentRegionAvail();
1193b4be Poul Sander 2025-02-03 21:28 9296
            ImVec2 pos = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 9297
            ImGui::ColorButton("viewport", ImVec4(0.5f, 0.2f, 0.5f, 1.0f), ImGuiColorEditFlags_NoTooltip | ImGuiColorEditFlags_NoDragDrop, avail_size);
1193b4be Poul Sander 2025-02-03 21:28 9298
            ImGui::SetCursorScreenPos(ImVec2(pos.x + 10, pos.y + 10));
1193b4be Poul Sander 2025-02-03 21:28 9299
            ImGui::Text("%.2f x %.2f", avail_size.x, avail_size.y);
1193b4be Poul Sander 2025-02-03 21:28 9300
        }
1193b4be Poul Sander 2025-02-03 21:28 9301
        else
1193b4be Poul Sander 2025-02-03 21:28 9302
        {
1193b4be Poul Sander 2025-02-03 21:28 9303
            ImGui::Text("(Hold SHIFT to display a dummy viewport)");
1193b4be Poul Sander 2025-02-03 21:28 9304
            if (ImGui::IsWindowDocked())
1193b4be Poul Sander 2025-02-03 21:28 9305
                ImGui::Text("Warning: Sizing Constraints won't work if the window is docked!");
1193b4be Poul Sander 2025-02-03 21:28 9306
            if (ImGui::Button("Set 200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9307
            if (ImGui::Button("Set 500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9308
            if (ImGui::Button("Set 800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
1193b4be Poul Sander 2025-02-03 21:28 9309
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
1193b4be Poul Sander 2025-02-03 21:28 9310
            ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
1193b4be Poul Sander 2025-02-03 21:28 9311
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 20);
1193b4be Poul Sander 2025-02-03 21:28 9312
            ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
1193b4be Poul Sander 2025-02-03 21:28 9313
            ImGui::Checkbox("Auto-resize", &auto_resize);
1193b4be Poul Sander 2025-02-03 21:28 9314
            ImGui::Checkbox("Window padding", &window_padding);
1193b4be Poul Sander 2025-02-03 21:28 9315
            for (int i = 0; i < display_lines; i++)
1193b4be Poul Sander 2025-02-03 21:28 9316
                ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
1193b4be Poul Sander 2025-02-03 21:28 9317
        }
1193b4be Poul Sander 2025-02-03 21:28 9318
    }
1193b4be Poul Sander 2025-02-03 21:28 9319
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9320
}
1193b4be Poul Sander 2025-02-03 21:28 9321
1193b4be Poul Sander 2025-02-03 21:28 9322
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9323
// [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
1193b4be Poul Sander 2025-02-03 21:28 9324
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9325
1193b4be Poul Sander 2025-02-03 21:28 9326
// Demonstrate creating a simple static window with no decoration
1193b4be Poul Sander 2025-02-03 21:28 9327
// + a context-menu to choose which corner of the screen to use.
1193b4be Poul Sander 2025-02-03 21:28 9328
static void ShowExampleAppSimpleOverlay(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 9329
{
1193b4be Poul Sander 2025-02-03 21:28 9330
    static int location = 0;
1193b4be Poul Sander 2025-02-03 21:28 9331
    ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 9332
    ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
1193b4be Poul Sander 2025-02-03 21:28 9333
    if (location >= 0)
1193b4be Poul Sander 2025-02-03 21:28 9334
    {
1193b4be Poul Sander 2025-02-03 21:28 9335
        const float PAD = 10.0f;
1193b4be Poul Sander 2025-02-03 21:28 9336
        const ImGuiViewport* viewport = ImGui::GetMainViewport();
1193b4be Poul Sander 2025-02-03 21:28 9337
        ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
1193b4be Poul Sander 2025-02-03 21:28 9338
        ImVec2 work_size = viewport->WorkSize;
1193b4be Poul Sander 2025-02-03 21:28 9339
        ImVec2 window_pos, window_pos_pivot;
1193b4be Poul Sander 2025-02-03 21:28 9340
        window_pos.x = (location & 1) ? (work_pos.x + work_size.x - PAD) : (work_pos.x + PAD);
1193b4be Poul Sander 2025-02-03 21:28 9341
        window_pos.y = (location & 2) ? (work_pos.y + work_size.y - PAD) : (work_pos.y + PAD);
1193b4be Poul Sander 2025-02-03 21:28 9342
        window_pos_pivot.x = (location & 1) ? 1.0f : 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 9343
        window_pos_pivot.y = (location & 2) ? 1.0f : 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 9344
        ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
1193b4be Poul Sander 2025-02-03 21:28 9345
        ImGui::SetNextWindowViewport(viewport->ID);
1193b4be Poul Sander 2025-02-03 21:28 9346
        window_flags |= ImGuiWindowFlags_NoMove;
1193b4be Poul Sander 2025-02-03 21:28 9347
    }
1193b4be Poul Sander 2025-02-03 21:28 9348
    else if (location == -2)
1193b4be Poul Sander 2025-02-03 21:28 9349
    {
1193b4be Poul Sander 2025-02-03 21:28 9350
        // Center window
1193b4be Poul Sander 2025-02-03 21:28 9351
        ImGui::SetNextWindowPos(ImGui::GetMainViewport()->GetCenter(), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
1193b4be Poul Sander 2025-02-03 21:28 9352
        window_flags |= ImGuiWindowFlags_NoMove;
1193b4be Poul Sander 2025-02-03 21:28 9353
    }
1193b4be Poul Sander 2025-02-03 21:28 9354
    ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
1193b4be Poul Sander 2025-02-03 21:28 9355
    if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
1193b4be Poul Sander 2025-02-03 21:28 9356
    {
1193b4be Poul Sander 2025-02-03 21:28 9357
        IMGUI_DEMO_MARKER("Examples/Simple Overlay");
1193b4be Poul Sander 2025-02-03 21:28 9358
        ImGui::Text("Simple overlay\n" "(right-click to change position)");
1193b4be Poul Sander 2025-02-03 21:28 9359
        ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 9360
        if (ImGui::IsMousePosValid())
1193b4be Poul Sander 2025-02-03 21:28 9361
            ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
1193b4be Poul Sander 2025-02-03 21:28 9362
        else
1193b4be Poul Sander 2025-02-03 21:28 9363
            ImGui::Text("Mouse Position: <invalid>");
1193b4be Poul Sander 2025-02-03 21:28 9364
        if (ImGui::BeginPopupContextWindow())
1193b4be Poul Sander 2025-02-03 21:28 9365
        {
1193b4be Poul Sander 2025-02-03 21:28 9366
            if (ImGui::MenuItem("Custom",       NULL, location == -1)) location = -1;
1193b4be Poul Sander 2025-02-03 21:28 9367
            if (ImGui::MenuItem("Center",       NULL, location == -2)) location = -2;
1193b4be Poul Sander 2025-02-03 21:28 9368
            if (ImGui::MenuItem("Top-left",     NULL, location == 0)) location = 0;
1193b4be Poul Sander 2025-02-03 21:28 9369
            if (ImGui::MenuItem("Top-right",    NULL, location == 1)) location = 1;
1193b4be Poul Sander 2025-02-03 21:28 9370
            if (ImGui::MenuItem("Bottom-left",  NULL, location == 2)) location = 2;
1193b4be Poul Sander 2025-02-03 21:28 9371
            if (ImGui::MenuItem("Bottom-right", NULL, location == 3)) location = 3;
1193b4be Poul Sander 2025-02-03 21:28 9372
            if (p_open && ImGui::MenuItem("Close")) *p_open = false;
1193b4be Poul Sander 2025-02-03 21:28 9373
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 9374
        }
1193b4be Poul Sander 2025-02-03 21:28 9375
    }
1193b4be Poul Sander 2025-02-03 21:28 9376
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9377
}
1193b4be Poul Sander 2025-02-03 21:28 9378
1193b4be Poul Sander 2025-02-03 21:28 9379
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9380
// [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
1193b4be Poul Sander 2025-02-03 21:28 9381
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9382
1193b4be Poul Sander 2025-02-03 21:28 9383
// Demonstrate creating a window covering the entire screen/viewport
1193b4be Poul Sander 2025-02-03 21:28 9384
static void ShowExampleAppFullscreen(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 9385
{
1193b4be Poul Sander 2025-02-03 21:28 9386
    static bool use_work_area = true;
1193b4be Poul Sander 2025-02-03 21:28 9387
    static ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings;
1193b4be Poul Sander 2025-02-03 21:28 9388
1193b4be Poul Sander 2025-02-03 21:28 9389
    // We demonstrate using the full viewport area or the work area (without menu-bars, task-bars etc.)
1193b4be Poul Sander 2025-02-03 21:28 9390
    // Based on your use case you may want one or the other.
1193b4be Poul Sander 2025-02-03 21:28 9391
    const ImGuiViewport* viewport = ImGui::GetMainViewport();
1193b4be Poul Sander 2025-02-03 21:28 9392
    ImGui::SetNextWindowPos(use_work_area ? viewport->WorkPos : viewport->Pos);
1193b4be Poul Sander 2025-02-03 21:28 9393
    ImGui::SetNextWindowSize(use_work_area ? viewport->WorkSize : viewport->Size);
1193b4be Poul Sander 2025-02-03 21:28 9394
1193b4be Poul Sander 2025-02-03 21:28 9395
    if (ImGui::Begin("Example: Fullscreen window", p_open, flags))
1193b4be Poul Sander 2025-02-03 21:28 9396
    {
1193b4be Poul Sander 2025-02-03 21:28 9397
        ImGui::Checkbox("Use work area instead of main area", &use_work_area);
1193b4be Poul Sander 2025-02-03 21:28 9398
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9399
        HelpMarker("Main Area = entire viewport,\nWork Area = entire viewport minus sections used by the main menu bars, task bars etc.\n\nEnable the main-menu bar in Examples menu to see the difference.");
1193b4be Poul Sander 2025-02-03 21:28 9400
1193b4be Poul Sander 2025-02-03 21:28 9401
        ImGui::CheckboxFlags("ImGuiWindowFlags_NoBackground", &flags, ImGuiWindowFlags_NoBackground);
1193b4be Poul Sander 2025-02-03 21:28 9402
        ImGui::CheckboxFlags("ImGuiWindowFlags_NoDecoration", &flags, ImGuiWindowFlags_NoDecoration);
1193b4be Poul Sander 2025-02-03 21:28 9403
        ImGui::Indent();
1193b4be Poul Sander 2025-02-03 21:28 9404
        ImGui::CheckboxFlags("ImGuiWindowFlags_NoTitleBar", &flags, ImGuiWindowFlags_NoTitleBar);
1193b4be Poul Sander 2025-02-03 21:28 9405
        ImGui::CheckboxFlags("ImGuiWindowFlags_NoCollapse", &flags, ImGuiWindowFlags_NoCollapse);
1193b4be Poul Sander 2025-02-03 21:28 9406
        ImGui::CheckboxFlags("ImGuiWindowFlags_NoScrollbar", &flags, ImGuiWindowFlags_NoScrollbar);
1193b4be Poul Sander 2025-02-03 21:28 9407
        ImGui::Unindent();
1193b4be Poul Sander 2025-02-03 21:28 9408
1193b4be Poul Sander 2025-02-03 21:28 9409
        if (p_open && ImGui::Button("Close this window"))
1193b4be Poul Sander 2025-02-03 21:28 9410
            *p_open = false;
1193b4be Poul Sander 2025-02-03 21:28 9411
    }
1193b4be Poul Sander 2025-02-03 21:28 9412
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9413
}
1193b4be Poul Sander 2025-02-03 21:28 9414
1193b4be Poul Sander 2025-02-03 21:28 9415
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9416
// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
1193b4be Poul Sander 2025-02-03 21:28 9417
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9418
1193b4be Poul Sander 2025-02-03 21:28 9419
// Demonstrate the use of "##" and "###" in identifiers to manipulate ID generation.
1193b4be Poul Sander 2025-02-03 21:28 9420
// This applies to all regular items as well.
1193b4be Poul Sander 2025-02-03 21:28 9421
// Read FAQ section "How can I have multiple widgets with the same label?" for details.
1193b4be Poul Sander 2025-02-03 21:28 9422
static void ShowExampleAppWindowTitles(bool*)
1193b4be Poul Sander 2025-02-03 21:28 9423
{
1193b4be Poul Sander 2025-02-03 21:28 9424
    const ImGuiViewport* viewport = ImGui::GetMainViewport();
1193b4be Poul Sander 2025-02-03 21:28 9425
    const ImVec2 base_pos = viewport->Pos;
1193b4be Poul Sander 2025-02-03 21:28 9426
1193b4be Poul Sander 2025-02-03 21:28 9427
    // By default, Windows are uniquely identified by their title.
1193b4be Poul Sander 2025-02-03 21:28 9428
    // You can use the "##" and "###" markers to manipulate the display/ID.
1193b4be Poul Sander 2025-02-03 21:28 9429
1193b4be Poul Sander 2025-02-03 21:28 9430
    // Using "##" to display same title but have unique identifier.
1193b4be Poul Sander 2025-02-03 21:28 9431
    ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 100), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 9432
    ImGui::Begin("Same title as another window##1");
1193b4be Poul Sander 2025-02-03 21:28 9433
    IMGUI_DEMO_MARKER("Examples/Manipulating window titles");
1193b4be Poul Sander 2025-02-03 21:28 9434
    ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
1193b4be Poul Sander 2025-02-03 21:28 9435
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9436
1193b4be Poul Sander 2025-02-03 21:28 9437
    ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 200), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 9438
    ImGui::Begin("Same title as another window##2");
1193b4be Poul Sander 2025-02-03 21:28 9439
    ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
1193b4be Poul Sander 2025-02-03 21:28 9440
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9441
1193b4be Poul Sander 2025-02-03 21:28 9442
    // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
1193b4be Poul Sander 2025-02-03 21:28 9443
    char buf[128];
1193b4be Poul Sander 2025-02-03 21:28 9444
    sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
1193b4be Poul Sander 2025-02-03 21:28 9445
    ImGui::SetNextWindowPos(ImVec2(base_pos.x + 100, base_pos.y + 300), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 9446
    ImGui::Begin(buf);
1193b4be Poul Sander 2025-02-03 21:28 9447
    ImGui::Text("This window has a changing title.");
1193b4be Poul Sander 2025-02-03 21:28 9448
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9449
}
1193b4be Poul Sander 2025-02-03 21:28 9450
1193b4be Poul Sander 2025-02-03 21:28 9451
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9452
// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
1193b4be Poul Sander 2025-02-03 21:28 9453
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9454
1193b4be Poul Sander 2025-02-03 21:28 9455
// Add a |_| looking shape
1193b4be Poul Sander 2025-02-03 21:28 9456
static void PathConcaveShape(ImDrawList* draw_list, float x, float y, float sz)
1193b4be Poul Sander 2025-02-03 21:28 9457
{
1193b4be Poul Sander 2025-02-03 21:28 9458
    const ImVec2 pos_norms[] = { { 0.0f, 0.0f }, { 0.3f, 0.0f }, { 0.3f, 0.7f }, { 0.7f, 0.7f }, { 0.7f, 0.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 0.0f, 1.0f } };
1193b4be Poul Sander 2025-02-03 21:28 9459
    for (const ImVec2& p : pos_norms)
1193b4be Poul Sander 2025-02-03 21:28 9460
        draw_list->PathLineTo(ImVec2(x + 0.5f + (int)(sz * p.x), y + 0.5f + (int)(sz * p.y)));
1193b4be Poul Sander 2025-02-03 21:28 9461
}
1193b4be Poul Sander 2025-02-03 21:28 9462
1193b4be Poul Sander 2025-02-03 21:28 9463
// Demonstrate using the low-level ImDrawList to draw custom shapes.
1193b4be Poul Sander 2025-02-03 21:28 9464
static void ShowExampleAppCustomRendering(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 9465
{
1193b4be Poul Sander 2025-02-03 21:28 9466
    if (!ImGui::Begin("Example: Custom rendering", p_open))
1193b4be Poul Sander 2025-02-03 21:28 9467
    {
1193b4be Poul Sander 2025-02-03 21:28 9468
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9469
        return;
1193b4be Poul Sander 2025-02-03 21:28 9470
    }
1193b4be Poul Sander 2025-02-03 21:28 9471
    IMGUI_DEMO_MARKER("Examples/Custom Rendering");
1193b4be Poul Sander 2025-02-03 21:28 9472
1193b4be Poul Sander 2025-02-03 21:28 9473
    // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of
1193b4be Poul Sander 2025-02-03 21:28 9474
    // overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your
1193b4be Poul Sander 2025-02-03 21:28 9475
    // types and ImVec2/ImVec4. Dear ImGui defines overloaded operators but they are internal to imgui.cpp and not
1193b4be Poul Sander 2025-02-03 21:28 9476
    // exposed outside (to avoid messing with your types) In this example we are not using the maths operators!
1193b4be Poul Sander 2025-02-03 21:28 9477
1193b4be Poul Sander 2025-02-03 21:28 9478
    if (ImGui::BeginTabBar("##TabBar"))
1193b4be Poul Sander 2025-02-03 21:28 9479
    {
1193b4be Poul Sander 2025-02-03 21:28 9480
        if (ImGui::BeginTabItem("Primitives"))
1193b4be Poul Sander 2025-02-03 21:28 9481
        {
1193b4be Poul Sander 2025-02-03 21:28 9482
            ImGui::PushItemWidth(-ImGui::GetFontSize() * 15);
1193b4be Poul Sander 2025-02-03 21:28 9483
            ImDrawList* draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 9484
1193b4be Poul Sander 2025-02-03 21:28 9485
            // Draw gradients
1193b4be Poul Sander 2025-02-03 21:28 9486
            // (note that those are currently exacerbating our sRGB/Linear issues)
1193b4be Poul Sander 2025-02-03 21:28 9487
            // Calling ImGui::GetColorU32() multiplies the given colors by the current Style Alpha, but you may pass the IM_COL32() directly as well..
1193b4be Poul Sander 2025-02-03 21:28 9488
            ImGui::Text("Gradients");
1193b4be Poul Sander 2025-02-03 21:28 9489
            ImVec2 gradient_size = ImVec2(ImGui::CalcItemWidth(), ImGui::GetFrameHeight());
1193b4be Poul Sander 2025-02-03 21:28 9490
            {
1193b4be Poul Sander 2025-02-03 21:28 9491
                ImVec2 p0 = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 9492
                ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
1193b4be Poul Sander 2025-02-03 21:28 9493
                ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 0, 0, 255));
1193b4be Poul Sander 2025-02-03 21:28 9494
                ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 255, 255, 255));
1193b4be Poul Sander 2025-02-03 21:28 9495
                draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
1193b4be Poul Sander 2025-02-03 21:28 9496
                ImGui::InvisibleButton("##gradient1", gradient_size);
1193b4be Poul Sander 2025-02-03 21:28 9497
            }
1193b4be Poul Sander 2025-02-03 21:28 9498
            {
1193b4be Poul Sander 2025-02-03 21:28 9499
                ImVec2 p0 = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 9500
                ImVec2 p1 = ImVec2(p0.x + gradient_size.x, p0.y + gradient_size.y);
1193b4be Poul Sander 2025-02-03 21:28 9501
                ImU32 col_a = ImGui::GetColorU32(IM_COL32(0, 255, 0, 255));
1193b4be Poul Sander 2025-02-03 21:28 9502
                ImU32 col_b = ImGui::GetColorU32(IM_COL32(255, 0, 0, 255));
1193b4be Poul Sander 2025-02-03 21:28 9503
                draw_list->AddRectFilledMultiColor(p0, p1, col_a, col_b, col_b, col_a);
1193b4be Poul Sander 2025-02-03 21:28 9504
                ImGui::InvisibleButton("##gradient2", gradient_size);
1193b4be Poul Sander 2025-02-03 21:28 9505
            }
1193b4be Poul Sander 2025-02-03 21:28 9506
1193b4be Poul Sander 2025-02-03 21:28 9507
            // Draw a bunch of primitives
1193b4be Poul Sander 2025-02-03 21:28 9508
            ImGui::Text("All primitives");
1193b4be Poul Sander 2025-02-03 21:28 9509
            static float sz = 36.0f;
1193b4be Poul Sander 2025-02-03 21:28 9510
            static float thickness = 3.0f;
1193b4be Poul Sander 2025-02-03 21:28 9511
            static int ngon_sides = 6;
1193b4be Poul Sander 2025-02-03 21:28 9512
            static bool circle_segments_override = false;
1193b4be Poul Sander 2025-02-03 21:28 9513
            static int circle_segments_override_v = 12;
1193b4be Poul Sander 2025-02-03 21:28 9514
            static bool curve_segments_override = false;
1193b4be Poul Sander 2025-02-03 21:28 9515
            static int curve_segments_override_v = 8;
1193b4be Poul Sander 2025-02-03 21:28 9516
            static ImVec4 colf = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
1193b4be Poul Sander 2025-02-03 21:28 9517
            ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 100.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 9518
            ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
1193b4be Poul Sander 2025-02-03 21:28 9519
            ImGui::SliderInt("N-gon sides", &ngon_sides, 3, 12);
1193b4be Poul Sander 2025-02-03 21:28 9520
            ImGui::Checkbox("##circlesegmentoverride", &circle_segments_override);
1193b4be Poul Sander 2025-02-03 21:28 9521
            ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 9522
            circle_segments_override |= ImGui::SliderInt("Circle segments override", &circle_segments_override_v, 3, 40);
1193b4be Poul Sander 2025-02-03 21:28 9523
            ImGui::Checkbox("##curvessegmentoverride", &curve_segments_override);
1193b4be Poul Sander 2025-02-03 21:28 9524
            ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1193b4be Poul Sander 2025-02-03 21:28 9525
            curve_segments_override |= ImGui::SliderInt("Curves segments override", &curve_segments_override_v, 3, 40);
1193b4be Poul Sander 2025-02-03 21:28 9526
            ImGui::ColorEdit4("Color", &colf.x);
1193b4be Poul Sander 2025-02-03 21:28 9527
1193b4be Poul Sander 2025-02-03 21:28 9528
            const ImVec2 p = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 9529
            const ImU32 col = ImColor(colf);
1193b4be Poul Sander 2025-02-03 21:28 9530
            const float spacing = 10.0f;
1193b4be Poul Sander 2025-02-03 21:28 9531
            const ImDrawFlags corners_tl_br = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersBottomRight;
1193b4be Poul Sander 2025-02-03 21:28 9532
            const float rounding = sz / 5.0f;
1193b4be Poul Sander 2025-02-03 21:28 9533
            const int circle_segments = circle_segments_override ? circle_segments_override_v : 0;
1193b4be Poul Sander 2025-02-03 21:28 9534
            const int curve_segments = curve_segments_override ? curve_segments_override_v : 0;
1193b4be Poul Sander 2025-02-03 21:28 9535
            const ImVec2 cp3[3] = { ImVec2(0.0f, sz * 0.6f), ImVec2(sz * 0.5f, -sz * 0.4f), ImVec2(sz, sz) }; // Control points for curves
1193b4be Poul Sander 2025-02-03 21:28 9536
            const ImVec2 cp4[4] = { ImVec2(0.0f, 0.0f), ImVec2(sz * 1.3f, sz * 0.3f), ImVec2(sz - sz * 1.3f, sz - sz * 0.3f), ImVec2(sz, sz) };
1193b4be Poul Sander 2025-02-03 21:28 9537
1193b4be Poul Sander 2025-02-03 21:28 9538
            float x = p.x + 4.0f;
1193b4be Poul Sander 2025-02-03 21:28 9539
            float y = p.y + 4.0f;
1193b4be Poul Sander 2025-02-03 21:28 9540
            for (int n = 0; n < 2; n++)
1193b4be Poul Sander 2025-02-03 21:28 9541
            {
1193b4be Poul Sander 2025-02-03 21:28 9542
                // First line uses a thickness of 1.0f, second line uses the configurable thickness
1193b4be Poul Sander 2025-02-03 21:28 9543
                float th = (n == 0) ? 1.0f : thickness;
1193b4be Poul Sander 2025-02-03 21:28 9544
                draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th);                 x += sz + spacing;  // N-gon
1193b4be Poul Sander 2025-02-03 21:28 9545
                draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th);          x += sz + spacing;  // Circle
1193b4be Poul Sander 2025-02-03 21:28 9546
                draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing;	// Ellipse
1193b4be Poul Sander 2025-02-03 21:28 9547
                draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th);          x += sz + spacing;  // Square
1193b4be Poul Sander 2025-02-03 21:28 9548
                draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th);      x += sz + spacing;  // Square with all rounded corners
1193b4be Poul Sander 2025-02-03 21:28 9549
                draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th);         x += sz + spacing;  // Square with two rounded corners
1193b4be Poul Sander 2025-02-03 21:28 9550
                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
1193b4be Poul Sander 2025-02-03 21:28 9551
                //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
1193b4be Poul Sander 2025-02-03 21:28 9552
                PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th);          x += sz + spacing;  // Concave Shape
1193b4be Poul Sander 2025-02-03 21:28 9553
                //draw_list->AddPolyline(concave_shape, IM_ARRAYSIZE(concave_shape), col, ImDrawFlags_Closed, th);
1193b4be Poul Sander 2025-02-03 21:28 9554
                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!)
1193b4be Poul Sander 2025-02-03 21:28 9555
                draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th);                                       x += spacing;       // Vertical line (note: drawing a filled rectangle will be faster!)
1193b4be Poul Sander 2025-02-03 21:28 9556
                draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th);                                  x += sz + spacing;  // Diagonal line
1193b4be Poul Sander 2025-02-03 21:28 9557
1193b4be Poul Sander 2025-02-03 21:28 9558
                // Path
1193b4be Poul Sander 2025-02-03 21:28 9559
                draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f);
1193b4be Poul Sander 2025-02-03 21:28 9560
                draw_list->PathStroke(col, ImDrawFlags_None, th);
1193b4be Poul Sander 2025-02-03 21:28 9561
                x += sz + spacing;
1193b4be Poul Sander 2025-02-03 21:28 9562
1193b4be Poul Sander 2025-02-03 21:28 9563
                // Quadratic Bezier Curve (3 control points)
1193b4be Poul Sander 2025-02-03 21:28 9564
                draw_list->AddBezierQuadratic(ImVec2(x + cp3[0].x, y + cp3[0].y), ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), col, th, curve_segments);
1193b4be Poul Sander 2025-02-03 21:28 9565
                x += sz + spacing;
1193b4be Poul Sander 2025-02-03 21:28 9566
1193b4be Poul Sander 2025-02-03 21:28 9567
                // Cubic Bezier Curve (4 control points)
1193b4be Poul Sander 2025-02-03 21:28 9568
                draw_list->AddBezierCubic(ImVec2(x + cp4[0].x, y + cp4[0].y), ImVec2(x + cp4[1].x, y + cp4[1].y), ImVec2(x + cp4[2].x, y + cp4[2].y), ImVec2(x + cp4[3].x, y + cp4[3].y), col, th, curve_segments);
1193b4be Poul Sander 2025-02-03 21:28 9569
1193b4be Poul Sander 2025-02-03 21:28 9570
                x = p.x + 4;
1193b4be Poul Sander 2025-02-03 21:28 9571
                y += sz + spacing;
1193b4be Poul Sander 2025-02-03 21:28 9572
            }
1193b4be Poul Sander 2025-02-03 21:28 9573
1193b4be Poul Sander 2025-02-03 21:28 9574
            // Filled shapes
1193b4be Poul Sander 2025-02-03 21:28 9575
            draw_list->AddNgonFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, ngon_sides);             x += sz + spacing;  // N-gon
1193b4be Poul Sander 2025-02-03 21:28 9576
            draw_list->AddCircleFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, col, circle_segments);      x += sz + spacing;  // Circle
1193b4be Poul Sander 2025-02-03 21:28 9577
            draw_list->AddEllipseFilled(ImVec2(x + sz * 0.5f, y + sz * 0.5f), ImVec2(sz * 0.5f, sz * 0.3f), col, -0.3f, circle_segments); x += sz + spacing;// Ellipse
1193b4be Poul Sander 2025-02-03 21:28 9578
            draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col);                                    x += sz + spacing;  // Square
1193b4be Poul Sander 2025-02-03 21:28 9579
            draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 10.0f);                             x += sz + spacing;  // Square with all rounded corners
1193b4be Poul Sander 2025-02-03 21:28 9580
            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
1193b4be Poul Sander 2025-02-03 21:28 9581
            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
1193b4be Poul Sander 2025-02-03 21:28 9582
            //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
1193b4be Poul Sander 2025-02-03 21:28 9583
            PathConcaveShape(draw_list, x, y, sz); draw_list->PathFillConcave(col);                                 x += sz + spacing;  // Concave shape
1193b4be Poul Sander 2025-02-03 21:28 9584
            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)
1193b4be Poul Sander 2025-02-03 21:28 9585
            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)
1193b4be Poul Sander 2025-02-03 21:28 9586
            draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x + 1, y + 1), col);                                      x += sz;            // Pixel (faster than AddLine)
1193b4be Poul Sander 2025-02-03 21:28 9587
1193b4be Poul Sander 2025-02-03 21:28 9588
            // Path
1193b4be Poul Sander 2025-02-03 21:28 9589
            draw_list->PathArcTo(ImVec2(x + sz * 0.5f, y + sz * 0.5f), sz * 0.5f, 3.141592f * -0.5f, 3.141592f);
1193b4be Poul Sander 2025-02-03 21:28 9590
            draw_list->PathFillConvex(col);
1193b4be Poul Sander 2025-02-03 21:28 9591
            x += sz + spacing;
1193b4be Poul Sander 2025-02-03 21:28 9592
1193b4be Poul Sander 2025-02-03 21:28 9593
            // Quadratic Bezier Curve (3 control points)
1193b4be Poul Sander 2025-02-03 21:28 9594
            draw_list->PathLineTo(ImVec2(x + cp3[0].x, y + cp3[0].y));
1193b4be Poul Sander 2025-02-03 21:28 9595
            draw_list->PathBezierQuadraticCurveTo(ImVec2(x + cp3[1].x, y + cp3[1].y), ImVec2(x + cp3[2].x, y + cp3[2].y), curve_segments);
1193b4be Poul Sander 2025-02-03 21:28 9596
            draw_list->PathFillConvex(col);
1193b4be Poul Sander 2025-02-03 21:28 9597
            x += sz + spacing;
1193b4be Poul Sander 2025-02-03 21:28 9598
1193b4be Poul Sander 2025-02-03 21:28 9599
            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));
1193b4be Poul Sander 2025-02-03 21:28 9600
            x += sz + spacing;
1193b4be Poul Sander 2025-02-03 21:28 9601
1193b4be Poul Sander 2025-02-03 21:28 9602
            ImGui::Dummy(ImVec2((sz + spacing) * 13.2f, (sz + spacing) * 3.0f));
1193b4be Poul Sander 2025-02-03 21:28 9603
            ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 9604
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 9605
        }
1193b4be Poul Sander 2025-02-03 21:28 9606
1193b4be Poul Sander 2025-02-03 21:28 9607
        if (ImGui::BeginTabItem("Canvas"))
1193b4be Poul Sander 2025-02-03 21:28 9608
        {
1193b4be Poul Sander 2025-02-03 21:28 9609
            static ImVector<ImVec2> points;
1193b4be Poul Sander 2025-02-03 21:28 9610
            static ImVec2 scrolling(0.0f, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 9611
            static bool opt_enable_grid = true;
1193b4be Poul Sander 2025-02-03 21:28 9612
            static bool opt_enable_context_menu = true;
1193b4be Poul Sander 2025-02-03 21:28 9613
            static bool adding_line = false;
1193b4be Poul Sander 2025-02-03 21:28 9614
1193b4be Poul Sander 2025-02-03 21:28 9615
            ImGui::Checkbox("Enable grid", &opt_enable_grid);
1193b4be Poul Sander 2025-02-03 21:28 9616
            ImGui::Checkbox("Enable context menu", &opt_enable_context_menu);
1193b4be Poul Sander 2025-02-03 21:28 9617
            ImGui::Text("Mouse Left: drag to add lines,\nMouse Right: drag to scroll, click for context menu.");
1193b4be Poul Sander 2025-02-03 21:28 9618
1193b4be Poul Sander 2025-02-03 21:28 9619
            // Typically you would use a BeginChild()/EndChild() pair to benefit from a clipping region + own scrolling.
1193b4be Poul Sander 2025-02-03 21:28 9620
            // Here we demonstrate that this can be replaced by simple offsetting + custom drawing + PushClipRect/PopClipRect() calls.
1193b4be Poul Sander 2025-02-03 21:28 9621
            // To use a child window instead we could use, e.g:
1193b4be Poul Sander 2025-02-03 21:28 9622
            //      ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));      // Disable padding
1193b4be Poul Sander 2025-02-03 21:28 9623
            //      ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(50, 50, 50, 255));  // Set a background color
1193b4be Poul Sander 2025-02-03 21:28 9624
            //      ImGui::BeginChild("canvas", ImVec2(0.0f, 0.0f), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove);
1193b4be Poul Sander 2025-02-03 21:28 9625
            //      ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 9626
            //      ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 9627
            //      [...]
1193b4be Poul Sander 2025-02-03 21:28 9628
            //      ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 9629
1193b4be Poul Sander 2025-02-03 21:28 9630
            // Using InvisibleButton() as a convenience 1) it will advance the layout cursor and 2) allows us to use IsItemHovered()/IsItemActive()
1193b4be Poul Sander 2025-02-03 21:28 9631
            ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();      // ImDrawList API uses screen coordinates!
1193b4be Poul Sander 2025-02-03 21:28 9632
            ImVec2 canvas_sz = ImGui::GetContentRegionAvail();   // Resize canvas to what's available
1193b4be Poul Sander 2025-02-03 21:28 9633
            if (canvas_sz.x < 50.0f) canvas_sz.x = 50.0f;
1193b4be Poul Sander 2025-02-03 21:28 9634
            if (canvas_sz.y < 50.0f) canvas_sz.y = 50.0f;
1193b4be Poul Sander 2025-02-03 21:28 9635
            ImVec2 canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
1193b4be Poul Sander 2025-02-03 21:28 9636
1193b4be Poul Sander 2025-02-03 21:28 9637
            // Draw border and background color
1193b4be Poul Sander 2025-02-03 21:28 9638
            ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 9639
            ImDrawList* draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 9640
            draw_list->AddRectFilled(canvas_p0, canvas_p1, IM_COL32(50, 50, 50, 255));
1193b4be Poul Sander 2025-02-03 21:28 9641
            draw_list->AddRect(canvas_p0, canvas_p1, IM_COL32(255, 255, 255, 255));
1193b4be Poul Sander 2025-02-03 21:28 9642
1193b4be Poul Sander 2025-02-03 21:28 9643
            // This will catch our interactions
1193b4be Poul Sander 2025-02-03 21:28 9644
            ImGui::InvisibleButton("canvas", canvas_sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight);
1193b4be Poul Sander 2025-02-03 21:28 9645
            const bool is_hovered = ImGui::IsItemHovered(); // Hovered
1193b4be Poul Sander 2025-02-03 21:28 9646
            const bool is_active = ImGui::IsItemActive();   // Held
1193b4be Poul Sander 2025-02-03 21:28 9647
            const ImVec2 origin(canvas_p0.x + scrolling.x, canvas_p0.y + scrolling.y); // Lock scrolled origin
1193b4be Poul Sander 2025-02-03 21:28 9648
            const ImVec2 mouse_pos_in_canvas(io.MousePos.x - origin.x, io.MousePos.y - origin.y);
1193b4be Poul Sander 2025-02-03 21:28 9649
1193b4be Poul Sander 2025-02-03 21:28 9650
            // Add first and second point
1193b4be Poul Sander 2025-02-03 21:28 9651
            if (is_hovered && !adding_line && ImGui::IsMouseClicked(ImGuiMouseButton_Left))
1193b4be Poul Sander 2025-02-03 21:28 9652
            {
1193b4be Poul Sander 2025-02-03 21:28 9653
                points.push_back(mouse_pos_in_canvas);
1193b4be Poul Sander 2025-02-03 21:28 9654
                points.push_back(mouse_pos_in_canvas);
1193b4be Poul Sander 2025-02-03 21:28 9655
                adding_line = true;
1193b4be Poul Sander 2025-02-03 21:28 9656
            }
1193b4be Poul Sander 2025-02-03 21:28 9657
            if (adding_line)
1193b4be Poul Sander 2025-02-03 21:28 9658
            {
1193b4be Poul Sander 2025-02-03 21:28 9659
                points.back() = mouse_pos_in_canvas;
1193b4be Poul Sander 2025-02-03 21:28 9660
                if (!ImGui::IsMouseDown(ImGuiMouseButton_Left))
1193b4be Poul Sander 2025-02-03 21:28 9661
                    adding_line = false;
1193b4be Poul Sander 2025-02-03 21:28 9662
            }
1193b4be Poul Sander 2025-02-03 21:28 9663
1193b4be Poul Sander 2025-02-03 21:28 9664
            // Pan (we use a zero mouse threshold when there's no context menu)
1193b4be Poul Sander 2025-02-03 21:28 9665
            // You may decide to make that threshold dynamic based on whether the mouse is hovering something etc.
1193b4be Poul Sander 2025-02-03 21:28 9666
            const float mouse_threshold_for_pan = opt_enable_context_menu ? -1.0f : 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 9667
            if (is_active && ImGui::IsMouseDragging(ImGuiMouseButton_Right, mouse_threshold_for_pan))
1193b4be Poul Sander 2025-02-03 21:28 9668
            {
1193b4be Poul Sander 2025-02-03 21:28 9669
                scrolling.x += io.MouseDelta.x;
1193b4be Poul Sander 2025-02-03 21:28 9670
                scrolling.y += io.MouseDelta.y;
1193b4be Poul Sander 2025-02-03 21:28 9671
            }
1193b4be Poul Sander 2025-02-03 21:28 9672
1193b4be Poul Sander 2025-02-03 21:28 9673
            // Context menu (under default mouse threshold)
1193b4be Poul Sander 2025-02-03 21:28 9674
            ImVec2 drag_delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Right);
1193b4be Poul Sander 2025-02-03 21:28 9675
            if (opt_enable_context_menu && drag_delta.x == 0.0f && drag_delta.y == 0.0f)
1193b4be Poul Sander 2025-02-03 21:28 9676
                ImGui::OpenPopupOnItemClick("context", ImGuiPopupFlags_MouseButtonRight);
1193b4be Poul Sander 2025-02-03 21:28 9677
            if (ImGui::BeginPopup("context"))
1193b4be Poul Sander 2025-02-03 21:28 9678
            {
1193b4be Poul Sander 2025-02-03 21:28 9679
                if (adding_line)
1193b4be Poul Sander 2025-02-03 21:28 9680
                    points.resize(points.size() - 2);
1193b4be Poul Sander 2025-02-03 21:28 9681
                adding_line = false;
1193b4be Poul Sander 2025-02-03 21:28 9682
                if (ImGui::MenuItem("Remove one", NULL, false, points.Size > 0)) { points.resize(points.size() - 2); }
1193b4be Poul Sander 2025-02-03 21:28 9683
                if (ImGui::MenuItem("Remove all", NULL, false, points.Size > 0)) { points.clear(); }
1193b4be Poul Sander 2025-02-03 21:28 9684
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 9685
            }
1193b4be Poul Sander 2025-02-03 21:28 9686
1193b4be Poul Sander 2025-02-03 21:28 9687
            // Draw grid + all lines in the canvas
1193b4be Poul Sander 2025-02-03 21:28 9688
            draw_list->PushClipRect(canvas_p0, canvas_p1, true);
1193b4be Poul Sander 2025-02-03 21:28 9689
            if (opt_enable_grid)
1193b4be Poul Sander 2025-02-03 21:28 9690
            {
1193b4be Poul Sander 2025-02-03 21:28 9691
                const float GRID_STEP = 64.0f;
1193b4be Poul Sander 2025-02-03 21:28 9692
                for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
1193b4be Poul Sander 2025-02-03 21:28 9693
                    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));
1193b4be Poul Sander 2025-02-03 21:28 9694
                for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
1193b4be Poul Sander 2025-02-03 21:28 9695
                    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));
1193b4be Poul Sander 2025-02-03 21:28 9696
            }
1193b4be Poul Sander 2025-02-03 21:28 9697
            for (int n = 0; n < points.Size; n += 2)
1193b4be Poul Sander 2025-02-03 21:28 9698
                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);
1193b4be Poul Sander 2025-02-03 21:28 9699
            draw_list->PopClipRect();
1193b4be Poul Sander 2025-02-03 21:28 9700
1193b4be Poul Sander 2025-02-03 21:28 9701
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 9702
        }
1193b4be Poul Sander 2025-02-03 21:28 9703
1193b4be Poul Sander 2025-02-03 21:28 9704
        if (ImGui::BeginTabItem("BG/FG draw lists"))
1193b4be Poul Sander 2025-02-03 21:28 9705
        {
1193b4be Poul Sander 2025-02-03 21:28 9706
            static bool draw_bg = true;
1193b4be Poul Sander 2025-02-03 21:28 9707
            static bool draw_fg = true;
1193b4be Poul Sander 2025-02-03 21:28 9708
            ImGui::Checkbox("Draw in Background draw list", &draw_bg);
1193b4be Poul Sander 2025-02-03 21:28 9709
            ImGui::SameLine(); HelpMarker("The Background draw list will be rendered below every Dear ImGui windows.");
1193b4be Poul Sander 2025-02-03 21:28 9710
            ImGui::Checkbox("Draw in Foreground draw list", &draw_fg);
1193b4be Poul Sander 2025-02-03 21:28 9711
            ImGui::SameLine(); HelpMarker("The Foreground draw list will be rendered over every Dear ImGui windows.");
1193b4be Poul Sander 2025-02-03 21:28 9712
            ImVec2 window_pos = ImGui::GetWindowPos();
1193b4be Poul Sander 2025-02-03 21:28 9713
            ImVec2 window_size = ImGui::GetWindowSize();
1193b4be Poul Sander 2025-02-03 21:28 9714
            ImVec2 window_center = ImVec2(window_pos.x + window_size.x * 0.5f, window_pos.y + window_size.y * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 9715
            if (draw_bg)
1193b4be Poul Sander 2025-02-03 21:28 9716
                ImGui::GetBackgroundDrawList()->AddCircle(window_center, window_size.x * 0.6f, IM_COL32(255, 0, 0, 200), 0, 10 + 4);
1193b4be Poul Sander 2025-02-03 21:28 9717
            if (draw_fg)
1193b4be Poul Sander 2025-02-03 21:28 9718
                ImGui::GetForegroundDrawList()->AddCircle(window_center, window_size.y * 0.6f, IM_COL32(0, 255, 0, 200), 0, 10);
1193b4be Poul Sander 2025-02-03 21:28 9719
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 9720
        }
1193b4be Poul Sander 2025-02-03 21:28 9721
1193b4be Poul Sander 2025-02-03 21:28 9722
        // Demonstrate out-of-order rendering via channels splitting
1193b4be Poul Sander 2025-02-03 21:28 9723
        // We use functions in ImDrawList as each draw list contains a convenience splitter,
1193b4be Poul Sander 2025-02-03 21:28 9724
        // but you can also instantiate your own ImDrawListSplitter if you need to nest them.
1193b4be Poul Sander 2025-02-03 21:28 9725
        if (ImGui::BeginTabItem("Draw Channels"))
1193b4be Poul Sander 2025-02-03 21:28 9726
        {
1193b4be Poul Sander 2025-02-03 21:28 9727
            ImDrawList* draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 9728
            {
1193b4be Poul Sander 2025-02-03 21:28 9729
                ImGui::Text("Blue shape is drawn first: appears in back");
1193b4be Poul Sander 2025-02-03 21:28 9730
                ImGui::Text("Red shape is drawn after: appears in front");
1193b4be Poul Sander 2025-02-03 21:28 9731
                ImVec2 p0 = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 9732
                draw_list->AddRectFilled(ImVec2(p0.x, p0.y), ImVec2(p0.x + 50, p0.y + 50), IM_COL32(0, 0, 255, 255)); // Blue
1193b4be Poul Sander 2025-02-03 21:28 9733
                draw_list->AddRectFilled(ImVec2(p0.x + 25, p0.y + 25), ImVec2(p0.x + 75, p0.y + 75), IM_COL32(255, 0, 0, 255)); // Red
1193b4be Poul Sander 2025-02-03 21:28 9734
                ImGui::Dummy(ImVec2(75, 75));
1193b4be Poul Sander 2025-02-03 21:28 9735
            }
1193b4be Poul Sander 2025-02-03 21:28 9736
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 9737
            {
1193b4be Poul Sander 2025-02-03 21:28 9738
                ImGui::Text("Blue shape is drawn first, into channel 1: appears in front");
1193b4be Poul Sander 2025-02-03 21:28 9739
                ImGui::Text("Red shape is drawn after, into channel 0: appears in back");
1193b4be Poul Sander 2025-02-03 21:28 9740
                ImVec2 p1 = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 9741
1193b4be Poul Sander 2025-02-03 21:28 9742
                // Create 2 channels and draw a Blue shape THEN a Red shape.
1193b4be Poul Sander 2025-02-03 21:28 9743
                // You can create any number of channels. Tables API use 1 channel per column in order to better batch draw calls.
1193b4be Poul Sander 2025-02-03 21:28 9744
                draw_list->ChannelsSplit(2);
1193b4be Poul Sander 2025-02-03 21:28 9745
                draw_list->ChannelsSetCurrent(1);
1193b4be Poul Sander 2025-02-03 21:28 9746
                draw_list->AddRectFilled(ImVec2(p1.x, p1.y), ImVec2(p1.x + 50, p1.y + 50), IM_COL32(0, 0, 255, 255)); // Blue
1193b4be Poul Sander 2025-02-03 21:28 9747
                draw_list->ChannelsSetCurrent(0);
1193b4be Poul Sander 2025-02-03 21:28 9748
                draw_list->AddRectFilled(ImVec2(p1.x + 25, p1.y + 25), ImVec2(p1.x + 75, p1.y + 75), IM_COL32(255, 0, 0, 255)); // Red
1193b4be Poul Sander 2025-02-03 21:28 9749
1193b4be Poul Sander 2025-02-03 21:28 9750
                // Flatten/reorder channels. Red shape is in channel 0 and it appears below the Blue shape in channel 1.
1193b4be Poul Sander 2025-02-03 21:28 9751
                // This works by copying draw indices only (vertices are not copied).
1193b4be Poul Sander 2025-02-03 21:28 9752
                draw_list->ChannelsMerge();
1193b4be Poul Sander 2025-02-03 21:28 9753
                ImGui::Dummy(ImVec2(75, 75));
1193b4be Poul Sander 2025-02-03 21:28 9754
                ImGui::Text("After reordering, contents of channel 0 appears below channel 1.");
1193b4be Poul Sander 2025-02-03 21:28 9755
            }
1193b4be Poul Sander 2025-02-03 21:28 9756
            ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 9757
        }
1193b4be Poul Sander 2025-02-03 21:28 9758
1193b4be Poul Sander 2025-02-03 21:28 9759
        ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 9760
    }
1193b4be Poul Sander 2025-02-03 21:28 9761
1193b4be Poul Sander 2025-02-03 21:28 9762
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9763
}
1193b4be Poul Sander 2025-02-03 21:28 9764
1193b4be Poul Sander 2025-02-03 21:28 9765
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9766
// [SECTION] Example App: Docking, DockSpace / ShowExampleAppDockSpace()
1193b4be Poul Sander 2025-02-03 21:28 9767
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9768
1193b4be Poul Sander 2025-02-03 21:28 9769
// Demonstrate using DockSpace() to create an explicit docking node within an existing window.
1193b4be Poul Sander 2025-02-03 21:28 9770
// Note: You can use most Docking facilities without calling any API. You DO NOT need to call DockSpace() to use Docking!
1193b4be Poul Sander 2025-02-03 21:28 9771
// - Drag from window title bar or their tab to dock/undock. Hold SHIFT to disable docking.
1193b4be Poul Sander 2025-02-03 21:28 9772
// - Drag from window menu button (upper-left button) to undock an entire node (all windows).
1193b4be Poul Sander 2025-02-03 21:28 9773
// - When io.ConfigDockingWithShift == true, you instead need to hold SHIFT to enable docking.
1193b4be Poul Sander 2025-02-03 21:28 9774
// About dockspaces:
1193b4be Poul Sander 2025-02-03 21:28 9775
// - Use DockSpace() to create an explicit dock node _within_ an existing window.
1193b4be Poul Sander 2025-02-03 21:28 9776
// - Use DockSpaceOverViewport() to create an explicit dock node covering the screen or a specific viewport.
1193b4be Poul Sander 2025-02-03 21:28 9777
//   This is often used with ImGuiDockNodeFlags_PassthruCentralNode.
1193b4be Poul Sander 2025-02-03 21:28 9778
// - Important: Dockspaces need to be submitted _before_ any window they can host. Submit it early in your frame! (*)
1193b4be Poul Sander 2025-02-03 21:28 9779
// - Important: Dockspaces need to be kept alive if hidden, otherwise windows docked into it will be undocked.
1193b4be Poul Sander 2025-02-03 21:28 9780
//   e.g. if you have multiple tabs with a dockspace inside each tab: submit the non-visible dockspaces with ImGuiDockNodeFlags_KeepAliveOnly.
1193b4be Poul Sander 2025-02-03 21:28 9781
// (*) because of this constraint, the implicit \"Debug\" window can not be docked into an explicit DockSpace() node,
1193b4be Poul Sander 2025-02-03 21:28 9782
// because that window is submitted as part of the part of the NewFrame() call. An easy workaround is that you can create
1193b4be Poul Sander 2025-02-03 21:28 9783
// your own implicit "Debug##2" window after calling DockSpace() and leave it in the window stack for anyone to use.
1193b4be Poul Sander 2025-02-03 21:28 9784
void ShowExampleAppDockSpace(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 9785
{
1193b4be Poul Sander 2025-02-03 21:28 9786
    // READ THIS !!!
1193b4be Poul Sander 2025-02-03 21:28 9787
    // TL;DR; this demo is more complicated than what most users you would normally use.
1193b4be Poul Sander 2025-02-03 21:28 9788
    // If we remove all options we are showcasing, this demo would become:
1193b4be Poul Sander 2025-02-03 21:28 9789
    //     void ShowExampleAppDockSpace()
1193b4be Poul Sander 2025-02-03 21:28 9790
    //     {
1193b4be Poul Sander 2025-02-03 21:28 9791
    //         ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport());
1193b4be Poul Sander 2025-02-03 21:28 9792
    //     }
1193b4be Poul Sander 2025-02-03 21:28 9793
    // In most cases you should be able to just call DockSpaceOverViewport() and ignore all the code below!
1193b4be Poul Sander 2025-02-03 21:28 9794
    // In this specific demo, we are not using DockSpaceOverViewport() because:
1193b4be Poul Sander 2025-02-03 21:28 9795
    // - (1) we allow the host window to be floating/moveable instead of filling the viewport (when opt_fullscreen == false)
1193b4be Poul Sander 2025-02-03 21:28 9796
    // - (2) we allow the host window to have padding (when opt_padding == true)
1193b4be Poul Sander 2025-02-03 21:28 9797
    // - (3) we expose many flags and need a way to have them visible.
1193b4be Poul Sander 2025-02-03 21:28 9798
    // - (4) we have a local menu bar in the host window (vs. you could use BeginMainMenuBar() + DockSpaceOverViewport()
1193b4be Poul Sander 2025-02-03 21:28 9799
    //      in your code, but we don't here because we allow the window to be floating)
1193b4be Poul Sander 2025-02-03 21:28 9800
1193b4be Poul Sander 2025-02-03 21:28 9801
    static bool opt_fullscreen = true;
1193b4be Poul Sander 2025-02-03 21:28 9802
    static bool opt_padding = false;
1193b4be Poul Sander 2025-02-03 21:28 9803
    static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
1193b4be Poul Sander 2025-02-03 21:28 9804
1193b4be Poul Sander 2025-02-03 21:28 9805
    // We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
1193b4be Poul Sander 2025-02-03 21:28 9806
    // because it would be confusing to have two docking targets within each others.
1193b4be Poul Sander 2025-02-03 21:28 9807
    ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
1193b4be Poul Sander 2025-02-03 21:28 9808
    if (opt_fullscreen)
1193b4be Poul Sander 2025-02-03 21:28 9809
    {
1193b4be Poul Sander 2025-02-03 21:28 9810
        const ImGuiViewport* viewport = ImGui::GetMainViewport();
1193b4be Poul Sander 2025-02-03 21:28 9811
        ImGui::SetNextWindowPos(viewport->WorkPos);
1193b4be Poul Sander 2025-02-03 21:28 9812
        ImGui::SetNextWindowSize(viewport->WorkSize);
1193b4be Poul Sander 2025-02-03 21:28 9813
        ImGui::SetNextWindowViewport(viewport->ID);
1193b4be Poul Sander 2025-02-03 21:28 9814
        ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 9815
        ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 9816
        window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
1193b4be Poul Sander 2025-02-03 21:28 9817
        window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
1193b4be Poul Sander 2025-02-03 21:28 9818
    }
1193b4be Poul Sander 2025-02-03 21:28 9819
    else
1193b4be Poul Sander 2025-02-03 21:28 9820
    {
1193b4be Poul Sander 2025-02-03 21:28 9821
        dockspace_flags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
1193b4be Poul Sander 2025-02-03 21:28 9822
    }
1193b4be Poul Sander 2025-02-03 21:28 9823
1193b4be Poul Sander 2025-02-03 21:28 9824
    // When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
1193b4be Poul Sander 2025-02-03 21:28 9825
    // and handle the pass-thru hole, so we ask Begin() to not render a background.
1193b4be Poul Sander 2025-02-03 21:28 9826
    if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
1193b4be Poul Sander 2025-02-03 21:28 9827
        window_flags |= ImGuiWindowFlags_NoBackground;
1193b4be Poul Sander 2025-02-03 21:28 9828
1193b4be Poul Sander 2025-02-03 21:28 9829
    // Important: note that we proceed even if Begin() returns false (aka window is collapsed).
1193b4be Poul Sander 2025-02-03 21:28 9830
    // This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
1193b4be Poul Sander 2025-02-03 21:28 9831
    // all active windows docked into it will lose their parent and become undocked.
1193b4be Poul Sander 2025-02-03 21:28 9832
    // We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
1193b4be Poul Sander 2025-02-03 21:28 9833
    // any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
1193b4be Poul Sander 2025-02-03 21:28 9834
    if (!opt_padding)
1193b4be Poul Sander 2025-02-03 21:28 9835
        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
1193b4be Poul Sander 2025-02-03 21:28 9836
    ImGui::Begin("DockSpace Demo", p_open, window_flags);
1193b4be Poul Sander 2025-02-03 21:28 9837
    if (!opt_padding)
1193b4be Poul Sander 2025-02-03 21:28 9838
        ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 9839
1193b4be Poul Sander 2025-02-03 21:28 9840
    if (opt_fullscreen)
1193b4be Poul Sander 2025-02-03 21:28 9841
        ImGui::PopStyleVar(2);
1193b4be Poul Sander 2025-02-03 21:28 9842
1193b4be Poul Sander 2025-02-03 21:28 9843
    // Submit the DockSpace
1193b4be Poul Sander 2025-02-03 21:28 9844
    ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 9845
    if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
1193b4be Poul Sander 2025-02-03 21:28 9846
    {
1193b4be Poul Sander 2025-02-03 21:28 9847
        ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
1193b4be Poul Sander 2025-02-03 21:28 9848
        ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
1193b4be Poul Sander 2025-02-03 21:28 9849
    }
1193b4be Poul Sander 2025-02-03 21:28 9850
    else
1193b4be Poul Sander 2025-02-03 21:28 9851
    {
1193b4be Poul Sander 2025-02-03 21:28 9852
        ShowDockingDisabledMessage();
1193b4be Poul Sander 2025-02-03 21:28 9853
    }
1193b4be Poul Sander 2025-02-03 21:28 9854
1193b4be Poul Sander 2025-02-03 21:28 9855
    if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 9856
    {
1193b4be Poul Sander 2025-02-03 21:28 9857
        if (ImGui::BeginMenu("Options"))
1193b4be Poul Sander 2025-02-03 21:28 9858
        {
1193b4be Poul Sander 2025-02-03 21:28 9859
            // Disabling fullscreen would allow the window to be moved to the front of other windows,
1193b4be Poul Sander 2025-02-03 21:28 9860
            // which we can't undo at the moment without finer window depth/z control.
1193b4be Poul Sander 2025-02-03 21:28 9861
            ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen);
1193b4be Poul Sander 2025-02-03 21:28 9862
            ImGui::MenuItem("Padding", NULL, &opt_padding);
1193b4be Poul Sander 2025-02-03 21:28 9863
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 9864
1193b4be Poul Sander 2025-02-03 21:28 9865
            if (ImGui::MenuItem("Flag: NoDockingOverCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingOverCentralNode; }
1193b4be Poul Sander 2025-02-03 21:28 9866
            if (ImGui::MenuItem("Flag: NoDockingSplit",         "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingSplit) != 0))             { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingSplit; }
1193b4be Poul Sander 2025-02-03 21:28 9867
            if (ImGui::MenuItem("Flag: NoUndocking",            "", (dockspace_flags & ImGuiDockNodeFlags_NoUndocking) != 0))                { dockspace_flags ^= ImGuiDockNodeFlags_NoUndocking; }
1193b4be Poul Sander 2025-02-03 21:28 9868
            if (ImGui::MenuItem("Flag: NoResize",               "", (dockspace_flags & ImGuiDockNodeFlags_NoResize) != 0))                   { dockspace_flags ^= ImGuiDockNodeFlags_NoResize; }
1193b4be Poul Sander 2025-02-03 21:28 9869
            if (ImGui::MenuItem("Flag: AutoHideTabBar",         "", (dockspace_flags & ImGuiDockNodeFlags_AutoHideTabBar) != 0))             { dockspace_flags ^= ImGuiDockNodeFlags_AutoHideTabBar; }
1193b4be Poul Sander 2025-02-03 21:28 9870
            if (ImGui::MenuItem("Flag: PassthruCentralNode",    "", (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0, opt_fullscreen)) { dockspace_flags ^= ImGuiDockNodeFlags_PassthruCentralNode; }
1193b4be Poul Sander 2025-02-03 21:28 9871
            ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 9872
1193b4be Poul Sander 2025-02-03 21:28 9873
            if (ImGui::MenuItem("Close", NULL, false, p_open != NULL))
1193b4be Poul Sander 2025-02-03 21:28 9874
                *p_open = false;
1193b4be Poul Sander 2025-02-03 21:28 9875
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 9876
        }
1193b4be Poul Sander 2025-02-03 21:28 9877
        HelpMarker(
1193b4be Poul Sander 2025-02-03 21:28 9878
            "When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n"
1193b4be Poul Sander 2025-02-03 21:28 9879
            "- Drag from window title bar or their tab to dock/undock." "\n"
1193b4be Poul Sander 2025-02-03 21:28 9880
            "- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n"
1193b4be Poul Sander 2025-02-03 21:28 9881
            "- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n"
1193b4be Poul Sander 2025-02-03 21:28 9882
            "- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)" "\n"
1193b4be Poul Sander 2025-02-03 21:28 9883
            "This demo app has nothing to do with enabling docking!" "\n\n"
1193b4be Poul Sander 2025-02-03 21:28 9884
            "This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window." "\n\n"
1193b4be Poul Sander 2025-02-03 21:28 9885
            "Read comments in ShowExampleAppDockSpace() for more details.");
1193b4be Poul Sander 2025-02-03 21:28 9886
1193b4be Poul Sander 2025-02-03 21:28 9887
        ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 9888
    }
1193b4be Poul Sander 2025-02-03 21:28 9889
1193b4be Poul Sander 2025-02-03 21:28 9890
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 9891
}
1193b4be Poul Sander 2025-02-03 21:28 9892
1193b4be Poul Sander 2025-02-03 21:28 9893
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9894
// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
1193b4be Poul Sander 2025-02-03 21:28 9895
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 9896
1193b4be Poul Sander 2025-02-03 21:28 9897
// Simplified structure to mimic a Document model
1193b4be Poul Sander 2025-02-03 21:28 9898
struct MyDocument
1193b4be Poul Sander 2025-02-03 21:28 9899
{
1193b4be Poul Sander 2025-02-03 21:28 9900
    char        Name[32];   // Document title
1193b4be Poul Sander 2025-02-03 21:28 9901
    int         UID;        // Unique ID (necessary as we can change title)
1193b4be Poul Sander 2025-02-03 21:28 9902
    bool        Open;       // Set when open (we keep an array of all available documents to simplify demo code!)
1193b4be Poul Sander 2025-02-03 21:28 9903
    bool        OpenPrev;   // Copy of Open from last update.
1193b4be Poul Sander 2025-02-03 21:28 9904
    bool        Dirty;      // Set when the document has been modified
1193b4be Poul Sander 2025-02-03 21:28 9905
    ImVec4      Color;      // An arbitrary variable associated to the document
1193b4be Poul Sander 2025-02-03 21:28 9906
1193b4be Poul Sander 2025-02-03 21:28 9907
    MyDocument(int uid, const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f))
1193b4be Poul Sander 2025-02-03 21:28 9908
    {
1193b4be Poul Sander 2025-02-03 21:28 9909
        UID = uid;
1193b4be Poul Sander 2025-02-03 21:28 9910
        snprintf(Name, sizeof(Name), "%s", name);
1193b4be Poul Sander 2025-02-03 21:28 9911
        Open = OpenPrev = open;
1193b4be Poul Sander 2025-02-03 21:28 9912
        Dirty = false;
1193b4be Poul Sander 2025-02-03 21:28 9913
        Color = color;
1193b4be Poul Sander 2025-02-03 21:28 9914
    }
1193b4be Poul Sander 2025-02-03 21:28 9915
    void DoOpen()       { Open = true; }
1193b4be Poul Sander 2025-02-03 21:28 9916
    void DoForceClose() { Open = false; Dirty = false; }
1193b4be Poul Sander 2025-02-03 21:28 9917
    void DoSave()       { Dirty = false; }
1193b4be Poul Sander 2025-02-03 21:28 9918
};
1193b4be Poul Sander 2025-02-03 21:28 9919
1193b4be Poul Sander 2025-02-03 21:28 9920
struct ExampleAppDocuments
1193b4be Poul Sander 2025-02-03 21:28 9921
{
1193b4be Poul Sander 2025-02-03 21:28 9922
    ImVector<MyDocument>    Documents;
1193b4be Poul Sander 2025-02-03 21:28 9923
    ImVector<MyDocument*>   CloseQueue;
1193b4be Poul Sander 2025-02-03 21:28 9924
    MyDocument*             RenamingDoc = NULL;
1193b4be Poul Sander 2025-02-03 21:28 9925
    bool                    RenamingStarted = false;
1193b4be Poul Sander 2025-02-03 21:28 9926
1193b4be Poul Sander 2025-02-03 21:28 9927
    ExampleAppDocuments()
1193b4be Poul Sander 2025-02-03 21:28 9928
    {
1193b4be Poul Sander 2025-02-03 21:28 9929
        Documents.push_back(MyDocument(0, "Lettuce",             true,  ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
1193b4be Poul Sander 2025-02-03 21:28 9930
        Documents.push_back(MyDocument(1, "Eggplant",            true,  ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
1193b4be Poul Sander 2025-02-03 21:28 9931
        Documents.push_back(MyDocument(2, "Carrot",              true,  ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
1193b4be Poul Sander 2025-02-03 21:28 9932
        Documents.push_back(MyDocument(3, "Tomato",              false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
1193b4be Poul Sander 2025-02-03 21:28 9933
        Documents.push_back(MyDocument(4, "A Rather Long Title", false, ImVec4(0.4f, 0.8f, 0.8f, 1.0f)));
1193b4be Poul Sander 2025-02-03 21:28 9934
        Documents.push_back(MyDocument(5, "Some Document",       false, ImVec4(0.8f, 0.8f, 1.0f, 1.0f)));
1193b4be Poul Sander 2025-02-03 21:28 9935
    }
1193b4be Poul Sander 2025-02-03 21:28 9936
1193b4be Poul Sander 2025-02-03 21:28 9937
    // As we allow to change document name, we append a never-changing document ID so tabs are stable
1193b4be Poul Sander 2025-02-03 21:28 9938
    void GetTabName(MyDocument* doc, char* out_buf, size_t out_buf_size)
1193b4be Poul Sander 2025-02-03 21:28 9939
    {
1193b4be Poul Sander 2025-02-03 21:28 9940
        snprintf(out_buf, out_buf_size, "%s###doc%d", doc->Name, doc->UID);
1193b4be Poul Sander 2025-02-03 21:28 9941
    }
1193b4be Poul Sander 2025-02-03 21:28 9942
1193b4be Poul Sander 2025-02-03 21:28 9943
    // Display placeholder contents for the Document
1193b4be Poul Sander 2025-02-03 21:28 9944
    void DisplayDocContents(MyDocument* doc)
1193b4be Poul Sander 2025-02-03 21:28 9945
    {
1193b4be Poul Sander 2025-02-03 21:28 9946
        ImGui::PushID(doc);
1193b4be Poul Sander 2025-02-03 21:28 9947
        ImGui::Text("Document \"%s\"", doc->Name);
1193b4be Poul Sander 2025-02-03 21:28 9948
        ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
1193b4be Poul Sander 2025-02-03 21:28 9949
        ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
1193b4be Poul Sander 2025-02-03 21:28 9950
        ImGui::PopStyleColor();
1193b4be Poul Sander 2025-02-03 21:28 9951
1193b4be Poul Sander 2025-02-03 21:28 9952
        ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_R, ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 9953
        if (ImGui::Button("Rename.."))
1193b4be Poul Sander 2025-02-03 21:28 9954
        {
1193b4be Poul Sander 2025-02-03 21:28 9955
            RenamingDoc = doc;
1193b4be Poul Sander 2025-02-03 21:28 9956
            RenamingStarted = true;
1193b4be Poul Sander 2025-02-03 21:28 9957
        }
1193b4be Poul Sander 2025-02-03 21:28 9958
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9959
1193b4be Poul Sander 2025-02-03 21:28 9960
        ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_M, ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 9961
        if (ImGui::Button("Modify"))
1193b4be Poul Sander 2025-02-03 21:28 9962
            doc->Dirty = true;
1193b4be Poul Sander 2025-02-03 21:28 9963
1193b4be Poul Sander 2025-02-03 21:28 9964
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9965
        ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_S, ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 9966
        if (ImGui::Button("Save"))
1193b4be Poul Sander 2025-02-03 21:28 9967
            doc->DoSave();
1193b4be Poul Sander 2025-02-03 21:28 9968
1193b4be Poul Sander 2025-02-03 21:28 9969
        ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 9970
        ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_W, ImGuiInputFlags_Tooltip);
1193b4be Poul Sander 2025-02-03 21:28 9971
        if (ImGui::Button("Close"))
1193b4be Poul Sander 2025-02-03 21:28 9972
            CloseQueue.push_back(doc);
1193b4be Poul Sander 2025-02-03 21:28 9973
        ImGui::ColorEdit3("color", &doc->Color.x);  // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
1193b4be Poul Sander 2025-02-03 21:28 9974
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 9975
    }
1193b4be Poul Sander 2025-02-03 21:28 9976
1193b4be Poul Sander 2025-02-03 21:28 9977
    // Display context menu for the Document
1193b4be Poul Sander 2025-02-03 21:28 9978
    void DisplayDocContextMenu(MyDocument* doc)
1193b4be Poul Sander 2025-02-03 21:28 9979
    {
1193b4be Poul Sander 2025-02-03 21:28 9980
        if (!ImGui::BeginPopupContextItem())
1193b4be Poul Sander 2025-02-03 21:28 9981
            return;
1193b4be Poul Sander 2025-02-03 21:28 9982
1193b4be Poul Sander 2025-02-03 21:28 9983
        char buf[256];
1193b4be Poul Sander 2025-02-03 21:28 9984
        sprintf(buf, "Save %s", doc->Name);
1193b4be Poul Sander 2025-02-03 21:28 9985
        if (ImGui::MenuItem(buf, "Ctrl+S", false, doc->Open))
1193b4be Poul Sander 2025-02-03 21:28 9986
            doc->DoSave();
1193b4be Poul Sander 2025-02-03 21:28 9987
        if (ImGui::MenuItem("Rename...", "Ctrl+R", false, doc->Open))
1193b4be Poul Sander 2025-02-03 21:28 9988
            RenamingDoc = doc;
1193b4be Poul Sander 2025-02-03 21:28 9989
        if (ImGui::MenuItem("Close", "Ctrl+W", false, doc->Open))
1193b4be Poul Sander 2025-02-03 21:28 9990
            CloseQueue.push_back(doc);
1193b4be Poul Sander 2025-02-03 21:28 9991
        ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 9992
    }
1193b4be Poul Sander 2025-02-03 21:28 9993
1193b4be Poul Sander 2025-02-03 21:28 9994
    // [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
1193b4be Poul Sander 2025-02-03 21:28 9995
    // If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo,
1193b4be Poul Sander 2025-02-03 21:28 9996
    // as opposed to clicking on the regular tab closing button) and stops being submitted, it will take a frame for
1193b4be Poul Sander 2025-02-03 21:28 9997
    // 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
1193b4be Poul Sander 2025-02-03 21:28 9998
    // disappeared was the selected one, the tab bar will report no selected tab during the frame. This will effectively
1193b4be Poul Sander 2025-02-03 21:28 9999
    // give the impression of a flicker for one frame.
1193b4be Poul Sander 2025-02-03 21:28 10000
    // We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
1193b4be Poul Sander 2025-02-03 21:28 10001
    // Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
1193b4be Poul Sander 2025-02-03 21:28 10002
    void NotifyOfDocumentsClosedElsewhere()
1193b4be Poul Sander 2025-02-03 21:28 10003
    {
1193b4be Poul Sander 2025-02-03 21:28 10004
        for (MyDocument& doc : Documents)
1193b4be Poul Sander 2025-02-03 21:28 10005
        {
1193b4be Poul Sander 2025-02-03 21:28 10006
            if (!doc.Open && doc.OpenPrev)
1193b4be Poul Sander 2025-02-03 21:28 10007
                ImGui::SetTabItemClosed(doc.Name);
1193b4be Poul Sander 2025-02-03 21:28 10008
            doc.OpenPrev = doc.Open;
1193b4be Poul Sander 2025-02-03 21:28 10009
        }
1193b4be Poul Sander 2025-02-03 21:28 10010
    }
1193b4be Poul Sander 2025-02-03 21:28 10011
};
1193b4be Poul Sander 2025-02-03 21:28 10012
1193b4be Poul Sander 2025-02-03 21:28 10013
void ShowExampleAppDocuments(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 10014
{
1193b4be Poul Sander 2025-02-03 21:28 10015
    static ExampleAppDocuments app;
1193b4be Poul Sander 2025-02-03 21:28 10016
1193b4be Poul Sander 2025-02-03 21:28 10017
    // Options
1193b4be Poul Sander 2025-02-03 21:28 10018
    enum Target
1193b4be Poul Sander 2025-02-03 21:28 10019
    {
1193b4be Poul Sander 2025-02-03 21:28 10020
        Target_None,
1193b4be Poul Sander 2025-02-03 21:28 10021
        Target_Tab,                 // Create documents as local tab into a local tab bar
1193b4be Poul Sander 2025-02-03 21:28 10022
        Target_DockSpaceAndWindow   // Create documents as regular windows, and create an embedded dockspace
1193b4be Poul Sander 2025-02-03 21:28 10023
    };
1193b4be Poul Sander 2025-02-03 21:28 10024
    static Target opt_target = Target_Tab;
1193b4be Poul Sander 2025-02-03 21:28 10025
    static bool opt_reorderable = true;
1193b4be Poul Sander 2025-02-03 21:28 10026
    static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
1193b4be Poul Sander 2025-02-03 21:28 10027
1193b4be Poul Sander 2025-02-03 21:28 10028
    // When (opt_target == Target_DockSpaceAndWindow) there is the possibily that one of our child Document window (e.g. "Eggplant")
1193b4be Poul Sander 2025-02-03 21:28 10029
    // that we emit gets docked into the same spot as the parent window ("Example: Documents").
1193b4be Poul Sander 2025-02-03 21:28 10030
    // This would create a problematic feedback loop because selecting the "Eggplant" tab would make the "Example: Documents" tab
1193b4be Poul Sander 2025-02-03 21:28 10031
    // not visible, which in turn would stop submitting the "Eggplant" window.
1193b4be Poul Sander 2025-02-03 21:28 10032
    // We avoid this problem by submitting our documents window even if our parent window is not currently visible.
1193b4be Poul Sander 2025-02-03 21:28 10033
    // Another solution may be to make the "Example: Documents" window use the ImGuiWindowFlags_NoDocking.
1193b4be Poul Sander 2025-02-03 21:28 10034
1193b4be Poul Sander 2025-02-03 21:28 10035
    bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
1193b4be Poul Sander 2025-02-03 21:28 10036
    if (!window_contents_visible && opt_target != Target_DockSpaceAndWindow)
1193b4be Poul Sander 2025-02-03 21:28 10037
    {
1193b4be Poul Sander 2025-02-03 21:28 10038
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 10039
        return;
1193b4be Poul Sander 2025-02-03 21:28 10040
    }
1193b4be Poul Sander 2025-02-03 21:28 10041
1193b4be Poul Sander 2025-02-03 21:28 10042
    // Menu
1193b4be Poul Sander 2025-02-03 21:28 10043
    if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 10044
    {
1193b4be Poul Sander 2025-02-03 21:28 10045
        if (ImGui::BeginMenu("File"))
1193b4be Poul Sander 2025-02-03 21:28 10046
        {
1193b4be Poul Sander 2025-02-03 21:28 10047
            int open_count = 0;
1193b4be Poul Sander 2025-02-03 21:28 10048
            for (MyDocument& doc : app.Documents)
1193b4be Poul Sander 2025-02-03 21:28 10049
                open_count += doc.Open ? 1 : 0;
1193b4be Poul Sander 2025-02-03 21:28 10050
1193b4be Poul Sander 2025-02-03 21:28 10051
            if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
1193b4be Poul Sander 2025-02-03 21:28 10052
            {
1193b4be Poul Sander 2025-02-03 21:28 10053
                for (MyDocument& doc : app.Documents)
1193b4be Poul Sander 2025-02-03 21:28 10054
                    if (!doc.Open && ImGui::MenuItem(doc.Name))
1193b4be Poul Sander 2025-02-03 21:28 10055
                        doc.DoOpen();
1193b4be Poul Sander 2025-02-03 21:28 10056
                ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 10057
            }
1193b4be Poul Sander 2025-02-03 21:28 10058
            if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
1193b4be Poul Sander 2025-02-03 21:28 10059
                for (MyDocument& doc : app.Documents)
1193b4be Poul Sander 2025-02-03 21:28 10060
                    app.CloseQueue.push_back(&doc);
1193b4be Poul Sander 2025-02-03 21:28 10061
            if (ImGui::MenuItem("Exit") && p_open)
1193b4be Poul Sander 2025-02-03 21:28 10062
                *p_open = false;
1193b4be Poul Sander 2025-02-03 21:28 10063
            ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 10064
        }
1193b4be Poul Sander 2025-02-03 21:28 10065
        ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 10066
    }
1193b4be Poul Sander 2025-02-03 21:28 10067
1193b4be Poul Sander 2025-02-03 21:28 10068
    // [Debug] List documents with one checkbox for each
1193b4be Poul Sander 2025-02-03 21:28 10069
    for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
1193b4be Poul Sander 2025-02-03 21:28 10070
    {
1193b4be Poul Sander 2025-02-03 21:28 10071
        MyDocument& doc = app.Documents[doc_n];
1193b4be Poul Sander 2025-02-03 21:28 10072
        if (doc_n > 0)
1193b4be Poul Sander 2025-02-03 21:28 10073
            ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 10074
        ImGui::PushID(&doc);
1193b4be Poul Sander 2025-02-03 21:28 10075
        if (ImGui::Checkbox(doc.Name, &doc.Open))
1193b4be Poul Sander 2025-02-03 21:28 10076
            if (!doc.Open)
1193b4be Poul Sander 2025-02-03 21:28 10077
                doc.DoForceClose();
1193b4be Poul Sander 2025-02-03 21:28 10078
        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 10079
    }
1193b4be Poul Sander 2025-02-03 21:28 10080
    ImGui::PushItemWidth(ImGui::GetFontSize() * 12);
1193b4be Poul Sander 2025-02-03 21:28 10081
    ImGui::Combo("Output", (int*)&opt_target, "None\0TabBar+Tabs\0DockSpace+Window\0");
1193b4be Poul Sander 2025-02-03 21:28 10082
    ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 10083
    bool redock_all = false;
1193b4be Poul Sander 2025-02-03 21:28 10084
    if (opt_target == Target_Tab)                { ImGui::SameLine(); ImGui::Checkbox("Reorderable Tabs", &opt_reorderable); }
1193b4be Poul Sander 2025-02-03 21:28 10085
    if (opt_target == Target_DockSpaceAndWindow) { ImGui::SameLine(); redock_all = ImGui::Button("Redock all"); }
1193b4be Poul Sander 2025-02-03 21:28 10086
1193b4be Poul Sander 2025-02-03 21:28 10087
    ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 10088
1193b4be Poul Sander 2025-02-03 21:28 10089
    // About the ImGuiWindowFlags_UnsavedDocument / ImGuiTabItemFlags_UnsavedDocument flags.
1193b4be Poul Sander 2025-02-03 21:28 10090
    // They have multiple effects:
1193b4be Poul Sander 2025-02-03 21:28 10091
    // - Display a dot next to the title.
1193b4be Poul Sander 2025-02-03 21:28 10092
    // - Tab is selected when clicking the X close button.
1193b4be Poul Sander 2025-02-03 21:28 10093
    // - Closure is not assumed (will wait for user to stop submitting the tab).
1193b4be Poul Sander 2025-02-03 21:28 10094
    //   Otherwise closure is assumed when pressing the X, so if you keep submitting the tab may reappear at end of tab bar.
1193b4be Poul Sander 2025-02-03 21:28 10095
    //   We need to assume closure by default otherwise waiting for "lack of submission" on the next frame would leave an empty
1193b4be Poul Sander 2025-02-03 21:28 10096
    //   hole for one-frame, both in the tab-bar and in tab-contents when closing a tab/window.
1193b4be Poul Sander 2025-02-03 21:28 10097
    //   The rarely used SetTabItemClosed() function is a way to notify of programmatic closure to avoid the one-frame hole.
1193b4be Poul Sander 2025-02-03 21:28 10098
1193b4be Poul Sander 2025-02-03 21:28 10099
    // Tabs
1193b4be Poul Sander 2025-02-03 21:28 10100
    if (opt_target == Target_Tab)
1193b4be Poul Sander 2025-02-03 21:28 10101
    {
1193b4be Poul Sander 2025-02-03 21:28 10102
        ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
1193b4be Poul Sander 2025-02-03 21:28 10103
        tab_bar_flags |= ImGuiTabBarFlags_DrawSelectedOverline;
1193b4be Poul Sander 2025-02-03 21:28 10104
        if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
1193b4be Poul Sander 2025-02-03 21:28 10105
        {
1193b4be Poul Sander 2025-02-03 21:28 10106
            if (opt_reorderable)
1193b4be Poul Sander 2025-02-03 21:28 10107
                app.NotifyOfDocumentsClosedElsewhere();
1193b4be Poul Sander 2025-02-03 21:28 10108
1193b4be Poul Sander 2025-02-03 21:28 10109
            // [DEBUG] Stress tests
1193b4be Poul Sander 2025-02-03 21:28 10110
            //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1;            // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
1193b4be Poul Sander 2025-02-03 21:28 10111
            //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name);  // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
1193b4be Poul Sander 2025-02-03 21:28 10112
1193b4be Poul Sander 2025-02-03 21:28 10113
            // Submit Tabs
1193b4be Poul Sander 2025-02-03 21:28 10114
            for (MyDocument& doc : app.Documents)
1193b4be Poul Sander 2025-02-03 21:28 10115
            {
1193b4be Poul Sander 2025-02-03 21:28 10116
                if (!doc.Open)
1193b4be Poul Sander 2025-02-03 21:28 10117
                    continue;
1193b4be Poul Sander 2025-02-03 21:28 10118
1193b4be Poul Sander 2025-02-03 21:28 10119
                // As we allow to change document name, we append a never-changing document id so tabs are stable
1193b4be Poul Sander 2025-02-03 21:28 10120
                char doc_name_buf[64];
1193b4be Poul Sander 2025-02-03 21:28 10121
                app.GetTabName(&doc, doc_name_buf, sizeof(doc_name_buf));
1193b4be Poul Sander 2025-02-03 21:28 10122
                ImGuiTabItemFlags tab_flags = (doc.Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
1193b4be Poul Sander 2025-02-03 21:28 10123
                bool visible = ImGui::BeginTabItem(doc_name_buf, &doc.Open, tab_flags);
1193b4be Poul Sander 2025-02-03 21:28 10124
1193b4be Poul Sander 2025-02-03 21:28 10125
                // Cancel attempt to close when unsaved add to save queue so we can display a popup.
1193b4be Poul Sander 2025-02-03 21:28 10126
                if (!doc.Open && doc.Dirty)
1193b4be Poul Sander 2025-02-03 21:28 10127
                {
1193b4be Poul Sander 2025-02-03 21:28 10128
                    doc.Open = true;
1193b4be Poul Sander 2025-02-03 21:28 10129
                    app.CloseQueue.push_back(&doc);
1193b4be Poul Sander 2025-02-03 21:28 10130
                }
1193b4be Poul Sander 2025-02-03 21:28 10131
1193b4be Poul Sander 2025-02-03 21:28 10132
                app.DisplayDocContextMenu(&doc);
1193b4be Poul Sander 2025-02-03 21:28 10133
                if (visible)
1193b4be Poul Sander 2025-02-03 21:28 10134
                {
1193b4be Poul Sander 2025-02-03 21:28 10135
                    app.DisplayDocContents(&doc);
1193b4be Poul Sander 2025-02-03 21:28 10136
                    ImGui::EndTabItem();
1193b4be Poul Sander 2025-02-03 21:28 10137
                }
1193b4be Poul Sander 2025-02-03 21:28 10138
            }
1193b4be Poul Sander 2025-02-03 21:28 10139
1193b4be Poul Sander 2025-02-03 21:28 10140
            ImGui::EndTabBar();
1193b4be Poul Sander 2025-02-03 21:28 10141
        }
1193b4be Poul Sander 2025-02-03 21:28 10142
    }
1193b4be Poul Sander 2025-02-03 21:28 10143
    else if (opt_target == Target_DockSpaceAndWindow)
1193b4be Poul Sander 2025-02-03 21:28 10144
    {
1193b4be Poul Sander 2025-02-03 21:28 10145
        if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_DockingEnable)
1193b4be Poul Sander 2025-02-03 21:28 10146
        {
1193b4be Poul Sander 2025-02-03 21:28 10147
            app.NotifyOfDocumentsClosedElsewhere();
1193b4be Poul Sander 2025-02-03 21:28 10148
1193b4be Poul Sander 2025-02-03 21:28 10149
            // Create a DockSpace node where any window can be docked
1193b4be Poul Sander 2025-02-03 21:28 10150
            ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
1193b4be Poul Sander 2025-02-03 21:28 10151
            ImGui::DockSpace(dockspace_id);
1193b4be Poul Sander 2025-02-03 21:28 10152
1193b4be Poul Sander 2025-02-03 21:28 10153
            // Create Windows
1193b4be Poul Sander 2025-02-03 21:28 10154
            for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
1193b4be Poul Sander 2025-02-03 21:28 10155
            {
1193b4be Poul Sander 2025-02-03 21:28 10156
                MyDocument* doc = &app.Documents[doc_n];
1193b4be Poul Sander 2025-02-03 21:28 10157
                if (!doc->Open)
1193b4be Poul Sander 2025-02-03 21:28 10158
                    continue;
1193b4be Poul Sander 2025-02-03 21:28 10159
1193b4be Poul Sander 2025-02-03 21:28 10160
                ImGui::SetNextWindowDockID(dockspace_id, redock_all ? ImGuiCond_Always : ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 10161
                ImGuiWindowFlags window_flags = (doc->Dirty ? ImGuiWindowFlags_UnsavedDocument : 0);
1193b4be Poul Sander 2025-02-03 21:28 10162
                bool visible = ImGui::Begin(doc->Name, &doc->Open, window_flags);
1193b4be Poul Sander 2025-02-03 21:28 10163
1193b4be Poul Sander 2025-02-03 21:28 10164
                // Cancel attempt to close when unsaved add to save queue so we can display a popup.
1193b4be Poul Sander 2025-02-03 21:28 10165
                if (!doc->Open && doc->Dirty)
1193b4be Poul Sander 2025-02-03 21:28 10166
                {
1193b4be Poul Sander 2025-02-03 21:28 10167
                    doc->Open = true;
1193b4be Poul Sander 2025-02-03 21:28 10168
                    app.CloseQueue.push_back(doc);
1193b4be Poul Sander 2025-02-03 21:28 10169
                }
1193b4be Poul Sander 2025-02-03 21:28 10170
1193b4be Poul Sander 2025-02-03 21:28 10171
                app.DisplayDocContextMenu(doc);
1193b4be Poul Sander 2025-02-03 21:28 10172
                if (visible)
1193b4be Poul Sander 2025-02-03 21:28 10173
                    app.DisplayDocContents(doc);
1193b4be Poul Sander 2025-02-03 21:28 10174
1193b4be Poul Sander 2025-02-03 21:28 10175
                ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 10176
            }
1193b4be Poul Sander 2025-02-03 21:28 10177
        }
1193b4be Poul Sander 2025-02-03 21:28 10178
        else
1193b4be Poul Sander 2025-02-03 21:28 10179
        {
1193b4be Poul Sander 2025-02-03 21:28 10180
            ShowDockingDisabledMessage();
1193b4be Poul Sander 2025-02-03 21:28 10181
        }
1193b4be Poul Sander 2025-02-03 21:28 10182
    }
1193b4be Poul Sander 2025-02-03 21:28 10183
1193b4be Poul Sander 2025-02-03 21:28 10184
    // Early out other contents
1193b4be Poul Sander 2025-02-03 21:28 10185
    if (!window_contents_visible)
1193b4be Poul Sander 2025-02-03 21:28 10186
    {
1193b4be Poul Sander 2025-02-03 21:28 10187
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 10188
        return;
1193b4be Poul Sander 2025-02-03 21:28 10189
    }
1193b4be Poul Sander 2025-02-03 21:28 10190
1193b4be Poul Sander 2025-02-03 21:28 10191
    // Display renaming UI
1193b4be Poul Sander 2025-02-03 21:28 10192
    if (app.RenamingDoc != NULL)
1193b4be Poul Sander 2025-02-03 21:28 10193
    {
1193b4be Poul Sander 2025-02-03 21:28 10194
        if (app.RenamingStarted)
1193b4be Poul Sander 2025-02-03 21:28 10195
            ImGui::OpenPopup("Rename");
1193b4be Poul Sander 2025-02-03 21:28 10196
        if (ImGui::BeginPopup("Rename"))
1193b4be Poul Sander 2025-02-03 21:28 10197
        {
1193b4be Poul Sander 2025-02-03 21:28 10198
            ImGui::SetNextItemWidth(ImGui::GetFontSize() * 30);
1193b4be Poul Sander 2025-02-03 21:28 10199
            if (ImGui::InputText("###Name", app.RenamingDoc->Name, IM_ARRAYSIZE(app.RenamingDoc->Name), ImGuiInputTextFlags_EnterReturnsTrue))
1193b4be Poul Sander 2025-02-03 21:28 10200
            {
1193b4be Poul Sander 2025-02-03 21:28 10201
                ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 10202
                app.RenamingDoc = NULL;
1193b4be Poul Sander 2025-02-03 21:28 10203
            }
1193b4be Poul Sander 2025-02-03 21:28 10204
            if (app.RenamingStarted)
1193b4be Poul Sander 2025-02-03 21:28 10205
                ImGui::SetKeyboardFocusHere(-1);
1193b4be Poul Sander 2025-02-03 21:28 10206
            ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 10207
        }
1193b4be Poul Sander 2025-02-03 21:28 10208
        else
1193b4be Poul Sander 2025-02-03 21:28 10209
        {
1193b4be Poul Sander 2025-02-03 21:28 10210
            app.RenamingDoc = NULL;
1193b4be Poul Sander 2025-02-03 21:28 10211
        }
1193b4be Poul Sander 2025-02-03 21:28 10212
        app.RenamingStarted = false;
1193b4be Poul Sander 2025-02-03 21:28 10213
    }
1193b4be Poul Sander 2025-02-03 21:28 10214
1193b4be Poul Sander 2025-02-03 21:28 10215
    // Display closing confirmation UI
1193b4be Poul Sander 2025-02-03 21:28 10216
    if (!app.CloseQueue.empty())
1193b4be Poul Sander 2025-02-03 21:28 10217
    {
1193b4be Poul Sander 2025-02-03 21:28 10218
        int close_queue_unsaved_documents = 0;
1193b4be Poul Sander 2025-02-03 21:28 10219
        for (int n = 0; n < app.CloseQueue.Size; n++)
1193b4be Poul Sander 2025-02-03 21:28 10220
            if (app.CloseQueue[n]->Dirty)
1193b4be Poul Sander 2025-02-03 21:28 10221
                close_queue_unsaved_documents++;
1193b4be Poul Sander 2025-02-03 21:28 10222
1193b4be Poul Sander 2025-02-03 21:28 10223
        if (close_queue_unsaved_documents == 0)
1193b4be Poul Sander 2025-02-03 21:28 10224
        {
1193b4be Poul Sander 2025-02-03 21:28 10225
            // Close documents when all are unsaved
1193b4be Poul Sander 2025-02-03 21:28 10226
            for (int n = 0; n < app.CloseQueue.Size; n++)
1193b4be Poul Sander 2025-02-03 21:28 10227
                app.CloseQueue[n]->DoForceClose();
1193b4be Poul Sander 2025-02-03 21:28 10228
            app.CloseQueue.clear();
1193b4be Poul Sander 2025-02-03 21:28 10229
        }
1193b4be Poul Sander 2025-02-03 21:28 10230
        else
1193b4be Poul Sander 2025-02-03 21:28 10231
        {
1193b4be Poul Sander 2025-02-03 21:28 10232
            if (!ImGui::IsPopupOpen("Save?"))
1193b4be Poul Sander 2025-02-03 21:28 10233
                ImGui::OpenPopup("Save?");
1193b4be Poul Sander 2025-02-03 21:28 10234
            if (ImGui::BeginPopupModal("Save?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
1193b4be Poul Sander 2025-02-03 21:28 10235
            {
1193b4be Poul Sander 2025-02-03 21:28 10236
                ImGui::Text("Save change to the following items?");
1193b4be Poul Sander 2025-02-03 21:28 10237
                float item_height = ImGui::GetTextLineHeightWithSpacing();
1193b4be Poul Sander 2025-02-03 21:28 10238
                if (ImGui::BeginChild(ImGui::GetID("frame"), ImVec2(-FLT_MIN, 6.25f * item_height), ImGuiChildFlags_FrameStyle))
1193b4be Poul Sander 2025-02-03 21:28 10239
                    for (MyDocument* doc : app.CloseQueue)
1193b4be Poul Sander 2025-02-03 21:28 10240
                        if (doc->Dirty)
1193b4be Poul Sander 2025-02-03 21:28 10241
                            ImGui::Text("%s", doc->Name);
1193b4be Poul Sander 2025-02-03 21:28 10242
                ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 10243
1193b4be Poul Sander 2025-02-03 21:28 10244
                ImVec2 button_size(ImGui::GetFontSize() * 7.0f, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 10245
                if (ImGui::Button("Yes", button_size))
1193b4be Poul Sander 2025-02-03 21:28 10246
                {
1193b4be Poul Sander 2025-02-03 21:28 10247
                    for (MyDocument* doc : app.CloseQueue)
1193b4be Poul Sander 2025-02-03 21:28 10248
                    {
1193b4be Poul Sander 2025-02-03 21:28 10249
                        if (doc->Dirty)
1193b4be Poul Sander 2025-02-03 21:28 10250
                            doc->DoSave();
1193b4be Poul Sander 2025-02-03 21:28 10251
                        doc->DoForceClose();
1193b4be Poul Sander 2025-02-03 21:28 10252
                    }
1193b4be Poul Sander 2025-02-03 21:28 10253
                    app.CloseQueue.clear();
1193b4be Poul Sander 2025-02-03 21:28 10254
                    ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 10255
                }
1193b4be Poul Sander 2025-02-03 21:28 10256
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 10257
                if (ImGui::Button("No", button_size))
1193b4be Poul Sander 2025-02-03 21:28 10258
                {
1193b4be Poul Sander 2025-02-03 21:28 10259
                    for (MyDocument* doc : app.CloseQueue)
1193b4be Poul Sander 2025-02-03 21:28 10260
                        doc->DoForceClose();
1193b4be Poul Sander 2025-02-03 21:28 10261
                    app.CloseQueue.clear();
1193b4be Poul Sander 2025-02-03 21:28 10262
                    ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 10263
                }
1193b4be Poul Sander 2025-02-03 21:28 10264
                ImGui::SameLine();
1193b4be Poul Sander 2025-02-03 21:28 10265
                if (ImGui::Button("Cancel", button_size))
1193b4be Poul Sander 2025-02-03 21:28 10266
                {
1193b4be Poul Sander 2025-02-03 21:28 10267
                    app.CloseQueue.clear();
1193b4be Poul Sander 2025-02-03 21:28 10268
                    ImGui::CloseCurrentPopup();
1193b4be Poul Sander 2025-02-03 21:28 10269
                }
1193b4be Poul Sander 2025-02-03 21:28 10270
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 10271
            }
1193b4be Poul Sander 2025-02-03 21:28 10272
        }
1193b4be Poul Sander 2025-02-03 21:28 10273
    }
1193b4be Poul Sander 2025-02-03 21:28 10274
1193b4be Poul Sander 2025-02-03 21:28 10275
    ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 10276
}
1193b4be Poul Sander 2025-02-03 21:28 10277
1193b4be Poul Sander 2025-02-03 21:28 10278
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 10279
// [SECTION] Example App: Assets Browser / ShowExampleAppAssetsBrowser()
1193b4be Poul Sander 2025-02-03 21:28 10280
//-----------------------------------------------------------------------------
1193b4be Poul Sander 2025-02-03 21:28 10281
1193b4be Poul Sander 2025-02-03 21:28 10282
//#include "imgui_internal.h" // NavMoveRequestTryWrapping()
1193b4be Poul Sander 2025-02-03 21:28 10283
1193b4be Poul Sander 2025-02-03 21:28 10284
struct ExampleAsset
1193b4be Poul Sander 2025-02-03 21:28 10285
{
1193b4be Poul Sander 2025-02-03 21:28 10286
    ImGuiID ID;
1193b4be Poul Sander 2025-02-03 21:28 10287
    int     Type;
1193b4be Poul Sander 2025-02-03 21:28 10288
1193b4be Poul Sander 2025-02-03 21:28 10289
    ExampleAsset(ImGuiID id, int type) { ID = id; Type = type; }
1193b4be Poul Sander 2025-02-03 21:28 10290
1193b4be Poul Sander 2025-02-03 21:28 10291
    static const ImGuiTableSortSpecs* s_current_sort_specs;
1193b4be Poul Sander 2025-02-03 21:28 10292
1193b4be Poul Sander 2025-02-03 21:28 10293
    static void SortWithSortSpecs(ImGuiTableSortSpecs* sort_specs, ExampleAsset* items, int items_count)
1193b4be Poul Sander 2025-02-03 21:28 10294
    {
1193b4be Poul Sander 2025-02-03 21:28 10295
        s_current_sort_specs = sort_specs; // Store in variable accessible by the sort function.
1193b4be Poul Sander 2025-02-03 21:28 10296
        if (items_count > 1)
1193b4be Poul Sander 2025-02-03 21:28 10297
            qsort(items, (size_t)items_count, sizeof(items[0]), ExampleAsset::CompareWithSortSpecs);
1193b4be Poul Sander 2025-02-03 21:28 10298
        s_current_sort_specs = NULL;
1193b4be Poul Sander 2025-02-03 21:28 10299
    }
1193b4be Poul Sander 2025-02-03 21:28 10300
1193b4be Poul Sander 2025-02-03 21:28 10301
    // Compare function to be used by qsort()
1193b4be Poul Sander 2025-02-03 21:28 10302
    static int IMGUI_CDECL CompareWithSortSpecs(const void* lhs, const void* rhs)
1193b4be Poul Sander 2025-02-03 21:28 10303
    {
1193b4be Poul Sander 2025-02-03 21:28 10304
        const ExampleAsset* a = (const ExampleAsset*)lhs;
1193b4be Poul Sander 2025-02-03 21:28 10305
        const ExampleAsset* b = (const ExampleAsset*)rhs;
1193b4be Poul Sander 2025-02-03 21:28 10306
        for (int n = 0; n < s_current_sort_specs->SpecsCount; n++)
1193b4be Poul Sander 2025-02-03 21:28 10307
        {
1193b4be Poul Sander 2025-02-03 21:28 10308
            const ImGuiTableColumnSortSpecs* sort_spec = &s_current_sort_specs->Specs[n];
1193b4be Poul Sander 2025-02-03 21:28 10309
            int delta = 0;
1193b4be Poul Sander 2025-02-03 21:28 10310
            if (sort_spec->ColumnIndex == 0)
1193b4be Poul Sander 2025-02-03 21:28 10311
                delta = ((int)a->ID - (int)b->ID);
1193b4be Poul Sander 2025-02-03 21:28 10312
            else if (sort_spec->ColumnIndex == 1)
1193b4be Poul Sander 2025-02-03 21:28 10313
                delta = (a->Type - b->Type);
1193b4be Poul Sander 2025-02-03 21:28 10314
            if (delta > 0)
1193b4be Poul Sander 2025-02-03 21:28 10315
                return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? +1 : -1;
1193b4be Poul Sander 2025-02-03 21:28 10316
            if (delta < 0)
1193b4be Poul Sander 2025-02-03 21:28 10317
                return (sort_spec->SortDirection == ImGuiSortDirection_Ascending) ? -1 : +1;
1193b4be Poul Sander 2025-02-03 21:28 10318
        }
1193b4be Poul Sander 2025-02-03 21:28 10319
        return ((int)a->ID - (int)b->ID);
1193b4be Poul Sander 2025-02-03 21:28 10320
    }
1193b4be Poul Sander 2025-02-03 21:28 10321
};
1193b4be Poul Sander 2025-02-03 21:28 10322
const ImGuiTableSortSpecs* ExampleAsset::s_current_sort_specs = NULL;
1193b4be Poul Sander 2025-02-03 21:28 10323
1193b4be Poul Sander 2025-02-03 21:28 10324
struct ExampleAssetsBrowser
1193b4be Poul Sander 2025-02-03 21:28 10325
{
1193b4be Poul Sander 2025-02-03 21:28 10326
    // Options
1193b4be Poul Sander 2025-02-03 21:28 10327
    bool            ShowTypeOverlay = true;
1193b4be Poul Sander 2025-02-03 21:28 10328
    bool            AllowSorting = true;
1193b4be Poul Sander 2025-02-03 21:28 10329
    bool            AllowDragUnselected = false;
1193b4be Poul Sander 2025-02-03 21:28 10330
    bool            AllowBoxSelect = true;
1193b4be Poul Sander 2025-02-03 21:28 10331
    float           IconSize = 32.0f;
1193b4be Poul Sander 2025-02-03 21:28 10332
    int             IconSpacing = 10;
1193b4be Poul Sander 2025-02-03 21:28 10333
    int             IconHitSpacing = 4;         // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
1193b4be Poul Sander 2025-02-03 21:28 10334
    bool            StretchSpacing = true;
1193b4be Poul Sander 2025-02-03 21:28 10335
1193b4be Poul Sander 2025-02-03 21:28 10336
    // State
1193b4be Poul Sander 2025-02-03 21:28 10337
    ImVector<ExampleAsset> Items;               // Our items
1193b4be Poul Sander 2025-02-03 21:28 10338
    ExampleSelectionWithDeletion Selection;     // Our selection (ImGuiSelectionBasicStorage + helper funcs to handle deletion)
1193b4be Poul Sander 2025-02-03 21:28 10339
    ImGuiID         NextItemId = 0;             // Unique identifier when creating new items
1193b4be Poul Sander 2025-02-03 21:28 10340
    bool            RequestDelete = false;      // Deferred deletion request
1193b4be Poul Sander 2025-02-03 21:28 10341
    bool            RequestSort = false;        // Deferred sort request
1193b4be Poul Sander 2025-02-03 21:28 10342
    float           ZoomWheelAccum = 0.0f;      // Mouse wheel accumulator to handle smooth wheels better
1193b4be Poul Sander 2025-02-03 21:28 10343
1193b4be Poul Sander 2025-02-03 21:28 10344
    // Calculated sizes for layout, output of UpdateLayoutSizes(). Could be locals but our code is simpler this way.
1193b4be Poul Sander 2025-02-03 21:28 10345
    ImVec2          LayoutItemSize;
1193b4be Poul Sander 2025-02-03 21:28 10346
    ImVec2          LayoutItemStep;             // == LayoutItemSize + LayoutItemSpacing
1193b4be Poul Sander 2025-02-03 21:28 10347
    float           LayoutItemSpacing = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 10348
    float           LayoutSelectableSpacing = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 10349
    float           LayoutOuterPadding = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 10350
    int             LayoutColumnCount = 0;
1193b4be Poul Sander 2025-02-03 21:28 10351
    int             LayoutLineCount = 0;
1193b4be Poul Sander 2025-02-03 21:28 10352
1193b4be Poul Sander 2025-02-03 21:28 10353
    // Functions
1193b4be Poul Sander 2025-02-03 21:28 10354
    ExampleAssetsBrowser()
1193b4be Poul Sander 2025-02-03 21:28 10355
    {
1193b4be Poul Sander 2025-02-03 21:28 10356
        AddItems(10000);
1193b4be Poul Sander 2025-02-03 21:28 10357
    }
1193b4be Poul Sander 2025-02-03 21:28 10358
    void AddItems(int count)
1193b4be Poul Sander 2025-02-03 21:28 10359
    {
1193b4be Poul Sander 2025-02-03 21:28 10360
        if (Items.Size == 0)
1193b4be Poul Sander 2025-02-03 21:28 10361
            NextItemId = 0;
1193b4be Poul Sander 2025-02-03 21:28 10362
        Items.reserve(Items.Size + count);
1193b4be Poul Sander 2025-02-03 21:28 10363
        for (int n = 0; n < count; n++, NextItemId++)
1193b4be Poul Sander 2025-02-03 21:28 10364
            Items.push_back(ExampleAsset(NextItemId, (NextItemId % 20) < 15 ? 0 : (NextItemId % 20) < 18 ? 1 : 2));
1193b4be Poul Sander 2025-02-03 21:28 10365
        RequestSort = true;
1193b4be Poul Sander 2025-02-03 21:28 10366
    }
1193b4be Poul Sander 2025-02-03 21:28 10367
    void ClearItems()
1193b4be Poul Sander 2025-02-03 21:28 10368
    {
1193b4be Poul Sander 2025-02-03 21:28 10369
        Items.clear();
1193b4be Poul Sander 2025-02-03 21:28 10370
        Selection.Clear();
1193b4be Poul Sander 2025-02-03 21:28 10371
    }
1193b4be Poul Sander 2025-02-03 21:28 10372
1193b4be Poul Sander 2025-02-03 21:28 10373
    // Logic would be written in the main code BeginChild() and outputing to local variables.
1193b4be Poul Sander 2025-02-03 21:28 10374
    // We extracted it into a function so we can call it easily from multiple places.
1193b4be Poul Sander 2025-02-03 21:28 10375
    void UpdateLayoutSizes(float avail_width)
1193b4be Poul Sander 2025-02-03 21:28 10376
    {
1193b4be Poul Sander 2025-02-03 21:28 10377
        // Layout: when not stretching: allow extending into right-most spacing.
1193b4be Poul Sander 2025-02-03 21:28 10378
        LayoutItemSpacing = (float)IconSpacing;
1193b4be Poul Sander 2025-02-03 21:28 10379
        if (StretchSpacing == false)
1193b4be Poul Sander 2025-02-03 21:28 10380
            avail_width += floorf(LayoutItemSpacing * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 10381
1193b4be Poul Sander 2025-02-03 21:28 10382
        // Layout: calculate number of icon per line and number of lines
1193b4be Poul Sander 2025-02-03 21:28 10383
        LayoutItemSize = ImVec2(floorf(IconSize), floorf(IconSize));
1193b4be Poul Sander 2025-02-03 21:28 10384
        LayoutColumnCount = IM_MAX((int)(avail_width / (LayoutItemSize.x + LayoutItemSpacing)), 1);
1193b4be Poul Sander 2025-02-03 21:28 10385
        LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
1193b4be Poul Sander 2025-02-03 21:28 10386
1193b4be Poul Sander 2025-02-03 21:28 10387
        // Layout: when stretching: allocate remaining space to more spacing. Round before division, so item_spacing may be non-integer.
1193b4be Poul Sander 2025-02-03 21:28 10388
        if (StretchSpacing && LayoutColumnCount > 1)
1193b4be Poul Sander 2025-02-03 21:28 10389
            LayoutItemSpacing = floorf(avail_width - LayoutItemSize.x * LayoutColumnCount) / LayoutColumnCount;
1193b4be Poul Sander 2025-02-03 21:28 10390
1193b4be Poul Sander 2025-02-03 21:28 10391
        LayoutItemStep = ImVec2(LayoutItemSize.x + LayoutItemSpacing, LayoutItemSize.y + LayoutItemSpacing);
1193b4be Poul Sander 2025-02-03 21:28 10392
        LayoutSelectableSpacing = IM_MAX(floorf(LayoutItemSpacing) - IconHitSpacing, 0.0f);
1193b4be Poul Sander 2025-02-03 21:28 10393
        LayoutOuterPadding = floorf(LayoutItemSpacing * 0.5f);
1193b4be Poul Sander 2025-02-03 21:28 10394
    }
1193b4be Poul Sander 2025-02-03 21:28 10395
1193b4be Poul Sander 2025-02-03 21:28 10396
    void Draw(const char* title, bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 10397
    {
1193b4be Poul Sander 2025-02-03 21:28 10398
        ImGui::SetNextWindowSize(ImVec2(IconSize * 25, IconSize * 15), ImGuiCond_FirstUseEver);
1193b4be Poul Sander 2025-02-03 21:28 10399
        if (!ImGui::Begin(title, p_open, ImGuiWindowFlags_MenuBar))
1193b4be Poul Sander 2025-02-03 21:28 10400
        {
1193b4be Poul Sander 2025-02-03 21:28 10401
            ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 10402
            return;
1193b4be Poul Sander 2025-02-03 21:28 10403
        }
1193b4be Poul Sander 2025-02-03 21:28 10404
1193b4be Poul Sander 2025-02-03 21:28 10405
        // Menu bar
1193b4be Poul Sander 2025-02-03 21:28 10406
        if (ImGui::BeginMenuBar())
1193b4be Poul Sander 2025-02-03 21:28 10407
        {
1193b4be Poul Sander 2025-02-03 21:28 10408
            if (ImGui::BeginMenu("File"))
1193b4be Poul Sander 2025-02-03 21:28 10409
            {
1193b4be Poul Sander 2025-02-03 21:28 10410
                if (ImGui::MenuItem("Add 10000 items"))
1193b4be Poul Sander 2025-02-03 21:28 10411
                    AddItems(10000);
1193b4be Poul Sander 2025-02-03 21:28 10412
                if (ImGui::MenuItem("Clear items"))
1193b4be Poul Sander 2025-02-03 21:28 10413
                    ClearItems();
1193b4be Poul Sander 2025-02-03 21:28 10414
                ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 10415
                if (ImGui::MenuItem("Close", NULL, false, p_open != NULL))
1193b4be Poul Sander 2025-02-03 21:28 10416
                    *p_open = false;
1193b4be Poul Sander 2025-02-03 21:28 10417
                ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 10418
            }
1193b4be Poul Sander 2025-02-03 21:28 10419
            if (ImGui::BeginMenu("Edit"))
1193b4be Poul Sander 2025-02-03 21:28 10420
            {
1193b4be Poul Sander 2025-02-03 21:28 10421
                if (ImGui::MenuItem("Delete", "Del", false, Selection.Size > 0))
1193b4be Poul Sander 2025-02-03 21:28 10422
                    RequestDelete = true;
1193b4be Poul Sander 2025-02-03 21:28 10423
                ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 10424
            }
1193b4be Poul Sander 2025-02-03 21:28 10425
            if (ImGui::BeginMenu("Options"))
1193b4be Poul Sander 2025-02-03 21:28 10426
            {
1193b4be Poul Sander 2025-02-03 21:28 10427
                ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
1193b4be Poul Sander 2025-02-03 21:28 10428
1193b4be Poul Sander 2025-02-03 21:28 10429
                ImGui::SeparatorText("Contents");
1193b4be Poul Sander 2025-02-03 21:28 10430
                ImGui::Checkbox("Show Type Overlay", &ShowTypeOverlay);
1193b4be Poul Sander 2025-02-03 21:28 10431
                ImGui::Checkbox("Allow Sorting", &AllowSorting);
1193b4be Poul Sander 2025-02-03 21:28 10432
1193b4be Poul Sander 2025-02-03 21:28 10433
                ImGui::SeparatorText("Selection Behavior");
1193b4be Poul Sander 2025-02-03 21:28 10434
                ImGui::Checkbox("Allow dragging unselected item", &AllowDragUnselected);
1193b4be Poul Sander 2025-02-03 21:28 10435
                ImGui::Checkbox("Allow box-selection", &AllowBoxSelect);
1193b4be Poul Sander 2025-02-03 21:28 10436
1193b4be Poul Sander 2025-02-03 21:28 10437
                ImGui::SeparatorText("Layout");
1193b4be Poul Sander 2025-02-03 21:28 10438
                ImGui::SliderFloat("Icon Size", &IconSize, 16.0f, 128.0f, "%.0f");
1193b4be Poul Sander 2025-02-03 21:28 10439
                ImGui::SameLine(); HelpMarker("Use CTRL+Wheel to zoom");
1193b4be Poul Sander 2025-02-03 21:28 10440
                ImGui::SliderInt("Icon Spacing", &IconSpacing, 0, 32);
1193b4be Poul Sander 2025-02-03 21:28 10441
                ImGui::SliderInt("Icon Hit Spacing", &IconHitSpacing, 0, 32);
1193b4be Poul Sander 2025-02-03 21:28 10442
                ImGui::Checkbox("Stretch Spacing", &StretchSpacing);
1193b4be Poul Sander 2025-02-03 21:28 10443
                ImGui::PopItemWidth();
1193b4be Poul Sander 2025-02-03 21:28 10444
                ImGui::EndMenu();
1193b4be Poul Sander 2025-02-03 21:28 10445
            }
1193b4be Poul Sander 2025-02-03 21:28 10446
            ImGui::EndMenuBar();
1193b4be Poul Sander 2025-02-03 21:28 10447
        }
1193b4be Poul Sander 2025-02-03 21:28 10448
1193b4be Poul Sander 2025-02-03 21:28 10449
        // Show a table with ONLY one header row to showcase the idea/possibility of using this to provide a sorting UI
1193b4be Poul Sander 2025-02-03 21:28 10450
        if (AllowSorting)
1193b4be Poul Sander 2025-02-03 21:28 10451
        {
1193b4be Poul Sander 2025-02-03 21:28 10452
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
1193b4be Poul Sander 2025-02-03 21:28 10453
            ImGuiTableFlags table_flags_for_sort_specs = ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Borders;
1193b4be Poul Sander 2025-02-03 21:28 10454
            if (ImGui::BeginTable("for_sort_specs_only", 2, table_flags_for_sort_specs, ImVec2(0.0f, ImGui::GetFrameHeight())))
1193b4be Poul Sander 2025-02-03 21:28 10455
            {
1193b4be Poul Sander 2025-02-03 21:28 10456
                ImGui::TableSetupColumn("Index");
1193b4be Poul Sander 2025-02-03 21:28 10457
                ImGui::TableSetupColumn("Type");
1193b4be Poul Sander 2025-02-03 21:28 10458
                ImGui::TableHeadersRow();
1193b4be Poul Sander 2025-02-03 21:28 10459
                if (ImGuiTableSortSpecs* sort_specs = ImGui::TableGetSortSpecs())
1193b4be Poul Sander 2025-02-03 21:28 10460
                    if (sort_specs->SpecsDirty || RequestSort)
1193b4be Poul Sander 2025-02-03 21:28 10461
                    {
1193b4be Poul Sander 2025-02-03 21:28 10462
                        ExampleAsset::SortWithSortSpecs(sort_specs, Items.Data, Items.Size);
1193b4be Poul Sander 2025-02-03 21:28 10463
                        sort_specs->SpecsDirty = RequestSort = false;
1193b4be Poul Sander 2025-02-03 21:28 10464
                    }
1193b4be Poul Sander 2025-02-03 21:28 10465
                ImGui::EndTable();
1193b4be Poul Sander 2025-02-03 21:28 10466
            }
1193b4be Poul Sander 2025-02-03 21:28 10467
            ImGui::PopStyleVar();
1193b4be Poul Sander 2025-02-03 21:28 10468
        }
1193b4be Poul Sander 2025-02-03 21:28 10469
1193b4be Poul Sander 2025-02-03 21:28 10470
        ImGuiIO& io = ImGui::GetIO();
1193b4be Poul Sander 2025-02-03 21:28 10471
        ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.x + LayoutItemSpacing)));
1193b4be Poul Sander 2025-02-03 21:28 10472
        if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove))
1193b4be Poul Sander 2025-02-03 21:28 10473
        {
1193b4be Poul Sander 2025-02-03 21:28 10474
            ImDrawList* draw_list = ImGui::GetWindowDrawList();
1193b4be Poul Sander 2025-02-03 21:28 10475
1193b4be Poul Sander 2025-02-03 21:28 10476
            const float avail_width = ImGui::GetContentRegionAvail().x;
1193b4be Poul Sander 2025-02-03 21:28 10477
            UpdateLayoutSizes(avail_width);
1193b4be Poul Sander 2025-02-03 21:28 10478
1193b4be Poul Sander 2025-02-03 21:28 10479
            // Calculate and store start position.
1193b4be Poul Sander 2025-02-03 21:28 10480
            ImVec2 start_pos = ImGui::GetCursorScreenPos();
1193b4be Poul Sander 2025-02-03 21:28 10481
            start_pos = ImVec2(start_pos.x + LayoutOuterPadding, start_pos.y + LayoutOuterPadding);
1193b4be Poul Sander 2025-02-03 21:28 10482
            ImGui::SetCursorScreenPos(start_pos);
1193b4be Poul Sander 2025-02-03 21:28 10483
1193b4be Poul Sander 2025-02-03 21:28 10484
            // Multi-select
1193b4be Poul Sander 2025-02-03 21:28 10485
            ImGuiMultiSelectFlags ms_flags = ImGuiMultiSelectFlags_ClearOnEscape | ImGuiMultiSelectFlags_ClearOnClickVoid;
1193b4be Poul Sander 2025-02-03 21:28 10486
1193b4be Poul Sander 2025-02-03 21:28 10487
            // - Enable box-select (in 2D mode, so that changing box-select rectangle X1/X2 boundaries will affect clipped items)
1193b4be Poul Sander 2025-02-03 21:28 10488
            if (AllowBoxSelect)
1193b4be Poul Sander 2025-02-03 21:28 10489
                ms_flags |= ImGuiMultiSelectFlags_BoxSelect2d;
1193b4be Poul Sander 2025-02-03 21:28 10490
1193b4be Poul Sander 2025-02-03 21:28 10491
            // - This feature allows dragging an unselected item without selecting it (rarely used)
1193b4be Poul Sander 2025-02-03 21:28 10492
            if (AllowDragUnselected)
1193b4be Poul Sander 2025-02-03 21:28 10493
                ms_flags |= ImGuiMultiSelectFlags_SelectOnClickRelease;
1193b4be Poul Sander 2025-02-03 21:28 10494
1193b4be Poul Sander 2025-02-03 21:28 10495
            // - Enable keyboard wrapping on X axis
1193b4be Poul Sander 2025-02-03 21:28 10496
            // (FIXME-MULTISELECT: We haven't designed/exposed a general nav wrapping api yet, so this flag is provided as a courtesy to avoid doing:
1193b4be Poul Sander 2025-02-03 21:28 10497
            //    ImGui::NavMoveRequestTryWrapping(ImGui::GetCurrentWindow(), ImGuiNavMoveFlags_WrapX);
1193b4be Poul Sander 2025-02-03 21:28 10498
            // When we finish implementing a more general API for this, we will obsolete this flag in favor of the new system)
1193b4be Poul Sander 2025-02-03 21:28 10499
            ms_flags |= ImGuiMultiSelectFlags_NavWrapX;
1193b4be Poul Sander 2025-02-03 21:28 10500
1193b4be Poul Sander 2025-02-03 21:28 10501
            ImGuiMultiSelectIO* ms_io = ImGui::BeginMultiSelect(ms_flags, Selection.Size, Items.Size);
1193b4be Poul Sander 2025-02-03 21:28 10502
1193b4be Poul Sander 2025-02-03 21:28 10503
            // Use custom selection adapter: store ID in selection (recommended)
1193b4be Poul Sander 2025-02-03 21:28 10504
            Selection.UserData = this;
1193b4be Poul Sander 2025-02-03 21:28 10505
            Selection.AdapterIndexToStorageId = [](ImGuiSelectionBasicStorage* self_, int idx) { ExampleAssetsBrowser* self = (ExampleAssetsBrowser*)self_->UserData; return self->Items[idx].ID; };
1193b4be Poul Sander 2025-02-03 21:28 10506
            Selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 10507
1193b4be Poul Sander 2025-02-03 21:28 10508
            const bool want_delete = (ImGui::Shortcut(ImGuiKey_Delete, ImGuiInputFlags_Repeat) && (Selection.Size > 0)) || RequestDelete;
1193b4be Poul Sander 2025-02-03 21:28 10509
            const int item_curr_idx_to_focus = want_delete ? Selection.ApplyDeletionPreLoop(ms_io, Items.Size) : -1;
1193b4be Poul Sander 2025-02-03 21:28 10510
            RequestDelete = false;
1193b4be Poul Sander 2025-02-03 21:28 10511
1193b4be Poul Sander 2025-02-03 21:28 10512
            // Push LayoutSelectableSpacing (which is LayoutItemSpacing minus hit-spacing, if we decide to have hit gaps between items)
1193b4be Poul Sander 2025-02-03 21:28 10513
            // Altering style ItemSpacing may seem unnecessary as we position every items using SetCursorScreenPos()...
1193b4be Poul Sander 2025-02-03 21:28 10514
            // But it is necessary for two reasons:
1193b4be Poul Sander 2025-02-03 21:28 10515
            // - Selectables uses it by default to visually fill the space between two items.
1193b4be Poul Sander 2025-02-03 21:28 10516
            // - The vertical spacing would be measured by Clipper to calculate line height if we didn't provide it explicitly (here we do).
1193b4be Poul Sander 2025-02-03 21:28 10517
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(LayoutSelectableSpacing, LayoutSelectableSpacing));
1193b4be Poul Sander 2025-02-03 21:28 10518
1193b4be Poul Sander 2025-02-03 21:28 10519
            // Rendering parameters
1193b4be Poul Sander 2025-02-03 21:28 10520
            const ImU32 icon_type_overlay_colors[3] = { 0, IM_COL32(200, 70, 70, 255), IM_COL32(70, 170, 70, 255) };
1193b4be Poul Sander 2025-02-03 21:28 10521
            const ImU32 icon_bg_color = ImGui::GetColorU32(ImGuiCol_MenuBarBg);
1193b4be Poul Sander 2025-02-03 21:28 10522
            const ImVec2 icon_type_overlay_size = ImVec2(4.0f, 4.0f);
1193b4be Poul Sander 2025-02-03 21:28 10523
            const bool display_label = (LayoutItemSize.x >= ImGui::CalcTextSize("999").x);
1193b4be Poul Sander 2025-02-03 21:28 10524
1193b4be Poul Sander 2025-02-03 21:28 10525
            const int column_count = LayoutColumnCount;
1193b4be Poul Sander 2025-02-03 21:28 10526
            ImGuiListClipper clipper;
1193b4be Poul Sander 2025-02-03 21:28 10527
            clipper.Begin(LayoutLineCount, LayoutItemStep.y);
1193b4be Poul Sander 2025-02-03 21:28 10528
            if (item_curr_idx_to_focus != -1)
1193b4be Poul Sander 2025-02-03 21:28 10529
                clipper.IncludeItemByIndex(item_curr_idx_to_focus / column_count); // Ensure focused item line is not clipped.
1193b4be Poul Sander 2025-02-03 21:28 10530
            if (ms_io->RangeSrcItem != -1)
1193b4be Poul Sander 2025-02-03 21:28 10531
                clipper.IncludeItemByIndex((int)ms_io->RangeSrcItem / column_count); // Ensure RangeSrc item line is not clipped.
1193b4be Poul Sander 2025-02-03 21:28 10532
            while (clipper.Step())
1193b4be Poul Sander 2025-02-03 21:28 10533
            {
1193b4be Poul Sander 2025-02-03 21:28 10534
                for (int line_idx = clipper.DisplayStart; line_idx < clipper.DisplayEnd; line_idx++)
1193b4be Poul Sander 2025-02-03 21:28 10535
                {
1193b4be Poul Sander 2025-02-03 21:28 10536
                    const int item_min_idx_for_current_line = line_idx * column_count;
1193b4be Poul Sander 2025-02-03 21:28 10537
                    const int item_max_idx_for_current_line = IM_MIN((line_idx + 1) * column_count, Items.Size);
1193b4be Poul Sander 2025-02-03 21:28 10538
                    for (int item_idx = item_min_idx_for_current_line; item_idx < item_max_idx_for_current_line; ++item_idx)
1193b4be Poul Sander 2025-02-03 21:28 10539
                    {
1193b4be Poul Sander 2025-02-03 21:28 10540
                        ExampleAsset* item_data = &Items[item_idx];
1193b4be Poul Sander 2025-02-03 21:28 10541
                        ImGui::PushID((int)item_data->ID);
1193b4be Poul Sander 2025-02-03 21:28 10542
1193b4be Poul Sander 2025-02-03 21:28 10543
                        // Position item
1193b4be Poul Sander 2025-02-03 21:28 10544
                        ImVec2 pos = ImVec2(start_pos.x + (item_idx % column_count) * LayoutItemStep.x, start_pos.y + line_idx * LayoutItemStep.y);
1193b4be Poul Sander 2025-02-03 21:28 10545
                        ImGui::SetCursorScreenPos(pos);
1193b4be Poul Sander 2025-02-03 21:28 10546
1193b4be Poul Sander 2025-02-03 21:28 10547
                        ImGui::SetNextItemSelectionUserData(item_idx);
1193b4be Poul Sander 2025-02-03 21:28 10548
                        bool item_is_selected = Selection.Contains((ImGuiID)item_data->ID);
1193b4be Poul Sander 2025-02-03 21:28 10549
                        bool item_is_visible = ImGui::IsRectVisible(LayoutItemSize);
1193b4be Poul Sander 2025-02-03 21:28 10550
                        ImGui::Selectable("", item_is_selected, ImGuiSelectableFlags_None, LayoutItemSize);
1193b4be Poul Sander 2025-02-03 21:28 10551
1193b4be Poul Sander 2025-02-03 21:28 10552
                        // Update our selection state immediately (without waiting for EndMultiSelect() requests)
1193b4be Poul Sander 2025-02-03 21:28 10553
                        // because we use this to alter the color of our text/icon.
1193b4be Poul Sander 2025-02-03 21:28 10554
                        if (ImGui::IsItemToggledSelection())
1193b4be Poul Sander 2025-02-03 21:28 10555
                            item_is_selected = !item_is_selected;
1193b4be Poul Sander 2025-02-03 21:28 10556
1193b4be Poul Sander 2025-02-03 21:28 10557
                        // Focus (for after deletion)
1193b4be Poul Sander 2025-02-03 21:28 10558
                        if (item_curr_idx_to_focus == item_idx)
1193b4be Poul Sander 2025-02-03 21:28 10559
                            ImGui::SetKeyboardFocusHere(-1);
1193b4be Poul Sander 2025-02-03 21:28 10560
1193b4be Poul Sander 2025-02-03 21:28 10561
                        // Drag and drop
1193b4be Poul Sander 2025-02-03 21:28 10562
                        if (ImGui::BeginDragDropSource())
1193b4be Poul Sander 2025-02-03 21:28 10563
                        {
1193b4be Poul Sander 2025-02-03 21:28 10564
                            // Create payload with full selection OR single unselected item.
1193b4be Poul Sander 2025-02-03 21:28 10565
                            // (the later is only possible when using ImGuiMultiSelectFlags_SelectOnClickRelease)
1193b4be Poul Sander 2025-02-03 21:28 10566
                            if (ImGui::GetDragDropPayload() == NULL)
1193b4be Poul Sander 2025-02-03 21:28 10567
                            {
1193b4be Poul Sander 2025-02-03 21:28 10568
                                ImVector<ImGuiID> payload_items;
1193b4be Poul Sander 2025-02-03 21:28 10569
                                void* it = NULL;
1193b4be Poul Sander 2025-02-03 21:28 10570
                                ImGuiID id = 0;
1193b4be Poul Sander 2025-02-03 21:28 10571
                                if (!item_is_selected)
1193b4be Poul Sander 2025-02-03 21:28 10572
                                    payload_items.push_back(item_data->ID);
1193b4be Poul Sander 2025-02-03 21:28 10573
                                else
1193b4be Poul Sander 2025-02-03 21:28 10574
                                    while (Selection.GetNextSelectedItem(&it, &id))
1193b4be Poul Sander 2025-02-03 21:28 10575
                                        payload_items.push_back(id);
1193b4be Poul Sander 2025-02-03 21:28 10576
                                ImGui::SetDragDropPayload("ASSETS_BROWSER_ITEMS", payload_items.Data, (size_t)payload_items.size_in_bytes());
1193b4be Poul Sander 2025-02-03 21:28 10577
                            }
1193b4be Poul Sander 2025-02-03 21:28 10578
1193b4be Poul Sander 2025-02-03 21:28 10579
                            // Display payload content in tooltip, by extracting it from the payload data
1193b4be Poul Sander 2025-02-03 21:28 10580
                            // (we could read from selection, but it is more correct and reusable to read from payload)
1193b4be Poul Sander 2025-02-03 21:28 10581
                            const ImGuiPayload* payload = ImGui::GetDragDropPayload();
1193b4be Poul Sander 2025-02-03 21:28 10582
                            const int payload_count = (int)payload->DataSize / (int)sizeof(ImGuiID);
1193b4be Poul Sander 2025-02-03 21:28 10583
                            ImGui::Text("%d assets", payload_count);
1193b4be Poul Sander 2025-02-03 21:28 10584
1193b4be Poul Sander 2025-02-03 21:28 10585
                            ImGui::EndDragDropSource();
1193b4be Poul Sander 2025-02-03 21:28 10586
                        }
1193b4be Poul Sander 2025-02-03 21:28 10587
1193b4be Poul Sander 2025-02-03 21:28 10588
                        // Render icon (a real app would likely display an image/thumbnail here)
1193b4be Poul Sander 2025-02-03 21:28 10589
                        // Because we use ImGuiMultiSelectFlags_BoxSelect2d, clipping vertical may occasionally be larger, so we coarse-clip our rendering as well.
1193b4be Poul Sander 2025-02-03 21:28 10590
                        if (item_is_visible)
1193b4be Poul Sander 2025-02-03 21:28 10591
                        {
1193b4be Poul Sander 2025-02-03 21:28 10592
                            ImVec2 box_min(pos.x - 1, pos.y - 1);
1193b4be Poul Sander 2025-02-03 21:28 10593
                            ImVec2 box_max(box_min.x + LayoutItemSize.x + 2, box_min.y + LayoutItemSize.y + 2); // Dubious
1193b4be Poul Sander 2025-02-03 21:28 10594
                            draw_list->AddRectFilled(box_min, box_max, icon_bg_color); // Background color
1193b4be Poul Sander 2025-02-03 21:28 10595
                            if (ShowTypeOverlay && item_data->Type != 0)
1193b4be Poul Sander 2025-02-03 21:28 10596
                            {
1193b4be Poul Sander 2025-02-03 21:28 10597
                                ImU32 type_col = icon_type_overlay_colors[item_data->Type % IM_ARRAYSIZE(icon_type_overlay_colors)];
1193b4be Poul Sander 2025-02-03 21:28 10598
                                draw_list->AddRectFilled(ImVec2(box_max.x - 2 - icon_type_overlay_size.x, box_min.y + 2), ImVec2(box_max.x - 2, box_min.y + 2 + icon_type_overlay_size.y), type_col);
1193b4be Poul Sander 2025-02-03 21:28 10599
                            }
1193b4be Poul Sander 2025-02-03 21:28 10600
                            if (display_label)
1193b4be Poul Sander 2025-02-03 21:28 10601
                            {
1193b4be Poul Sander 2025-02-03 21:28 10602
                                ImU32 label_col = ImGui::GetColorU32(item_is_selected ? ImGuiCol_Text : ImGuiCol_TextDisabled);
1193b4be Poul Sander 2025-02-03 21:28 10603
                                char label[32];
1193b4be Poul Sander 2025-02-03 21:28 10604
                                sprintf(label, "%d", item_data->ID);
1193b4be Poul Sander 2025-02-03 21:28 10605
                                draw_list->AddText(ImVec2(box_min.x, box_max.y - ImGui::GetFontSize()), label_col, label);
1193b4be Poul Sander 2025-02-03 21:28 10606
                            }
1193b4be Poul Sander 2025-02-03 21:28 10607
                        }
1193b4be Poul Sander 2025-02-03 21:28 10608
1193b4be Poul Sander 2025-02-03 21:28 10609
                        ImGui::PopID();
1193b4be Poul Sander 2025-02-03 21:28 10610
                    }
1193b4be Poul Sander 2025-02-03 21:28 10611
                }
1193b4be Poul Sander 2025-02-03 21:28 10612
            }
1193b4be Poul Sander 2025-02-03 21:28 10613
            clipper.End();
1193b4be Poul Sander 2025-02-03 21:28 10614
            ImGui::PopStyleVar(); // ImGuiStyleVar_ItemSpacing
1193b4be Poul Sander 2025-02-03 21:28 10615
1193b4be Poul Sander 2025-02-03 21:28 10616
            // Context menu
1193b4be Poul Sander 2025-02-03 21:28 10617
            if (ImGui::BeginPopupContextWindow())
1193b4be Poul Sander 2025-02-03 21:28 10618
            {
1193b4be Poul Sander 2025-02-03 21:28 10619
                ImGui::Text("Selection: %d items", Selection.Size);
1193b4be Poul Sander 2025-02-03 21:28 10620
                ImGui::Separator();
1193b4be Poul Sander 2025-02-03 21:28 10621
                if (ImGui::MenuItem("Delete", "Del", false, Selection.Size > 0))
1193b4be Poul Sander 2025-02-03 21:28 10622
                    RequestDelete = true;
1193b4be Poul Sander 2025-02-03 21:28 10623
                ImGui::EndPopup();
1193b4be Poul Sander 2025-02-03 21:28 10624
            }
1193b4be Poul Sander 2025-02-03 21:28 10625
1193b4be Poul Sander 2025-02-03 21:28 10626
            ms_io = ImGui::EndMultiSelect();
1193b4be Poul Sander 2025-02-03 21:28 10627
            Selection.ApplyRequests(ms_io);
1193b4be Poul Sander 2025-02-03 21:28 10628
            if (want_delete)
1193b4be Poul Sander 2025-02-03 21:28 10629
                Selection.ApplyDeletionPostLoop(ms_io, Items, item_curr_idx_to_focus);
1193b4be Poul Sander 2025-02-03 21:28 10630
1193b4be Poul Sander 2025-02-03 21:28 10631
            // Zooming with CTRL+Wheel
1193b4be Poul Sander 2025-02-03 21:28 10632
            if (ImGui::IsWindowAppearing())
1193b4be Poul Sander 2025-02-03 21:28 10633
                ZoomWheelAccum = 0.0f;
1193b4be Poul Sander 2025-02-03 21:28 10634
            if (ImGui::IsWindowHovered() && io.MouseWheel != 0.0f && ImGui::IsKeyDown(ImGuiMod_Ctrl) && ImGui::IsAnyItemActive() == false)
1193b4be Poul Sander 2025-02-03 21:28 10635
            {
1193b4be Poul Sander 2025-02-03 21:28 10636
                ZoomWheelAccum += io.MouseWheel;
1193b4be Poul Sander 2025-02-03 21:28 10637
                if (fabsf(ZoomWheelAccum) >= 1.0f)
1193b4be Poul Sander 2025-02-03 21:28 10638
                {
1193b4be Poul Sander 2025-02-03 21:28 10639
                    // Calculate hovered item index from mouse location
1193b4be Poul Sander 2025-02-03 21:28 10640
                    // FIXME: Locking aiming on 'hovered_item_idx' (with a cool-down timer) would ensure zoom keeps on it.
1193b4be Poul Sander 2025-02-03 21:28 10641
                    const float hovered_item_nx = (io.MousePos.x - start_pos.x + LayoutItemSpacing * 0.5f) / LayoutItemStep.x;
1193b4be Poul Sander 2025-02-03 21:28 10642
                    const float hovered_item_ny = (io.MousePos.y - start_pos.y + LayoutItemSpacing * 0.5f) / LayoutItemStep.y;
1193b4be Poul Sander 2025-02-03 21:28 10643
                    const int hovered_item_idx = ((int)hovered_item_ny * LayoutColumnCount) + (int)hovered_item_nx;
1193b4be Poul Sander 2025-02-03 21:28 10644
                    //ImGui::SetTooltip("%f,%f -> item %d", hovered_item_nx, hovered_item_ny, hovered_item_idx); // Move those 4 lines in block above for easy debugging
1193b4be Poul Sander 2025-02-03 21:28 10645
1193b4be Poul Sander 2025-02-03 21:28 10646
                    // Zoom
1193b4be Poul Sander 2025-02-03 21:28 10647
                    IconSize *= powf(1.1f, (float)(int)ZoomWheelAccum);
1193b4be Poul Sander 2025-02-03 21:28 10648
                    IconSize = IM_CLAMP(IconSize, 16.0f, 128.0f);
1193b4be Poul Sander 2025-02-03 21:28 10649
                    ZoomWheelAccum -= (int)ZoomWheelAccum;
1193b4be Poul Sander 2025-02-03 21:28 10650
                    UpdateLayoutSizes(avail_width);
1193b4be Poul Sander 2025-02-03 21:28 10651
1193b4be Poul Sander 2025-02-03 21:28 10652
                    // Manipulate scroll to that we will land at the same Y location of currently hovered item.
1193b4be Poul Sander 2025-02-03 21:28 10653
                    // - Calculate next frame position of item under mouse
1193b4be Poul Sander 2025-02-03 21:28 10654
                    // - Set new scroll position to be used in next ImGui::BeginChild() call.
1193b4be Poul Sander 2025-02-03 21:28 10655
                    float hovered_item_rel_pos_y = ((float)(hovered_item_idx / LayoutColumnCount) + fmodf(hovered_item_ny, 1.0f)) * LayoutItemStep.y;
1193b4be Poul Sander 2025-02-03 21:28 10656
                    hovered_item_rel_pos_y += ImGui::GetStyle().WindowPadding.y;
1193b4be Poul Sander 2025-02-03 21:28 10657
                    float mouse_local_y = io.MousePos.y - ImGui::GetWindowPos().y;
1193b4be Poul Sander 2025-02-03 21:28 10658
                    ImGui::SetScrollY(hovered_item_rel_pos_y - mouse_local_y);
1193b4be Poul Sander 2025-02-03 21:28 10659
                }
1193b4be Poul Sander 2025-02-03 21:28 10660
            }
1193b4be Poul Sander 2025-02-03 21:28 10661
        }
1193b4be Poul Sander 2025-02-03 21:28 10662
        ImGui::EndChild();
1193b4be Poul Sander 2025-02-03 21:28 10663
1193b4be Poul Sander 2025-02-03 21:28 10664
        ImGui::Text("Selected: %d/%d items", Selection.Size, Items.Size);
1193b4be Poul Sander 2025-02-03 21:28 10665
        ImGui::End();
1193b4be Poul Sander 2025-02-03 21:28 10666
    }
1193b4be Poul Sander 2025-02-03 21:28 10667
};
1193b4be Poul Sander 2025-02-03 21:28 10668
1193b4be Poul Sander 2025-02-03 21:28 10669
void ShowExampleAppAssetsBrowser(bool* p_open)
1193b4be Poul Sander 2025-02-03 21:28 10670
{
1193b4be Poul Sander 2025-02-03 21:28 10671
    IMGUI_DEMO_MARKER("Examples/Assets Browser");
1193b4be Poul Sander 2025-02-03 21:28 10672
    static ExampleAssetsBrowser assets_browser;
1193b4be Poul Sander 2025-02-03 21:28 10673
    assets_browser.Draw("Example: Assets Browser", p_open);
1193b4be Poul Sander 2025-02-03 21:28 10674
}
1193b4be Poul Sander 2025-02-03 21:28 10675
1193b4be Poul Sander 2025-02-03 21:28 10676
// End of Demo code
1193b4be Poul Sander 2025-02-03 21:28 10677
#else
1193b4be Poul Sander 2025-02-03 21:28 10678
1193b4be Poul Sander 2025-02-03 21:28 10679
void ImGui::ShowAboutWindow(bool*) {}
1193b4be Poul Sander 2025-02-03 21:28 10680
void ImGui::ShowDemoWindow(bool*) {}
1193b4be Poul Sander 2025-02-03 21:28 10681
void ImGui::ShowUserGuide() {}
1193b4be Poul Sander 2025-02-03 21:28 10682
void ImGui::ShowStyleEditor(ImGuiStyle*) {}
1193b4be Poul Sander 2025-02-03 21:28 10683
1193b4be Poul Sander 2025-02-03 21:28 10684
#endif
1193b4be Poul Sander 2025-02-03 21:28 10685
1193b4be Poul Sander 2025-02-03 21:28 10686
#endif // #ifndef IMGUI_DISABLE
1970-01-01 00:00 10687