1// dear imgui, v1.90.0
2// (demo code)
3
4// Help:
5// - Read FAQ at http://dearimgui.com/faq
6// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
7// - Need help integrating Dear ImGui in your codebase?
8// - Read Getting Started https://github.com/ocornut/imgui/wiki/Getting-Started
9// - Read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
10// Read imgui.cpp for more details, documentation and comments.
11// Get the latest version at https://github.com/ocornut/imgui
12
13//---------------------------------------------------
14// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT!
15//---------------------------------------------------
16// Message to the person tempted to delete this file when integrating Dear ImGui into their codebase:
17// Think again! It is the most useful reference code that you and other coders will want to refer to and call.
18// Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of your game/app!
19// Also include Metrics! ItemPicker! DebugLog! and other debug features.
20// Removing this file from your project is hindering access to documentation for everyone in your team,
21// likely leading you to poorer usage of the library.
22// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
23// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
24// linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
25// In another situation, whenever you have Dear ImGui available you probably want this to be available for reference.
26// Thank you,
27// -Your beloved friend, imgui_demo.cpp (which you won't delete)
28
29//--------------------------------------------
30// ABOUT THE MEANING OF THE 'static' KEYWORD:
31//--------------------------------------------
32// In this demo code, we frequently use 'static' variables inside functions.
33// A static variable persists across calls. It is essentially a global variable but declared inside the scope of the function.
34// Think of "static int n = 0;" as "global int n = 0;" !
35// We do this IN THE DEMO because we want:
36// - to gather code and data in the same place.
37// - to make the demo source code faster to read, faster to change, smaller in size.
38// - it is also a convenient way of storing simple UI related information as long as your function
39// doesn't need to be reentrant or used in multiple threads.
40// This might be a pattern you will want to use in your code, but most of the data you would be working
41// with in a complex codebase is likely going to be stored outside your functions.
42
43//-----------------------------------------
44// ABOUT THE CODING STYLE OF OUR DEMO CODE
45//-----------------------------------------
46// The Demo code in this file is designed to be easy to copy-and-paste into your application!
47// Because of this:
48// - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
49// - We try to declare static variables in the local scope, as close as possible to the code using them.
50// - We never use any of the helpers/facilities used internally by Dear ImGui, unless available in the public API.
51// - We never use maths operators on ImVec2/ImVec4. For our other sources files we use them, and they are provided
52// by imgui.h using the IMGUI_DEFINE_MATH_OPERATORS define. For your own sources file they are optional
53// and require you either enable those, either provide your own via IM_VEC2_CLASS_EXTRA in imconfig.h.
54// Because we can't assume anything about your support of maths operators, we cannot use them in imgui_demo.cpp.
55
56// Navigating this file:
57// - In Visual Studio IDE: CTRL+comma ("Edit.GoToAll") can follow symbols in comments, whereas CTRL+F12 ("Edit.GoToImplementation") cannot.
58// - With Visual Assist installed: ALT+G ("VAssistX.GoToImplementation") can also follow symbols in comments.
59
60/*
61
62Index of this file:
63
64// [SECTION] Forward Declarations
65// [SECTION] Helpers
66// [SECTION] Demo Window / ShowDemoWindow()
67// - ShowDemoWindow()
68// - sub section: ShowDemoWindowWidgets()
69// - sub section: ShowDemoWindowLayout()
70// - sub section: ShowDemoWindowPopups()
71// - sub section: ShowDemoWindowTables()
72// - sub section: ShowDemoWindowInputs()
73// [SECTION] About Window / ShowAboutWindow()
74// [SECTION] Style Editor / ShowStyleEditor()
75// [SECTION] User Guide / ShowUserGuide()
76// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
77// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
78// [SECTION] Example App: Debug Log / ShowExampleAppLog()
79// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
80// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
81// [SECTION] Example App: Long Text / ShowExampleAppLongText()
82// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
83// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
84// [SECTION] Example App: Simple overlay / ShowExampleAppSimpleOverlay()
85// [SECTION] Example App: Fullscreen window / ShowExampleAppFullscreen()
86// [SECTION] Example App: Manipulating window titles / ShowExampleAppWindowTitles()
87// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
88// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
89
90*/
91
92#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
93#define _CRT_SECURE_NO_WARNINGS
94#endif
95
96#include "imgui.h"
97#ifndef IMGUI_DISABLE
98
99// System includes
100#include <ctype.h> // toupper
101#include <limits.h> // INT_MIN, INT_MAX
102#include <math.h> // sqrtf, powf, cosf, sinf, floorf, ceilf
103#include <stdio.h> // vsnprintf, sscanf, printf
104#include <stdlib.h> // NULL, malloc, free, atoi
105#include <stdint.h> // intptr_t
106#if !defined(_MSC_VER) || _MSC_VER >= 1800
107#include <inttypes.h> // PRId64/PRIu64, not avail in some MinGW headers.
108#endif
109
110// Visual Studio warnings
111#ifdef _MSC_VER
112#pragma warning (disable: 4127) // condition expression is constant
113#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
114#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).
115#endif
116
117// Clang/GCC warnings with -Weverything
118#if defined(__clang__)
119#if __has_warning("-Wunknown-warning-option")
120#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!
121#endif
122#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
123#pragma clang diagnostic ignored "-Wold-style-cast" // warning: use of old-style cast // yes, they are more terse.
124#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)
125#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning: cast to 'void *' from smaller integer type
126#pragma clang diagnostic ignored "-Wformat-security" // warning: format string is not a string literal
127#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.
128#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.
129#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" // warning: zero as null pointer constant // some standard header variations use #define NULL 0
130#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.
131#pragma clang diagnostic ignored "-Wreserved-id-macro" // warning: macro name is a reserved identifier
132#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
133#elif defined(__GNUC__)
134#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
135#pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
136#pragma GCC diagnostic ignored "-Wformat-security" // warning: format string is not a string literal (potentially insecure)
137#pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
138#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
139#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.
140#endif
141
142// Play it nice with Windows users (Update: May 2018, Notepad now supports Unix-style carriage returns!)
143#ifdef _WIN32
144#define IM_NEWLINE "\r\n"
145#else
146#define IM_NEWLINE "\n"
147#endif
148
149// Helpers
150#if defined(_MSC_VER) && !defined(snprintf)
151#define snprintf _snprintf
152#endif
153#if defined(_MSC_VER) && !defined(vsnprintf)
154#define vsnprintf _vsnprintf
155#endif
156
157// Format specifiers for 64-bit values (hasn't been decently standardized before VS2013)
158#if !defined(PRId64) && defined(_MSC_VER)
159#define PRId64 "I64d"
160#define PRIu64 "I64u"
161#elif !defined(PRId64)
162#define PRId64 "lld"
163#define PRIu64 "llu"
164#endif
165
166// Helpers macros
167// We normally try to not use many helpers in imgui_demo.cpp in order to make code easier to copy and paste,
168// but making an exception here as those are largely simplifying code...
169// In other imgui sources we can use nicer internal functions from imgui_internal.h (ImMin/ImMax) but not in the demo.
170#define IM_MIN(A, B) (((A) < (B)) ? (A) : (B))
171#define IM_MAX(A, B) (((A) >= (B)) ? (A) : (B))
172#define IM_CLAMP(V, MN, MX) ((V) < (MN) ? (MN) : (V) > (MX) ? (MX) : (V))
173
174// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall
175#ifndef IMGUI_CDECL
176#ifdef _MSC_VER
177#define IMGUI_CDECL __cdecl
178#else
179#define IMGUI_CDECL
180#endif
181#endif
182
183//-----------------------------------------------------------------------------
184// [SECTION] Forward Declarations, Helpers
185//-----------------------------------------------------------------------------
186
187#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
188
189// Forward Declarations
190static void ShowExampleAppMainMenuBar();
191static void ShowExampleAppConsole(bool* p_open);
192static void ShowExampleAppCustomRendering(bool* p_open);
193static void ShowExampleAppDocuments(bool* p_open);
194static void ShowExampleAppLog(bool* p_open);
195static void ShowExampleAppLayout(bool* p_open);
196static void ShowExampleAppPropertyEditor(bool* p_open);
197static void ShowExampleAppSimpleOverlay(bool* p_open);
198static void ShowExampleAppAutoResize(bool* p_open);
199static void ShowExampleAppConstrainedResize(bool* p_open);
200static void ShowExampleAppFullscreen(bool* p_open);
201static void ShowExampleAppLongText(bool* p_open);
202static void ShowExampleAppWindowTitles(bool* p_open);
203static void ShowExampleMenuFile();
204
205// We split the contents of the big ShowDemoWindow() function into smaller functions
206// (because the link time of very large functions grow non-linearly)
207static void ShowDemoWindowWidgets();
208static void ShowDemoWindowLayout();
209static void ShowDemoWindowPopups();
210static void ShowDemoWindowTables();
211static void ShowDemoWindowColumns();
212static void ShowDemoWindowInputs();
213
214//-----------------------------------------------------------------------------
215// [SECTION] Helpers
216//-----------------------------------------------------------------------------
217
218// Helper to display a little (?) mark which shows a tooltip when hovered.
219// In your own code you may want to display an actual icon if you are using a merged icon fonts (see docs/FONTS.md)
220static void HelpMarker(const char* desc)
221{
222 ImGui::TextDisabled(fmt: "(?)");
223 if (ImGui::BeginItemTooltip())
224 {
225 ImGui::PushTextWrapPos(wrap_local_pos_x: ImGui::GetFontSize() * 35.0f);
226 ImGui::TextUnformatted(text: desc);
227 ImGui::PopTextWrapPos();
228 ImGui::EndTooltip();
229 }
230}
231
232// Helper to wire demo markers located in code to an interactive browser
233typedef void (*ImGuiDemoMarkerCallback)(const char* file, int line, const char* section, void* user_data);
234extern ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback;
235extern void* GImGuiDemoMarkerCallbackUserData;
236ImGuiDemoMarkerCallback GImGuiDemoMarkerCallback = NULL;
237void* GImGuiDemoMarkerCallbackUserData = NULL;
238#define IMGUI_DEMO_MARKER(section) do { if (GImGuiDemoMarkerCallback != NULL) GImGuiDemoMarkerCallback(__FILE__, __LINE__, section, GImGuiDemoMarkerCallbackUserData); } while (0)
239
240//-----------------------------------------------------------------------------
241// [SECTION] Demo Window / ShowDemoWindow()
242//-----------------------------------------------------------------------------
243// - ShowDemoWindow()
244// - ShowDemoWindowWidgets()
245// - ShowDemoWindowLayout()
246// - ShowDemoWindowPopups()
247// - ShowDemoWindowTables()
248// - ShowDemoWindowColumns()
249// - ShowDemoWindowInputs()
250//-----------------------------------------------------------------------------
251
252// Demonstrate most Dear ImGui features (this is big function!)
253// You may execute this function to experiment with the UI and understand what it does.
254// You may then search for keywords in the code when you are interested by a specific feature.
255void ImGui::ShowDemoWindow(bool* p_open)
256{
257 // Exceptionally add an extra assert here for people confused about initial Dear ImGui setup
258 // Most functions would normally just assert/crash if the context is missing.
259 IM_ASSERT(ImGui::GetCurrentContext() != NULL && "Missing Dear ImGui context. Refer to examples app!");
260
261 // Examples Apps (accessible from the "Examples" menu)
262 static bool show_app_main_menu_bar = false;
263 static bool show_app_console = false;
264 static bool show_app_custom_rendering = false;
265 static bool show_app_documents = false;
266 static bool show_app_log = false;
267 static bool show_app_layout = false;
268 static bool show_app_property_editor = false;
269 static bool show_app_simple_overlay = false;
270 static bool show_app_auto_resize = false;
271 static bool show_app_constrained_resize = false;
272 static bool show_app_fullscreen = false;
273 static bool show_app_long_text = false;
274 static bool show_app_window_titles = false;
275
276 if (show_app_main_menu_bar) ShowExampleAppMainMenuBar();
277 if (show_app_documents) ShowExampleAppDocuments(p_open: &show_app_documents);
278 if (show_app_console) ShowExampleAppConsole(p_open: &show_app_console);
279 if (show_app_custom_rendering) ShowExampleAppCustomRendering(p_open: &show_app_custom_rendering);
280 if (show_app_log) ShowExampleAppLog(p_open: &show_app_log);
281 if (show_app_layout) ShowExampleAppLayout(p_open: &show_app_layout);
282 if (show_app_property_editor) ShowExampleAppPropertyEditor(p_open: &show_app_property_editor);
283 if (show_app_simple_overlay) ShowExampleAppSimpleOverlay(p_open: &show_app_simple_overlay);
284 if (show_app_auto_resize) ShowExampleAppAutoResize(p_open: &show_app_auto_resize);
285 if (show_app_constrained_resize) ShowExampleAppConstrainedResize(p_open: &show_app_constrained_resize);
286 if (show_app_fullscreen) ShowExampleAppFullscreen(p_open: &show_app_fullscreen);
287 if (show_app_long_text) ShowExampleAppLongText(p_open: &show_app_long_text);
288 if (show_app_window_titles) ShowExampleAppWindowTitles(p_open: &show_app_window_titles);
289
290 // Dear ImGui Tools (accessible from the "Tools" menu)
291 static bool show_tool_metrics = false;
292 static bool show_tool_debug_log = false;
293 static bool show_tool_id_stack_tool = false;
294 static bool show_tool_style_editor = false;
295 static bool show_tool_about = false;
296
297 if (show_tool_metrics)
298 ImGui::ShowMetricsWindow(p_open: &show_tool_metrics);
299 if (show_tool_debug_log)
300 ImGui::ShowDebugLogWindow(p_open: &show_tool_debug_log);
301 if (show_tool_id_stack_tool)
302 ImGui::ShowIDStackToolWindow(p_open: &show_tool_id_stack_tool);
303 if (show_tool_style_editor)
304 {
305 ImGui::Begin(name: "Dear ImGui Style Editor", p_open: &show_tool_style_editor);
306 ImGui::ShowStyleEditor();
307 ImGui::End();
308 }
309 if (show_tool_about)
310 ImGui::ShowAboutWindow(p_open: &show_tool_about);
311
312 // Demonstrate the various window flags. Typically you would just use the default!
313 static bool no_titlebar = false;
314 static bool no_scrollbar = false;
315 static bool no_menu = false;
316 static bool no_move = false;
317 static bool no_resize = false;
318 static bool no_collapse = false;
319 static bool no_close = false;
320 static bool no_nav = false;
321 static bool no_background = false;
322 static bool no_bring_to_front = false;
323 static bool unsaved_document = false;
324
325 ImGuiWindowFlags window_flags = 0;
326 if (no_titlebar) window_flags |= ImGuiWindowFlags_NoTitleBar;
327 if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
328 if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
329 if (no_move) window_flags |= ImGuiWindowFlags_NoMove;
330 if (no_resize) window_flags |= ImGuiWindowFlags_NoResize;
331 if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
332 if (no_nav) window_flags |= ImGuiWindowFlags_NoNav;
333 if (no_background) window_flags |= ImGuiWindowFlags_NoBackground;
334 if (no_bring_to_front) window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
335 if (unsaved_document) window_flags |= ImGuiWindowFlags_UnsavedDocument;
336 if (no_close) p_open = NULL; // Don't pass our bool* to Begin
337
338 // We specify a default position/size in case there's no data in the .ini file.
339 // We only do it to make the demo applications a little more welcoming, but typically this isn't required.
340 const ImGuiViewport* main_viewport = ImGui::GetMainViewport();
341 ImGui::SetNextWindowPos(pos: ImVec2(main_viewport->WorkPos.x + 650, main_viewport->WorkPos.y + 20), cond: ImGuiCond_FirstUseEver);
342 ImGui::SetNextWindowSize(size: ImVec2(550, 680), cond: ImGuiCond_FirstUseEver);
343
344 // Main body of the Demo window starts here.
345 if (!ImGui::Begin(name: "Dear ImGui Demo", p_open, flags: window_flags))
346 {
347 // Early out if the window is collapsed, as an optimization.
348 ImGui::End();
349 return;
350 }
351
352 // Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
353 // e.g. Use 2/3 of the space for widgets and 1/3 for labels (right align)
354 //ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.35f);
355 // e.g. Leave a fixed amount of width for labels (by passing a negative value), the rest goes to widgets.
356 ImGui::PushItemWidth(item_width: ImGui::GetFontSize() * -12);
357
358 // Menu Bar
359 if (ImGui::BeginMenuBar())
360 {
361 if (ImGui::BeginMenu(label: "Menu"))
362 {
363 IMGUI_DEMO_MARKER("Menu/File");
364 ShowExampleMenuFile();
365 ImGui::EndMenu();
366 }
367 if (ImGui::BeginMenu(label: "Examples"))
368 {
369 IMGUI_DEMO_MARKER("Menu/Examples");
370 ImGui::MenuItem(label: "Main menu bar", NULL, p_selected: &show_app_main_menu_bar);
371
372 ImGui::SeparatorText(label: "Mini apps");
373 ImGui::MenuItem(label: "Console", NULL, p_selected: &show_app_console);
374 ImGui::MenuItem(label: "Custom rendering", NULL, p_selected: &show_app_custom_rendering);
375 ImGui::MenuItem(label: "Documents", NULL, p_selected: &show_app_documents);
376 ImGui::MenuItem(label: "Log", NULL, p_selected: &show_app_log);
377 ImGui::MenuItem(label: "Property editor", NULL, p_selected: &show_app_property_editor);
378 ImGui::MenuItem(label: "Simple layout", NULL, p_selected: &show_app_layout);
379 ImGui::MenuItem(label: "Simple overlay", NULL, p_selected: &show_app_simple_overlay);
380
381 ImGui::SeparatorText(label: "Concepts");
382 ImGui::MenuItem(label: "Auto-resizing window", NULL, p_selected: &show_app_auto_resize);
383 ImGui::MenuItem(label: "Constrained-resizing window", NULL, p_selected: &show_app_constrained_resize);
384 ImGui::MenuItem(label: "Fullscreen window", NULL, p_selected: &show_app_fullscreen);
385 ImGui::MenuItem(label: "Long text display", NULL, p_selected: &show_app_long_text);
386 ImGui::MenuItem(label: "Manipulating window titles", NULL, p_selected: &show_app_window_titles);
387
388 ImGui::EndMenu();
389 }
390 //if (ImGui::MenuItem("MenuItem")) {} // You can also use MenuItem() inside a menu bar!
391 if (ImGui::BeginMenu(label: "Tools"))
392 {
393 IMGUI_DEMO_MARKER("Menu/Tools");
394#ifndef IMGUI_DISABLE_DEBUG_TOOLS
395 const bool has_debug_tools = true;
396#else
397 const bool has_debug_tools = false;
398#endif
399 ImGui::MenuItem(label: "Metrics/Debugger", NULL, p_selected: &show_tool_metrics, enabled: has_debug_tools);
400 ImGui::MenuItem(label: "Debug Log", NULL, p_selected: &show_tool_debug_log, enabled: has_debug_tools);
401 ImGui::MenuItem(label: "ID Stack Tool", NULL, p_selected: &show_tool_id_stack_tool, enabled: has_debug_tools);
402 ImGui::MenuItem(label: "Style Editor", NULL, p_selected: &show_tool_style_editor);
403 ImGui::MenuItem(label: "About Dear ImGui", NULL, p_selected: &show_tool_about);
404 ImGui::EndMenu();
405 }
406 ImGui::EndMenuBar();
407 }
408
409 ImGui::Text(fmt: "dear imgui says hello! (%s) (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
410 ImGui::Spacing();
411
412 IMGUI_DEMO_MARKER("Help");
413 if (ImGui::CollapsingHeader(label: "Help"))
414 {
415 ImGui::SeparatorText(label: "ABOUT THIS DEMO:");
416 ImGui::BulletText(fmt: "Sections below are demonstrating many aspects of the library.");
417 ImGui::BulletText(fmt: "The \"Examples\" menu above leads to more demo contents.");
418 ImGui::BulletText(fmt: "The \"Tools\" menu above gives access to: About Box, Style Editor,\n"
419 "and Metrics/Debugger (general purpose Dear ImGui debugging tool).");
420
421 ImGui::SeparatorText(label: "PROGRAMMER GUIDE:");
422 ImGui::BulletText(fmt: "See the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
423 ImGui::BulletText(fmt: "See comments in imgui.cpp.");
424 ImGui::BulletText(fmt: "See example applications in the examples/ folder.");
425 ImGui::BulletText(fmt: "Read the FAQ at https://www.dearimgui.com/faq/");
426 ImGui::BulletText(fmt: "Set 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
427 ImGui::BulletText(fmt: "Set 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
428
429 ImGui::SeparatorText(label: "USER GUIDE:");
430 ImGui::ShowUserGuide();
431 }
432
433 IMGUI_DEMO_MARKER("Configuration");
434 if (ImGui::CollapsingHeader(label: "Configuration"))
435 {
436 ImGuiIO& io = ImGui::GetIO();
437
438 if (ImGui::TreeNode(label: "Configuration##2"))
439 {
440 ImGui::SeparatorText(label: "General");
441 ImGui::CheckboxFlags(label: "io.ConfigFlags: NavEnableKeyboard", flags: &io.ConfigFlags, flags_value: ImGuiConfigFlags_NavEnableKeyboard);
442 ImGui::SameLine(); HelpMarker(desc: "Enable keyboard controls.");
443 ImGui::CheckboxFlags(label: "io.ConfigFlags: NavEnableGamepad", flags: &io.ConfigFlags, flags_value: ImGuiConfigFlags_NavEnableGamepad);
444 ImGui::SameLine(); HelpMarker(desc: "Enable gamepad controls. Require backend to set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
445 ImGui::CheckboxFlags(label: "io.ConfigFlags: NavEnableSetMousePos", flags: &io.ConfigFlags, flags_value: ImGuiConfigFlags_NavEnableSetMousePos);
446 ImGui::SameLine(); HelpMarker(desc: "Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
447 ImGui::CheckboxFlags(label: "io.ConfigFlags: NoMouse", flags: &io.ConfigFlags, flags_value: ImGuiConfigFlags_NoMouse);
448 if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)
449 {
450 // The "NoMouse" option can get us stuck with a disabled mouse! Let's provide an alternative way to fix it:
451 if (fmodf(x: (float)ImGui::GetTime(), y: 0.40f) < 0.20f)
452 {
453 ImGui::SameLine();
454 ImGui::Text(fmt: "<<PRESS SPACE TO DISABLE>>");
455 }
456 if (ImGui::IsKeyPressed(key: ImGuiKey_Space))
457 io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
458 }
459 ImGui::CheckboxFlags(label: "io.ConfigFlags: NoMouseCursorChange", flags: &io.ConfigFlags, flags_value: ImGuiConfigFlags_NoMouseCursorChange);
460 ImGui::SameLine(); HelpMarker(desc: "Instruct backend to not alter mouse cursor shape and visibility.");
461 ImGui::Checkbox(label: "io.ConfigInputTrickleEventQueue", v: &io.ConfigInputTrickleEventQueue);
462 ImGui::SameLine(); HelpMarker(desc: "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.");
463 ImGui::Checkbox(label: "io.MouseDrawCursor", v: &io.MouseDrawCursor);
464 ImGui::SameLine(); HelpMarker(desc: "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).");
465
466 ImGui::SeparatorText(label: "Widgets");
467 ImGui::Checkbox(label: "io.ConfigInputTextCursorBlink", v: &io.ConfigInputTextCursorBlink);
468 ImGui::SameLine(); HelpMarker(desc: "Enable blinking cursor (optional as some users consider it to be distracting).");
469 ImGui::Checkbox(label: "io.ConfigInputTextEnterKeepActive", v: &io.ConfigInputTextEnterKeepActive);
470 ImGui::SameLine(); HelpMarker(desc: "Pressing Enter will keep item active and select contents (single-line only).");
471 ImGui::Checkbox(label: "io.ConfigDragClickToInputText", v: &io.ConfigDragClickToInputText);
472 ImGui::SameLine(); HelpMarker(desc: "Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving).");
473 ImGui::Checkbox(label: "io.ConfigWindowsResizeFromEdges", v: &io.ConfigWindowsResizeFromEdges);
474 ImGui::SameLine(); HelpMarker(desc: "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.");
475 ImGui::Checkbox(label: "io.ConfigWindowsMoveFromTitleBarOnly", v: &io.ConfigWindowsMoveFromTitleBarOnly);
476 ImGui::Checkbox(label: "io.ConfigMacOSXBehaviors", v: &io.ConfigMacOSXBehaviors);
477 ImGui::Text(fmt: "Also see Style->Rendering for rendering options.");
478
479 ImGui::SeparatorText(label: "Debug");
480 ImGui::BeginDisabled();
481 ImGui::Checkbox(label: "io.ConfigDebugBeginReturnValueOnce", v: &io.ConfigDebugBeginReturnValueOnce); // .
482 ImGui::EndDisabled();
483 ImGui::SameLine(); HelpMarker(desc: "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");
484 ImGui::Checkbox(label: "io.ConfigDebugBeginReturnValueLoop", v: &io.ConfigDebugBeginReturnValueLoop);
485 ImGui::SameLine(); HelpMarker(desc: "Some calls to Begin()/BeginChild() will return false.\n\nWill cycle through window depths then repeat. Windows should be flickering while running.");
486 ImGui::Checkbox(label: "io.ConfigDebugIgnoreFocusLoss", v: &io.ConfigDebugIgnoreFocusLoss);
487 ImGui::SameLine(); HelpMarker(desc: "Option to deactivate io.AddFocusEvent(false) handling. May facilitate interactions with a debugger when focus loss leads to clearing inputs data.");
488 ImGui::Checkbox(label: "io.ConfigDebugIniSettings", v: &io.ConfigDebugIniSettings);
489 ImGui::SameLine(); HelpMarker(desc: "Option to save .ini data with extra comments (particularly helpful for Docking, but makes saving slower).");
490
491 ImGui::TreePop();
492 ImGui::Spacing();
493 }
494
495 IMGUI_DEMO_MARKER("Configuration/Backend Flags");
496 if (ImGui::TreeNode(label: "Backend Flags"))
497 {
498 HelpMarker(
499 desc: "Those flags are set by the backends (imgui_impl_xxx files) to specify their capabilities.\n"
500 "Here we expose them as read-only fields to avoid breaking interactions with your backend.");
501
502 // FIXME: Maybe we need a BeginReadonly() equivalent to keep label bright?
503 ImGui::BeginDisabled();
504 ImGui::CheckboxFlags(label: "io.BackendFlags: HasGamepad", flags: &io.BackendFlags, flags_value: ImGuiBackendFlags_HasGamepad);
505 ImGui::CheckboxFlags(label: "io.BackendFlags: HasMouseCursors", flags: &io.BackendFlags, flags_value: ImGuiBackendFlags_HasMouseCursors);
506 ImGui::CheckboxFlags(label: "io.BackendFlags: HasSetMousePos", flags: &io.BackendFlags, flags_value: ImGuiBackendFlags_HasSetMousePos);
507 ImGui::CheckboxFlags(label: "io.BackendFlags: RendererHasVtxOffset", flags: &io.BackendFlags, flags_value: ImGuiBackendFlags_RendererHasVtxOffset);
508 ImGui::EndDisabled();
509 ImGui::TreePop();
510 ImGui::Spacing();
511 }
512
513 IMGUI_DEMO_MARKER("Configuration/Style");
514 if (ImGui::TreeNode(label: "Style"))
515 {
516 HelpMarker(desc: "The same contents can be accessed in 'Tools->Style Editor' or by calling the ShowStyleEditor() function.");
517 ImGui::ShowStyleEditor();
518 ImGui::TreePop();
519 ImGui::Spacing();
520 }
521
522 IMGUI_DEMO_MARKER("Configuration/Capture, Logging");
523 if (ImGui::TreeNode(label: "Capture/Logging"))
524 {
525 HelpMarker(
526 desc: "The logging API redirects all text output so you can easily capture the content of "
527 "a window or a block. Tree nodes can be automatically expanded.\n"
528 "Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
529 ImGui::LogButtons();
530
531 HelpMarker(desc: "You can also call ImGui::LogText() to output directly to the log without a visual output.");
532 if (ImGui::Button(label: "Copy \"Hello, world!\" to clipboard"))
533 {
534 ImGui::LogToClipboard();
535 ImGui::LogText(fmt: "Hello, world!");
536 ImGui::LogFinish();
537 }
538 ImGui::TreePop();
539 }
540 }
541
542 IMGUI_DEMO_MARKER("Window options");
543 if (ImGui::CollapsingHeader(label: "Window options"))
544 {
545 if (ImGui::BeginTable(str_id: "split", column: 3))
546 {
547 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No titlebar", v: &no_titlebar);
548 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No scrollbar", v: &no_scrollbar);
549 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No menu", v: &no_menu);
550 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No move", v: &no_move);
551 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No resize", v: &no_resize);
552 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No collapse", v: &no_collapse);
553 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No close", v: &no_close);
554 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No nav", v: &no_nav);
555 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No background", v: &no_background);
556 ImGui::TableNextColumn(); ImGui::Checkbox(label: "No bring to front", v: &no_bring_to_front);
557 ImGui::TableNextColumn(); ImGui::Checkbox(label: "Unsaved document", v: &unsaved_document);
558 ImGui::EndTable();
559 }
560 }
561
562 // All demo contents
563 ShowDemoWindowWidgets();
564 ShowDemoWindowLayout();
565 ShowDemoWindowPopups();
566 ShowDemoWindowTables();
567 ShowDemoWindowInputs();
568
569 // End of ShowDemoWindow()
570 ImGui::PopItemWidth();
571 ImGui::End();
572}
573
574static void ShowDemoWindowWidgets()
575{
576 IMGUI_DEMO_MARKER("Widgets");
577 if (!ImGui::CollapsingHeader(label: "Widgets"))
578 return;
579
580 static bool disable_all = false; // The Checkbox for that is inside the "Disabled" section at the bottom
581 if (disable_all)
582 ImGui::BeginDisabled();
583
584 IMGUI_DEMO_MARKER("Widgets/Basic");
585 if (ImGui::TreeNode(label: "Basic"))
586 {
587 ImGui::SeparatorText(label: "General");
588
589 IMGUI_DEMO_MARKER("Widgets/Basic/Button");
590 static int clicked = 0;
591 if (ImGui::Button(label: "Button"))
592 clicked++;
593 if (clicked & 1)
594 {
595 ImGui::SameLine();
596 ImGui::Text(fmt: "Thanks for clicking me!");
597 }
598
599 IMGUI_DEMO_MARKER("Widgets/Basic/Checkbox");
600 static bool check = true;
601 ImGui::Checkbox(label: "checkbox", v: &check);
602
603 IMGUI_DEMO_MARKER("Widgets/Basic/RadioButton");
604 static int e = 0;
605 ImGui::RadioButton(label: "radio a", v: &e, v_button: 0); ImGui::SameLine();
606 ImGui::RadioButton(label: "radio b", v: &e, v_button: 1); ImGui::SameLine();
607 ImGui::RadioButton(label: "radio c", v: &e, v_button: 2);
608
609 // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
610 IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Colored)");
611 for (int i = 0; i < 7; i++)
612 {
613 if (i > 0)
614 ImGui::SameLine();
615 ImGui::PushID(int_id: i);
616 ImGui::PushStyleColor(idx: ImGuiCol_Button, col: (ImVec4)ImColor::HSV(h: i / 7.0f, s: 0.6f, v: 0.6f));
617 ImGui::PushStyleColor(idx: ImGuiCol_ButtonHovered, col: (ImVec4)ImColor::HSV(h: i / 7.0f, s: 0.7f, v: 0.7f));
618 ImGui::PushStyleColor(idx: ImGuiCol_ButtonActive, col: (ImVec4)ImColor::HSV(h: i / 7.0f, s: 0.8f, v: 0.8f));
619 ImGui::Button(label: "Click");
620 ImGui::PopStyleColor(count: 3);
621 ImGui::PopID();
622 }
623
624 // Use AlignTextToFramePadding() to align text baseline to the baseline of framed widgets elements
625 // (otherwise a Text+SameLine+Button sequence will have the text a little too high by default!)
626 // See 'Demo->Layout->Text Baseline Alignment' for details.
627 ImGui::AlignTextToFramePadding();
628 ImGui::Text(fmt: "Hold to repeat:");
629 ImGui::SameLine();
630
631 // Arrow buttons with Repeater
632 IMGUI_DEMO_MARKER("Widgets/Basic/Buttons (Repeating)");
633 static int counter = 0;
634 float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
635 ImGui::PushButtonRepeat(repeat: true);
636 if (ImGui::ArrowButton(str_id: "##left", dir: ImGuiDir_Left)) { counter--; }
637 ImGui::SameLine(offset_from_start_x: 0.0f, spacing);
638 if (ImGui::ArrowButton(str_id: "##right", dir: ImGuiDir_Right)) { counter++; }
639 ImGui::PopButtonRepeat();
640 ImGui::SameLine();
641 ImGui::Text(fmt: "%d", counter);
642
643 ImGui::Button(label: "Tooltip");
644 ImGui::SetItemTooltip("I am a tooltip");
645
646 ImGui::LabelText(label: "label", fmt: "Value");
647
648 ImGui::SeparatorText(label: "Inputs");
649
650 {
651 // To wire InputText() with std::string or any other custom string type,
652 // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
653 IMGUI_DEMO_MARKER("Widgets/Basic/InputText");
654 static char str0[128] = "Hello, world!";
655 ImGui::InputText(label: "input text", buf: str0, IM_ARRAYSIZE(str0));
656 ImGui::SameLine(); HelpMarker(
657 desc: "USER:\n"
658 "Hold SHIFT or use mouse to select text.\n"
659 "CTRL+Left/Right to word jump.\n"
660 "CTRL+A or Double-Click to select all.\n"
661 "CTRL+X,CTRL+C,CTRL+V clipboard.\n"
662 "CTRL+Z,CTRL+Y undo/redo.\n"
663 "ESCAPE to revert.\n\n"
664 "PROGRAMMER:\n"
665 "You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() "
666 "to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated "
667 "in imgui_demo.cpp).");
668
669 static char str1[128] = "";
670 ImGui::InputTextWithHint(label: "input text (w/ hint)", hint: "enter text here", buf: str1, IM_ARRAYSIZE(str1));
671
672 IMGUI_DEMO_MARKER("Widgets/Basic/InputInt, InputFloat");
673 static int i0 = 123;
674 ImGui::InputInt(label: "input int", v: &i0);
675
676 static float f0 = 0.001f;
677 ImGui::InputFloat(label: "input float", v: &f0, step: 0.01f, step_fast: 1.0f, format: "%.3f");
678
679 static double d0 = 999999.00000001;
680 ImGui::InputDouble(label: "input double", v: &d0, step: 0.01f, step_fast: 1.0f, format: "%.8f");
681
682 static float f1 = 1.e10f;
683 ImGui::InputFloat(label: "input scientific", v: &f1, step: 0.0f, step_fast: 0.0f, format: "%e");
684 ImGui::SameLine(); HelpMarker(
685 desc: "You can input value using the scientific notation,\n"
686 " e.g. \"1e+8\" becomes \"100000000\".");
687
688 static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
689 ImGui::InputFloat3(label: "input float3", v: vec4a);
690 }
691
692 ImGui::SeparatorText(label: "Drags");
693
694 {
695 IMGUI_DEMO_MARKER("Widgets/Basic/DragInt, DragFloat");
696 static int i1 = 50, i2 = 42;
697 ImGui::DragInt(label: "drag int", v: &i1, v_speed: 1);
698 ImGui::SameLine(); HelpMarker(
699 desc: "Click and drag to edit value.\n"
700 "Hold SHIFT/ALT for faster/slower edit.\n"
701 "Double-click or CTRL+click to input value.");
702
703 ImGui::DragInt(label: "drag int 0..100", v: &i2, v_speed: 1, v_min: 0, v_max: 100, format: "%d%%", flags: ImGuiSliderFlags_AlwaysClamp);
704
705 static float f1 = 1.00f, f2 = 0.0067f;
706 ImGui::DragFloat(label: "drag float", v: &f1, v_speed: 0.005f);
707 ImGui::DragFloat(label: "drag small float", v: &f2, v_speed: 0.0001f, v_min: 0.0f, v_max: 0.0f, format: "%.06f ns");
708 }
709
710 ImGui::SeparatorText(label: "Sliders");
711
712 {
713 IMGUI_DEMO_MARKER("Widgets/Basic/SliderInt, SliderFloat");
714 static int i1 = 0;
715 ImGui::SliderInt(label: "slider int", v: &i1, v_min: -1, v_max: 3);
716 ImGui::SameLine(); HelpMarker(desc: "CTRL+click to input value.");
717
718 static float f1 = 0.123f, f2 = 0.0f;
719 ImGui::SliderFloat(label: "slider float", v: &f1, v_min: 0.0f, v_max: 1.0f, format: "ratio = %.3f");
720 ImGui::SliderFloat(label: "slider float (log)", v: &f2, v_min: -10.0f, v_max: 10.0f, format: "%.4f", flags: ImGuiSliderFlags_Logarithmic);
721
722 IMGUI_DEMO_MARKER("Widgets/Basic/SliderAngle");
723 static float angle = 0.0f;
724 ImGui::SliderAngle(label: "slider angle", v_rad: &angle);
725
726 // Using the format string to display a name instead of an integer.
727 // Here we completely omit '%d' from the format string, so it'll only display a name.
728 // This technique can also be used with DragInt().
729 IMGUI_DEMO_MARKER("Widgets/Basic/Slider (enum)");
730 enum Element { Element_Fire, Element_Earth, Element_Air, Element_Water, Element_COUNT };
731 static int elem = Element_Fire;
732 const char* elems_names[Element_COUNT] = { "Fire", "Earth", "Air", "Water" };
733 const char* elem_name = (elem >= 0 && elem < Element_COUNT) ? elems_names[elem] : "Unknown";
734 ImGui::SliderInt(label: "slider enum", v: &elem, v_min: 0, v_max: Element_COUNT - 1, format: elem_name); // Use ImGuiSliderFlags_NoInput flag to disable CTRL+Click here.
735 ImGui::SameLine(); HelpMarker(desc: "Using the format string parameter to display a name instead of the underlying integer.");
736 }
737
738 ImGui::SeparatorText(label: "Selectors/Pickers");
739
740 {
741 IMGUI_DEMO_MARKER("Widgets/Basic/ColorEdit3, ColorEdit4");
742 static float col1[3] = { 1.0f, 0.0f, 0.2f };
743 static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
744 ImGui::ColorEdit3(label: "color 1", col: col1);
745 ImGui::SameLine(); HelpMarker(
746 desc: "Click on the color square to open a color picker.\n"
747 "Click and hold to use drag and drop.\n"
748 "Right-click on the color square to show options.\n"
749 "CTRL+click on individual component to input value.\n");
750
751 ImGui::ColorEdit4(label: "color 2", col: col2);
752 }
753
754 {
755 // Using the _simplified_ one-liner Combo() api here
756 // See "Combo" section for examples of how to use the more flexible BeginCombo()/EndCombo() api.
757 IMGUI_DEMO_MARKER("Widgets/Basic/Combo");
758 const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIIIIII", "JJJJ", "KKKKKKK" };
759 static int item_current = 0;
760 ImGui::Combo(label: "combo", current_item: &item_current, items, IM_ARRAYSIZE(items));
761 ImGui::SameLine(); HelpMarker(
762 desc: "Using the simplified one-liner Combo API here.\nRefer to the \"Combo\" section below for an explanation of how to use the more flexible and general BeginCombo/EndCombo API.");
763 }
764
765 {
766 // Using the _simplified_ one-liner ListBox() api here
767 // See "List boxes" section for examples of how to use the more flexible BeginListBox()/EndListBox() api.
768 IMGUI_DEMO_MARKER("Widgets/Basic/ListBox");
769 const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
770 static int item_current = 1;
771 ImGui::ListBox(label: "listbox", current_item: &item_current, items, IM_ARRAYSIZE(items), height_in_items: 4);
772 ImGui::SameLine(); HelpMarker(
773 desc: "Using the simplified one-liner ListBox API here.\nRefer to the \"List boxes\" section below for an explanation of how to use the more flexible and general BeginListBox/EndListBox API.");
774 }
775
776 ImGui::TreePop();
777 }
778
779 IMGUI_DEMO_MARKER("Widgets/Tooltips");
780 if (ImGui::TreeNode(label: "Tooltips"))
781 {
782 // Tooltips are windows following the mouse. They do not take focus away.
783 ImGui::SeparatorText(label: "General");
784
785 // Typical use cases:
786 // - Short-form (text only): SetItemTooltip("Hello");
787 // - Short-form (any contents): if (BeginItemTooltip()) { Text("Hello"); EndTooltip(); }
788
789 // - Full-form (text only): if (IsItemHovered(...)) { SetTooltip("Hello"); }
790 // - Full-form (any contents): if (IsItemHovered(...) && BeginTooltip()) { Text("Hello"); EndTooltip(); }
791
792 HelpMarker(
793 desc: "Tooltip are typically created by using a IsItemHovered() + SetTooltip() sequence.\n\n"
794 "We provide a helper SetItemTooltip() function to perform the two with standards flags.");
795
796 ImVec2 sz = ImVec2(-FLT_MIN, 0.0f);
797
798 ImGui::Button(label: "Basic", size: sz);
799 ImGui::SetItemTooltip("I am a tooltip");
800
801 ImGui::Button(label: "Fancy", size: sz);
802 if (ImGui::BeginItemTooltip())
803 {
804 ImGui::Text(fmt: "I am a fancy tooltip");
805 static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
806 ImGui::PlotLines(label: "Curve", values: arr, IM_ARRAYSIZE(arr));
807 ImGui::Text(fmt: "Sin(time) = %f", sinf(x: (float)ImGui::GetTime()));
808 ImGui::EndTooltip();
809 }
810
811 ImGui::SeparatorText(label: "Always On");
812
813 // Showcase NOT relying on a IsItemHovered() to emit a tooltip.
814 // Here the tooltip is always emitted when 'always_on == true'.
815 static int always_on = 0;
816 ImGui::RadioButton(label: "Off", v: &always_on, v_button: 0);
817 ImGui::SameLine();
818 ImGui::RadioButton(label: "Always On (Simple)", v: &always_on, v_button: 1);
819 ImGui::SameLine();
820 ImGui::RadioButton(label: "Always On (Advanced)", v: &always_on, v_button: 2);
821 if (always_on == 1)
822 ImGui::SetTooltip("I am following you around.");
823 else if (always_on == 2 && ImGui::BeginTooltip())
824 {
825 ImGui::ProgressBar(fraction: sinf(x: (float)ImGui::GetTime()) * 0.5f + 0.5f, size_arg: ImVec2(ImGui::GetFontSize() * 25, 0.0f));
826 ImGui::EndTooltip();
827 }
828
829 ImGui::SeparatorText(label: "Custom");
830
831 HelpMarker(
832 desc: "Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() is the preferred way to standardize"
833 "tooltip activation details across your application. You may however decide to use custom"
834 "flags for a specific tooltip instance.");
835
836 // The following examples are passed for documentation purpose but may not be useful to most users.
837 // Passing ImGuiHoveredFlags_ForTooltip to IsItemHovered() will pull ImGuiHoveredFlags flags values from
838 // 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav' depending on whether mouse or gamepad/keyboard is being used.
839 // With default settings, ImGuiHoveredFlags_ForTooltip is equivalent to ImGuiHoveredFlags_DelayShort + ImGuiHoveredFlags_Stationary.
840 ImGui::Button(label: "Manual", size: sz);
841 if (ImGui::IsItemHovered(flags: ImGuiHoveredFlags_ForTooltip))
842 ImGui::SetTooltip("I am a manually emitted tooltip.");
843
844 ImGui::Button(label: "DelayNone", size: sz);
845 if (ImGui::IsItemHovered(flags: ImGuiHoveredFlags_DelayNone))
846 ImGui::SetTooltip("I am a tooltip with no delay.");
847
848 ImGui::Button(label: "DelayShort", size: sz);
849 if (ImGui::IsItemHovered(flags: ImGuiHoveredFlags_DelayShort | ImGuiHoveredFlags_NoSharedDelay))
850 ImGui::SetTooltip("I am a tooltip with a short delay (%0.2f sec).", ImGui::GetStyle().HoverDelayShort);
851
852 ImGui::Button(label: "DelayLong", size: sz);
853 if (ImGui::IsItemHovered(flags: ImGuiHoveredFlags_DelayNormal | ImGuiHoveredFlags_NoSharedDelay))
854 ImGui::SetTooltip("I am a tooltip with a long delay (%0.2f sec).", ImGui::GetStyle().HoverDelayNormal);
855
856 ImGui::Button(label: "Stationary", size: sz);
857 if (ImGui::IsItemHovered(flags: ImGuiHoveredFlags_Stationary))
858 ImGui::SetTooltip("I am a tooltip requiring mouse to be stationary before activating.");
859
860 // Using ImGuiHoveredFlags_ForTooltip will pull flags from 'style.HoverFlagsForTooltipMouse' or 'style.HoverFlagsForTooltipNav',
861 // which default value include the ImGuiHoveredFlags_AllowWhenDisabled flag.
862 // As a result, Set
863 ImGui::BeginDisabled();
864 ImGui::Button(label: "Disabled item", size: sz);
865 ImGui::EndDisabled();
866 if (ImGui::IsItemHovered(flags: ImGuiHoveredFlags_ForTooltip))
867 ImGui::SetTooltip("I am a a tooltip for a disabled item.");
868
869 ImGui::TreePop();
870 }
871
872 // Testing ImGuiOnceUponAFrame helper.
873 //static ImGuiOnceUponAFrame once;
874 //for (int i = 0; i < 5; i++)
875 // if (once)
876 // ImGui::Text("This will be displayed only once.");
877
878 IMGUI_DEMO_MARKER("Widgets/Tree Nodes");
879 if (ImGui::TreeNode(label: "Tree Nodes"))
880 {
881 IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees");
882 if (ImGui::TreeNode(label: "Basic trees"))
883 {
884 for (int i = 0; i < 5; i++)
885 {
886 // Use SetNextItemOpen() so set the default state of a node to be open. We could
887 // also use TreeNodeEx() with the ImGuiTreeNodeFlags_DefaultOpen flag to achieve the same thing!
888 if (i == 0)
889 ImGui::SetNextItemOpen(is_open: true, cond: ImGuiCond_Once);
890
891 if (ImGui::TreeNode(ptr_id: (void*)(intptr_t)i, fmt: "Child %d", i))
892 {
893 ImGui::Text(fmt: "blah blah");
894 ImGui::SameLine();
895 if (ImGui::SmallButton(label: "button")) {}
896 ImGui::TreePop();
897 }
898 }
899 ImGui::TreePop();
900 }
901
902 IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes");
903 if (ImGui::TreeNode(label: "Advanced, with Selectable nodes"))
904 {
905 HelpMarker(
906 desc: "This is a more typical looking tree with selectable nodes.\n"
907 "Click to select, CTRL+Click to toggle, click on arrows or double-click to open.");
908 static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
909 static bool align_label_with_current_x_position = false;
910 static bool test_drag_and_drop = false;
911 ImGui::CheckboxFlags(label: "ImGuiTreeNodeFlags_OpenOnArrow", flags: &base_flags, flags_value: ImGuiTreeNodeFlags_OpenOnArrow);
912 ImGui::CheckboxFlags(label: "ImGuiTreeNodeFlags_OpenOnDoubleClick", flags: &base_flags, flags_value: ImGuiTreeNodeFlags_OpenOnDoubleClick);
913 ImGui::CheckboxFlags(label: "ImGuiTreeNodeFlags_SpanAvailWidth", flags: &base_flags, flags_value: ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker(desc: "Extend hit area to all available width instead of allowing more items to be laid out after the node.");
914 ImGui::CheckboxFlags(label: "ImGuiTreeNodeFlags_SpanFullWidth", flags: &base_flags, flags_value: ImGuiTreeNodeFlags_SpanFullWidth);
915 ImGui::CheckboxFlags(label: "ImGuiTreeNodeFlags_SpanAllColumns", flags: &base_flags, flags_value: ImGuiTreeNodeFlags_SpanAllColumns); ImGui::SameLine(); HelpMarker(desc: "For use in Tables only.");
916 ImGui::Checkbox(label: "Align label with current X position", v: &align_label_with_current_x_position);
917 ImGui::Checkbox(label: "Test tree node as drag source", v: &test_drag_and_drop);
918 ImGui::Text(fmt: "Hello!");
919 if (align_label_with_current_x_position)
920 ImGui::Unindent(indent_w: ImGui::GetTreeNodeToLabelSpacing());
921
922 // 'selection_mask' is dumb representation of what may be user-side selection state.
923 // You may retain selection state inside or outside your objects in whatever format you see fit.
924 // 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
925 /// of the loop. May be a pointer to your own node type, etc.
926 static int selection_mask = (1 << 2);
927 int node_clicked = -1;
928 for (int i = 0; i < 6; i++)
929 {
930 // Disable the default "open on single-click behavior" + set Selected flag according to our selection.
931 // To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection.
932 ImGuiTreeNodeFlags node_flags = base_flags;
933 const bool is_selected = (selection_mask & (1 << i)) != 0;
934 if (is_selected)
935 node_flags |= ImGuiTreeNodeFlags_Selected;
936 if (i < 3)
937 {
938 // Items 0..2 are Tree Node
939 bool node_open = ImGui::TreeNodeEx(ptr_id: (void*)(intptr_t)i, flags: node_flags, fmt: "Selectable Node %d", i);
940 if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
941 node_clicked = i;
942 if (test_drag_and_drop && ImGui::BeginDragDropSource())
943 {
944 ImGui::SetDragDropPayload(type: "_TREENODE", NULL, sz: 0);
945 ImGui::Text(fmt: "This is a drag and drop source");
946 ImGui::EndDragDropSource();
947 }
948 if (node_open)
949 {
950 ImGui::BulletText(fmt: "Blah blah\nBlah Blah");
951 ImGui::TreePop();
952 }
953 }
954 else
955 {
956 // Items 3..5 are Tree Leaves
957 // The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
958 // use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
959 node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
960 ImGui::TreeNodeEx(ptr_id: (void*)(intptr_t)i, flags: node_flags, fmt: "Selectable Leaf %d", i);
961 if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
962 node_clicked = i;
963 if (test_drag_and_drop && ImGui::BeginDragDropSource())
964 {
965 ImGui::SetDragDropPayload(type: "_TREENODE", NULL, sz: 0);
966 ImGui::Text(fmt: "This is a drag and drop source");
967 ImGui::EndDragDropSource();
968 }
969 }
970 }
971 if (node_clicked != -1)
972 {
973 // Update selection state
974 // (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
975 if (ImGui::GetIO().KeyCtrl)
976 selection_mask ^= (1 << node_clicked); // CTRL+click to toggle
977 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
978 selection_mask = (1 << node_clicked); // Click to single-select
979 }
980 if (align_label_with_current_x_position)
981 ImGui::Indent(indent_w: ImGui::GetTreeNodeToLabelSpacing());
982 ImGui::TreePop();
983 }
984 ImGui::TreePop();
985 }
986
987 IMGUI_DEMO_MARKER("Widgets/Collapsing Headers");
988 if (ImGui::TreeNode(label: "Collapsing Headers"))
989 {
990 static bool closable_group = true;
991 ImGui::Checkbox(label: "Show 2nd header", v: &closable_group);
992 if (ImGui::CollapsingHeader(label: "Header", flags: ImGuiTreeNodeFlags_None))
993 {
994 ImGui::Text(fmt: "IsItemHovered: %d", ImGui::IsItemHovered());
995 for (int i = 0; i < 5; i++)
996 ImGui::Text(fmt: "Some content %d", i);
997 }
998 if (ImGui::CollapsingHeader(label: "Header with a close button", p_visible: &closable_group))
999 {
1000 ImGui::Text(fmt: "IsItemHovered: %d", ImGui::IsItemHovered());
1001 for (int i = 0; i < 5; i++)
1002 ImGui::Text(fmt: "More content %d", i);
1003 }
1004 /*
1005 if (ImGui::CollapsingHeader("Header with a bullet", ImGuiTreeNodeFlags_Bullet))
1006 ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
1007 */
1008 ImGui::TreePop();
1009 }
1010
1011 IMGUI_DEMO_MARKER("Widgets/Bullets");
1012 if (ImGui::TreeNode(label: "Bullets"))
1013 {
1014 ImGui::BulletText(fmt: "Bullet point 1");
1015 ImGui::BulletText(fmt: "Bullet point 2\nOn multiple lines");
1016 if (ImGui::TreeNode(label: "Tree node"))
1017 {
1018 ImGui::BulletText(fmt: "Another bullet point");
1019 ImGui::TreePop();
1020 }
1021 ImGui::Bullet(); ImGui::Text(fmt: "Bullet point 3 (two calls)");
1022 ImGui::Bullet(); ImGui::SmallButton(label: "Button");
1023 ImGui::TreePop();
1024 }
1025
1026 IMGUI_DEMO_MARKER("Widgets/Text");
1027 if (ImGui::TreeNode(label: "Text"))
1028 {
1029 IMGUI_DEMO_MARKER("Widgets/Text/Colored Text");
1030 if (ImGui::TreeNode(label: "Colorful Text"))
1031 {
1032 // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
1033 ImGui::TextColored(col: ImVec4(1.0f, 0.0f, 1.0f, 1.0f), fmt: "Pink");
1034 ImGui::TextColored(col: ImVec4(1.0f, 1.0f, 0.0f, 1.0f), fmt: "Yellow");
1035 ImGui::TextDisabled(fmt: "Disabled");
1036 ImGui::SameLine(); HelpMarker(desc: "The TextDisabled color is stored in ImGuiStyle.");
1037 ImGui::TreePop();
1038 }
1039
1040 IMGUI_DEMO_MARKER("Widgets/Text/Word Wrapping");
1041 if (ImGui::TreeNode(label: "Word Wrapping"))
1042 {
1043 // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
1044 ImGui::TextWrapped(
1045 fmt: "This text should automatically wrap on the edge of the window. The current implementation "
1046 "for text wrapping follows simple rules suitable for English and possibly other languages.");
1047 ImGui::Spacing();
1048
1049 static float wrap_width = 200.0f;
1050 ImGui::SliderFloat(label: "Wrap width", v: &wrap_width, v_min: -20, v_max: 600, format: "%.0f");
1051
1052 ImDrawList* draw_list = ImGui::GetWindowDrawList();
1053 for (int n = 0; n < 2; n++)
1054 {
1055 ImGui::Text(fmt: "Test paragraph %d:", n);
1056 ImVec2 pos = ImGui::GetCursorScreenPos();
1057 ImVec2 marker_min = ImVec2(pos.x + wrap_width, pos.y);
1058 ImVec2 marker_max = ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight());
1059 ImGui::PushTextWrapPos(wrap_local_pos_x: ImGui::GetCursorPos().x + wrap_width);
1060 if (n == 0)
1061 ImGui::Text(fmt: "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);
1062 else
1063 ImGui::Text(fmt: "aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
1064
1065 // Draw actual text bounding box, following by marker of our expected limit (should not overlap!)
1066 draw_list->AddRect(p_min: ImGui::GetItemRectMin(), p_max: ImGui::GetItemRectMax(), IM_COL32(255, 255, 0, 255));
1067 draw_list->AddRectFilled(p_min: marker_min, p_max: marker_max, IM_COL32(255, 0, 255, 255));
1068 ImGui::PopTextWrapPos();
1069 }
1070
1071 ImGui::TreePop();
1072 }
1073
1074 IMGUI_DEMO_MARKER("Widgets/Text/UTF-8 Text");
1075 if (ImGui::TreeNode(label: "UTF-8 Text"))
1076 {
1077 // UTF-8 test with Japanese characters
1078 // (Needs a suitable font? Try "Google Noto" or "Arial Unicode". See docs/FONTS.md for details.)
1079 // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
1080 // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. in Visual Studio, you
1081 // can save your source files as 'UTF-8 without signature').
1082 // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8
1083 // CHARACTERS IN THIS SOURCE FILE. Instead we are encoding a few strings with hexadecimal constants.
1084 // Don't do this in your application! Please use u8"text in any language" in your application!
1085 // Note that characters values are preserved even by InputText() if the font cannot be displayed,
1086 // so you can safely copy & paste garbled characters into another application.
1087 ImGui::TextWrapped(
1088 fmt: "CJK text will only appear if the font was loaded with the appropriate CJK character ranges. "
1089 "Call io.Fonts->AddFontFromFileTTF() manually to load extra character ranges. "
1090 "Read docs/FONTS.md for details.");
1091 ImGui::Text(fmt: "Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
1092 ImGui::Text(fmt: "Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
1093 static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
1094 //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
1095 ImGui::InputText(label: "UTF-8 input", buf, IM_ARRAYSIZE(buf));
1096 ImGui::TreePop();
1097 }
1098 ImGui::TreePop();
1099 }
1100
1101 IMGUI_DEMO_MARKER("Widgets/Images");
1102 if (ImGui::TreeNode(label: "Images"))
1103 {
1104 ImGuiIO& io = ImGui::GetIO();
1105 ImGui::TextWrapped(
1106 fmt: "Below we are displaying the font texture (which is the only texture we have access to in this demo). "
1107 "Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. "
1108 "Hover the texture for a zoomed view!");
1109
1110 // Below we are displaying the font texture because it is the only texture we have access to inside the demo!
1111 // Remember that ImTextureID is just storage for whatever you want it to be. It is essentially a value that
1112 // will be passed to the rendering backend via the ImDrawCmd structure.
1113 // If you use one of the default imgui_impl_XXXX.cpp rendering backend, they all have comments at the top
1114 // of their respective source file to specify what they expect to be stored in ImTextureID, for example:
1115 // - The imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer
1116 // - The imgui_impl_opengl3.cpp renderer expect a GLuint OpenGL texture identifier, etc.
1117 // More:
1118 // - If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers
1119 // to ImGui::Image(), and gather width/height through your own functions, etc.
1120 // - You can use ShowMetricsWindow() to inspect the draw data that are being passed to your renderer,
1121 // it will help you debug issues if you are confused about it.
1122 // - Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
1123 // - Read https://github.com/ocornut/imgui/blob/master/docs/FAQ.md
1124 // - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
1125 ImTextureID my_tex_id = io.Fonts->TexID;
1126 float my_tex_w = (float)io.Fonts->TexWidth;
1127 float my_tex_h = (float)io.Fonts->TexHeight;
1128 {
1129 static bool use_text_color_for_tint = false;
1130 ImGui::Checkbox(label: "Use Text Color for Tint", v: &use_text_color_for_tint);
1131 ImGui::Text(fmt: "%.0fx%.0f", my_tex_w, my_tex_h);
1132 ImVec2 pos = ImGui::GetCursorScreenPos();
1133 ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
1134 ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
1135 ImVec4 tint_col = use_text_color_for_tint ? ImGui::GetStyleColorVec4(idx: ImGuiCol_Text) : ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
1136 ImVec4 border_col = ImGui::GetStyleColorVec4(idx: ImGuiCol_Border);
1137 ImGui::Image(user_texture_id: my_tex_id, size: ImVec2(my_tex_w, my_tex_h), uv0: uv_min, uv1: uv_max, tint_col, border_col);
1138 if (ImGui::BeginItemTooltip())
1139 {
1140 float region_sz = 32.0f;
1141 float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
1142 float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
1143 float zoom = 4.0f;
1144 if (region_x < 0.0f) { region_x = 0.0f; }
1145 else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
1146 if (region_y < 0.0f) { region_y = 0.0f; }
1147 else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
1148 ImGui::Text(fmt: "Min: (%.2f, %.2f)", region_x, region_y);
1149 ImGui::Text(fmt: "Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
1150 ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
1151 ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
1152 ImGui::Image(user_texture_id: my_tex_id, size: ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, tint_col, border_col);
1153 ImGui::EndTooltip();
1154 }
1155 }
1156
1157 IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons");
1158 ImGui::TextWrapped(fmt: "And now some textured buttons..");
1159 static int pressed_count = 0;
1160 for (int i = 0; i < 8; i++)
1161 {
1162 // UV coordinates are often (0.0f, 0.0f) and (1.0f, 1.0f) to display an entire textures.
1163 // Here are trying to display only a 32x32 pixels area of the texture, hence the UV computation.
1164 // Read about UV coordinates here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
1165 ImGui::PushID(int_id: i);
1166 if (i > 0)
1167 ImGui::PushStyleVar(idx: ImGuiStyleVar_FramePadding, val: ImVec2(i - 1.0f, i - 1.0f));
1168 ImVec2 size = ImVec2(32.0f, 32.0f); // Size of the image we want to make visible
1169 ImVec2 uv0 = ImVec2(0.0f, 0.0f); // UV coordinates for lower-left
1170 ImVec2 uv1 = ImVec2(32.0f / my_tex_w, 32.0f / my_tex_h); // UV coordinates for (32,32) in our texture
1171 ImVec4 bg_col = ImVec4(0.0f, 0.0f, 0.0f, 1.0f); // Black background
1172 ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // No tint
1173 if (ImGui::ImageButton(str_id: "", user_texture_id: my_tex_id, image_size: size, uv0, uv1, bg_col, tint_col))
1174 pressed_count += 1;
1175 if (i > 0)
1176 ImGui::PopStyleVar();
1177 ImGui::PopID();
1178 ImGui::SameLine();
1179 }
1180 ImGui::NewLine();
1181 ImGui::Text(fmt: "Pressed %d times.", pressed_count);
1182 ImGui::TreePop();
1183 }
1184
1185 IMGUI_DEMO_MARKER("Widgets/Combo");
1186 if (ImGui::TreeNode(label: "Combo"))
1187 {
1188 // Combo Boxes are also called "Dropdown" in other systems
1189 // Expose flags as checkbox for the demo
1190 static ImGuiComboFlags flags = 0;
1191 ImGui::CheckboxFlags(label: "ImGuiComboFlags_PopupAlignLeft", flags: &flags, flags_value: ImGuiComboFlags_PopupAlignLeft);
1192 ImGui::SameLine(); HelpMarker(desc: "Only makes a difference if the popup is larger than the combo");
1193 if (ImGui::CheckboxFlags(label: "ImGuiComboFlags_NoArrowButton", flags: &flags, flags_value: ImGuiComboFlags_NoArrowButton))
1194 flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both
1195 if (ImGui::CheckboxFlags(label: "ImGuiComboFlags_NoPreview", flags: &flags, flags_value: ImGuiComboFlags_NoPreview))
1196 flags &= ~(ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_WidthFitPreview); // Clear the other flag, as we cannot combine both
1197 if (ImGui::CheckboxFlags(label: "ImGuiComboFlags_WidthFitPreview", flags: &flags, flags_value: ImGuiComboFlags_WidthFitPreview))
1198 flags &= ~ImGuiComboFlags_NoPreview;
1199
1200 // Override default popup height
1201 if (ImGui::CheckboxFlags(label: "ImGuiComboFlags_HeightSmall", flags: &flags, flags_value: ImGuiComboFlags_HeightSmall))
1202 flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightSmall);
1203 if (ImGui::CheckboxFlags(label: "ImGuiComboFlags_HeightRegular", flags: &flags, flags_value: ImGuiComboFlags_HeightRegular))
1204 flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightRegular);
1205 if (ImGui::CheckboxFlags(label: "ImGuiComboFlags_HeightLargest", flags: &flags, flags_value: ImGuiComboFlags_HeightLargest))
1206 flags &= ~(ImGuiComboFlags_HeightMask_ & ~ImGuiComboFlags_HeightLargest);
1207
1208 // Using the generic BeginCombo() API, you have full control over how to display the combo contents.
1209 // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
1210 // stored in the object itself, etc.)
1211 const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
1212 static int item_current_idx = 0; // Here we store our selection data as an index.
1213 const char* combo_preview_value = items[item_current_idx]; // Pass in the preview value visible before opening the combo (it could be anything)
1214 if (ImGui::BeginCombo(label: "combo 1", preview_value: combo_preview_value, flags))
1215 {
1216 for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1217 {
1218 const bool is_selected = (item_current_idx == n);
1219 if (ImGui::Selectable(label: items[n], selected: is_selected))
1220 item_current_idx = n;
1221
1222 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1223 if (is_selected)
1224 ImGui::SetItemDefaultFocus();
1225 }
1226 ImGui::EndCombo();
1227 }
1228
1229 ImGui::Spacing();
1230 ImGui::SeparatorText(label: "One-liner variants");
1231 HelpMarker(desc: "Flags above don't apply to this section.");
1232
1233 // Simplified one-liner Combo() API, using values packed in a single constant string
1234 // This is a convenience for when the selection set is small and known at compile-time.
1235 static int item_current_2 = 0;
1236 ImGui::Combo(label: "combo 2 (one-liner)", current_item: &item_current_2, items_separated_by_zeros: "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
1237
1238 // Simplified one-liner Combo() using an array of const char*
1239 // This is not very useful (may obsolete): prefer using BeginCombo()/EndCombo() for full control.
1240 static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
1241 ImGui::Combo(label: "combo 3 (array)", current_item: &item_current_3, items, IM_ARRAYSIZE(items));
1242
1243 // Simplified one-liner Combo() using an accessor function
1244 static int item_current_4 = 0;
1245 ImGui::Combo(label: "combo 4 (function)", current_item: &item_current_4, getter: [](void* data, int n) { return ((const char**)data)[n]; }, user_data: items, IM_ARRAYSIZE(items));
1246
1247 ImGui::TreePop();
1248 }
1249
1250 IMGUI_DEMO_MARKER("Widgets/List Boxes");
1251 if (ImGui::TreeNode(label: "List boxes"))
1252 {
1253 // BeginListBox() is essentially a thin wrapper to using BeginChild()/EndChild() with the ImGuiChildFlags_FrameStyle flag for stylistic changes + displaying a label.
1254 // You may be tempted to simply use BeginChild() directly, however note that BeginChild() requires EndChild() to always be called (inconsistent with BeginListBox()/EndListBox()).
1255
1256 // Using the generic BeginListBox() API, you have full control over how to display the combo contents.
1257 // (your selection data could be an index, a pointer to the object, an id for the object, a flag intrusively
1258 // stored in the object itself, etc.)
1259 const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
1260 static int item_current_idx = 0; // Here we store our selection data as an index.
1261 if (ImGui::BeginListBox(label: "listbox 1"))
1262 {
1263 for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1264 {
1265 const bool is_selected = (item_current_idx == n);
1266 if (ImGui::Selectable(label: items[n], selected: is_selected))
1267 item_current_idx = n;
1268
1269 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1270 if (is_selected)
1271 ImGui::SetItemDefaultFocus();
1272 }
1273 ImGui::EndListBox();
1274 }
1275
1276 // Custom size: use all width, 5 items tall
1277 ImGui::Text(fmt: "Full-width:");
1278 if (ImGui::BeginListBox(label: "##listbox 2", size: ImVec2(-FLT_MIN, 5 * ImGui::GetTextLineHeightWithSpacing())))
1279 {
1280 for (int n = 0; n < IM_ARRAYSIZE(items); n++)
1281 {
1282 const bool is_selected = (item_current_idx == n);
1283 if (ImGui::Selectable(label: items[n], selected: is_selected))
1284 item_current_idx = n;
1285
1286 // Set the initial focus when opening the combo (scrolling + keyboard navigation focus)
1287 if (is_selected)
1288 ImGui::SetItemDefaultFocus();
1289 }
1290 ImGui::EndListBox();
1291 }
1292
1293 ImGui::TreePop();
1294 }
1295
1296 IMGUI_DEMO_MARKER("Widgets/Selectables");
1297 if (ImGui::TreeNode(label: "Selectables"))
1298 {
1299 // Selectable() has 2 overloads:
1300 // - The one taking "bool selected" as a read-only selection information.
1301 // When Selectable() has been clicked it returns true and you can alter selection state accordingly.
1302 // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
1303 // The earlier is more flexible, as in real application your selection may be stored in many different ways
1304 // and not necessarily inside a bool value (e.g. in flags within objects, as an external list, etc).
1305 IMGUI_DEMO_MARKER("Widgets/Selectables/Basic");
1306 if (ImGui::TreeNode(label: "Basic"))
1307 {
1308 static bool selection[5] = { false, true, false, false };
1309 ImGui::Selectable(label: "1. I am selectable", p_selected: &selection[0]);
1310 ImGui::Selectable(label: "2. I am selectable", p_selected: &selection[1]);
1311 ImGui::Selectable(label: "3. I am selectable", p_selected: &selection[2]);
1312 if (ImGui::Selectable(label: "4. I am double clickable", selected: selection[3], flags: ImGuiSelectableFlags_AllowDoubleClick))
1313 if (ImGui::IsMouseDoubleClicked(button: 0))
1314 selection[3] = !selection[3];
1315 ImGui::TreePop();
1316 }
1317
1318 IMGUI_DEMO_MARKER("Widgets/Selectables/Single Selection");
1319 if (ImGui::TreeNode(label: "Selection State: Single Selection"))
1320 {
1321 static int selected = -1;
1322 for (int n = 0; n < 5; n++)
1323 {
1324 char buf[32];
1325 sprintf(s: buf, format: "Object %d", n);
1326 if (ImGui::Selectable(label: buf, selected: selected == n))
1327 selected = n;
1328 }
1329 ImGui::TreePop();
1330 }
1331 IMGUI_DEMO_MARKER("Widgets/Selectables/Multiple Selection");
1332 if (ImGui::TreeNode(label: "Selection State: Multiple Selection"))
1333 {
1334 HelpMarker(desc: "Hold CTRL and click to select multiple items.");
1335 static bool selection[5] = { false, false, false, false, false };
1336 for (int n = 0; n < 5; n++)
1337 {
1338 char buf[32];
1339 sprintf(s: buf, format: "Object %d", n);
1340 if (ImGui::Selectable(label: buf, selected: selection[n]))
1341 {
1342 if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held
1343 memset(s: selection, c: 0, n: sizeof(selection));
1344 selection[n] ^= 1;
1345 }
1346 }
1347 ImGui::TreePop();
1348 }
1349 IMGUI_DEMO_MARKER("Widgets/Selectables/Rendering more items on the same line");
1350 if (ImGui::TreeNode(label: "Rendering more items on the same line"))
1351 {
1352 // (1) Using SetNextItemAllowOverlap()
1353 // (2) Using the Selectable() override that takes "bool* p_selected" parameter, the bool value is toggled automatically.
1354 static bool selected[3] = { false, false, false };
1355 ImGui::SetNextItemAllowOverlap(); ImGui::Selectable(label: "main.c", p_selected: &selected[0]); ImGui::SameLine(); ImGui::SmallButton(label: "Link 1");
1356 ImGui::SetNextItemAllowOverlap(); ImGui::Selectable(label: "Hello.cpp", p_selected: &selected[1]); ImGui::SameLine(); ImGui::SmallButton(label: "Link 2");
1357 ImGui::SetNextItemAllowOverlap(); ImGui::Selectable(label: "Hello.h", p_selected: &selected[2]); ImGui::SameLine(); ImGui::SmallButton(label: "Link 3");
1358 ImGui::TreePop();
1359 }
1360
1361 IMGUI_DEMO_MARKER("Widgets/Selectables/In columns");
1362 if (ImGui::TreeNode(label: "In columns"))
1363 {
1364 static bool selected[10] = {};
1365
1366 if (ImGui::BeginTable(str_id: "split1", column: 3, flags: ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
1367 {
1368 for (int i = 0; i < 10; i++)
1369 {
1370 char label[32];
1371 sprintf(s: label, format: "Item %d", i);
1372 ImGui::TableNextColumn();
1373 ImGui::Selectable(label, p_selected: &selected[i]); // FIXME-TABLE: Selection overlap
1374 }
1375 ImGui::EndTable();
1376 }
1377 ImGui::Spacing();
1378 if (ImGui::BeginTable(str_id: "split2", column: 3, flags: ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings | ImGuiTableFlags_Borders))
1379 {
1380 for (int i = 0; i < 10; i++)
1381 {
1382 char label[32];
1383 sprintf(s: label, format: "Item %d", i);
1384 ImGui::TableNextRow();
1385 ImGui::TableNextColumn();
1386 ImGui::Selectable(label, p_selected: &selected[i], flags: ImGuiSelectableFlags_SpanAllColumns);
1387 ImGui::TableNextColumn();
1388 ImGui::Text(fmt: "Some other contents");
1389 ImGui::TableNextColumn();
1390 ImGui::Text(fmt: "123456");
1391 }
1392 ImGui::EndTable();
1393 }
1394 ImGui::TreePop();
1395 }
1396
1397 IMGUI_DEMO_MARKER("Widgets/Selectables/Grid");
1398 if (ImGui::TreeNode(label: "Grid"))
1399 {
1400 static char selected[4][4] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 }, { 0, 0, 0, 1 } };
1401
1402 // Add in a bit of silly fun...
1403 const float time = (float)ImGui::GetTime();
1404 const bool winning_state = memchr(s: selected, c: 0, n: sizeof(selected)) == NULL; // If all cells are selected...
1405 if (winning_state)
1406 ImGui::PushStyleVar(idx: ImGuiStyleVar_SelectableTextAlign, val: ImVec2(0.5f + 0.5f * cosf(x: time * 2.0f), 0.5f + 0.5f * sinf(x: time * 3.0f)));
1407
1408 for (int y = 0; y < 4; y++)
1409 for (int x = 0; x < 4; x++)
1410 {
1411 if (x > 0)
1412 ImGui::SameLine();
1413 ImGui::PushID(int_id: y * 4 + x);
1414 if (ImGui::Selectable(label: "Sailor", selected: selected[y][x] != 0, flags: 0, size: ImVec2(50, 50)))
1415 {
1416 // Toggle clicked cell + toggle neighbors
1417 selected[y][x] ^= 1;
1418 if (x > 0) { selected[y][x - 1] ^= 1; }
1419 if (x < 3) { selected[y][x + 1] ^= 1; }
1420 if (y > 0) { selected[y - 1][x] ^= 1; }
1421 if (y < 3) { selected[y + 1][x] ^= 1; }
1422 }
1423 ImGui::PopID();
1424 }
1425
1426 if (winning_state)
1427 ImGui::PopStyleVar();
1428 ImGui::TreePop();
1429 }
1430 IMGUI_DEMO_MARKER("Widgets/Selectables/Alignment");
1431 if (ImGui::TreeNode(label: "Alignment"))
1432 {
1433 HelpMarker(
1434 desc: "By default, Selectables uses style.SelectableTextAlign but it can be overridden on a per-item "
1435 "basis using PushStyleVar(). You'll probably want to always keep your default situation to "
1436 "left-align otherwise it becomes difficult to layout multiple items on a same line");
1437 static bool selected[3 * 3] = { true, false, true, false, true, false, true, false, true };
1438 for (int y = 0; y < 3; y++)
1439 {
1440 for (int x = 0; x < 3; x++)
1441 {
1442 ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
1443 char name[32];
1444 sprintf(s: name, format: "(%.1f,%.1f)", alignment.x, alignment.y);
1445 if (x > 0) ImGui::SameLine();
1446 ImGui::PushStyleVar(idx: ImGuiStyleVar_SelectableTextAlign, val: alignment);
1447 ImGui::Selectable(label: name, p_selected: &selected[3 * y + x], flags: ImGuiSelectableFlags_None, size: ImVec2(80, 80));
1448 ImGui::PopStyleVar();
1449 }
1450 }
1451 ImGui::TreePop();
1452 }
1453 ImGui::TreePop();
1454 }
1455
1456 // To wire InputText() with std::string or any other custom string type,
1457 // see the "Text Input > Resize Callback" section of this demo, and the misc/cpp/imgui_stdlib.h file.
1458 IMGUI_DEMO_MARKER("Widgets/Text Input");
1459 if (ImGui::TreeNode(label: "Text Input"))
1460 {
1461 IMGUI_DEMO_MARKER("Widgets/Text Input/Multi-line Text Input");
1462 if (ImGui::TreeNode(label: "Multi-line Text Input"))
1463 {
1464 // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
1465 // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
1466 static char text[1024 * 16] =
1467 "/*\n"
1468 " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
1469 " the hexadecimal encoding of one offending instruction,\n"
1470 " more formally, the invalid operand with locked CMPXCHG8B\n"
1471 " instruction bug, is a design flaw in the majority of\n"
1472 " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
1473 " processors (all in the P5 microarchitecture).\n"
1474 "*/\n\n"
1475 "label:\n"
1476 "\tlock cmpxchg8b eax\n";
1477
1478 static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
1479 HelpMarker(desc: "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)");
1480 ImGui::CheckboxFlags(label: "ImGuiInputTextFlags_ReadOnly", flags: &flags, flags_value: ImGuiInputTextFlags_ReadOnly);
1481 ImGui::CheckboxFlags(label: "ImGuiInputTextFlags_AllowTabInput", flags: &flags, flags_value: ImGuiInputTextFlags_AllowTabInput);
1482 ImGui::CheckboxFlags(label: "ImGuiInputTextFlags_CtrlEnterForNewLine", flags: &flags, flags_value: ImGuiInputTextFlags_CtrlEnterForNewLine);
1483 ImGui::InputTextMultiline(label: "##source", buf: text, IM_ARRAYSIZE(text), size: ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
1484 ImGui::TreePop();
1485 }
1486
1487 IMGUI_DEMO_MARKER("Widgets/Text Input/Filtered Text Input");
1488 if (ImGui::TreeNode(label: "Filtered Text Input"))
1489 {
1490 struct TextFilters
1491 {
1492 // Modify character input by altering 'data->Eventchar' (ImGuiInputTextFlags_CallbackCharFilter callback)
1493 static int FilterCasingSwap(ImGuiInputTextCallbackData* data)
1494 {
1495 if (data->EventChar >= 'a' && data->EventChar <= 'z') { data->EventChar -= 'a' - 'A'; } // Lowercase becomes uppercase
1496 else if (data->EventChar >= 'A' && data->EventChar <= 'Z') { data->EventChar += 'a' - 'A'; } // Uppercase becomes lowercase
1497 return 0;
1498 }
1499
1500 // Return 0 (pass) if the character is 'i' or 'm' or 'g' or 'u' or 'i', otherwise return 1 (filter out)
1501 static int FilterImGuiLetters(ImGuiInputTextCallbackData* data)
1502 {
1503 if (data->EventChar < 256 && strchr(s: "imgui", c: (char)data->EventChar))
1504 return 0;
1505 return 1;
1506 }
1507 };
1508
1509 static char buf1[32] = ""; ImGui::InputText(label: "default", buf: buf1, buf_size: 32);
1510 static char buf2[32] = ""; ImGui::InputText(label: "decimal", buf: buf2, buf_size: 32, flags: ImGuiInputTextFlags_CharsDecimal);
1511 static char buf3[32] = ""; ImGui::InputText(label: "hexadecimal", buf: buf3, buf_size: 32, flags: ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
1512 static char buf4[32] = ""; ImGui::InputText(label: "uppercase", buf: buf4, buf_size: 32, flags: ImGuiInputTextFlags_CharsUppercase);
1513 static char buf5[32] = ""; ImGui::InputText(label: "no blank", buf: buf5, buf_size: 32, flags: ImGuiInputTextFlags_CharsNoBlank);
1514 static char buf6[32] = ""; ImGui::InputText(label: "casing swap", buf: buf6, buf_size: 32, flags: ImGuiInputTextFlags_CallbackCharFilter, callback: TextFilters::FilterCasingSwap); // Use CharFilter callback to replace characters.
1515 static char buf7[32] = ""; ImGui::InputText(label: "\"imgui\"", buf: buf7, buf_size: 32, flags: ImGuiInputTextFlags_CallbackCharFilter, callback: TextFilters::FilterImGuiLetters); // Use CharFilter callback to disable some characters.
1516 ImGui::TreePop();
1517 }
1518
1519 IMGUI_DEMO_MARKER("Widgets/Text Input/Password input");
1520 if (ImGui::TreeNode(label: "Password Input"))
1521 {
1522 static char password[64] = "password123";
1523 ImGui::InputText(label: "password", buf: password, IM_ARRAYSIZE(password), flags: ImGuiInputTextFlags_Password);
1524 ImGui::SameLine(); HelpMarker(desc: "Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
1525 ImGui::InputTextWithHint(label: "password (w/ hint)", hint: "<password>", buf: password, IM_ARRAYSIZE(password), flags: ImGuiInputTextFlags_Password);
1526 ImGui::InputText(label: "password (clear)", buf: password, IM_ARRAYSIZE(password));
1527 ImGui::TreePop();
1528 }
1529
1530 IMGUI_DEMO_MARKER("Widgets/Text Input/Completion, History, Edit Callbacks");
1531 if (ImGui::TreeNode(label: "Completion, History, Edit Callbacks"))
1532 {
1533 struct Funcs
1534 {
1535 static int MyCallback(ImGuiInputTextCallbackData* data)
1536 {
1537 if (data->EventFlag == ImGuiInputTextFlags_CallbackCompletion)
1538 {
1539 data->InsertChars(pos: data->CursorPos, text: "..");
1540 }
1541 else if (data->EventFlag == ImGuiInputTextFlags_CallbackHistory)
1542 {
1543 if (data->EventKey == ImGuiKey_UpArrow)
1544 {
1545 data->DeleteChars(pos: 0, bytes_count: data->BufTextLen);
1546 data->InsertChars(pos: 0, text: "Pressed Up!");
1547 data->SelectAll();
1548 }
1549 else if (data->EventKey == ImGuiKey_DownArrow)
1550 {
1551 data->DeleteChars(pos: 0, bytes_count: data->BufTextLen);
1552 data->InsertChars(pos: 0, text: "Pressed Down!");
1553 data->SelectAll();
1554 }
1555 }
1556 else if (data->EventFlag == ImGuiInputTextFlags_CallbackEdit)
1557 {
1558 // Toggle casing of first character
1559 char c = data->Buf[0];
1560 if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) data->Buf[0] ^= 32;
1561 data->BufDirty = true;
1562
1563 // Increment a counter
1564 int* p_int = (int*)data->UserData;
1565 *p_int = *p_int + 1;
1566 }
1567 return 0;
1568 }
1569 };
1570 static char buf1[64];
1571 ImGui::InputText(label: "Completion", buf: buf1, buf_size: 64, flags: ImGuiInputTextFlags_CallbackCompletion, callback: Funcs::MyCallback);
1572 ImGui::SameLine(); HelpMarker(desc: "Here we append \"..\" each time Tab is pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
1573
1574 static char buf2[64];
1575 ImGui::InputText(label: "History", buf: buf2, buf_size: 64, flags: ImGuiInputTextFlags_CallbackHistory, callback: Funcs::MyCallback);
1576 ImGui::SameLine(); HelpMarker(desc: "Here we replace and select text each time Up/Down are pressed. See 'Examples>Console' for a more meaningful demonstration of using this callback.");
1577
1578 static char buf3[64];
1579 static int edit_count = 0;
1580 ImGui::InputText(label: "Edit", buf: buf3, buf_size: 64, flags: ImGuiInputTextFlags_CallbackEdit, callback: Funcs::MyCallback, user_data: (void*)&edit_count);
1581 ImGui::SameLine(); HelpMarker(desc: "Here we toggle the casing of the first character on every edit + count edits.");
1582 ImGui::SameLine(); ImGui::Text(fmt: "(%d)", edit_count);
1583
1584 ImGui::TreePop();
1585 }
1586
1587 IMGUI_DEMO_MARKER("Widgets/Text Input/Resize Callback");
1588 if (ImGui::TreeNode(label: "Resize Callback"))
1589 {
1590 // To wire InputText() with std::string or any other custom string type,
1591 // you can use the ImGuiInputTextFlags_CallbackResize flag + create a custom ImGui::InputText() wrapper
1592 // using your preferred type. See misc/cpp/imgui_stdlib.h for an implementation of this using std::string.
1593 HelpMarker(
1594 desc: "Using ImGuiInputTextFlags_CallbackResize to wire your custom string type to InputText().\n\n"
1595 "See misc/cpp/imgui_stdlib.h for an implementation of this for std::string.");
1596 struct Funcs
1597 {
1598 static int MyResizeCallback(ImGuiInputTextCallbackData* data)
1599 {
1600 if (data->EventFlag == ImGuiInputTextFlags_CallbackResize)
1601 {
1602 ImVector<char>* my_str = (ImVector<char>*)data->UserData;
1603 IM_ASSERT(my_str->begin() == data->Buf);
1604 my_str->resize(new_size: data->BufSize); // NB: On resizing calls, generally data->BufSize == data->BufTextLen + 1
1605 data->Buf = my_str->begin();
1606 }
1607 return 0;
1608 }
1609
1610 // Note: Because ImGui:: is a namespace you would typically add your own function into the namespace.
1611 // For example, you code may declare a function 'ImGui::InputText(const char* label, MyString* my_str)'
1612 static bool MyInputTextMultiline(const char* label, ImVector<char>* my_str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0)
1613 {
1614 IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0);
1615 return ImGui::InputTextMultiline(label, buf: my_str->begin(), buf_size: (size_t)my_str->size(), size, flags: flags | ImGuiInputTextFlags_CallbackResize, callback: Funcs::MyResizeCallback, user_data: (void*)my_str);
1616 }
1617 };
1618
1619 // For this demo we are using ImVector as a string container.
1620 // Note that because we need to store a terminating zero character, our size/capacity are 1 more
1621 // than usually reported by a typical string class.
1622 static ImVector<char> my_str;
1623 if (my_str.empty())
1624 my_str.push_back(v: 0);
1625 Funcs::MyInputTextMultiline(label: "##MyStr", my_str: &my_str, size: ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16));
1626 ImGui::Text(fmt: "Data: %p\nSize: %d\nCapacity: %d", (void*)my_str.begin(), my_str.size(), my_str.capacity());
1627 ImGui::TreePop();
1628 }
1629
1630 IMGUI_DEMO_MARKER("Widgets/Text Input/Miscellaneous");
1631 if (ImGui::TreeNode(label: "Miscellaneous"))
1632 {
1633 static char buf1[16];
1634 static ImGuiInputTextFlags flags = ImGuiInputTextFlags_EscapeClearsAll;
1635 ImGui::CheckboxFlags(label: "ImGuiInputTextFlags_EscapeClearsAll", flags: &flags, flags_value: ImGuiInputTextFlags_EscapeClearsAll);
1636 ImGui::CheckboxFlags(label: "ImGuiInputTextFlags_ReadOnly", flags: &flags, flags_value: ImGuiInputTextFlags_ReadOnly);
1637 ImGui::CheckboxFlags(label: "ImGuiInputTextFlags_NoUndoRedo", flags: &flags, flags_value: ImGuiInputTextFlags_NoUndoRedo);
1638 ImGui::InputText(label: "Hello", buf: buf1, IM_ARRAYSIZE(buf1), flags);
1639 ImGui::TreePop();
1640 }
1641
1642 ImGui::TreePop();
1643 }
1644
1645 // Tabs
1646 IMGUI_DEMO_MARKER("Widgets/Tabs");
1647 if (ImGui::TreeNode(label: "Tabs"))
1648 {
1649 IMGUI_DEMO_MARKER("Widgets/Tabs/Basic");
1650 if (ImGui::TreeNode(label: "Basic"))
1651 {
1652 ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
1653 if (ImGui::BeginTabBar(str_id: "MyTabBar", flags: tab_bar_flags))
1654 {
1655 if (ImGui::BeginTabItem(label: "Avocado"))
1656 {
1657 ImGui::Text(fmt: "This is the Avocado tab!\nblah blah blah blah blah");
1658 ImGui::EndTabItem();
1659 }
1660 if (ImGui::BeginTabItem(label: "Broccoli"))
1661 {
1662 ImGui::Text(fmt: "This is the Broccoli tab!\nblah blah blah blah blah");
1663 ImGui::EndTabItem();
1664 }
1665 if (ImGui::BeginTabItem(label: "Cucumber"))
1666 {
1667 ImGui::Text(fmt: "This is the Cucumber tab!\nblah blah blah blah blah");
1668 ImGui::EndTabItem();
1669 }
1670 ImGui::EndTabBar();
1671 }
1672 ImGui::Separator();
1673 ImGui::TreePop();
1674 }
1675
1676 IMGUI_DEMO_MARKER("Widgets/Tabs/Advanced & Close Button");
1677 if (ImGui::TreeNode(label: "Advanced & Close Button"))
1678 {
1679 // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
1680 static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
1681 ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_Reorderable", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_Reorderable);
1682 ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_AutoSelectNewTabs", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_AutoSelectNewTabs);
1683 ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_TabListPopupButton", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_TabListPopupButton);
1684 ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
1685 if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
1686 tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
1687 if (ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_FittingPolicyResizeDown", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_FittingPolicyResizeDown))
1688 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
1689 if (ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_FittingPolicyScroll", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_FittingPolicyScroll))
1690 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
1691
1692 // Tab Bar
1693 const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
1694 static bool opened[4] = { true, true, true, true }; // Persistent user state
1695 for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1696 {
1697 if (n > 0) { ImGui::SameLine(); }
1698 ImGui::Checkbox(label: names[n], v: &opened[n]);
1699 }
1700
1701 // Passing a bool* to BeginTabItem() is similar to passing one to Begin():
1702 // the underlying bool will be set to false when the tab is closed.
1703 if (ImGui::BeginTabBar(str_id: "MyTabBar", flags: tab_bar_flags))
1704 {
1705 for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1706 if (opened[n] && ImGui::BeginTabItem(label: names[n], p_open: &opened[n], flags: ImGuiTabItemFlags_None))
1707 {
1708 ImGui::Text(fmt: "This is the %s tab!", names[n]);
1709 if (n & 1)
1710 ImGui::Text(fmt: "I am an odd tab.");
1711 ImGui::EndTabItem();
1712 }
1713 ImGui::EndTabBar();
1714 }
1715 ImGui::Separator();
1716 ImGui::TreePop();
1717 }
1718
1719 IMGUI_DEMO_MARKER("Widgets/Tabs/TabItemButton & Leading-Trailing flags");
1720 if (ImGui::TreeNode(label: "TabItemButton & Leading/Trailing flags"))
1721 {
1722 static ImVector<int> active_tabs;
1723 static int next_tab_id = 0;
1724 if (next_tab_id == 0) // Initialize with some default tabs
1725 for (int i = 0; i < 3; i++)
1726 active_tabs.push_back(v: next_tab_id++);
1727
1728 // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together.
1729 // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags...
1730 // but they tend to make more sense together)
1731 static bool show_leading_button = true;
1732 static bool show_trailing_button = true;
1733 ImGui::Checkbox(label: "Show Leading TabItemButton()", v: &show_leading_button);
1734 ImGui::Checkbox(label: "Show Trailing TabItemButton()", v: &show_trailing_button);
1735
1736 // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs
1737 static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown;
1738 ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_TabListPopupButton", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_TabListPopupButton);
1739 if (ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_FittingPolicyResizeDown", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_FittingPolicyResizeDown))
1740 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
1741 if (ImGui::CheckboxFlags(label: "ImGuiTabBarFlags_FittingPolicyScroll", flags: &tab_bar_flags, flags_value: ImGuiTabBarFlags_FittingPolicyScroll))
1742 tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
1743
1744 if (ImGui::BeginTabBar(str_id: "MyTabBar", flags: tab_bar_flags))
1745 {
1746 // Demo a Leading TabItemButton(): click the "?" button to open a menu
1747 if (show_leading_button)
1748 if (ImGui::TabItemButton(label: "?", flags: ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip))
1749 ImGui::OpenPopup(str_id: "MyHelpMenu");
1750 if (ImGui::BeginPopup(str_id: "MyHelpMenu"))
1751 {
1752 ImGui::Selectable(label: "Hello!");
1753 ImGui::EndPopup();
1754 }
1755
1756 // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+")
1757 // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end.
1758 if (show_trailing_button)
1759 if (ImGui::TabItemButton(label: "+", flags: ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip))
1760 active_tabs.push_back(v: next_tab_id++); // Add new tab
1761
1762 // Submit our regular tabs
1763 for (int n = 0; n < active_tabs.Size; )
1764 {
1765 bool open = true;
1766 char name[16];
1767 snprintf(s: name, IM_ARRAYSIZE(name), format: "%04d", active_tabs[n]);
1768 if (ImGui::BeginTabItem(label: name, p_open: &open, flags: ImGuiTabItemFlags_None))
1769 {
1770 ImGui::Text(fmt: "This is the %s tab!", name);
1771 ImGui::EndTabItem();
1772 }
1773
1774 if (!open)
1775 active_tabs.erase(it: active_tabs.Data + n);
1776 else
1777 n++;
1778 }
1779
1780 ImGui::EndTabBar();
1781 }
1782 ImGui::Separator();
1783 ImGui::TreePop();
1784 }
1785 ImGui::TreePop();
1786 }
1787
1788 // Plot/Graph widgets are not very good.
1789 // Consider using a third-party library such as ImPlot: https://github.com/epezent/implot
1790 // (see others https://github.com/ocornut/imgui/wiki/Useful-Extensions)
1791 IMGUI_DEMO_MARKER("Widgets/Plotting");
1792 if (ImGui::TreeNode(label: "Plotting"))
1793 {
1794 static bool animate = true;
1795 ImGui::Checkbox(label: "Animate", v: &animate);
1796
1797 // Plot as lines and plot as histogram
1798 IMGUI_DEMO_MARKER("Widgets/Plotting/PlotLines, PlotHistogram");
1799 static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
1800 ImGui::PlotLines(label: "Frame Times", values: arr, IM_ARRAYSIZE(arr));
1801 ImGui::PlotHistogram(label: "Histogram", values: arr, IM_ARRAYSIZE(arr), values_offset: 0, NULL, scale_min: 0.0f, scale_max: 1.0f, graph_size: ImVec2(0, 80.0f));
1802
1803 // Fill an array of contiguous float values to plot
1804 // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float
1805 // and the sizeof() of your structure in the "stride" parameter.
1806 static float values[90] = {};
1807 static int values_offset = 0;
1808 static double refresh_time = 0.0;
1809 if (!animate || refresh_time == 0.0)
1810 refresh_time = ImGui::GetTime();
1811 while (refresh_time < ImGui::GetTime()) // Create data at fixed 60 Hz rate for the demo
1812 {
1813 static float phase = 0.0f;
1814 values[values_offset] = cosf(x: phase);
1815 values_offset = (values_offset + 1) % IM_ARRAYSIZE(values);
1816 phase += 0.10f * values_offset;
1817 refresh_time += 1.0f / 60.0f;
1818 }
1819
1820 // Plots can display overlay texts
1821 // (in this example, we will display an average value)
1822 {
1823 float average = 0.0f;
1824 for (int n = 0; n < IM_ARRAYSIZE(values); n++)
1825 average += values[n];
1826 average /= (float)IM_ARRAYSIZE(values);
1827 char overlay[32];
1828 sprintf(s: overlay, format: "avg %f", average);
1829 ImGui::PlotLines(label: "Lines", values, IM_ARRAYSIZE(values), values_offset, overlay_text: overlay, scale_min: -1.0f, scale_max: 1.0f, graph_size: ImVec2(0, 80.0f));
1830 }
1831
1832 // Use functions to generate output
1833 // FIXME: This is actually VERY awkward because current plot API only pass in indices.
1834 // We probably want an API passing floats and user provide sample rate/count.
1835 struct Funcs
1836 {
1837 static float Sin(void*, int i) { return sinf(x: i * 0.1f); }
1838 static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
1839 };
1840 static int func_type = 0, display_count = 70;
1841 ImGui::SeparatorText(label: "Functions");
1842 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
1843 ImGui::Combo(label: "func", current_item: &func_type, items_separated_by_zeros: "Sin\0Saw\0");
1844 ImGui::SameLine();
1845 ImGui::SliderInt(label: "Sample count", v: &display_count, v_min: 1, v_max: 400);
1846 float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
1847 ImGui::PlotLines(label: "Lines", values_getter: func, NULL, values_count: display_count, values_offset: 0, NULL, scale_min: -1.0f, scale_max: 1.0f, graph_size: ImVec2(0, 80));
1848 ImGui::PlotHistogram(label: "Histogram", values_getter: func, NULL, values_count: display_count, values_offset: 0, NULL, scale_min: -1.0f, scale_max: 1.0f, graph_size: ImVec2(0, 80));
1849 ImGui::Separator();
1850
1851 // Animate a simple progress bar
1852 IMGUI_DEMO_MARKER("Widgets/Plotting/ProgressBar");
1853 static float progress = 0.0f, progress_dir = 1.0f;
1854 if (animate)
1855 {
1856 progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
1857 if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
1858 if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
1859 }
1860
1861 // Typically we would use ImVec2(-1.0f,0.0f) or ImVec2(-FLT_MIN,0.0f) to use all available width,
1862 // or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
1863 ImGui::ProgressBar(fraction: progress, size_arg: ImVec2(0.0f, 0.0f));
1864 ImGui::SameLine(offset_from_start_x: 0.0f, spacing: ImGui::GetStyle().ItemInnerSpacing.x);
1865 ImGui::Text(fmt: "Progress Bar");
1866
1867 float progress_saturated = IM_CLAMP(progress, 0.0f, 1.0f);
1868 char buf[32];
1869 sprintf(s: buf, format: "%d/%d", (int)(progress_saturated * 1753), 1753);
1870 ImGui::ProgressBar(fraction: progress, size_arg: ImVec2(0.f, 0.f), overlay: buf);
1871 ImGui::TreePop();
1872 }
1873
1874 IMGUI_DEMO_MARKER("Widgets/Color");
1875 if (ImGui::TreeNode(label: "Color/Picker Widgets"))
1876 {
1877 static ImVec4 color = ImVec4(114.0f / 255.0f, 144.0f / 255.0f, 154.0f / 255.0f, 200.0f / 255.0f);
1878
1879 static bool alpha_preview = true;
1880 static bool alpha_half_preview = false;
1881 static bool drag_and_drop = true;
1882 static bool options_menu = true;
1883 static bool hdr = false;
1884 ImGui::SeparatorText(label: "Options");
1885 ImGui::Checkbox(label: "With Alpha Preview", v: &alpha_preview);
1886 ImGui::Checkbox(label: "With Half Alpha Preview", v: &alpha_half_preview);
1887 ImGui::Checkbox(label: "With Drag and Drop", v: &drag_and_drop);
1888 ImGui::Checkbox(label: "With Options Menu", v: &options_menu); ImGui::SameLine(); HelpMarker(desc: "Right-click on the individual color widget to show options.");
1889 ImGui::Checkbox(label: "With HDR", v: &hdr); ImGui::SameLine(); HelpMarker(desc: "Currently all this does is to lift the 0..1 limits on dragging widgets.");
1890 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);
1891
1892 IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit");
1893 ImGui::SeparatorText(label: "Inline color editor");
1894 ImGui::Text(fmt: "Color widget:");
1895 ImGui::SameLine(); HelpMarker(
1896 desc: "Click on the color square to open a color picker.\n"
1897 "CTRL+click on individual component to input value.\n");
1898 ImGui::ColorEdit3(label: "MyColor##1", col: (float*)&color, flags: misc_flags);
1899
1900 IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (HSV, with Alpha)");
1901 ImGui::Text(fmt: "Color widget HSV with Alpha:");
1902 ImGui::ColorEdit4(label: "MyColor##2", col: (float*)&color, flags: ImGuiColorEditFlags_DisplayHSV | misc_flags);
1903
1904 IMGUI_DEMO_MARKER("Widgets/Color/ColorEdit (float display)");
1905 ImGui::Text(fmt: "Color widget with Float Display:");
1906 ImGui::ColorEdit4(label: "MyColor##2f", col: (float*)&color, flags: ImGuiColorEditFlags_Float | misc_flags);
1907
1908 IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with Picker)");
1909 ImGui::Text(fmt: "Color button with Picker:");
1910 ImGui::SameLine(); HelpMarker(
1911 desc: "With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\n"
1912 "With the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only "
1913 "be used for the tooltip and picker popup.");
1914 ImGui::ColorEdit4(label: "MyColor##3", col: (float*)&color, flags: ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
1915
1916 IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (with custom Picker popup)");
1917 ImGui::Text(fmt: "Color button with Custom Picker Popup:");
1918
1919 // Generate a default palette. The palette will persist and can be edited.
1920 static bool saved_palette_init = true;
1921 static ImVec4 saved_palette[32] = {};
1922 if (saved_palette_init)
1923 {
1924 for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1925 {
1926 ImGui::ColorConvertHSVtoRGB(h: n / 31.0f, s: 0.8f, v: 0.8f,
1927 out_r&: saved_palette[n].x, out_g&: saved_palette[n].y, out_b&: saved_palette[n].z);
1928 saved_palette[n].w = 1.0f; // Alpha
1929 }
1930 saved_palette_init = false;
1931 }
1932
1933 static ImVec4 backup_color;
1934 bool open_popup = ImGui::ColorButton(desc_id: "MyColor##3b", col: color, flags: misc_flags);
1935 ImGui::SameLine(offset_from_start_x: 0, spacing: ImGui::GetStyle().ItemInnerSpacing.x);
1936 open_popup |= ImGui::Button(label: "Palette");
1937 if (open_popup)
1938 {
1939 ImGui::OpenPopup(str_id: "mypicker");
1940 backup_color = color;
1941 }
1942 if (ImGui::BeginPopup(str_id: "mypicker"))
1943 {
1944 ImGui::Text(fmt: "MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
1945 ImGui::Separator();
1946 ImGui::ColorPicker4(label: "##picker", col: (float*)&color, flags: misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
1947 ImGui::SameLine();
1948
1949 ImGui::BeginGroup(); // Lock X position
1950 ImGui::Text(fmt: "Current");
1951 ImGui::ColorButton(desc_id: "##current", col: color, flags: ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, size: ImVec2(60, 40));
1952 ImGui::Text(fmt: "Previous");
1953 if (ImGui::ColorButton(desc_id: "##previous", col: backup_color, flags: ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, size: ImVec2(60, 40)))
1954 color = backup_color;
1955 ImGui::Separator();
1956 ImGui::Text(fmt: "Palette");
1957 for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1958 {
1959 ImGui::PushID(int_id: n);
1960 if ((n % 8) != 0)
1961 ImGui::SameLine(offset_from_start_x: 0.0f, spacing: ImGui::GetStyle().ItemSpacing.y);
1962
1963 ImGuiColorEditFlags palette_button_flags = ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip;
1964 if (ImGui::ColorButton(desc_id: "##palette", col: saved_palette[n], flags: palette_button_flags, size: ImVec2(20, 20)))
1965 color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
1966
1967 // Allow user to drop colors into each palette entry. Note that ColorButton() is already a
1968 // drag source by default, unless specifying the ImGuiColorEditFlags_NoDragDrop flag.
1969 if (ImGui::BeginDragDropTarget())
1970 {
1971 if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
1972 memcpy(dest: (float*)&saved_palette[n], src: payload->Data, n: sizeof(float) * 3);
1973 if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
1974 memcpy(dest: (float*)&saved_palette[n], src: payload->Data, n: sizeof(float) * 4);
1975 ImGui::EndDragDropTarget();
1976 }
1977
1978 ImGui::PopID();
1979 }
1980 ImGui::EndGroup();
1981 ImGui::EndPopup();
1982 }
1983
1984 IMGUI_DEMO_MARKER("Widgets/Color/ColorButton (simple)");
1985 ImGui::Text(fmt: "Color button only:");
1986 static bool no_border = false;
1987 ImGui::Checkbox(label: "ImGuiColorEditFlags_NoBorder", v: &no_border);
1988 ImGui::ColorButton(desc_id: "MyColor##3c", col: *(ImVec4*)&color, flags: misc_flags | (no_border ? ImGuiColorEditFlags_NoBorder : 0), size: ImVec2(80, 80));
1989
1990 IMGUI_DEMO_MARKER("Widgets/Color/ColorPicker");
1991 ImGui::SeparatorText(label: "Color picker");
1992 static bool alpha = true;
1993 static bool alpha_bar = true;
1994 static bool side_preview = true;
1995 static bool ref_color = false;
1996 static ImVec4 ref_color_v(1.0f, 0.0f, 1.0f, 0.5f);
1997 static int display_mode = 0;
1998 static int picker_mode = 0;
1999 ImGui::Checkbox(label: "With Alpha", v: &alpha);
2000 ImGui::Checkbox(label: "With Alpha Bar", v: &alpha_bar);
2001 ImGui::Checkbox(label: "With Side Preview", v: &side_preview);
2002 if (side_preview)
2003 {
2004 ImGui::SameLine();
2005 ImGui::Checkbox(label: "With Ref Color", v: &ref_color);
2006 if (ref_color)
2007 {
2008 ImGui::SameLine();
2009 ImGui::ColorEdit4(label: "##RefColor", col: &ref_color_v.x, flags: ImGuiColorEditFlags_NoInputs | misc_flags);
2010 }
2011 }
2012 ImGui::Combo(label: "Display Mode", current_item: &display_mode, items_separated_by_zeros: "Auto/Current\0None\0RGB Only\0HSV Only\0Hex Only\0");
2013 ImGui::SameLine(); HelpMarker(
2014 desc: "ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
2015 "but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
2016 "if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
2017 ImGui::SameLine(); HelpMarker(desc: "When not specified explicitly (Auto/Current mode), user can right-click the picker to change mode.");
2018 ImGuiColorEditFlags flags = misc_flags;
2019 if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
2020 if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
2021 if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
2022 if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
2023 if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
2024 if (display_mode == 1) flags |= ImGuiColorEditFlags_NoInputs; // Disable all RGB/HSV/Hex displays
2025 if (display_mode == 2) flags |= ImGuiColorEditFlags_DisplayRGB; // Override display mode
2026 if (display_mode == 3) flags |= ImGuiColorEditFlags_DisplayHSV;
2027 if (display_mode == 4) flags |= ImGuiColorEditFlags_DisplayHex;
2028 ImGui::ColorPicker4(label: "MyColor##4", col: (float*)&color, flags, ref_col: ref_color ? &ref_color_v.x : NULL);
2029
2030 ImGui::Text(fmt: "Set defaults in code:");
2031 ImGui::SameLine(); HelpMarker(
2032 desc: "SetColorEditOptions() is designed to allow you to set boot-time default.\n"
2033 "We don't have Push/Pop functions because you can force options on a per-widget basis if needed,"
2034 "and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid"
2035 "encouraging you to persistently save values that aren't forward-compatible.");
2036 if (ImGui::Button(label: "Default: Uint8 + HSV + Hue Bar"))
2037 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
2038 if (ImGui::Button(label: "Default: Float + HDR + Hue Wheel"))
2039 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
2040
2041 // Always both a small version of both types of pickers (to make it more visible in the demo to people who are skimming quickly through it)
2042 ImGui::Text(fmt: "Both types:");
2043 float w = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.y) * 0.40f;
2044 ImGui::SetNextItemWidth(w);
2045 ImGui::ColorPicker3(label: "##MyColor##5", col: (float*)&color, flags: ImGuiColorEditFlags_PickerHueBar | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
2046 ImGui::SameLine();
2047 ImGui::SetNextItemWidth(w);
2048 ImGui::ColorPicker3(label: "##MyColor##6", col: (float*)&color, flags: ImGuiColorEditFlags_PickerHueWheel | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoAlpha);
2049
2050 // HSV encoded support (to avoid RGB<>HSV round trips and singularities when S==0 or V==0)
2051 static ImVec4 color_hsv(0.23f, 1.0f, 1.0f, 1.0f); // Stored as HSV!
2052 ImGui::Spacing();
2053 ImGui::Text(fmt: "HSV encoded colors");
2054 ImGui::SameLine(); HelpMarker(
2055 desc: "By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV"
2056 "allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the"
2057 "added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
2058 ImGui::Text(fmt: "Color widget with InputHSV:");
2059 ImGui::ColorEdit4(label: "HSV shown as RGB##1", col: (float*)&color_hsv, flags: ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
2060 ImGui::ColorEdit4(label: "HSV shown as HSV##1", col: (float*)&color_hsv, flags: ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
2061 ImGui::DragFloat4(label: "Raw HSV values", v: (float*)&color_hsv, v_speed: 0.01f, v_min: 0.0f, v_max: 1.0f);
2062
2063 ImGui::TreePop();
2064 }
2065
2066 IMGUI_DEMO_MARKER("Widgets/Drag and Slider Flags");
2067 if (ImGui::TreeNode(label: "Drag/Slider Flags"))
2068 {
2069 // Demonstrate using advanced flags for DragXXX and SliderXXX functions. Note that the flags are the same!
2070 static ImGuiSliderFlags flags = ImGuiSliderFlags_None;
2071 ImGui::CheckboxFlags(label: "ImGuiSliderFlags_AlwaysClamp", flags: &flags, flags_value: ImGuiSliderFlags_AlwaysClamp);
2072 ImGui::SameLine(); HelpMarker(desc: "Always clamp value to min/max bounds (if any) when input manually with CTRL+Click.");
2073 ImGui::CheckboxFlags(label: "ImGuiSliderFlags_Logarithmic", flags: &flags, flags_value: ImGuiSliderFlags_Logarithmic);
2074 ImGui::SameLine(); HelpMarker(desc: "Enable logarithmic editing (more precision for small values).");
2075 ImGui::CheckboxFlags(label: "ImGuiSliderFlags_NoRoundToFormat", flags: &flags, flags_value: ImGuiSliderFlags_NoRoundToFormat);
2076 ImGui::SameLine(); HelpMarker(desc: "Disable rounding underlying value to match precision of the format string (e.g. %.3f values are rounded to those 3 digits).");
2077 ImGui::CheckboxFlags(label: "ImGuiSliderFlags_NoInput", flags: &flags, flags_value: ImGuiSliderFlags_NoInput);
2078 ImGui::SameLine(); HelpMarker(desc: "Disable CTRL+Click or Enter key allowing to input text directly into the widget.");
2079
2080 // Drags
2081 static float drag_f = 0.5f;
2082 static int drag_i = 50;
2083 ImGui::Text(fmt: "Underlying float value: %f", drag_f);
2084 ImGui::DragFloat(label: "DragFloat (0 -> 1)", v: &drag_f, v_speed: 0.005f, v_min: 0.0f, v_max: 1.0f, format: "%.3f", flags);
2085 ImGui::DragFloat(label: "DragFloat (0 -> +inf)", v: &drag_f, v_speed: 0.005f, v_min: 0.0f, FLT_MAX, format: "%.3f", flags);
2086 ImGui::DragFloat(label: "DragFloat (-inf -> 1)", v: &drag_f, v_speed: 0.005f, v_min: -FLT_MAX, v_max: 1.0f, format: "%.3f", flags);
2087 ImGui::DragFloat(label: "DragFloat (-inf -> +inf)", v: &drag_f, v_speed: 0.005f, v_min: -FLT_MAX, v_max: +FLT_MAX, format: "%.3f", flags);
2088 ImGui::DragInt(label: "DragInt (0 -> 100)", v: &drag_i, v_speed: 0.5f, v_min: 0, v_max: 100, format: "%d", flags);
2089
2090 // Sliders
2091 static float slider_f = 0.5f;
2092 static int slider_i = 50;
2093 ImGui::Text(fmt: "Underlying float value: %f", slider_f);
2094 ImGui::SliderFloat(label: "SliderFloat (0 -> 1)", v: &slider_f, v_min: 0.0f, v_max: 1.0f, format: "%.3f", flags);
2095 ImGui::SliderInt(label: "SliderInt (0 -> 100)", v: &slider_i, v_min: 0, v_max: 100, format: "%d", flags);
2096
2097 ImGui::TreePop();
2098 }
2099
2100 IMGUI_DEMO_MARKER("Widgets/Range Widgets");
2101 if (ImGui::TreeNode(label: "Range Widgets"))
2102 {
2103 static float begin = 10, end = 90;
2104 static int begin_i = 100, end_i = 1000;
2105 ImGui::DragFloatRange2(label: "range float", v_current_min: &begin, v_current_max: &end, v_speed: 0.25f, v_min: 0.0f, v_max: 100.0f, format: "Min: %.1f %%", format_max: "Max: %.1f %%", flags: ImGuiSliderFlags_AlwaysClamp);
2106 ImGui::DragIntRange2(label: "range int", v_current_min: &begin_i, v_current_max: &end_i, v_speed: 5, v_min: 0, v_max: 1000, format: "Min: %d units", format_max: "Max: %d units");
2107 ImGui::DragIntRange2(label: "range int (no bounds)", v_current_min: &begin_i, v_current_max: &end_i, v_speed: 5, v_min: 0, v_max: 0, format: "Min: %d units", format_max: "Max: %d units");
2108 ImGui::TreePop();
2109 }
2110
2111 IMGUI_DEMO_MARKER("Widgets/Data Types");
2112 if (ImGui::TreeNode(label: "Data Types"))
2113 {
2114 // DragScalar/InputScalar/SliderScalar functions allow various data types
2115 // - signed/unsigned
2116 // - 8/16/32/64-bits
2117 // - integer/float/double
2118 // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum
2119 // to pass the type, and passing all arguments by pointer.
2120 // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each type.
2121 // In practice, if you frequently use a given type that is not covered by the normal API entry points,
2122 // you can wrap it yourself inside a 1 line function which can take typed argument as value instead of void*,
2123 // and then pass their address to the generic function. For example:
2124 // bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
2125 // {
2126 // return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
2127 // }
2128
2129 // Setup limits (as helper variables so we can take their address, as explained above)
2130 // Note: SliderScalar() functions have a maximum usable range of half the natural type maximum, hence the /2.
2131 #ifndef LLONG_MIN
2132 ImS64 LLONG_MIN = -9223372036854775807LL - 1;
2133 ImS64 LLONG_MAX = 9223372036854775807LL;
2134 ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
2135 #endif
2136 const char s8_zero = 0, s8_one = 1, s8_fifty = 50, s8_min = -128, s8_max = 127;
2137 const ImU8 u8_zero = 0, u8_one = 1, u8_fifty = 50, u8_min = 0, u8_max = 255;
2138 const short s16_zero = 0, s16_one = 1, s16_fifty = 50, s16_min = -32768, s16_max = 32767;
2139 const ImU16 u16_zero = 0, u16_one = 1, u16_fifty = 50, u16_min = 0, u16_max = 65535;
2140 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;
2141 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;
2142 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;
2143 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;
2144 const float f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
2145 const double f64_zero = 0., f64_one = 1., f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
2146
2147 // State
2148 static char s8_v = 127;
2149 static ImU8 u8_v = 255;
2150 static short s16_v = 32767;
2151 static ImU16 u16_v = 65535;
2152 static ImS32 s32_v = -1;
2153 static ImU32 u32_v = (ImU32)-1;
2154 static ImS64 s64_v = -1;
2155 static ImU64 u64_v = (ImU64)-1;
2156 static float f32_v = 0.123f;
2157 static double f64_v = 90000.01234567890123456789;
2158
2159 const float drag_speed = 0.2f;
2160 static bool drag_clamp = false;
2161 IMGUI_DEMO_MARKER("Widgets/Data Types/Drags");
2162 ImGui::SeparatorText(label: "Drags");
2163 ImGui::Checkbox(label: "Clamp integers to 0..50", v: &drag_clamp);
2164 ImGui::SameLine(); HelpMarker(
2165 desc: "As with every widget in dear imgui, we never modify values unless there is a user interaction.\n"
2166 "You can override the clamping limits by using CTRL+Click to input a value.");
2167 ImGui::DragScalar(label: "drag s8", data_type: ImGuiDataType_S8, p_data: &s8_v, v_speed: drag_speed, p_min: drag_clamp ? &s8_zero : NULL, p_max: drag_clamp ? &s8_fifty : NULL);
2168 ImGui::DragScalar(label: "drag u8", data_type: ImGuiDataType_U8, p_data: &u8_v, v_speed: drag_speed, p_min: drag_clamp ? &u8_zero : NULL, p_max: drag_clamp ? &u8_fifty : NULL, format: "%u ms");
2169 ImGui::DragScalar(label: "drag s16", data_type: ImGuiDataType_S16, p_data: &s16_v, v_speed: drag_speed, p_min: drag_clamp ? &s16_zero : NULL, p_max: drag_clamp ? &s16_fifty : NULL);
2170 ImGui::DragScalar(label: "drag u16", data_type: ImGuiDataType_U16, p_data: &u16_v, v_speed: drag_speed, p_min: drag_clamp ? &u16_zero : NULL, p_max: drag_clamp ? &u16_fifty : NULL, format: "%u ms");
2171 ImGui::DragScalar(label: "drag s32", data_type: ImGuiDataType_S32, p_data: &s32_v, v_speed: drag_speed, p_min: drag_clamp ? &s32_zero : NULL, p_max: drag_clamp ? &s32_fifty : NULL);
2172 ImGui::DragScalar(label: "drag s32 hex", data_type: ImGuiDataType_S32, p_data: &s32_v, v_speed: drag_speed, p_min: drag_clamp ? &s32_zero : NULL, p_max: drag_clamp ? &s32_fifty : NULL, format: "0x%08X");
2173 ImGui::DragScalar(label: "drag u32", data_type: ImGuiDataType_U32, p_data: &u32_v, v_speed: drag_speed, p_min: drag_clamp ? &u32_zero : NULL, p_max: drag_clamp ? &u32_fifty : NULL, format: "%u ms");
2174 ImGui::DragScalar(label: "drag s64", data_type: ImGuiDataType_S64, p_data: &s64_v, v_speed: drag_speed, p_min: drag_clamp ? &s64_zero : NULL, p_max: drag_clamp ? &s64_fifty : NULL);
2175 ImGui::DragScalar(label: "drag u64", data_type: ImGuiDataType_U64, p_data: &u64_v, v_speed: drag_speed, p_min: drag_clamp ? &u64_zero : NULL, p_max: drag_clamp ? &u64_fifty : NULL);
2176 ImGui::DragScalar(label: "drag float", data_type: ImGuiDataType_Float, p_data: &f32_v, v_speed: 0.005f, p_min: &f32_zero, p_max: &f32_one, format: "%f");
2177 ImGui::DragScalar(label: "drag float log", data_type: ImGuiDataType_Float, p_data: &f32_v, v_speed: 0.005f, p_min: &f32_zero, p_max: &f32_one, format: "%f", flags: ImGuiSliderFlags_Logarithmic);
2178 ImGui::DragScalar(label: "drag double", data_type: ImGuiDataType_Double, p_data: &f64_v, v_speed: 0.0005f, p_min: &f64_zero, NULL, format: "%.10f grams");
2179 ImGui::DragScalar(label: "drag double log",data_type: ImGuiDataType_Double, p_data: &f64_v, v_speed: 0.0005f, p_min: &f64_zero, p_max: &f64_one, format: "0 < %.10f < 1", flags: ImGuiSliderFlags_Logarithmic);
2180
2181 IMGUI_DEMO_MARKER("Widgets/Data Types/Sliders");
2182 ImGui::SeparatorText(label: "Sliders");
2183 ImGui::SliderScalar(label: "slider s8 full", data_type: ImGuiDataType_S8, p_data: &s8_v, p_min: &s8_min, p_max: &s8_max, format: "%d");
2184 ImGui::SliderScalar(label: "slider u8 full", data_type: ImGuiDataType_U8, p_data: &u8_v, p_min: &u8_min, p_max: &u8_max, format: "%u");
2185 ImGui::SliderScalar(label: "slider s16 full", data_type: ImGuiDataType_S16, p_data: &s16_v, p_min: &s16_min, p_max: &s16_max, format: "%d");
2186 ImGui::SliderScalar(label: "slider u16 full", data_type: ImGuiDataType_U16, p_data: &u16_v, p_min: &u16_min, p_max: &u16_max, format: "%u");
2187 ImGui::SliderScalar(label: "slider s32 low", data_type: ImGuiDataType_S32, p_data: &s32_v, p_min: &s32_zero, p_max: &s32_fifty,format: "%d");
2188 ImGui::SliderScalar(label: "slider s32 high", data_type: ImGuiDataType_S32, p_data: &s32_v, p_min: &s32_hi_a, p_max: &s32_hi_b, format: "%d");
2189 ImGui::SliderScalar(label: "slider s32 full", data_type: ImGuiDataType_S32, p_data: &s32_v, p_min: &s32_min, p_max: &s32_max, format: "%d");
2190 ImGui::SliderScalar(label: "slider s32 hex", data_type: ImGuiDataType_S32, p_data: &s32_v, p_min: &s32_zero, p_max: &s32_fifty, format: "0x%04X");
2191 ImGui::SliderScalar(label: "slider u32 low", data_type: ImGuiDataType_U32, p_data: &u32_v, p_min: &u32_zero, p_max: &u32_fifty,format: "%u");
2192 ImGui::SliderScalar(label: "slider u32 high", data_type: ImGuiDataType_U32, p_data: &u32_v, p_min: &u32_hi_a, p_max: &u32_hi_b, format: "%u");
2193 ImGui::SliderScalar(label: "slider u32 full", data_type: ImGuiDataType_U32, p_data: &u32_v, p_min: &u32_min, p_max: &u32_max, format: "%u");
2194 ImGui::SliderScalar(label: "slider s64 low", data_type: ImGuiDataType_S64, p_data: &s64_v, p_min: &s64_zero, p_max: &s64_fifty,format: "%" PRId64);
2195 ImGui::SliderScalar(label: "slider s64 high", data_type: ImGuiDataType_S64, p_data: &s64_v, p_min: &s64_hi_a, p_max: &s64_hi_b, format: "%" PRId64);
2196 ImGui::SliderScalar(label: "slider s64 full", data_type: ImGuiDataType_S64, p_data: &s64_v, p_min: &s64_min, p_max: &s64_max, format: "%" PRId64);
2197 ImGui::SliderScalar(label: "slider u64 low", data_type: ImGuiDataType_U64, p_data: &u64_v, p_min: &u64_zero, p_max: &u64_fifty,format: "%" PRIu64 " ms");
2198 ImGui::SliderScalar(label: "slider u64 high", data_type: ImGuiDataType_U64, p_data: &u64_v, p_min: &u64_hi_a, p_max: &u64_hi_b, format: "%" PRIu64 " ms");
2199 ImGui::SliderScalar(label: "slider u64 full", data_type: ImGuiDataType_U64, p_data: &u64_v, p_min: &u64_min, p_max: &u64_max, format: "%" PRIu64 " ms");
2200 ImGui::SliderScalar(label: "slider float low", data_type: ImGuiDataType_Float, p_data: &f32_v, p_min: &f32_zero, p_max: &f32_one);
2201 ImGui::SliderScalar(label: "slider float low log", data_type: ImGuiDataType_Float, p_data: &f32_v, p_min: &f32_zero, p_max: &f32_one, format: "%.10f", flags: ImGuiSliderFlags_Logarithmic);
2202 ImGui::SliderScalar(label: "slider float high", data_type: ImGuiDataType_Float, p_data: &f32_v, p_min: &f32_lo_a, p_max: &f32_hi_a, format: "%e");
2203 ImGui::SliderScalar(label: "slider double low", data_type: ImGuiDataType_Double, p_data: &f64_v, p_min: &f64_zero, p_max: &f64_one, format: "%.10f grams");
2204 ImGui::SliderScalar(label: "slider double low log",data_type: ImGuiDataType_Double, p_data: &f64_v, p_min: &f64_zero, p_max: &f64_one, format: "%.10f", flags: ImGuiSliderFlags_Logarithmic);
2205 ImGui::SliderScalar(label: "slider double high", data_type: ImGuiDataType_Double, p_data: &f64_v, p_min: &f64_lo_a, p_max: &f64_hi_a, format: "%e grams");
2206
2207 ImGui::SeparatorText(label: "Sliders (reverse)");
2208 ImGui::SliderScalar(label: "slider s8 reverse", data_type: ImGuiDataType_S8, p_data: &s8_v, p_min: &s8_max, p_max: &s8_min, format: "%d");
2209 ImGui::SliderScalar(label: "slider u8 reverse", data_type: ImGuiDataType_U8, p_data: &u8_v, p_min: &u8_max, p_max: &u8_min, format: "%u");
2210 ImGui::SliderScalar(label: "slider s32 reverse", data_type: ImGuiDataType_S32, p_data: &s32_v, p_min: &s32_fifty, p_max: &s32_zero, format: "%d");
2211 ImGui::SliderScalar(label: "slider u32 reverse", data_type: ImGuiDataType_U32, p_data: &u32_v, p_min: &u32_fifty, p_max: &u32_zero, format: "%u");
2212 ImGui::SliderScalar(label: "slider s64 reverse", data_type: ImGuiDataType_S64, p_data: &s64_v, p_min: &s64_fifty, p_max: &s64_zero, format: "%" PRId64);
2213 ImGui::SliderScalar(label: "slider u64 reverse", data_type: ImGuiDataType_U64, p_data: &u64_v, p_min: &u64_fifty, p_max: &u64_zero, format: "%" PRIu64 " ms");
2214
2215 IMGUI_DEMO_MARKER("Widgets/Data Types/Inputs");
2216 static bool inputs_step = true;
2217 ImGui::SeparatorText(label: "Inputs");
2218 ImGui::Checkbox(label: "Show step buttons", v: &inputs_step);
2219 ImGui::InputScalar(label: "input s8", data_type: ImGuiDataType_S8, p_data: &s8_v, p_step: inputs_step ? &s8_one : NULL, NULL, format: "%d");
2220 ImGui::InputScalar(label: "input u8", data_type: ImGuiDataType_U8, p_data: &u8_v, p_step: inputs_step ? &u8_one : NULL, NULL, format: "%u");
2221 ImGui::InputScalar(label: "input s16", data_type: ImGuiDataType_S16, p_data: &s16_v, p_step: inputs_step ? &s16_one : NULL, NULL, format: "%d");
2222 ImGui::InputScalar(label: "input u16", data_type: ImGuiDataType_U16, p_data: &u16_v, p_step: inputs_step ? &u16_one : NULL, NULL, format: "%u");
2223 ImGui::InputScalar(label: "input s32", data_type: ImGuiDataType_S32, p_data: &s32_v, p_step: inputs_step ? &s32_one : NULL, NULL, format: "%d");
2224 ImGui::InputScalar(label: "input s32 hex", data_type: ImGuiDataType_S32, p_data: &s32_v, p_step: inputs_step ? &s32_one : NULL, NULL, format: "%04X");
2225 ImGui::InputScalar(label: "input u32", data_type: ImGuiDataType_U32, p_data: &u32_v, p_step: inputs_step ? &u32_one : NULL, NULL, format: "%u");
2226 ImGui::InputScalar(label: "input u32 hex", data_type: ImGuiDataType_U32, p_data: &u32_v, p_step: inputs_step ? &u32_one : NULL, NULL, format: "%08X");
2227 ImGui::InputScalar(label: "input s64", data_type: ImGuiDataType_S64, p_data: &s64_v, p_step: inputs_step ? &s64_one : NULL);
2228 ImGui::InputScalar(label: "input u64", data_type: ImGuiDataType_U64, p_data: &u64_v, p_step: inputs_step ? &u64_one : NULL);
2229 ImGui::InputScalar(label: "input float", data_type: ImGuiDataType_Float, p_data: &f32_v, p_step: inputs_step ? &f32_one : NULL);
2230 ImGui::InputScalar(label: "input double", data_type: ImGuiDataType_Double, p_data: &f64_v, p_step: inputs_step ? &f64_one : NULL);
2231
2232 ImGui::TreePop();
2233 }
2234
2235 IMGUI_DEMO_MARKER("Widgets/Multi-component Widgets");
2236 if (ImGui::TreeNode(label: "Multi-component Widgets"))
2237 {
2238 static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
2239 static int vec4i[4] = { 1, 5, 100, 255 };
2240
2241 ImGui::SeparatorText(label: "2-wide");
2242 ImGui::InputFloat2(label: "input float2", v: vec4f);
2243 ImGui::DragFloat2(label: "drag float2", v: vec4f, v_speed: 0.01f, v_min: 0.0f, v_max: 1.0f);
2244 ImGui::SliderFloat2(label: "slider float2", v: vec4f, v_min: 0.0f, v_max: 1.0f);
2245 ImGui::InputInt2(label: "input int2", v: vec4i);
2246 ImGui::DragInt2(label: "drag int2", v: vec4i, v_speed: 1, v_min: 0, v_max: 255);
2247 ImGui::SliderInt2(label: "slider int2", v: vec4i, v_min: 0, v_max: 255);
2248
2249 ImGui::SeparatorText(label: "3-wide");
2250 ImGui::InputFloat3(label: "input float3", v: vec4f);
2251 ImGui::DragFloat3(label: "drag float3", v: vec4f, v_speed: 0.01f, v_min: 0.0f, v_max: 1.0f);
2252 ImGui::SliderFloat3(label: "slider float3", v: vec4f, v_min: 0.0f, v_max: 1.0f);
2253 ImGui::InputInt3(label: "input int3", v: vec4i);
2254 ImGui::DragInt3(label: "drag int3", v: vec4i, v_speed: 1, v_min: 0, v_max: 255);
2255 ImGui::SliderInt3(label: "slider int3", v: vec4i, v_min: 0, v_max: 255);
2256
2257 ImGui::SeparatorText(label: "4-wide");
2258 ImGui::InputFloat4(label: "input float4", v: vec4f);
2259 ImGui::DragFloat4(label: "drag float4", v: vec4f, v_speed: 0.01f, v_min: 0.0f, v_max: 1.0f);
2260 ImGui::SliderFloat4(label: "slider float4", v: vec4f, v_min: 0.0f, v_max: 1.0f);
2261 ImGui::InputInt4(label: "input int4", v: vec4i);
2262 ImGui::DragInt4(label: "drag int4", v: vec4i, v_speed: 1, v_min: 0, v_max: 255);
2263 ImGui::SliderInt4(label: "slider int4", v: vec4i, v_min: 0, v_max: 255);
2264
2265 ImGui::TreePop();
2266 }
2267
2268 IMGUI_DEMO_MARKER("Widgets/Vertical Sliders");
2269 if (ImGui::TreeNode(label: "Vertical Sliders"))
2270 {
2271 const float spacing = 4;
2272 ImGui::PushStyleVar(idx: ImGuiStyleVar_ItemSpacing, val: ImVec2(spacing, spacing));
2273
2274 static int int_value = 0;
2275 ImGui::VSliderInt(label: "##int", size: ImVec2(18, 160), v: &int_value, v_min: 0, v_max: 5);
2276 ImGui::SameLine();
2277
2278 static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
2279 ImGui::PushID(str_id: "set1");
2280 for (int i = 0; i < 7; i++)
2281 {
2282 if (i > 0) ImGui::SameLine();
2283 ImGui::PushID(int_id: i);
2284 ImGui::PushStyleColor(idx: ImGuiCol_FrameBg, col: (ImVec4)ImColor::HSV(h: i / 7.0f, s: 0.5f, v: 0.5f));
2285 ImGui::PushStyleColor(idx: ImGuiCol_FrameBgHovered, col: (ImVec4)ImColor::HSV(h: i / 7.0f, s: 0.6f, v: 0.5f));
2286 ImGui::PushStyleColor(idx: ImGuiCol_FrameBgActive, col: (ImVec4)ImColor::HSV(h: i / 7.0f, s: 0.7f, v: 0.5f));
2287 ImGui::PushStyleColor(idx: ImGuiCol_SliderGrab, col: (ImVec4)ImColor::HSV(h: i / 7.0f, s: 0.9f, v: 0.9f));
2288 ImGui::VSliderFloat(label: "##v", size: ImVec2(18, 160), v: &values[i], v_min: 0.0f, v_max: 1.0f, format: "");
2289 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
2290 ImGui::SetTooltip("%.3f", values[i]);
2291 ImGui::PopStyleColor(count: 4);
2292 ImGui::PopID();
2293 }
2294 ImGui::PopID();
2295
2296 ImGui::SameLine();
2297 ImGui::PushID(str_id: "set2");
2298 static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
2299 const int rows = 3;
2300 const ImVec2 small_slider_size(18, (float)(int)((160.0f - (rows - 1) * spacing) / rows));
2301 for (int nx = 0; nx < 4; nx++)
2302 {
2303 if (nx > 0) ImGui::SameLine();
2304 ImGui::BeginGroup();
2305 for (int ny = 0; ny < rows; ny++)
2306 {
2307 ImGui::PushID(int_id: nx * rows + ny);
2308 ImGui::VSliderFloat(label: "##v", size: small_slider_size, v: &values2[nx], v_min: 0.0f, v_max: 1.0f, format: "");
2309 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
2310 ImGui::SetTooltip("%.3f", values2[nx]);
2311 ImGui::PopID();
2312 }
2313 ImGui::EndGroup();
2314 }
2315 ImGui::PopID();
2316
2317 ImGui::SameLine();
2318 ImGui::PushID(str_id: "set3");
2319 for (int i = 0; i < 4; i++)
2320 {
2321 if (i > 0) ImGui::SameLine();
2322 ImGui::PushID(int_id: i);
2323 ImGui::PushStyleVar(idx: ImGuiStyleVar_GrabMinSize, val: 40);
2324 ImGui::VSliderFloat(label: "##v", size: ImVec2(40, 160), v: &values[i], v_min: 0.0f, v_max: 1.0f, format: "%.2f\nsec");
2325 ImGui::PopStyleVar();
2326 ImGui::PopID();
2327 }
2328 ImGui::PopID();
2329 ImGui::PopStyleVar();
2330 ImGui::TreePop();
2331 }
2332
2333 IMGUI_DEMO_MARKER("Widgets/Drag and drop");
2334 if (ImGui::TreeNode(label: "Drag and Drop"))
2335 {
2336 IMGUI_DEMO_MARKER("Widgets/Drag and drop/Standard widgets");
2337 if (ImGui::TreeNode(label: "Drag and drop in standard widgets"))
2338 {
2339 // ColorEdit widgets automatically act as drag source and drag target.
2340 // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F
2341 // to allow your own widgets to use colors in their drag and drop interaction.
2342 // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo.
2343 HelpMarker(desc: "You can drag from the color squares.");
2344 static float col1[3] = { 1.0f, 0.0f, 0.2f };
2345 static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f };
2346 ImGui::ColorEdit3(label: "color 1", col: col1);
2347 ImGui::ColorEdit4(label: "color 2", col: col2);
2348 ImGui::TreePop();
2349 }
2350
2351 IMGUI_DEMO_MARKER("Widgets/Drag and drop/Copy-swap items");
2352 if (ImGui::TreeNode(label: "Drag and drop to copy/swap items"))
2353 {
2354 enum Mode
2355 {
2356 Mode_Copy,
2357 Mode_Move,
2358 Mode_Swap
2359 };
2360 static int mode = 0;
2361 if (ImGui::RadioButton(label: "Copy", active: mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
2362 if (ImGui::RadioButton(label: "Move", active: mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
2363 if (ImGui::RadioButton(label: "Swap", active: mode == Mode_Swap)) { mode = Mode_Swap; }
2364 static const char* names[9] =
2365 {
2366 "Bobby", "Beatrice", "Betty",
2367 "Brianna", "Barry", "Bernard",
2368 "Bibi", "Blaine", "Bryn"
2369 };
2370 for (int n = 0; n < IM_ARRAYSIZE(names); n++)
2371 {
2372 ImGui::PushID(int_id: n);
2373 if ((n % 3) != 0)
2374 ImGui::SameLine();
2375 ImGui::Button(label: names[n], size: ImVec2(60, 60));
2376
2377 // Our buttons are both drag sources and drag targets here!
2378 if (ImGui::BeginDragDropSource(flags: ImGuiDragDropFlags_None))
2379 {
2380 // Set payload to carry the index of our item (could be anything)
2381 ImGui::SetDragDropPayload(type: "DND_DEMO_CELL", data: &n, sz: sizeof(int));
2382
2383 // Display preview (could be anything, e.g. when dragging an image we could decide to display
2384 // the filename and a small preview of the image, etc.)
2385 if (mode == Mode_Copy) { ImGui::Text(fmt: "Copy %s", names[n]); }
2386 if (mode == Mode_Move) { ImGui::Text(fmt: "Move %s", names[n]); }
2387 if (mode == Mode_Swap) { ImGui::Text(fmt: "Swap %s", names[n]); }
2388 ImGui::EndDragDropSource();
2389 }
2390 if (ImGui::BeginDragDropTarget())
2391 {
2392 if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(type: "DND_DEMO_CELL"))
2393 {
2394 IM_ASSERT(payload->DataSize == sizeof(int));
2395 int payload_n = *(const int*)payload->Data;
2396 if (mode == Mode_Copy)
2397 {
2398 names[n] = names[payload_n];
2399 }
2400 if (mode == Mode_Move)
2401 {
2402 names[n] = names[payload_n];
2403 names[payload_n] = "";
2404 }
2405 if (mode == Mode_Swap)
2406 {
2407 const char* tmp = names[n];
2408 names[n] = names[payload_n];
2409 names[payload_n] = tmp;
2410 }
2411 }
2412 ImGui::EndDragDropTarget();
2413 }
2414 ImGui::PopID();
2415 }
2416 ImGui::TreePop();
2417 }
2418
2419 IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Drag to reorder items (simple)");
2420 if (ImGui::TreeNode(label: "Drag to reorder items (simple)"))
2421 {
2422 // Simple reordering
2423 HelpMarker(
2424 desc: "We don't use the drag and drop api at all here! "
2425 "Instead we query when the item is held but not hovered, and order items accordingly.");
2426 static const char* item_names[] = { "Item One", "Item Two", "Item Three", "Item Four", "Item Five" };
2427 for (int n = 0; n < IM_ARRAYSIZE(item_names); n++)
2428 {
2429 const char* item = item_names[n];
2430 ImGui::Selectable(label: item);
2431
2432 if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
2433 {
2434 int n_next = n + (ImGui::GetMouseDragDelta(button: 0).y < 0.f ? -1 : 1);
2435 if (n_next >= 0 && n_next < IM_ARRAYSIZE(item_names))
2436 {
2437 item_names[n] = item_names[n_next];
2438 item_names[n_next] = item;
2439 ImGui::ResetMouseDragDelta();
2440 }
2441 }
2442 }
2443 ImGui::TreePop();
2444 }
2445
2446 IMGUI_DEMO_MARKER("Widgets/Drag and Drop/Tooltip at target location");
2447 if (ImGui::TreeNode(label: "Tooltip at target location"))
2448 {
2449 for (int n = 0; n < 2; n++)
2450 {
2451 // Drop targets
2452 ImGui::Button(label: n ? "drop here##1" : "drop here##0");
2453 if (ImGui::BeginDragDropTarget())
2454 {
2455 ImGuiDragDropFlags drop_target_flags = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoPreviewTooltip;
2456 if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, flags: drop_target_flags))
2457 {
2458 IM_UNUSED(payload);
2459 ImGui::SetMouseCursor(ImGuiMouseCursor_NotAllowed);
2460 ImGui::BeginTooltip();
2461 ImGui::Text(fmt: "Cannot drop here!");
2462 ImGui::EndTooltip();
2463 }
2464 ImGui::EndDragDropTarget();
2465 }
2466
2467 // Drop source
2468 static ImVec4 col4 = { 1.0f, 0.0f, 0.2f, 1.0f };
2469 if (n == 0)
2470 ImGui::ColorButton(desc_id: "drag me", col: col4);
2471
2472 }
2473 ImGui::TreePop();
2474 }
2475
2476 ImGui::TreePop();
2477 }
2478
2479 IMGUI_DEMO_MARKER("Widgets/Querying Item Status (Edited,Active,Hovered etc.)");
2480 if (ImGui::TreeNode(label: "Querying Item Status (Edited/Active/Hovered etc.)"))
2481 {
2482 // Select an item type
2483 const char* item_names[] =
2484 {
2485 "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputTextMultiline", "InputFloat",
2486 "InputFloat3", "ColorEdit4", "Selectable", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"
2487 };
2488 static int item_type = 4;
2489 static bool item_disabled = false;
2490 ImGui::Combo(label: "Item Type", current_item: &item_type, items: item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
2491 ImGui::SameLine();
2492 HelpMarker(desc: "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().");
2493 ImGui::Checkbox(label: "Item Disabled", v: &item_disabled);
2494
2495 // Submit selected items so we can query their status in the code following it.
2496 bool ret = false;
2497 static bool b = false;
2498 static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
2499 static char str[16] = {};
2500 if (item_disabled)
2501 ImGui::BeginDisabled(disabled: true);
2502 if (item_type == 0) { ImGui::Text(fmt: "ITEM: Text"); } // Testing text items with no identifier/interaction
2503 if (item_type == 1) { ret = ImGui::Button(label: "ITEM: Button"); } // Testing button
2504 if (item_type == 2) { ImGui::PushButtonRepeat(repeat: true); ret = ImGui::Button(label: "ITEM: Button"); ImGui::PopButtonRepeat(); } // Testing button (with repeater)
2505 if (item_type == 3) { ret = ImGui::Checkbox(label: "ITEM: Checkbox", v: &b); } // Testing checkbox
2506 if (item_type == 4) { ret = ImGui::SliderFloat(label: "ITEM: SliderFloat", v: &col4f[0], v_min: 0.0f, v_max: 1.0f); } // Testing basic item
2507 if (item_type == 5) { ret = ImGui::InputText(label: "ITEM: InputText", buf: &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which handles tabbing)
2508 if (item_type == 6) { ret = ImGui::InputTextMultiline(label: "ITEM: InputTextMultiline", buf: &str[0], IM_ARRAYSIZE(str)); } // Testing input text (which uses a child window)
2509 if (item_type == 7) { ret = ImGui::InputFloat(label: "ITEM: InputFloat", v: col4f, step: 1.0f); } // Testing +/- buttons on scalar input
2510 if (item_type == 8) { ret = ImGui::InputFloat3(label: "ITEM: InputFloat3", v: col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
2511 if (item_type == 9) { ret = ImGui::ColorEdit4(label: "ITEM: ColorEdit4", col: col4f); } // Testing multi-component items (IsItemXXX flags are reported merged)
2512 if (item_type == 10){ ret = ImGui::Selectable(label: "ITEM: Selectable"); } // Testing selectable item
2513 if (item_type == 11){ ret = ImGui::MenuItem(label: "ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
2514 if (item_type == 12){ ret = ImGui::TreeNode(label: "ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node
2515 if (item_type == 13){ ret = ImGui::TreeNodeEx(label: "ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", flags: ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
2516 if (item_type == 14){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo(label: "ITEM: Combo", current_item: &current, items, IM_ARRAYSIZE(items)); }
2517 if (item_type == 15){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox(label: "ITEM: ListBox", current_item: &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
2518
2519 bool hovered_delay_none = ImGui::IsItemHovered();
2520 bool hovered_delay_stationary = ImGui::IsItemHovered(flags: ImGuiHoveredFlags_Stationary);
2521 bool hovered_delay_short = ImGui::IsItemHovered(flags: ImGuiHoveredFlags_DelayShort);
2522 bool hovered_delay_normal = ImGui::IsItemHovered(flags: ImGuiHoveredFlags_DelayNormal);
2523 bool hovered_delay_tooltip = ImGui::IsItemHovered(flags: ImGuiHoveredFlags_ForTooltip); // = Normal + Stationary
2524
2525 // Display the values of IsItemHovered() and other common item state functions.
2526 // Note that the ImGuiHoveredFlags_XXX flags can be combined.
2527 // Because BulletText is an item itself and that would affect the output of IsItemXXX functions,
2528 // we query every state in a single call to avoid storing them and to simplify the code.
2529 ImGui::BulletText(
2530 fmt: "Return value = %d\n"
2531 "IsItemFocused() = %d\n"
2532 "IsItemHovered() = %d\n"
2533 "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
2534 "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
2535 "IsItemHovered(_AllowWhenOverlappedByItem) = %d\n"
2536 "IsItemHovered(_AllowWhenOverlappedByWindow) = %d\n"
2537 "IsItemHovered(_AllowWhenDisabled) = %d\n"
2538 "IsItemHovered(_RectOnly) = %d\n"
2539 "IsItemActive() = %d\n"
2540 "IsItemEdited() = %d\n"
2541 "IsItemActivated() = %d\n"
2542 "IsItemDeactivated() = %d\n"
2543 "IsItemDeactivatedAfterEdit() = %d\n"
2544 "IsItemVisible() = %d\n"
2545 "IsItemClicked() = %d\n"
2546 "IsItemToggledOpen() = %d\n"
2547 "GetItemRectMin() = (%.1f, %.1f)\n"
2548 "GetItemRectMax() = (%.1f, %.1f)\n"
2549 "GetItemRectSize() = (%.1f, %.1f)",
2550 ret,
2551 ImGui::IsItemFocused(),
2552 ImGui::IsItemHovered(),
2553 ImGui::IsItemHovered(flags: ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2554 ImGui::IsItemHovered(flags: ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
2555 ImGui::IsItemHovered(flags: ImGuiHoveredFlags_AllowWhenOverlappedByItem),
2556 ImGui::IsItemHovered(flags: ImGuiHoveredFlags_AllowWhenOverlappedByWindow),
2557 ImGui::IsItemHovered(flags: ImGuiHoveredFlags_AllowWhenDisabled),
2558 ImGui::IsItemHovered(flags: ImGuiHoveredFlags_RectOnly),
2559 ImGui::IsItemActive(),
2560 ImGui::IsItemEdited(),
2561 ImGui::IsItemActivated(),
2562 ImGui::IsItemDeactivated(),
2563 ImGui::IsItemDeactivatedAfterEdit(),
2564 ImGui::IsItemVisible(),
2565 ImGui::IsItemClicked(),
2566 ImGui::IsItemToggledOpen(),
2567 ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
2568 ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
2569 ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
2570 );
2571 ImGui::BulletText(
2572 fmt: "with Hovering Delay or Stationary test:\n"
2573 "IsItemHovered() = = %d\n"
2574 "IsItemHovered(_Stationary) = %d\n"
2575 "IsItemHovered(_DelayShort) = %d\n"
2576 "IsItemHovered(_DelayNormal) = %d\n"
2577 "IsItemHovered(_Tooltip) = %d",
2578 hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip);
2579
2580 if (item_disabled)
2581 ImGui::EndDisabled();
2582
2583 char buf[1] = "";
2584 ImGui::InputText(label: "unused", buf, IM_ARRAYSIZE(buf), flags: ImGuiInputTextFlags_ReadOnly);
2585 ImGui::SameLine();
2586 HelpMarker(desc: "This widget is only here to be able to tab-out of the widgets above and see e.g. Deactivated() status.");
2587
2588 ImGui::TreePop();
2589 }
2590
2591 IMGUI_DEMO_MARKER("Widgets/Querying Window Status (Focused,Hovered etc.)");
2592 if (ImGui::TreeNode(label: "Querying Window Status (Focused/Hovered etc.)"))
2593 {
2594 static bool embed_all_inside_a_child_window = false;
2595 ImGui::Checkbox(label: "Embed everything inside a child window for testing _RootWindow flag.", v: &embed_all_inside_a_child_window);
2596 if (embed_all_inside_a_child_window)
2597 ImGui::BeginChild(str_id: "outer_child", size: ImVec2(0, ImGui::GetFontSize() * 20.0f), child_flags: ImGuiChildFlags_Border);
2598
2599 // Testing IsWindowFocused() function with its various flags.
2600 ImGui::BulletText(
2601 fmt: "IsWindowFocused() = %d\n"
2602 "IsWindowFocused(_ChildWindows) = %d\n"
2603 "IsWindowFocused(_ChildWindows|_NoPopupHierarchy) = %d\n"
2604 "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
2605 "IsWindowFocused(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
2606 "IsWindowFocused(_RootWindow) = %d\n"
2607 "IsWindowFocused(_RootWindow|_NoPopupHierarchy) = %d\n"
2608 "IsWindowFocused(_AnyWindow) = %d\n",
2609 ImGui::IsWindowFocused(),
2610 ImGui::IsWindowFocused(flags: ImGuiFocusedFlags_ChildWindows),
2611 ImGui::IsWindowFocused(flags: ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_NoPopupHierarchy),
2612 ImGui::IsWindowFocused(flags: ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
2613 ImGui::IsWindowFocused(flags: ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
2614 ImGui::IsWindowFocused(flags: ImGuiFocusedFlags_RootWindow),
2615 ImGui::IsWindowFocused(flags: ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_NoPopupHierarchy),
2616 ImGui::IsWindowFocused(flags: ImGuiFocusedFlags_AnyWindow));
2617
2618 // Testing IsWindowHovered() function with its various flags.
2619 ImGui::BulletText(
2620 fmt: "IsWindowHovered() = %d\n"
2621 "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
2622 "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
2623 "IsWindowHovered(_ChildWindows) = %d\n"
2624 "IsWindowHovered(_ChildWindows|_NoPopupHierarchy) = %d\n"
2625 "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
2626 "IsWindowHovered(_ChildWindows|_RootWindow|_NoPopupHierarchy) = %d\n"
2627 "IsWindowHovered(_RootWindow) = %d\n"
2628 "IsWindowHovered(_RootWindow|_NoPopupHierarchy) = %d\n"
2629 "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
2630 "IsWindowHovered(_AnyWindow) = %d\n"
2631 "IsWindowHovered(_Stationary) = %d\n",
2632 ImGui::IsWindowHovered(),
2633 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2634 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
2635 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_ChildWindows),
2636 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_NoPopupHierarchy),
2637 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
2638 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
2639 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_RootWindow),
2640 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_NoPopupHierarchy),
2641 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
2642 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_AnyWindow),
2643 ImGui::IsWindowHovered(flags: ImGuiHoveredFlags_Stationary));
2644
2645 ImGui::BeginChild(str_id: "child", size: ImVec2(0, 50), child_flags: ImGuiChildFlags_Border);
2646 ImGui::Text(fmt: "This is another child window for testing the _ChildWindows flag.");
2647 ImGui::EndChild();
2648 if (embed_all_inside_a_child_window)
2649 ImGui::EndChild();
2650
2651 // Calling IsItemHovered() after begin returns the hovered status of the title bar.
2652 // This is useful in particular if you want to create a context menu associated to the title bar of a window.
2653 static bool test_window = false;
2654 ImGui::Checkbox(label: "Hovered/Active tests after Begin() for title bar testing", v: &test_window);
2655 if (test_window)
2656 {
2657 ImGui::Begin(name: "Title bar Hovered/Active tests", p_open: &test_window);
2658 if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
2659 {
2660 if (ImGui::MenuItem(label: "Close")) { test_window = false; }
2661 ImGui::EndPopup();
2662 }
2663 ImGui::Text(
2664 fmt: "IsItemHovered() after begin = %d (== is title bar hovered)\n"
2665 "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
2666 ImGui::IsItemHovered(), ImGui::IsItemActive());
2667 ImGui::End();
2668 }
2669
2670 ImGui::TreePop();
2671 }
2672
2673 // Demonstrate BeginDisabled/EndDisabled using a checkbox located at the bottom of the section (which is a bit odd:
2674 // logically we'd have this checkbox at the top of the section, but we don't want this feature to steal that space)
2675 if (disable_all)
2676 ImGui::EndDisabled();
2677
2678 IMGUI_DEMO_MARKER("Widgets/Disable Block");
2679 if (ImGui::TreeNode(label: "Disable block"))
2680 {
2681 ImGui::Checkbox(label: "Disable entire section above", v: &disable_all);
2682 ImGui::SameLine(); HelpMarker(desc: "Demonstrate using BeginDisabled()/EndDisabled() across this section.");
2683 ImGui::TreePop();
2684 }
2685
2686 IMGUI_DEMO_MARKER("Widgets/Text Filter");
2687 if (ImGui::TreeNode(label: "Text Filter"))
2688 {
2689 // Helper class to easy setup a text filter.
2690 // You may want to implement a more feature-full filtering scheme in your own application.
2691 HelpMarker(desc: "Not a widget per-se, but ImGuiTextFilter is a helper to perform simple filtering on text strings.");
2692 static ImGuiTextFilter filter;
2693 ImGui::Text(fmt: "Filter usage:\n"
2694 " \"\" display all lines\n"
2695 " \"xxx\" display lines containing \"xxx\"\n"
2696 " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
2697 " \"-xxx\" hide lines containing \"xxx\"");
2698 filter.Draw();
2699 const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
2700 for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
2701 if (filter.PassFilter(text: lines[i]))
2702 ImGui::BulletText(fmt: "%s", lines[i]);
2703 ImGui::TreePop();
2704 }
2705}
2706
2707static void ShowDemoWindowLayout()
2708{
2709 IMGUI_DEMO_MARKER("Layout");
2710 if (!ImGui::CollapsingHeader(label: "Layout & Scrolling"))
2711 return;
2712
2713 IMGUI_DEMO_MARKER("Layout/Child windows");
2714 if (ImGui::TreeNode(label: "Child windows"))
2715 {
2716 ImGui::SeparatorText(label: "Child windows");
2717
2718 HelpMarker(desc: "Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
2719 static bool disable_mouse_wheel = false;
2720 static bool disable_menu = false;
2721 ImGui::Checkbox(label: "Disable Mouse Wheel", v: &disable_mouse_wheel);
2722 ImGui::Checkbox(label: "Disable Menu", v: &disable_menu);
2723
2724 // Child 1: no border, enable horizontal scrollbar
2725 {
2726 ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
2727 if (disable_mouse_wheel)
2728 window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
2729 ImGui::BeginChild(str_id: "ChildL", size: ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, 260), child_flags: ImGuiChildFlags_None, window_flags);
2730 for (int i = 0; i < 100; i++)
2731 ImGui::Text(fmt: "%04d: scrollable region", i);
2732 ImGui::EndChild();
2733 }
2734
2735 ImGui::SameLine();
2736
2737 // Child 2: rounded border
2738 {
2739 ImGuiWindowFlags window_flags = ImGuiWindowFlags_None;
2740 if (disable_mouse_wheel)
2741 window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
2742 if (!disable_menu)
2743 window_flags |= ImGuiWindowFlags_MenuBar;
2744 ImGui::PushStyleVar(idx: ImGuiStyleVar_ChildRounding, val: 5.0f);
2745 ImGui::BeginChild(str_id: "ChildR", size: ImVec2(0, 260), child_flags: ImGuiChildFlags_Border, window_flags);
2746 if (!disable_menu && ImGui::BeginMenuBar())
2747 {
2748 if (ImGui::BeginMenu(label: "Menu"))
2749 {
2750 ShowExampleMenuFile();
2751 ImGui::EndMenu();
2752 }
2753 ImGui::EndMenuBar();
2754 }
2755 if (ImGui::BeginTable(str_id: "split", column: 2, flags: ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
2756 {
2757 for (int i = 0; i < 100; i++)
2758 {
2759 char buf[32];
2760 sprintf(s: buf, format: "%03d", i);
2761 ImGui::TableNextColumn();
2762 ImGui::Button(label: buf, size: ImVec2(-FLT_MIN, 0.0f));
2763 }
2764 ImGui::EndTable();
2765 }
2766 ImGui::EndChild();
2767 ImGui::PopStyleVar();
2768 }
2769
2770 // Child 3: manual-resize
2771 ImGui::SeparatorText(label: "Manual-resize");
2772 {
2773 HelpMarker(desc: "Drag bottom border to resize. Double-click bottom border to auto-fit to vertical contents.");
2774 ImGui::PushStyleColor(idx: ImGuiCol_ChildBg, col: ImGui::GetStyleColorVec4(idx: ImGuiCol_FrameBg));
2775 if (ImGui::BeginChild(str_id: "ResizableChild", size: ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 8), child_flags: ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY))
2776 for (int n = 0; n < 10; n++)
2777 ImGui::Text(fmt: "Line %04d", n);
2778 ImGui::PopStyleColor();
2779 ImGui::EndChild();
2780 }
2781
2782 // Child 4: auto-resizing height with a limit
2783 ImGui::SeparatorText(label: "Auto-resize with constraints");
2784 {
2785 static int draw_lines = 3;
2786 static int max_height_in_lines = 10;
2787 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
2788 ImGui::DragInt(label: "Lines Count", v: &draw_lines, v_speed: 0.2f);
2789 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
2790 ImGui::DragInt(label: "Max Height (in Lines)", v: &max_height_in_lines, v_speed: 0.2f);
2791
2792 ImGui::SetNextWindowSizeConstraints(size_min: ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 1), size_max: ImVec2(FLT_MAX, ImGui::GetTextLineHeightWithSpacing() * max_height_in_lines));
2793 if (ImGui::BeginChild(str_id: "ConstrainedChild", size: ImVec2(-FLT_MIN, 0.0f), child_flags: ImGuiChildFlags_Border | ImGuiChildFlags_AutoResizeY))
2794 for (int n = 0; n < draw_lines; n++)
2795 ImGui::Text(fmt: "Line %04d", n);
2796 ImGui::EndChild();
2797 }
2798
2799 ImGui::SeparatorText(label: "Misc/Advanced");
2800
2801 // Demonstrate a few extra things
2802 // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
2803 // - Using SetCursorPos() to position child window (the child window is an item from the POV of parent window)
2804 // You can also call SetNextWindowPos() to position the child window. The parent window will effectively
2805 // layout from this position.
2806 // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from
2807 // the POV of the parent window). See 'Demo->Querying Status (Edited/Active/Hovered etc.)' for details.
2808 {
2809 static int offset_x = 0;
2810 static bool override_bg_color = true;
2811 static ImGuiChildFlags child_flags = ImGuiChildFlags_Border | ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY;
2812 ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
2813 ImGui::DragInt(label: "Offset X", v: &offset_x, v_speed: 1.0f, v_min: -1000, v_max: 1000);
2814 ImGui::Checkbox(label: "Override ChildBg color", v: &override_bg_color);
2815 ImGui::CheckboxFlags(label: "ImGuiChildFlags_Border", flags: &child_flags, flags_value: ImGuiChildFlags_Border);
2816 ImGui::CheckboxFlags(label: "ImGuiChildFlags_AlwaysUseWindowPadding", flags: &child_flags, flags_value: ImGuiChildFlags_AlwaysUseWindowPadding);
2817 ImGui::CheckboxFlags(label: "ImGuiChildFlags_ResizeX", flags: &child_flags, flags_value: ImGuiChildFlags_ResizeX);
2818 ImGui::CheckboxFlags(label: "ImGuiChildFlags_ResizeY", flags: &child_flags, flags_value: ImGuiChildFlags_ResizeY);
2819 ImGui::CheckboxFlags(label: "ImGuiChildFlags_FrameStyle", flags: &child_flags, flags_value: ImGuiChildFlags_FrameStyle);
2820 ImGui::SameLine(); HelpMarker(desc: "Style the child window like a framed item: use FrameBg, FrameRounding, FrameBorderSize, FramePadding instead of ChildBg, ChildRounding, ChildBorderSize, WindowPadding.");
2821 if (child_flags & ImGuiChildFlags_FrameStyle)
2822 override_bg_color = false;
2823
2824 ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
2825 if (override_bg_color)
2826 ImGui::PushStyleColor(idx: ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
2827 ImGui::BeginChild(str_id: "Red", size: ImVec2(200, 100), child_flags, window_flags: ImGuiWindowFlags_None);
2828 if (override_bg_color)
2829 ImGui::PopStyleColor();
2830
2831 for (int n = 0; n < 50; n++)
2832 ImGui::Text(fmt: "Some test %d", n);
2833 ImGui::EndChild();
2834 bool child_is_hovered = ImGui::IsItemHovered();
2835 ImVec2 child_rect_min = ImGui::GetItemRectMin();
2836 ImVec2 child_rect_max = ImGui::GetItemRectMax();
2837 ImGui::Text(fmt: "Hovered: %d", child_is_hovered);
2838 ImGui::Text(fmt: "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);
2839 }
2840
2841 ImGui::TreePop();
2842 }
2843
2844 IMGUI_DEMO_MARKER("Layout/Widgets Width");
2845 if (ImGui::TreeNode(label: "Widgets Width"))
2846 {
2847 static float f = 0.0f;
2848 static bool show_indented_items = true;
2849 ImGui::Checkbox(label: "Show indented items", v: &show_indented_items);
2850
2851 // Use SetNextItemWidth() to set the width of a single upcoming item.
2852 // Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
2853 // In real code use you'll probably want to choose width values that are proportional to your font size
2854 // e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
2855
2856 ImGui::Text(fmt: "SetNextItemWidth/PushItemWidth(100)");
2857 ImGui::SameLine(); HelpMarker(desc: "Fixed width.");
2858 ImGui::PushItemWidth(item_width: 100);
2859 ImGui::DragFloat(label: "float##1b", v: &f);
2860 if (show_indented_items)
2861 {
2862 ImGui::Indent();
2863 ImGui::DragFloat(label: "float (indented)##1b", v: &f);
2864 ImGui::Unindent();
2865 }
2866 ImGui::PopItemWidth();
2867
2868 ImGui::Text(fmt: "SetNextItemWidth/PushItemWidth(-100)");
2869 ImGui::SameLine(); HelpMarker(desc: "Align to right edge minus 100");
2870 ImGui::PushItemWidth(item_width: -100);
2871 ImGui::DragFloat(label: "float##2a", v: &f);
2872 if (show_indented_items)
2873 {
2874 ImGui::Indent();
2875 ImGui::DragFloat(label: "float (indented)##2b", v: &f);
2876 ImGui::Unindent();
2877 }
2878 ImGui::PopItemWidth();
2879
2880 ImGui::Text(fmt: "SetNextItemWidth/PushItemWidth(GetContentRegionAvail().x * 0.5f)");
2881 ImGui::SameLine(); HelpMarker(desc: "Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
2882 ImGui::PushItemWidth(item_width: ImGui::GetContentRegionAvail().x * 0.5f);
2883 ImGui::DragFloat(label: "float##3a", v: &f);
2884 if (show_indented_items)
2885 {
2886 ImGui::Indent();
2887 ImGui::DragFloat(label: "float (indented)##3b", v: &f);
2888 ImGui::Unindent();
2889 }
2890 ImGui::PopItemWidth();
2891
2892 ImGui::Text(fmt: "SetNextItemWidth/PushItemWidth(-GetContentRegionAvail().x * 0.5f)");
2893 ImGui::SameLine(); HelpMarker(desc: "Align to right edge minus half");
2894 ImGui::PushItemWidth(item_width: -ImGui::GetContentRegionAvail().x * 0.5f);
2895 ImGui::DragFloat(label: "float##4a", v: &f);
2896 if (show_indented_items)
2897 {
2898 ImGui::Indent();
2899 ImGui::DragFloat(label: "float (indented)##4b", v: &f);
2900 ImGui::Unindent();
2901 }
2902 ImGui::PopItemWidth();
2903
2904 // Demonstrate using PushItemWidth to surround three items.
2905 // Calling SetNextItemWidth() before each of them would have the same effect.
2906 ImGui::Text(fmt: "SetNextItemWidth/PushItemWidth(-FLT_MIN)");
2907 ImGui::SameLine(); HelpMarker(desc: "Align to right edge");
2908 ImGui::PushItemWidth(item_width: -FLT_MIN);
2909 ImGui::DragFloat(label: "##float5a", v: &f);
2910 if (show_indented_items)
2911 {
2912 ImGui::Indent();
2913 ImGui::DragFloat(label: "float (indented)##5b", v: &f);
2914 ImGui::Unindent();
2915 }
2916 ImGui::PopItemWidth();
2917
2918 ImGui::TreePop();
2919 }
2920
2921 IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout");
2922 if (ImGui::TreeNode(label: "Basic Horizontal Layout"))
2923 {
2924 ImGui::TextWrapped(fmt: "(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
2925
2926 // Text
2927 IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine");
2928 ImGui::Text(fmt: "Two items: Hello"); ImGui::SameLine();
2929 ImGui::TextColored(col: ImVec4(1, 1, 0, 1), fmt: "Sailor");
2930
2931 // Adjust spacing
2932 ImGui::Text(fmt: "More spacing: Hello"); ImGui::SameLine(offset_from_start_x: 0, spacing: 20);
2933 ImGui::TextColored(col: ImVec4(1, 1, 0, 1), fmt: "Sailor");
2934
2935 // Button
2936 ImGui::AlignTextToFramePadding();
2937 ImGui::Text(fmt: "Normal buttons"); ImGui::SameLine();
2938 ImGui::Button(label: "Banana"); ImGui::SameLine();
2939 ImGui::Button(label: "Apple"); ImGui::SameLine();
2940 ImGui::Button(label: "Corniflower");
2941
2942 // Button
2943 ImGui::Text(fmt: "Small buttons"); ImGui::SameLine();
2944 ImGui::SmallButton(label: "Like this one"); ImGui::SameLine();
2945 ImGui::Text(fmt: "can fit within a text block.");
2946
2947 // Aligned to arbitrary position. Easy/cheap column.
2948 IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (with offset)");
2949 ImGui::Text(fmt: "Aligned");
2950 ImGui::SameLine(offset_from_start_x: 150); ImGui::Text(fmt: "x=150");
2951 ImGui::SameLine(offset_from_start_x: 300); ImGui::Text(fmt: "x=300");
2952 ImGui::Text(fmt: "Aligned");
2953 ImGui::SameLine(offset_from_start_x: 150); ImGui::SmallButton(label: "x=150");
2954 ImGui::SameLine(offset_from_start_x: 300); ImGui::SmallButton(label: "x=300");
2955
2956 // Checkbox
2957 IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/SameLine (more)");
2958 static bool c1 = false, c2 = false, c3 = false, c4 = false;
2959 ImGui::Checkbox(label: "My", v: &c1); ImGui::SameLine();
2960 ImGui::Checkbox(label: "Tailor", v: &c2); ImGui::SameLine();
2961 ImGui::Checkbox(label: "Is", v: &c3); ImGui::SameLine();
2962 ImGui::Checkbox(label: "Rich", v: &c4);
2963
2964 // Various
2965 static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
2966 ImGui::PushItemWidth(item_width: 80);
2967 const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
2968 static int item = -1;
2969 ImGui::Combo(label: "Combo", current_item: &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
2970 ImGui::SliderFloat(label: "X", v: &f0, v_min: 0.0f, v_max: 5.0f); ImGui::SameLine();
2971 ImGui::SliderFloat(label: "Y", v: &f1, v_min: 0.0f, v_max: 5.0f); ImGui::SameLine();
2972 ImGui::SliderFloat(label: "Z", v: &f2, v_min: 0.0f, v_max: 5.0f);
2973 ImGui::PopItemWidth();
2974
2975 ImGui::PushItemWidth(item_width: 80);
2976 ImGui::Text(fmt: "Lists:");
2977 static int selection[4] = { 0, 1, 2, 3 };
2978 for (int i = 0; i < 4; i++)
2979 {
2980 if (i > 0) ImGui::SameLine();
2981 ImGui::PushID(int_id: i);
2982 ImGui::ListBox(label: "", current_item: &selection[i], items, IM_ARRAYSIZE(items));
2983 ImGui::PopID();
2984 //ImGui::SetItemTooltip("ListBox %d hovered", i);
2985 }
2986 ImGui::PopItemWidth();
2987
2988 // Dummy
2989 IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Dummy");
2990 ImVec2 button_sz(40, 40);
2991 ImGui::Button(label: "A", size: button_sz); ImGui::SameLine();
2992 ImGui::Dummy(size: button_sz); ImGui::SameLine();
2993 ImGui::Button(label: "B", size: button_sz);
2994
2995 // Manually wrapping
2996 // (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
2997 IMGUI_DEMO_MARKER("Layout/Basic Horizontal Layout/Manual wrapping");
2998 ImGui::Text(fmt: "Manual wrapping:");
2999 ImGuiStyle& style = ImGui::GetStyle();
3000 int buttons_count = 20;
3001 float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
3002 for (int n = 0; n < buttons_count; n++)
3003 {
3004 ImGui::PushID(int_id: n);
3005 ImGui::Button(label: "Box", size: button_sz);
3006 float last_button_x2 = ImGui::GetItemRectMax().x;
3007 float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
3008 if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
3009 ImGui::SameLine();
3010 ImGui::PopID();
3011 }
3012
3013 ImGui::TreePop();
3014 }
3015
3016 IMGUI_DEMO_MARKER("Layout/Groups");
3017 if (ImGui::TreeNode(label: "Groups"))
3018 {
3019 HelpMarker(
3020 desc: "BeginGroup() basically locks the horizontal position for new line. "
3021 "EndGroup() bundles the whole group so that you can use \"item\" functions such as "
3022 "IsItemHovered()/IsItemActive() or SameLine() etc. on the whole group.");
3023 ImGui::BeginGroup();
3024 {
3025 ImGui::BeginGroup();
3026 ImGui::Button(label: "AAA");
3027 ImGui::SameLine();
3028 ImGui::Button(label: "BBB");
3029 ImGui::SameLine();
3030 ImGui::BeginGroup();
3031 ImGui::Button(label: "CCC");
3032 ImGui::Button(label: "DDD");
3033 ImGui::EndGroup();
3034 ImGui::SameLine();
3035 ImGui::Button(label: "EEE");
3036 ImGui::EndGroup();
3037 ImGui::SetItemTooltip("First group hovered");
3038 }
3039 // Capture the group size and create widgets using the same size
3040 ImVec2 size = ImGui::GetItemRectSize();
3041 const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
3042 ImGui::PlotHistogram(label: "##values", values, IM_ARRAYSIZE(values), values_offset: 0, NULL, scale_min: 0.0f, scale_max: 1.0f, graph_size: size);
3043
3044 ImGui::Button(label: "ACTION", size: ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
3045 ImGui::SameLine();
3046 ImGui::Button(label: "REACTION", size: ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x) * 0.5f, size.y));
3047 ImGui::EndGroup();
3048 ImGui::SameLine();
3049
3050 ImGui::Button(label: "LEVERAGE\nBUZZWORD", size);
3051 ImGui::SameLine();
3052
3053 if (ImGui::BeginListBox(label: "List", size))
3054 {
3055 ImGui::Selectable(label: "Selected", selected: true);
3056 ImGui::Selectable(label: "Not Selected", selected: false);
3057 ImGui::EndListBox();
3058 }
3059
3060 ImGui::TreePop();
3061 }
3062
3063 IMGUI_DEMO_MARKER("Layout/Text Baseline Alignment");
3064 if (ImGui::TreeNode(label: "Text Baseline Alignment"))
3065 {
3066 {
3067 ImGui::BulletText(fmt: "Text baseline:");
3068 ImGui::SameLine(); HelpMarker(
3069 desc: "This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. "
3070 "Lines only composed of text or \"small\" widgets use less vertical space than lines with framed widgets.");
3071 ImGui::Indent();
3072
3073 ImGui::Text(fmt: "KO Blahblah"); ImGui::SameLine();
3074 ImGui::Button(label: "Some framed item"); ImGui::SameLine();
3075 HelpMarker(desc: "Baseline of button will look misaligned with text..");
3076
3077 // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
3078 // (because we don't know what's coming after the Text() statement, we need to move the text baseline
3079 // down by FramePadding.y ahead of time)
3080 ImGui::AlignTextToFramePadding();
3081 ImGui::Text(fmt: "OK Blahblah"); ImGui::SameLine();
3082 ImGui::Button(label: "Some framed item"); ImGui::SameLine();
3083 HelpMarker(desc: "We call AlignTextToFramePadding() to vertically align the text baseline by +FramePadding.y");
3084
3085 // SmallButton() uses the same vertical padding as Text
3086 ImGui::Button(label: "TEST##1"); ImGui::SameLine();
3087 ImGui::Text(fmt: "TEST"); ImGui::SameLine();
3088 ImGui::SmallButton(label: "TEST##2");
3089
3090 // If your line starts with text, call AlignTextToFramePadding() to align text to upcoming widgets.
3091 ImGui::AlignTextToFramePadding();
3092 ImGui::Text(fmt: "Text aligned to framed item"); ImGui::SameLine();
3093 ImGui::Button(label: "Item##1"); ImGui::SameLine();
3094 ImGui::Text(fmt: "Item"); ImGui::SameLine();
3095 ImGui::SmallButton(label: "Item##2"); ImGui::SameLine();
3096 ImGui::Button(label: "Item##3");
3097
3098 ImGui::Unindent();
3099 }
3100
3101 ImGui::Spacing();
3102
3103 {
3104 ImGui::BulletText(fmt: "Multi-line text:");
3105 ImGui::Indent();
3106 ImGui::Text(fmt: "One\nTwo\nThree"); ImGui::SameLine();
3107 ImGui::Text(fmt: "Hello\nWorld"); ImGui::SameLine();
3108 ImGui::Text(fmt: "Banana");
3109
3110 ImGui::Text(fmt: "Banana"); ImGui::SameLine();
3111 ImGui::Text(fmt: "Hello\nWorld"); ImGui::SameLine();
3112 ImGui::Text(fmt: "One\nTwo\nThree");
3113
3114 ImGui::Button(label: "HOP##1"); ImGui::SameLine();
3115 ImGui::Text(fmt: "Banana"); ImGui::SameLine();
3116 ImGui::Text(fmt: "Hello\nWorld"); ImGui::SameLine();
3117 ImGui::Text(fmt: "Banana");
3118
3119 ImGui::Button(label: "HOP##2"); ImGui::SameLine();
3120 ImGui::Text(fmt: "Hello\nWorld"); ImGui::SameLine();
3121 ImGui::Text(fmt: "Banana");
3122 ImGui::Unindent();
3123 }
3124
3125 ImGui::Spacing();
3126
3127 {
3128 ImGui::BulletText(fmt: "Misc items:");
3129 ImGui::Indent();
3130
3131 // SmallButton() sets FramePadding to zero. Text baseline is aligned to match baseline of previous Button.
3132 ImGui::Button(label: "80x80", size: ImVec2(80, 80));
3133 ImGui::SameLine();
3134 ImGui::Button(label: "50x50", size: ImVec2(50, 50));
3135 ImGui::SameLine();
3136 ImGui::Button(label: "Button()");
3137 ImGui::SameLine();
3138 ImGui::SmallButton(label: "SmallButton()");
3139
3140 // Tree
3141 const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
3142 ImGui::Button(label: "Button##1");
3143 ImGui::SameLine(offset_from_start_x: 0.0f, spacing);
3144 if (ImGui::TreeNode(label: "Node##1"))
3145 {
3146 // Placeholder tree data
3147 for (int i = 0; i < 6; i++)
3148 ImGui::BulletText(fmt: "Item %d..", i);
3149 ImGui::TreePop();
3150 }
3151
3152 // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget.
3153 // Otherwise you can use SmallButton() (smaller fit).
3154 ImGui::AlignTextToFramePadding();
3155
3156 // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add
3157 // other contents below the node.
3158 bool node_open = ImGui::TreeNode(label: "Node##2");
3159 ImGui::SameLine(offset_from_start_x: 0.0f, spacing); ImGui::Button(label: "Button##2");
3160 if (node_open)
3161 {
3162 // Placeholder tree data
3163 for (int i = 0; i < 6; i++)
3164 ImGui::BulletText(fmt: "Item %d..", i);
3165 ImGui::TreePop();
3166 }
3167
3168 // Bullet
3169 ImGui::Button(label: "Button##3");
3170 ImGui::SameLine(offset_from_start_x: 0.0f, spacing);
3171 ImGui::BulletText(fmt: "Bullet text");
3172
3173 ImGui::AlignTextToFramePadding();
3174 ImGui::BulletText(fmt: "Node");
3175 ImGui::SameLine(offset_from_start_x: 0.0f, spacing); ImGui::Button(label: "Button##4");
3176 ImGui::Unindent();
3177 }
3178
3179 ImGui::TreePop();
3180 }
3181
3182 IMGUI_DEMO_MARKER("Layout/Scrolling");
3183 if (ImGui::TreeNode(label: "Scrolling"))
3184 {
3185 // Vertical scroll functions
3186 IMGUI_DEMO_MARKER("Layout/Scrolling/Vertical");
3187 HelpMarker(desc: "Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given vertical position.");
3188
3189 static int track_item = 50;
3190 static bool enable_track = true;
3191 static bool enable_extra_decorations = false;
3192 static float scroll_to_off_px = 0.0f;
3193 static float scroll_to_pos_px = 200.0f;
3194
3195 ImGui::Checkbox(label: "Decoration", v: &enable_extra_decorations);
3196
3197 ImGui::Checkbox(label: "Track", v: &enable_track);
3198 ImGui::PushItemWidth(item_width: 100);
3199 ImGui::SameLine(offset_from_start_x: 140); enable_track |= ImGui::DragInt(label: "##item", v: &track_item, v_speed: 0.25f, v_min: 0, v_max: 99, format: "Item = %d");
3200
3201 bool scroll_to_off = ImGui::Button(label: "Scroll Offset");
3202 ImGui::SameLine(offset_from_start_x: 140); scroll_to_off |= ImGui::DragFloat(label: "##off", v: &scroll_to_off_px, v_speed: 1.00f, v_min: 0, FLT_MAX, format: "+%.0f px");
3203
3204 bool scroll_to_pos = ImGui::Button(label: "Scroll To Pos");
3205 ImGui::SameLine(offset_from_start_x: 140); scroll_to_pos |= ImGui::DragFloat(label: "##pos", v: &scroll_to_pos_px, v_speed: 1.00f, v_min: -10, FLT_MAX, format: "X/Y = %.0f px");
3206 ImGui::PopItemWidth();
3207
3208 if (scroll_to_off || scroll_to_pos)
3209 enable_track = false;
3210
3211 ImGuiStyle& style = ImGui::GetStyle();
3212 float child_w = (ImGui::GetContentRegionAvail().x - 4 * style.ItemSpacing.x) / 5;
3213 if (child_w < 1.0f)
3214 child_w = 1.0f;
3215 ImGui::PushID(str_id: "##VerticalScrolling");
3216 for (int i = 0; i < 5; i++)
3217 {
3218 if (i > 0) ImGui::SameLine();
3219 ImGui::BeginGroup();
3220 const char* names[] = { "Top", "25%", "Center", "75%", "Bottom" };
3221 ImGui::TextUnformatted(text: names[i]);
3222
3223 const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
3224 const ImGuiID child_id = ImGui::GetID(ptr_id: (void*)(intptr_t)i);
3225 const bool child_is_visible = ImGui::BeginChild(id: child_id, size: ImVec2(child_w, 200.0f), child_flags: ImGuiChildFlags_Border, window_flags: child_flags);
3226 if (ImGui::BeginMenuBar())
3227 {
3228 ImGui::TextUnformatted(text: "abc");
3229 ImGui::EndMenuBar();
3230 }
3231 if (scroll_to_off)
3232 ImGui::SetScrollY(scroll_to_off_px);
3233 if (scroll_to_pos)
3234 ImGui::SetScrollFromPosY(local_y: ImGui::GetCursorStartPos().y + scroll_to_pos_px, center_y_ratio: i * 0.25f);
3235 if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
3236 {
3237 for (int item = 0; item < 100; item++)
3238 {
3239 if (enable_track && item == track_item)
3240 {
3241 ImGui::TextColored(col: ImVec4(1, 1, 0, 1), fmt: "Item %d", item);
3242 ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
3243 }
3244 else
3245 {
3246 ImGui::Text(fmt: "Item %d", item);
3247 }
3248 }
3249 }
3250 float scroll_y = ImGui::GetScrollY();
3251 float scroll_max_y = ImGui::GetScrollMaxY();
3252 ImGui::EndChild();
3253 ImGui::Text(fmt: "%.0f/%.0f", scroll_y, scroll_max_y);
3254 ImGui::EndGroup();
3255 }
3256 ImGui::PopID();
3257
3258 // Horizontal scroll functions
3259 IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal");
3260 ImGui::Spacing();
3261 HelpMarker(
3262 desc: "Use SetScrollHereX() or SetScrollFromPosX() to scroll to a given horizontal position.\n\n"
3263 "Because the clipping rectangle of most window hides half worth of WindowPadding on the "
3264 "left/right, using SetScrollFromPosX(+1) will usually result in clipped text whereas the "
3265 "equivalent SetScrollFromPosY(+1) wouldn't.");
3266 ImGui::PushID(str_id: "##HorizontalScrolling");
3267 for (int i = 0; i < 5; i++)
3268 {
3269 float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
3270 ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
3271 ImGuiID child_id = ImGui::GetID(ptr_id: (void*)(intptr_t)i);
3272 bool child_is_visible = ImGui::BeginChild(id: child_id, size: ImVec2(-100, child_height), child_flags: ImGuiChildFlags_Border, window_flags: child_flags);
3273 if (scroll_to_off)
3274 ImGui::SetScrollX(scroll_to_off_px);
3275 if (scroll_to_pos)
3276 ImGui::SetScrollFromPosX(local_x: ImGui::GetCursorStartPos().x + scroll_to_pos_px, center_x_ratio: i * 0.25f);
3277 if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
3278 {
3279 for (int item = 0; item < 100; item++)
3280 {
3281 if (item > 0)
3282 ImGui::SameLine();
3283 if (enable_track && item == track_item)
3284 {
3285 ImGui::TextColored(col: ImVec4(1, 1, 0, 1), fmt: "Item %d", item);
3286 ImGui::SetScrollHereX(i * 0.25f); // 0.0f:left, 0.5f:center, 1.0f:right
3287 }
3288 else
3289 {
3290 ImGui::Text(fmt: "Item %d", item);
3291 }
3292 }
3293 }
3294 float scroll_x = ImGui::GetScrollX();
3295 float scroll_max_x = ImGui::GetScrollMaxX();
3296 ImGui::EndChild();
3297 ImGui::SameLine();
3298 const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
3299 ImGui::Text(fmt: "%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
3300 ImGui::Spacing();
3301 }
3302 ImGui::PopID();
3303
3304 // Miscellaneous Horizontal Scrolling Demo
3305 IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal (more)");
3306 HelpMarker(
3307 desc: "Horizontal scrolling for a window is enabled via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\n"
3308 "You may want to also explicitly specify content width by using SetNextWindowContentWidth() before Begin().");
3309 static int lines = 7;
3310 ImGui::SliderInt(label: "Lines", v: &lines, v_min: 1, v_max: 15);
3311 ImGui::PushStyleVar(idx: ImGuiStyleVar_FrameRounding, val: 3.0f);
3312 ImGui::PushStyleVar(idx: ImGuiStyleVar_FramePadding, val: ImVec2(2.0f, 1.0f));
3313 ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
3314 ImGui::BeginChild(str_id: "scrolling", size: scrolling_child_size, child_flags: ImGuiChildFlags_Border, window_flags: ImGuiWindowFlags_HorizontalScrollbar);
3315 for (int line = 0; line < lines; line++)
3316 {
3317 // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
3318 // If you want to create your own time line for a real application you may be better off manipulating
3319 // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
3320 // yourself. You may also want to use the lower-level ImDrawList API.
3321 int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
3322 for (int n = 0; n < num_buttons; n++)
3323 {
3324 if (n > 0) ImGui::SameLine();
3325 ImGui::PushID(int_id: n + line * 1000);
3326 char num_buf[16];
3327 sprintf(s: num_buf, format: "%d", n);
3328 const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
3329 float hue = n * 0.05f;
3330 ImGui::PushStyleColor(idx: ImGuiCol_Button, col: (ImVec4)ImColor::HSV(h: hue, s: 0.6f, v: 0.6f));
3331 ImGui::PushStyleColor(idx: ImGuiCol_ButtonHovered, col: (ImVec4)ImColor::HSV(h: hue, s: 0.7f, v: 0.7f));
3332 ImGui::PushStyleColor(idx: ImGuiCol_ButtonActive, col: (ImVec4)ImColor::HSV(h: hue, s: 0.8f, v: 0.8f));
3333 ImGui::Button(label, size: ImVec2(40.0f + sinf(x: (float)(line + n)) * 20.0f, 0.0f));
3334 ImGui::PopStyleColor(count: 3);
3335 ImGui::PopID();
3336 }
3337 }
3338 float scroll_x = ImGui::GetScrollX();
3339 float scroll_max_x = ImGui::GetScrollMaxX();
3340 ImGui::EndChild();
3341 ImGui::PopStyleVar(count: 2);
3342 float scroll_x_delta = 0.0f;
3343 ImGui::SmallButton(label: "<<");
3344 if (ImGui::IsItemActive())
3345 scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f;
3346 ImGui::SameLine();
3347 ImGui::Text(fmt: "Scroll from code"); ImGui::SameLine();
3348 ImGui::SmallButton(label: ">>");
3349 if (ImGui::IsItemActive())
3350 scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f;
3351 ImGui::SameLine();
3352 ImGui::Text(fmt: "%.0f/%.0f", scroll_x, scroll_max_x);
3353 if (scroll_x_delta != 0.0f)
3354 {
3355 // Demonstrate a trick: you can use Begin to set yourself in the context of another window
3356 // (here we are already out of your child window)
3357 ImGui::BeginChild(str_id: "scrolling");
3358 ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
3359 ImGui::EndChild();
3360 }
3361 ImGui::Spacing();
3362
3363 static bool show_horizontal_contents_size_demo_window = false;
3364 ImGui::Checkbox(label: "Show Horizontal contents size demo window", v: &show_horizontal_contents_size_demo_window);
3365
3366 if (show_horizontal_contents_size_demo_window)
3367 {
3368 static bool show_h_scrollbar = true;
3369 static bool show_button = true;
3370 static bool show_tree_nodes = true;
3371 static bool show_text_wrapped = false;
3372 static bool show_columns = true;
3373 static bool show_tab_bar = true;
3374 static bool show_child = false;
3375 static bool explicit_content_size = false;
3376 static float contents_size_x = 300.0f;
3377 if (explicit_content_size)
3378 ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
3379 ImGui::Begin(name: "Horizontal contents size demo window", p_open: &show_horizontal_contents_size_demo_window, flags: show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
3380 IMGUI_DEMO_MARKER("Layout/Scrolling/Horizontal contents size demo window");
3381 ImGui::PushStyleVar(idx: ImGuiStyleVar_ItemSpacing, val: ImVec2(2, 0));
3382 ImGui::PushStyleVar(idx: ImGuiStyleVar_FramePadding, val: ImVec2(2, 0));
3383 HelpMarker(desc: "Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
3384 ImGui::Checkbox(label: "H-scrollbar", v: &show_h_scrollbar);
3385 ImGui::Checkbox(label: "Button", v: &show_button); // Will grow contents size (unless explicitly overwritten)
3386 ImGui::Checkbox(label: "Tree nodes", v: &show_tree_nodes); // Will grow contents size and display highlight over full width
3387 ImGui::Checkbox(label: "Text wrapped", v: &show_text_wrapped);// Will grow and use contents size
3388 ImGui::Checkbox(label: "Columns", v: &show_columns); // Will use contents size
3389 ImGui::Checkbox(label: "Tab bar", v: &show_tab_bar); // Will use contents size
3390 ImGui::Checkbox(label: "Child", v: &show_child); // Will grow and use contents size
3391 ImGui::Checkbox(label: "Explicit content size", v: &explicit_content_size);
3392 ImGui::Text(fmt: "Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
3393 if (explicit_content_size)
3394 {
3395 ImGui::SameLine();
3396 ImGui::SetNextItemWidth(100);
3397 ImGui::DragFloat(label: "##csx", v: &contents_size_x);
3398 ImVec2 p = ImGui::GetCursorScreenPos();
3399 ImGui::GetWindowDrawList()->AddRectFilled(p_min: p, p_max: ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
3400 ImGui::GetWindowDrawList()->AddRectFilled(p_min: ImVec2(p.x + contents_size_x - 10, p.y), p_max: ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
3401 ImGui::Dummy(size: ImVec2(0, 10));
3402 }
3403 ImGui::PopStyleVar(count: 2);
3404 ImGui::Separator();
3405 if (show_button)
3406 {
3407 ImGui::Button(label: "this is a 300-wide button", size: ImVec2(300, 0));
3408 }
3409 if (show_tree_nodes)
3410 {
3411 bool open = true;
3412 if (ImGui::TreeNode(label: "this is a tree node"))
3413 {
3414 if (ImGui::TreeNode(label: "another one of those tree node..."))
3415 {
3416 ImGui::Text(fmt: "Some tree contents");
3417 ImGui::TreePop();
3418 }
3419 ImGui::TreePop();
3420 }
3421 ImGui::CollapsingHeader(label: "CollapsingHeader", p_visible: &open);
3422 }
3423 if (show_text_wrapped)
3424 {
3425 ImGui::TextWrapped(fmt: "This text should automatically wrap on the edge of the work rectangle.");
3426 }
3427 if (show_columns)
3428 {
3429 ImGui::Text(fmt: "Tables:");
3430 if (ImGui::BeginTable(str_id: "table", column: 4, flags: ImGuiTableFlags_Borders))
3431 {
3432 for (int n = 0; n < 4; n++)
3433 {
3434 ImGui::TableNextColumn();
3435 ImGui::Text(fmt: "Width %.2f", ImGui::GetContentRegionAvail().x);
3436 }
3437 ImGui::EndTable();
3438 }
3439 ImGui::Text(fmt: "Columns:");
3440 ImGui::Columns(count: 4);
3441 for (int n = 0; n < 4; n++)
3442 {
3443 ImGui::Text(fmt: "Width %.2f", ImGui::GetColumnWidth());
3444 ImGui::NextColumn();
3445 }
3446 ImGui::Columns(count: 1);
3447 }
3448 if (show_tab_bar && ImGui::BeginTabBar(str_id: "Hello"))
3449 {
3450 if (ImGui::BeginTabItem(label: "OneOneOne")) { ImGui::EndTabItem(); }
3451 if (ImGui::BeginTabItem(label: "TwoTwoTwo")) { ImGui::EndTabItem(); }
3452 if (ImGui::BeginTabItem(label: "ThreeThreeThree")) { ImGu