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