1b8e80941Smrg// dear imgui, v1.68 WIP
2b8e80941Smrg// (demo code)
3b8e80941Smrg
4b8e80941Smrg// Message to the person tempted to delete this file when integrating Dear ImGui into their code base:
5b8e80941Smrg// Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other coders
6b8e80941Smrg// will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of
7b8e80941Smrg// your game/app! Removing this file from your project is hindering access to documentation for everyone in your team,
8b8e80941Smrg// likely leading you to poorer usage of the library.
9b8e80941Smrg// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
10b8e80941Smrg// If you want to link core Dear ImGui in your shipped builds but want an easy guarantee that the demo will not be linked,
11b8e80941Smrg// you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
12b8e80941Smrg// In other situation, whenever you have Dear ImGui available you probably want this to be available for reference.
13b8e80941Smrg// Thank you,
14b8e80941Smrg// -Your beloved friend, imgui_demo.cpp (that you won't delete)
15b8e80941Smrg
16b8e80941Smrg// Message to beginner C/C++ programmers about the meaning of the 'static' keyword:
17b8e80941Smrg// In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls, so it is
18b8e80941Smrg// essentially like a global variable but declared inside the scope of the function. We do this as a way to gather code and data
19b8e80941Smrg// in the same place, to make the demo source code faster to read, faster to write, and smaller in size.
20b8e80941Smrg// It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant
21b8e80941Smrg// or used in threads. This might be a pattern you will want to use in your code, but most of the real data you would be editing is
22b8e80941Smrg// likely going to be stored outside your functions.
23b8e80941Smrg
24b8e80941Smrg/*
25b8e80941Smrg
26b8e80941SmrgIndex of this file:
27b8e80941Smrg
28b8e80941Smrg// [SECTION] Forward Declarations, Helpers
29b8e80941Smrg// [SECTION] Demo Window / ShowDemoWindow()
30b8e80941Smrg// [SECTION] About Window / ShowAboutWindow()
31b8e80941Smrg// [SECTION] Style Editor / ShowStyleEditor()
32b8e80941Smrg// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
33b8e80941Smrg// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
34b8e80941Smrg// [SECTION] Example App: Debug Log / ShowExampleAppLog()
35b8e80941Smrg// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
36b8e80941Smrg// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
37b8e80941Smrg// [SECTION] Example App: Long Text / ShowExampleAppLongText()
38b8e80941Smrg// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
39b8e80941Smrg// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
40b8e80941Smrg// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
41b8e80941Smrg// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
42b8e80941Smrg// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
43b8e80941Smrg// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
44b8e80941Smrg
45b8e80941Smrg*/
46b8e80941Smrg
47b8e80941Smrg#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
48b8e80941Smrg#define _CRT_SECURE_NO_WARNINGS
49b8e80941Smrg#endif
50b8e80941Smrg
51b8e80941Smrg#include "imgui.h"
52b8e80941Smrg#include <ctype.h>          // toupper, isprint
53b8e80941Smrg#include <limits.h>         // INT_MIN, INT_MAX
54b8e80941Smrg#include <math.h>           // sqrtf, powf, cosf, sinf, floorf, ceilf
55b8e80941Smrg#include <stdio.h>          // vsnprintf, sscanf, printf
56b8e80941Smrg#include <stdlib.h>         // NULL, malloc, free, atoi
57b8e80941Smrg#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
58b8e80941Smrg#include <stddef.h>         // intptr_t
59b8e80941Smrg#else
60b8e80941Smrg#include <stdint.h>         // intptr_t
61b8e80941Smrg#endif
62b8e80941Smrg
63b8e80941Smrg#ifdef _MSC_VER
64b8e80941Smrg#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
65b8e80941Smrg#endif
66b8e80941Smrg#ifdef __clang__
67b8e80941Smrg#pragma clang diagnostic ignored "-Wold-style-cast"             // warning : use of old-style cast                              // yes, they are more terse.
68b8e80941Smrg#pragma clang diagnostic ignored "-Wdeprecated-declarations"    // warning : 'xx' is deprecated: The POSIX name for this item.. // for strdup used in demo code (so user can copy & paste the code)
69b8e80941Smrg#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast"   // warning : cast to 'void *' from smaller integer type 'int'
70b8e80941Smrg#pragma clang diagnostic ignored "-Wformat-security"            // warning : warning: format string is not a string literal
71b8e80941Smrg#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.
72b8e80941Smrg#pragma clang diagnostic ignored "-Wunused-macros"              // warning : warning: macro is not used                         // we define snprintf/vsnprintf on Windows so they are available, but not always used.
73b8e80941Smrg#if __has_warning("-Wzero-as-null-pointer-constant")
74b8e80941Smrg#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"  // warning : zero as null pointer constant                  // some standard header variations use #define NULL 0
75b8e80941Smrg#endif
76b8e80941Smrg#if __has_warning("-Wdouble-promotion")
77b8e80941Smrg#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.
78b8e80941Smrg#endif
79b8e80941Smrg#if __has_warning("-Wreserved-id-macro")
80b8e80941Smrg#pragma clang diagnostic ignored "-Wreserved-id-macro"          // warning : macro name is a reserved identifier                //
81b8e80941Smrg#endif
82b8e80941Smrg#elif defined(__GNUC__)
83b8e80941Smrg#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"          // warning: cast to pointer from integer of different size
84b8e80941Smrg#pragma GCC diagnostic ignored "-Wformat-security"              // warning : format string is not a string literal (potentially insecure)
85b8e80941Smrg#pragma GCC diagnostic ignored "-Wdouble-promotion"             // warning: implicit conversion from 'float' to 'double' when passing argument to function
86b8e80941Smrg#pragma GCC diagnostic ignored "-Wconversion"                   // warning: conversion to 'xxxx' from 'xxxx' may alter its value
87b8e80941Smrg#if (__GNUC__ >= 6)
88b8e80941Smrg#pragma GCC diagnostic ignored "-Wmisleading-indentation"       // warning: this 'if' clause does not guard this statement      // GCC 6.0+ only. See #883 on GitHub.
89b8e80941Smrg#endif
90b8e80941Smrg#endif
91b8e80941Smrg
92b8e80941Smrg// Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n.
93b8e80941Smrg#ifdef _WIN32
94b8e80941Smrg#define IM_NEWLINE  "\r\n"
95b8e80941Smrg#define snprintf    _snprintf
96b8e80941Smrg#define vsnprintf   _vsnprintf
97b8e80941Smrg#else
98b8e80941Smrg#define IM_NEWLINE  "\n"
99b8e80941Smrg#endif
100b8e80941Smrg
101b8e80941Smrg#define IM_MAX(_A,_B)       (((_A) >= (_B)) ? (_A) : (_B))
102b8e80941Smrg
103b8e80941Smrg//-----------------------------------------------------------------------------
104b8e80941Smrg// [SECTION] Forward Declarations, Helpers
105b8e80941Smrg//-----------------------------------------------------------------------------
106b8e80941Smrg
107b8e80941Smrg#if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS)   // Obsolete name since 1.53, TEST->DEMO
108b8e80941Smrg#define IMGUI_DISABLE_DEMO_WINDOWS
109b8e80941Smrg#endif
110b8e80941Smrg
111b8e80941Smrg#if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
112b8e80941Smrg
113b8e80941Smrg// Forward Declarations
114b8e80941Smrgstatic void ShowExampleAppDocuments(bool* p_open);
115b8e80941Smrgstatic void ShowExampleAppMainMenuBar();
116b8e80941Smrgstatic void ShowExampleAppConsole(bool* p_open);
117b8e80941Smrgstatic void ShowExampleAppLog(bool* p_open);
118b8e80941Smrgstatic void ShowExampleAppLayout(bool* p_open);
119b8e80941Smrgstatic void ShowExampleAppPropertyEditor(bool* p_open);
120b8e80941Smrgstatic void ShowExampleAppLongText(bool* p_open);
121b8e80941Smrgstatic void ShowExampleAppAutoResize(bool* p_open);
122b8e80941Smrgstatic void ShowExampleAppConstrainedResize(bool* p_open);
123b8e80941Smrgstatic void ShowExampleAppSimpleOverlay(bool* p_open);
124b8e80941Smrgstatic void ShowExampleAppWindowTitles(bool* p_open);
125b8e80941Smrgstatic void ShowExampleAppCustomRendering(bool* p_open);
126b8e80941Smrgstatic void ShowExampleMenuFile();
127b8e80941Smrg
128b8e80941Smrg// Helper to display a little (?) mark which shows a tooltip when hovered.
129b8e80941Smrgstatic void ShowHelpMarker(const char* desc)
130b8e80941Smrg{
131b8e80941Smrg    ImGui::TextDisabled("(?)");
132b8e80941Smrg    if (ImGui::IsItemHovered())
133b8e80941Smrg    {
134b8e80941Smrg        ImGui::BeginTooltip();
135b8e80941Smrg        ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
136b8e80941Smrg        ImGui::TextUnformatted(desc);
137b8e80941Smrg        ImGui::PopTextWrapPos();
138b8e80941Smrg        ImGui::EndTooltip();
139b8e80941Smrg    }
140b8e80941Smrg}
141b8e80941Smrg
142b8e80941Smrg// Helper to display basic user controls.
143b8e80941Smrgvoid ImGui::ShowUserGuide()
144b8e80941Smrg{
145b8e80941Smrg    ImGui::BulletText("Double-click on title bar to collapse window.");
146b8e80941Smrg    ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
147b8e80941Smrg    ImGui::BulletText("Click and drag on any empty space to move window.");
148b8e80941Smrg    ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
149b8e80941Smrg    ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
150b8e80941Smrg    if (ImGui::GetIO().FontAllowUserScaling)
151b8e80941Smrg        ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
152b8e80941Smrg    ImGui::BulletText("Mouse Wheel to scroll.");
153b8e80941Smrg    ImGui::BulletText("While editing text:\n");
154b8e80941Smrg    ImGui::Indent();
155b8e80941Smrg    ImGui::BulletText("Hold SHIFT or use mouse to select text.");
156b8e80941Smrg    ImGui::BulletText("CTRL+Left/Right to word jump.");
157b8e80941Smrg    ImGui::BulletText("CTRL+A or double-click to select all.");
158b8e80941Smrg    ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
159b8e80941Smrg    ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
160b8e80941Smrg    ImGui::BulletText("ESCAPE to revert.");
161b8e80941Smrg    ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
162b8e80941Smrg    ImGui::Unindent();
163b8e80941Smrg}
164b8e80941Smrg
165b8e80941Smrg//-----------------------------------------------------------------------------
166b8e80941Smrg// [SECTION] Demo Window / ShowDemoWindow()
167b8e80941Smrg//-----------------------------------------------------------------------------
168b8e80941Smrg
169b8e80941Smrg// We split the contents of the big ShowDemoWindow() function into smaller functions (because the link time of very large functions grow non-linearly)
170b8e80941Smrgstatic void ShowDemoWindowWidgets();
171b8e80941Smrgstatic void ShowDemoWindowLayout();
172b8e80941Smrgstatic void ShowDemoWindowPopups();
173b8e80941Smrgstatic void ShowDemoWindowColumns();
174b8e80941Smrgstatic void ShowDemoWindowMisc();
175b8e80941Smrg
176b8e80941Smrg// Demonstrate most Dear ImGui features (this is big function!)
177b8e80941Smrg// You may execute this function to experiment with the UI and understand what it does. You may then search for keywords in the code when you are interested by a specific feature.
178b8e80941Smrgvoid ImGui::ShowDemoWindow(bool* p_open)
179b8e80941Smrg{
180b8e80941Smrg    // Examples Apps (accessible from the "Examples" menu)
181b8e80941Smrg    static bool show_app_documents = false;
182b8e80941Smrg    static bool show_app_main_menu_bar = false;
183b8e80941Smrg    static bool show_app_console = false;
184b8e80941Smrg    static bool show_app_log = false;
185b8e80941Smrg    static bool show_app_layout = false;
186b8e80941Smrg    static bool show_app_property_editor = false;
187b8e80941Smrg    static bool show_app_long_text = false;
188b8e80941Smrg    static bool show_app_auto_resize = false;
189b8e80941Smrg    static bool show_app_constrained_resize = false;
190b8e80941Smrg    static bool show_app_simple_overlay = false;
191b8e80941Smrg    static bool show_app_window_titles = false;
192b8e80941Smrg    static bool show_app_custom_rendering = false;
193b8e80941Smrg
194b8e80941Smrg    if (show_app_documents)           ShowExampleAppDocuments(&show_app_documents);     // Process the Document app next, as it may also use a DockSpace()
195b8e80941Smrg    if (show_app_main_menu_bar)       ShowExampleAppMainMenuBar();
196b8e80941Smrg    if (show_app_console)             ShowExampleAppConsole(&show_app_console);
197b8e80941Smrg    if (show_app_log)                 ShowExampleAppLog(&show_app_log);
198b8e80941Smrg    if (show_app_layout)              ShowExampleAppLayout(&show_app_layout);
199b8e80941Smrg    if (show_app_property_editor)     ShowExampleAppPropertyEditor(&show_app_property_editor);
200b8e80941Smrg    if (show_app_long_text)           ShowExampleAppLongText(&show_app_long_text);
201b8e80941Smrg    if (show_app_auto_resize)         ShowExampleAppAutoResize(&show_app_auto_resize);
202b8e80941Smrg    if (show_app_constrained_resize)  ShowExampleAppConstrainedResize(&show_app_constrained_resize);
203b8e80941Smrg    if (show_app_simple_overlay)      ShowExampleAppSimpleOverlay(&show_app_simple_overlay);
204b8e80941Smrg    if (show_app_window_titles)       ShowExampleAppWindowTitles(&show_app_window_titles);
205b8e80941Smrg    if (show_app_custom_rendering)    ShowExampleAppCustomRendering(&show_app_custom_rendering);
206b8e80941Smrg
207b8e80941Smrg    // Dear ImGui Apps (accessible from the "Help" menu)
208b8e80941Smrg    static bool show_app_metrics = false;
209b8e80941Smrg    static bool show_app_style_editor = false;
210b8e80941Smrg    static bool show_app_about = false;
211b8e80941Smrg
212b8e80941Smrg    if (show_app_metrics)             { ImGui::ShowMetricsWindow(&show_app_metrics); }
213b8e80941Smrg    if (show_app_style_editor)        { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); }
214b8e80941Smrg    if (show_app_about)               { ImGui::ShowAboutWindow(&show_app_about); }
215b8e80941Smrg
216b8e80941Smrg    // Demonstrate the various window flags. Typically you would just use the default!
217b8e80941Smrg    static bool no_titlebar = false;
218b8e80941Smrg    static bool no_scrollbar = false;
219b8e80941Smrg    static bool no_menu = false;
220b8e80941Smrg    static bool no_move = false;
221b8e80941Smrg    static bool no_resize = false;
222b8e80941Smrg    static bool no_collapse = false;
223b8e80941Smrg    static bool no_close = false;
224b8e80941Smrg    static bool no_nav = false;
225b8e80941Smrg    static bool no_background = false;
226b8e80941Smrg    static bool no_bring_to_front = false;
227b8e80941Smrg
228b8e80941Smrg    ImGuiWindowFlags window_flags = 0;
229b8e80941Smrg    if (no_titlebar)        window_flags |= ImGuiWindowFlags_NoTitleBar;
230b8e80941Smrg    if (no_scrollbar)       window_flags |= ImGuiWindowFlags_NoScrollbar;
231b8e80941Smrg    if (!no_menu)           window_flags |= ImGuiWindowFlags_MenuBar;
232b8e80941Smrg    if (no_move)            window_flags |= ImGuiWindowFlags_NoMove;
233b8e80941Smrg    if (no_resize)          window_flags |= ImGuiWindowFlags_NoResize;
234b8e80941Smrg    if (no_collapse)        window_flags |= ImGuiWindowFlags_NoCollapse;
235b8e80941Smrg    if (no_nav)             window_flags |= ImGuiWindowFlags_NoNav;
236b8e80941Smrg    if (no_background)      window_flags |= ImGuiWindowFlags_NoBackground;
237b8e80941Smrg    if (no_bring_to_front)  window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus;
238b8e80941Smrg    if (no_close)           p_open = NULL; // Don't pass our bool* to Begin
239b8e80941Smrg
240b8e80941Smrg    // We specify a default position/size in case there's no data in the .ini file. Typically this isn't required! We only do it to make the Demo applications a little more welcoming.
241b8e80941Smrg    ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver);
242b8e80941Smrg    ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver);
243b8e80941Smrg
244b8e80941Smrg    // Main body of the Demo window starts here.
245b8e80941Smrg    if (!ImGui::Begin("ImGui Demo", p_open, window_flags))
246b8e80941Smrg    {
247b8e80941Smrg        // Early out if the window is collapsed, as an optimization.
248b8e80941Smrg        ImGui::End();
249b8e80941Smrg        return;
250b8e80941Smrg    }
251b8e80941Smrg    ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION);
252b8e80941Smrg
253b8e80941Smrg    // Most "big" widgets share a common width settings by default.
254b8e80941Smrg    //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f);    // Use 2/3 of the space for widgets and 1/3 for labels (default)
255b8e80941Smrg    ImGui::PushItemWidth(ImGui::GetFontSize() * -12);           // Use fixed width for labels (by passing a negative value), the rest goes to widgets. We choose a width proportional to our font size.
256b8e80941Smrg
257b8e80941Smrg    // Menu
258b8e80941Smrg    if (ImGui::BeginMenuBar())
259b8e80941Smrg    {
260b8e80941Smrg        if (ImGui::BeginMenu("Menu"))
261b8e80941Smrg        {
262b8e80941Smrg            ShowExampleMenuFile();
263b8e80941Smrg            ImGui::EndMenu();
264b8e80941Smrg        }
265b8e80941Smrg        if (ImGui::BeginMenu("Examples"))
266b8e80941Smrg        {
267b8e80941Smrg            ImGui::MenuItem("Main menu bar", NULL, &show_app_main_menu_bar);
268b8e80941Smrg            ImGui::MenuItem("Console", NULL, &show_app_console);
269b8e80941Smrg            ImGui::MenuItem("Log", NULL, &show_app_log);
270b8e80941Smrg            ImGui::MenuItem("Simple layout", NULL, &show_app_layout);
271b8e80941Smrg            ImGui::MenuItem("Property editor", NULL, &show_app_property_editor);
272b8e80941Smrg            ImGui::MenuItem("Long text display", NULL, &show_app_long_text);
273b8e80941Smrg            ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize);
274b8e80941Smrg            ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize);
275b8e80941Smrg            ImGui::MenuItem("Simple overlay", NULL, &show_app_simple_overlay);
276b8e80941Smrg            ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles);
277b8e80941Smrg            ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering);
278b8e80941Smrg            ImGui::MenuItem("Documents", NULL, &show_app_documents);
279b8e80941Smrg            ImGui::EndMenu();
280b8e80941Smrg        }
281b8e80941Smrg        if (ImGui::BeginMenu("Help"))
282b8e80941Smrg        {
283b8e80941Smrg            ImGui::MenuItem("Metrics", NULL, &show_app_metrics);
284b8e80941Smrg            ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor);
285b8e80941Smrg            ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about);
286b8e80941Smrg            ImGui::EndMenu();
287b8e80941Smrg        }
288b8e80941Smrg        ImGui::EndMenuBar();
289b8e80941Smrg    }
290b8e80941Smrg
291b8e80941Smrg    ImGui::Spacing();
292b8e80941Smrg    if (ImGui::CollapsingHeader("Help"))
293b8e80941Smrg    {
294b8e80941Smrg        ImGui::Text("PROGRAMMER GUIDE:");
295b8e80941Smrg        ImGui::BulletText("Please see the ShowDemoWindow() code in imgui_demo.cpp. <- you are here!");
296b8e80941Smrg        ImGui::BulletText("Please see the comments in imgui.cpp.");
297b8e80941Smrg        ImGui::BulletText("Please see the examples/ in application.");
298b8e80941Smrg        ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableKeyboard' for keyboard controls.");
299b8e80941Smrg        ImGui::BulletText("Enable 'io.ConfigFlags |= NavEnableGamepad' for gamepad controls.");
300b8e80941Smrg        ImGui::Separator();
301b8e80941Smrg
302b8e80941Smrg        ImGui::Text("USER GUIDE:");
303b8e80941Smrg        ImGui::ShowUserGuide();
304b8e80941Smrg    }
305b8e80941Smrg
306b8e80941Smrg    if (ImGui::CollapsingHeader("Configuration"))
307b8e80941Smrg    {
308b8e80941Smrg        ImGuiIO& io = ImGui::GetIO();
309b8e80941Smrg
310b8e80941Smrg        if (ImGui::TreeNode("Configuration##2"))
311b8e80941Smrg        {
312b8e80941Smrg            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard);
313b8e80941Smrg            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad);
314b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Required back-end to feed in gamepad inputs in io.NavInputs[] and set io.BackendFlags |= ImGuiBackendFlags_HasGamepad.\n\nRead instructions in imgui.cpp for details.");
315b8e80941Smrg            ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos);
316b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
317b8e80941Smrg            ImGui::CheckboxFlags("io.ConfigFlags: NoMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouse);
318b8e80941Smrg            if (io.ConfigFlags & ImGuiConfigFlags_NoMouse) // Create a way to restore this flag otherwise we could be stuck completely!
319b8e80941Smrg            {
320b8e80941Smrg                if (fmodf((float)ImGui::GetTime(), 0.40f) < 0.20f)
321b8e80941Smrg                {
322b8e80941Smrg                    ImGui::SameLine();
323b8e80941Smrg                    ImGui::Text("<<PRESS SPACE TO DISABLE>>");
324b8e80941Smrg                }
325b8e80941Smrg                if (ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Space)))
326b8e80941Smrg                    io.ConfigFlags &= ~ImGuiConfigFlags_NoMouse;
327b8e80941Smrg            }
328b8e80941Smrg            ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange);
329b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
330b8e80941Smrg            ImGui::Checkbox("io.ConfigInputTextCursorBlink", &io.ConfigInputTextCursorBlink);
331b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Set to false to disable blinking cursor, for users who consider it distracting");
332b8e80941Smrg            ImGui::Checkbox("io.ConfigWindowsResizeFromEdges", &io.ConfigWindowsResizeFromEdges);
333b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("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.");
334b8e80941Smrg            ImGui::Checkbox("io.ConfigWindowsMoveFromTitleBarOnly", &io.ConfigWindowsMoveFromTitleBarOnly);
335b8e80941Smrg            ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor);
336b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Instruct Dear ImGui to render a mouse cursor for you. 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).");
337b8e80941Smrg            ImGui::TreePop();
338b8e80941Smrg            ImGui::Separator();
339b8e80941Smrg        }
340b8e80941Smrg
341b8e80941Smrg        if (ImGui::TreeNode("Backend Flags"))
342b8e80941Smrg        {
343b8e80941Smrg            ShowHelpMarker("Those flags are set by the back-ends (imgui_impl_xxx files) to specify their capabilities.");
344b8e80941Smrg            ImGuiBackendFlags backend_flags = io.BackendFlags; // Make a local copy to avoid modifying the back-end flags.
345b8e80941Smrg            ImGui::CheckboxFlags("io.BackendFlags: HasGamepad", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasGamepad);
346b8e80941Smrg            ImGui::CheckboxFlags("io.BackendFlags: HasMouseCursors", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasMouseCursors);
347b8e80941Smrg            ImGui::CheckboxFlags("io.BackendFlags: HasSetMousePos", (unsigned int *)&backend_flags, ImGuiBackendFlags_HasSetMousePos);
348b8e80941Smrg            ImGui::TreePop();
349b8e80941Smrg            ImGui::Separator();
350b8e80941Smrg        }
351b8e80941Smrg
352b8e80941Smrg        if (ImGui::TreeNode("Style"))
353b8e80941Smrg        {
354b8e80941Smrg            ImGui::ShowStyleEditor();
355b8e80941Smrg            ImGui::TreePop();
356b8e80941Smrg            ImGui::Separator();
357b8e80941Smrg        }
358b8e80941Smrg
359b8e80941Smrg        if (ImGui::TreeNode("Capture/Logging"))
360b8e80941Smrg        {
361b8e80941Smrg            ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded.");
362b8e80941Smrg            ShowHelpMarker("Try opening any of the contents below in this window and then click one of the \"Log To\" button.");
363b8e80941Smrg            ImGui::LogButtons();
364b8e80941Smrg            ImGui::TextWrapped("You can also call ImGui::LogText() to output directly to the log without a visual output.");
365b8e80941Smrg            if (ImGui::Button("Copy \"Hello, world!\" to clipboard"))
366b8e80941Smrg            {
367b8e80941Smrg                ImGui::LogToClipboard();
368b8e80941Smrg                ImGui::LogText("Hello, world!");
369b8e80941Smrg                ImGui::LogFinish();
370b8e80941Smrg            }
371b8e80941Smrg            ImGui::TreePop();
372b8e80941Smrg        }
373b8e80941Smrg    }
374b8e80941Smrg
375b8e80941Smrg    if (ImGui::CollapsingHeader("Window options"))
376b8e80941Smrg    {
377b8e80941Smrg        ImGui::Checkbox("No titlebar", &no_titlebar); ImGui::SameLine(150);
378b8e80941Smrg        ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300);
379b8e80941Smrg        ImGui::Checkbox("No menu", &no_menu);
380b8e80941Smrg        ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150);
381b8e80941Smrg        ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300);
382b8e80941Smrg        ImGui::Checkbox("No collapse", &no_collapse);
383b8e80941Smrg        ImGui::Checkbox("No close", &no_close); ImGui::SameLine(150);
384b8e80941Smrg        ImGui::Checkbox("No nav", &no_nav); ImGui::SameLine(300);
385b8e80941Smrg        ImGui::Checkbox("No background", &no_background);
386b8e80941Smrg        ImGui::Checkbox("No bring to front", &no_bring_to_front);
387b8e80941Smrg    }
388b8e80941Smrg
389b8e80941Smrg    // All demo contents
390b8e80941Smrg    ShowDemoWindowWidgets();
391b8e80941Smrg    ShowDemoWindowLayout();
392b8e80941Smrg    ShowDemoWindowPopups();
393b8e80941Smrg    ShowDemoWindowColumns();
394b8e80941Smrg    ShowDemoWindowMisc();
395b8e80941Smrg
396b8e80941Smrg    // End of ShowDemoWindow()
397b8e80941Smrg    ImGui::End();
398b8e80941Smrg}
399b8e80941Smrg
400b8e80941Smrgstatic void ShowDemoWindowWidgets()
401b8e80941Smrg{
402b8e80941Smrg    if (!ImGui::CollapsingHeader("Widgets"))
403b8e80941Smrg        return;
404b8e80941Smrg
405b8e80941Smrg    if (ImGui::TreeNode("Basic"))
406b8e80941Smrg    {
407b8e80941Smrg        static int clicked = 0;
408b8e80941Smrg        if (ImGui::Button("Button"))
409b8e80941Smrg            clicked++;
410b8e80941Smrg        if (clicked & 1)
411b8e80941Smrg        {
412b8e80941Smrg            ImGui::SameLine();
413b8e80941Smrg            ImGui::Text("Thanks for clicking me!");
414b8e80941Smrg        }
415b8e80941Smrg
416b8e80941Smrg        static bool check = true;
417b8e80941Smrg        ImGui::Checkbox("checkbox", &check);
418b8e80941Smrg
419b8e80941Smrg        static int e = 0;
420b8e80941Smrg        ImGui::RadioButton("radio a", &e, 0); ImGui::SameLine();
421b8e80941Smrg        ImGui::RadioButton("radio b", &e, 1); ImGui::SameLine();
422b8e80941Smrg        ImGui::RadioButton("radio c", &e, 2);
423b8e80941Smrg
424b8e80941Smrg        // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
425b8e80941Smrg        for (int i = 0; i < 7; i++)
426b8e80941Smrg        {
427b8e80941Smrg            if (i > 0)
428b8e80941Smrg                ImGui::SameLine();
429b8e80941Smrg            ImGui::PushID(i);
430b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.6f));
431b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.7f));
432b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i/7.0f, 0.8f, 0.8f));
433b8e80941Smrg            ImGui::Button("Click");
434b8e80941Smrg            ImGui::PopStyleColor(3);
435b8e80941Smrg            ImGui::PopID();
436b8e80941Smrg        }
437b8e80941Smrg
438b8e80941Smrg        // Use AlignTextToFramePadding() to align text baseline to the baseline of framed elements (otherwise a Text+SameLine+Button sequence will have the text a little too high by default)
439b8e80941Smrg        ImGui::AlignTextToFramePadding();
440b8e80941Smrg        ImGui::Text("Hold to repeat:");
441b8e80941Smrg        ImGui::SameLine();
442b8e80941Smrg
443b8e80941Smrg        // Arrow buttons with Repeater
444b8e80941Smrg        static int counter = 0;
445b8e80941Smrg        float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
446b8e80941Smrg        ImGui::PushButtonRepeat(true);
447b8e80941Smrg        if (ImGui::ArrowButton("##left", ImGuiDir_Left)) { counter--; }
448b8e80941Smrg        ImGui::SameLine(0.0f, spacing);
449b8e80941Smrg        if (ImGui::ArrowButton("##right", ImGuiDir_Right)) { counter++; }
450b8e80941Smrg        ImGui::PopButtonRepeat();
451b8e80941Smrg        ImGui::SameLine();
452b8e80941Smrg        ImGui::Text("%d", counter);
453b8e80941Smrg
454b8e80941Smrg        ImGui::Text("Hover over me");
455b8e80941Smrg        if (ImGui::IsItemHovered())
456b8e80941Smrg            ImGui::SetTooltip("I am a tooltip");
457b8e80941Smrg
458b8e80941Smrg        ImGui::SameLine();
459b8e80941Smrg        ImGui::Text("- or me");
460b8e80941Smrg        if (ImGui::IsItemHovered())
461b8e80941Smrg        {
462b8e80941Smrg            ImGui::BeginTooltip();
463b8e80941Smrg            ImGui::Text("I am a fancy tooltip");
464b8e80941Smrg            static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
465b8e80941Smrg            ImGui::PlotLines("Curve", arr, IM_ARRAYSIZE(arr));
466b8e80941Smrg            ImGui::EndTooltip();
467b8e80941Smrg        }
468b8e80941Smrg
469b8e80941Smrg        ImGui::Separator();
470b8e80941Smrg
471b8e80941Smrg        ImGui::LabelText("label", "Value");
472b8e80941Smrg
473b8e80941Smrg        {
474b8e80941Smrg            // Using the _simplified_ one-liner Combo() api here
475b8e80941Smrg            // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
476b8e80941Smrg            const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
477b8e80941Smrg            static int item_current = 0;
478b8e80941Smrg            ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items));
479b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
480b8e80941Smrg        }
481b8e80941Smrg
482b8e80941Smrg        {
483b8e80941Smrg            static char str0[128] = "Hello, world!";
484b8e80941Smrg            static int i0 = 123;
485b8e80941Smrg            ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0));
486b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("USER:\nHold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp).");
487b8e80941Smrg
488b8e80941Smrg            ImGui::InputInt("input int", &i0);
489b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n  e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
490b8e80941Smrg
491b8e80941Smrg            static float f0 = 0.001f;
492b8e80941Smrg            ImGui::InputFloat("input float", &f0, 0.01f, 1.0f, "%.3f");
493b8e80941Smrg
494b8e80941Smrg            static double d0 = 999999.00000001;
495b8e80941Smrg            ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.8f");
496b8e80941Smrg
497b8e80941Smrg            static float f1 = 1.e10f;
498b8e80941Smrg            ImGui::InputFloat("input scientific", &f1, 0.0f, 0.0f, "%e");
499b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n  e.g. \"1e+8\" becomes \"100000000\".\n");
500b8e80941Smrg
501b8e80941Smrg            static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
502b8e80941Smrg            ImGui::InputFloat3("input float3", vec4a);
503b8e80941Smrg        }
504b8e80941Smrg
505b8e80941Smrg        {
506b8e80941Smrg            static int i1 = 50, i2 = 42;
507b8e80941Smrg            ImGui::DragInt("drag int", &i1, 1);
508b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
509b8e80941Smrg
510b8e80941Smrg            ImGui::DragInt("drag int 0..100", &i2, 1, 0, 100, "%d%%");
511b8e80941Smrg
512b8e80941Smrg            static float f1=1.00f, f2=0.0067f;
513b8e80941Smrg            ImGui::DragFloat("drag float", &f1, 0.005f);
514b8e80941Smrg            ImGui::DragFloat("drag small float", &f2, 0.0001f, 0.0f, 0.0f, "%.06f ns");
515b8e80941Smrg        }
516b8e80941Smrg
517b8e80941Smrg        {
518b8e80941Smrg            static int i1=0;
519b8e80941Smrg            ImGui::SliderInt("slider int", &i1, -1, 3);
520b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
521b8e80941Smrg
522b8e80941Smrg            static float f1=0.123f, f2=0.0f;
523b8e80941Smrg            ImGui::SliderFloat("slider float", &f1, 0.0f, 1.0f, "ratio = %.3f");
524b8e80941Smrg            ImGui::SliderFloat("slider float (curve)", &f2, -10.0f, 10.0f, "%.4f", 2.0f);
525b8e80941Smrg            static float angle = 0.0f;
526b8e80941Smrg            ImGui::SliderAngle("slider angle", &angle);
527b8e80941Smrg        }
528b8e80941Smrg
529b8e80941Smrg        {
530b8e80941Smrg            static float col1[3] = { 1.0f,0.0f,0.2f };
531b8e80941Smrg            static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
532b8e80941Smrg            ImGui::ColorEdit3("color 1", col1);
533b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nClick and hold to use drag and drop.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n");
534b8e80941Smrg
535b8e80941Smrg            ImGui::ColorEdit4("color 2", col2);
536b8e80941Smrg        }
537b8e80941Smrg
538b8e80941Smrg        {
539b8e80941Smrg            // List box
540b8e80941Smrg            const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
541b8e80941Smrg            static int listbox_item_current = 1;
542b8e80941Smrg            ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
543b8e80941Smrg
544b8e80941Smrg            //static int listbox_item_current2 = 2;
545b8e80941Smrg            //ImGui::PushItemWidth(-1);
546b8e80941Smrg            //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
547b8e80941Smrg            //ImGui::PopItemWidth();
548b8e80941Smrg        }
549b8e80941Smrg
550b8e80941Smrg        ImGui::TreePop();
551b8e80941Smrg    }
552b8e80941Smrg
553b8e80941Smrg    // Testing ImGuiOnceUponAFrame helper.
554b8e80941Smrg    //static ImGuiOnceUponAFrame once;
555b8e80941Smrg    //for (int i = 0; i < 5; i++)
556b8e80941Smrg    //    if (once)
557b8e80941Smrg    //        ImGui::Text("This will be displayed only once.");
558b8e80941Smrg
559b8e80941Smrg    if (ImGui::TreeNode("Trees"))
560b8e80941Smrg    {
561b8e80941Smrg        if (ImGui::TreeNode("Basic trees"))
562b8e80941Smrg        {
563b8e80941Smrg            for (int i = 0; i < 5; i++)
564b8e80941Smrg                if (ImGui::TreeNode((void*)(intptr_t)i, "Child %d", i))
565b8e80941Smrg                {
566b8e80941Smrg                    ImGui::Text("blah blah");
567b8e80941Smrg                    ImGui::SameLine();
568b8e80941Smrg                    if (ImGui::SmallButton("button")) { };
569b8e80941Smrg                    ImGui::TreePop();
570b8e80941Smrg                }
571b8e80941Smrg            ImGui::TreePop();
572b8e80941Smrg        }
573b8e80941Smrg
574b8e80941Smrg        if (ImGui::TreeNode("Advanced, with Selectable nodes"))
575b8e80941Smrg        {
576b8e80941Smrg            ShowHelpMarker("This is a more standard looking tree with selectable nodes.\nClick to select, CTRL+Click to toggle, click on arrows or double-click to open.");
577b8e80941Smrg            static bool align_label_with_current_x_position = false;
578b8e80941Smrg            ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position);
579b8e80941Smrg            ImGui::Text("Hello!");
580b8e80941Smrg            if (align_label_with_current_x_position)
581b8e80941Smrg                ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
582b8e80941Smrg
583b8e80941Smrg            static int selection_mask = (1 << 2); // Dumb representation of what may be user-side selection state. You may carry selection state inside or outside your objects in whatever format you see fit.
584b8e80941Smrg            int node_clicked = -1;                // Temporary storage of what node we have clicked to process selection at the end of the loop. May be a pointer to your own node type, etc.
585b8e80941Smrg            ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
586b8e80941Smrg            for (int i = 0; i < 6; i++)
587b8e80941Smrg            {
588b8e80941Smrg                // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
589b8e80941Smrg                ImGuiTreeNodeFlags node_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ((selection_mask & (1 << i)) ? ImGuiTreeNodeFlags_Selected : 0);
590b8e80941Smrg                if (i < 3)
591b8e80941Smrg                {
592b8e80941Smrg                    // Node
593b8e80941Smrg                    bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
594b8e80941Smrg                    if (ImGui::IsItemClicked())
595b8e80941Smrg                        node_clicked = i;
596b8e80941Smrg                    if (node_open)
597b8e80941Smrg                    {
598b8e80941Smrg                        ImGui::Text("Blah blah\nBlah Blah");
599b8e80941Smrg                        ImGui::TreePop();
600b8e80941Smrg                    }
601b8e80941Smrg                }
602b8e80941Smrg                else
603b8e80941Smrg                {
604b8e80941Smrg                    // Leaf: The only reason we have a TreeNode at all is to allow selection of the leaf. Otherwise we can use BulletText() or TreeAdvanceToLabelPos()+Text().
605b8e80941Smrg                    node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
606b8e80941Smrg                    ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
607b8e80941Smrg                    if (ImGui::IsItemClicked())
608b8e80941Smrg                        node_clicked = i;
609b8e80941Smrg                }
610b8e80941Smrg            }
611b8e80941Smrg            if (node_clicked != -1)
612b8e80941Smrg            {
613b8e80941Smrg                // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
614b8e80941Smrg                if (ImGui::GetIO().KeyCtrl)
615b8e80941Smrg                    selection_mask ^= (1 << node_clicked);          // CTRL+click to toggle
616b8e80941Smrg                else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, this commented bit preserve selection when clicking on item that is part of the selection
617b8e80941Smrg                    selection_mask = (1 << node_clicked);           // Click to single-select
618b8e80941Smrg            }
619b8e80941Smrg            ImGui::PopStyleVar();
620b8e80941Smrg            if (align_label_with_current_x_position)
621b8e80941Smrg                ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
622b8e80941Smrg            ImGui::TreePop();
623b8e80941Smrg        }
624b8e80941Smrg        ImGui::TreePop();
625b8e80941Smrg    }
626b8e80941Smrg
627b8e80941Smrg    if (ImGui::TreeNode("Collapsing Headers"))
628b8e80941Smrg    {
629b8e80941Smrg        static bool closable_group = true;
630b8e80941Smrg        ImGui::Checkbox("Enable extra group", &closable_group);
631b8e80941Smrg        if (ImGui::CollapsingHeader("Header"))
632b8e80941Smrg        {
633b8e80941Smrg            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
634b8e80941Smrg            for (int i = 0; i < 5; i++)
635b8e80941Smrg                ImGui::Text("Some content %d", i);
636b8e80941Smrg        }
637b8e80941Smrg        if (ImGui::CollapsingHeader("Header with a close button", &closable_group))
638b8e80941Smrg        {
639b8e80941Smrg            ImGui::Text("IsItemHovered: %d", ImGui::IsItemHovered());
640b8e80941Smrg            for (int i = 0; i < 5; i++)
641b8e80941Smrg                ImGui::Text("More content %d", i);
642b8e80941Smrg        }
643b8e80941Smrg        ImGui::TreePop();
644b8e80941Smrg    }
645b8e80941Smrg
646b8e80941Smrg    if (ImGui::TreeNode("Bullets"))
647b8e80941Smrg    {
648b8e80941Smrg        ImGui::BulletText("Bullet point 1");
649b8e80941Smrg        ImGui::BulletText("Bullet point 2\nOn multiple lines");
650b8e80941Smrg        ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
651b8e80941Smrg        ImGui::Bullet(); ImGui::SmallButton("Button");
652b8e80941Smrg        ImGui::TreePop();
653b8e80941Smrg    }
654b8e80941Smrg
655b8e80941Smrg    if (ImGui::TreeNode("Text"))
656b8e80941Smrg    {
657b8e80941Smrg        if (ImGui::TreeNode("Colored Text"))
658b8e80941Smrg        {
659b8e80941Smrg            // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
660b8e80941Smrg            ImGui::TextColored(ImVec4(1.0f,0.0f,1.0f,1.0f), "Pink");
661b8e80941Smrg            ImGui::TextColored(ImVec4(1.0f,1.0f,0.0f,1.0f), "Yellow");
662b8e80941Smrg            ImGui::TextDisabled("Disabled");
663b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
664b8e80941Smrg            ImGui::TreePop();
665b8e80941Smrg        }
666b8e80941Smrg
667b8e80941Smrg        if (ImGui::TreeNode("Word Wrapping"))
668b8e80941Smrg        {
669b8e80941Smrg            // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
670b8e80941Smrg            ImGui::TextWrapped("This text should automatically wrap on the edge of the window. The current implementation for text wrapping follows simple rules suitable for English and possibly other languages.");
671b8e80941Smrg            ImGui::Spacing();
672b8e80941Smrg
673b8e80941Smrg            static float wrap_width = 200.0f;
674b8e80941Smrg            ImGui::SliderFloat("Wrap width", &wrap_width, -20, 600, "%.0f");
675b8e80941Smrg
676b8e80941Smrg            ImGui::Text("Test paragraph 1:");
677b8e80941Smrg            ImVec2 pos = ImGui::GetCursorScreenPos();
678b8e80941Smrg            ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));
679b8e80941Smrg            ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
680b8e80941Smrg            ImGui::Text("The lazy dog is a good dog. This paragraph is made to fit within %.0f pixels. Testing a 1 character word. The quick brown fox jumps over the lazy dog.", wrap_width);
681b8e80941Smrg            ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
682b8e80941Smrg            ImGui::PopTextWrapPos();
683b8e80941Smrg
684b8e80941Smrg            ImGui::Text("Test paragraph 2:");
685b8e80941Smrg            pos = ImGui::GetCursorScreenPos();
686b8e80941Smrg            ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(pos.x + wrap_width, pos.y), ImVec2(pos.x + wrap_width + 10, pos.y + ImGui::GetTextLineHeight()), IM_COL32(255,0,255,255));
687b8e80941Smrg            ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + wrap_width);
688b8e80941Smrg            ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee   ffffffff. gggggggg!hhhhhhhh");
689b8e80941Smrg            ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
690b8e80941Smrg            ImGui::PopTextWrapPos();
691b8e80941Smrg
692b8e80941Smrg            ImGui::TreePop();
693b8e80941Smrg        }
694b8e80941Smrg
695b8e80941Smrg        if (ImGui::TreeNode("UTF-8 Text"))
696b8e80941Smrg        {
697b8e80941Smrg            // UTF-8 test with Japanese characters
698b8e80941Smrg            // (Needs a suitable font, try Noto, or Arial Unicode, or M+ fonts. Read misc/fonts/README.txt for details.)
699b8e80941Smrg            // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
700b8e80941Smrg            // - For earlier compiler, you may be able to encode your sources as UTF-8 (e.g. Visual Studio save your file as 'UTF-8 without signature')
701b8e80941Smrg            // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.
702b8e80941Smrg            //   Instead we are encoding a few strings with hexadecimal constants. Don't do this in your application!
703b8e80941Smrg            //   Please use u8"text in any language" in your application!
704b8e80941Smrg            // Note that characters values are preserved even by InputText() if the font cannot be displayed, so you can safely copy & paste garbled characters into another application.
705b8e80941Smrg            ImGui::TextWrapped("CJK text will only appears if the font was loaded with the appropriate CJK character ranges. Call io.Font->AddFontFromFileTTF() manually to load extra character ranges. Read misc/fonts/README.txt for details.");
706b8e80941Smrg            ImGui::Text("Hiragana: \xe3\x81\x8b\xe3\x81\x8d\xe3\x81\x8f\xe3\x81\x91\xe3\x81\x93 (kakikukeko)"); // Normally we would use u8"blah blah" with the proper characters directly in the string.
707b8e80941Smrg            ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
708b8e80941Smrg            static char buf[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
709b8e80941Smrg            //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
710b8e80941Smrg            ImGui::InputText("UTF-8 input", buf, IM_ARRAYSIZE(buf));
711b8e80941Smrg            ImGui::TreePop();
712b8e80941Smrg        }
713b8e80941Smrg        ImGui::TreePop();
714b8e80941Smrg    }
715b8e80941Smrg
716b8e80941Smrg    if (ImGui::TreeNode("Images"))
717b8e80941Smrg    {
718b8e80941Smrg        ImGuiIO& io = ImGui::GetIO();
719b8e80941Smrg        ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!");
720b8e80941Smrg
721b8e80941Smrg        // Here we are grabbing the font texture because that's the only one we have access to inside the demo code.
722b8e80941Smrg        // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure.
723b8e80941Smrg        // If you use one of the default imgui_impl_XXXX.cpp renderer, they all have comments at the top of their file to specify what they expect to be stored in ImTextureID.
724b8e80941Smrg        // (for example, the imgui_impl_dx11.cpp renderer expect a 'ID3D11ShaderResourceView*' pointer. The imgui_impl_glfw_gl3.cpp renderer expect a GLuint OpenGL texture identifier etc.)
725b8e80941Smrg        // If you decided that ImTextureID = MyEngineTexture*, then you can pass your MyEngineTexture* pointers to ImGui::Image(), and gather width/height through your own functions, etc.
726b8e80941Smrg        // Using ShowMetricsWindow() as a "debugger" to inspect the draw data that are being passed to your render will help you debug issues if you are confused about this.
727b8e80941Smrg        // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
728b8e80941Smrg        ImTextureID my_tex_id = io.Fonts->TexID;
729b8e80941Smrg        float my_tex_w = (float)io.Fonts->TexWidth;
730b8e80941Smrg        float my_tex_h = (float)io.Fonts->TexHeight;
731b8e80941Smrg
732b8e80941Smrg        ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
733b8e80941Smrg        ImVec2 pos = ImGui::GetCursorScreenPos();
734b8e80941Smrg        ImGui::Image(my_tex_id, ImVec2(my_tex_w, my_tex_h), ImVec2(0,0), ImVec2(1,1), ImColor(255,255,255,255), ImColor(255,255,255,128));
735b8e80941Smrg        if (ImGui::IsItemHovered())
736b8e80941Smrg        {
737b8e80941Smrg            ImGui::BeginTooltip();
738b8e80941Smrg            float region_sz = 32.0f;
739b8e80941Smrg            float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; if (region_x < 0.0f) region_x = 0.0f; else if (region_x > my_tex_w - region_sz) region_x = my_tex_w - region_sz;
740b8e80941Smrg            float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; if (region_y < 0.0f) region_y = 0.0f; else if (region_y > my_tex_h - region_sz) region_y = my_tex_h - region_sz;
741b8e80941Smrg            float zoom = 4.0f;
742b8e80941Smrg            ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
743b8e80941Smrg            ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
744b8e80941Smrg            ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
745b8e80941Smrg            ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
746b8e80941Smrg            ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128));
747b8e80941Smrg            ImGui::EndTooltip();
748b8e80941Smrg        }
749b8e80941Smrg        ImGui::TextWrapped("And now some textured buttons..");
750b8e80941Smrg        static int pressed_count = 0;
751b8e80941Smrg        for (int i = 0; i < 8; i++)
752b8e80941Smrg        {
753b8e80941Smrg            ImGui::PushID(i);
754b8e80941Smrg            int frame_padding = -1 + i;     // -1 = uses default padding
755b8e80941Smrg            if (ImGui::ImageButton(my_tex_id, ImVec2(32,32), ImVec2(0,0), ImVec2(32.0f/my_tex_w,32/my_tex_h), frame_padding, ImColor(0,0,0,255)))
756b8e80941Smrg                pressed_count += 1;
757b8e80941Smrg            ImGui::PopID();
758b8e80941Smrg            ImGui::SameLine();
759b8e80941Smrg        }
760b8e80941Smrg        ImGui::NewLine();
761b8e80941Smrg        ImGui::Text("Pressed %d times.", pressed_count);
762b8e80941Smrg        ImGui::TreePop();
763b8e80941Smrg    }
764b8e80941Smrg
765b8e80941Smrg    if (ImGui::TreeNode("Combo"))
766b8e80941Smrg    {
767b8e80941Smrg        // Expose flags as checkbox for the demo
768b8e80941Smrg        static ImGuiComboFlags flags = 0;
769b8e80941Smrg        ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
770b8e80941Smrg        if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
771b8e80941Smrg            flags &= ~ImGuiComboFlags_NoPreview;     // Clear the other flag, as we cannot combine both
772b8e80941Smrg        if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
773b8e80941Smrg            flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both
774b8e80941Smrg
775b8e80941Smrg        // General BeginCombo() API, you have full control over your selection data and display type.
776b8e80941Smrg        // (your selection data could be an index, a pointer to the object, an id for the object, a flag stored in the object itself, etc.)
777b8e80941Smrg        const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
778b8e80941Smrg        static const char* item_current = items[0];            // Here our selection is a single pointer stored outside the object.
779b8e80941Smrg        if (ImGui::BeginCombo("combo 1", item_current, flags)) // The second parameter is the label previewed before opening the combo.
780b8e80941Smrg        {
781b8e80941Smrg            for (int n = 0; n < IM_ARRAYSIZE(items); n++)
782b8e80941Smrg            {
783b8e80941Smrg                bool is_selected = (item_current == items[n]);
784b8e80941Smrg                if (ImGui::Selectable(items[n], is_selected))
785b8e80941Smrg                    item_current = items[n];
786b8e80941Smrg                if (is_selected)
787b8e80941Smrg                    ImGui::SetItemDefaultFocus();   // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
788b8e80941Smrg            }
789b8e80941Smrg            ImGui::EndCombo();
790b8e80941Smrg        }
791b8e80941Smrg
792b8e80941Smrg        // Simplified one-liner Combo() API, using values packed in a single constant string
793b8e80941Smrg        static int item_current_2 = 0;
794b8e80941Smrg        ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
795b8e80941Smrg
796b8e80941Smrg        // Simplified one-liner Combo() using an array of const char*
797b8e80941Smrg        static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview
798b8e80941Smrg        ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items));
799b8e80941Smrg
800b8e80941Smrg        // Simplified one-liner Combo() using an accessor function
801b8e80941Smrg        struct FuncHolder { static bool ItemGetter(void* data, int idx, const char** out_str) { *out_str = ((const char**)data)[idx]; return true; } };
802b8e80941Smrg        static int item_current_4 = 0;
803b8e80941Smrg        ImGui::Combo("combo 4 (function)", &item_current_4, &FuncHolder::ItemGetter, items, IM_ARRAYSIZE(items));
804b8e80941Smrg
805b8e80941Smrg        ImGui::TreePop();
806b8e80941Smrg    }
807b8e80941Smrg
808b8e80941Smrg    if (ImGui::TreeNode("Selectables"))
809b8e80941Smrg    {
810b8e80941Smrg        // Selectable() has 2 overloads:
811b8e80941Smrg        // - The one taking "bool selected" as a read-only selection information. When Selectable() has been clicked is returns true and you can alter selection state accordingly.
812b8e80941Smrg        // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
813b8e80941Smrg        // The earlier is more flexible, as in real application your selection may be stored in a different manner (in flags within objects, as an external list, etc).
814b8e80941Smrg        if (ImGui::TreeNode("Basic"))
815b8e80941Smrg        {
816b8e80941Smrg            static bool selection[5] = { false, true, false, false, false };
817b8e80941Smrg            ImGui::Selectable("1. I am selectable", &selection[0]);
818b8e80941Smrg            ImGui::Selectable("2. I am selectable", &selection[1]);
819b8e80941Smrg            ImGui::Text("3. I am not selectable");
820b8e80941Smrg            ImGui::Selectable("4. I am selectable", &selection[3]);
821b8e80941Smrg            if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick))
822b8e80941Smrg                if (ImGui::IsMouseDoubleClicked(0))
823b8e80941Smrg                    selection[4] = !selection[4];
824b8e80941Smrg            ImGui::TreePop();
825b8e80941Smrg        }
826b8e80941Smrg        if (ImGui::TreeNode("Selection State: Single Selection"))
827b8e80941Smrg        {
828b8e80941Smrg            static int selected = -1;
829b8e80941Smrg            for (int n = 0; n < 5; n++)
830b8e80941Smrg            {
831b8e80941Smrg                char buf[32];
832b8e80941Smrg                sprintf(buf, "Object %d", n);
833b8e80941Smrg                if (ImGui::Selectable(buf, selected == n))
834b8e80941Smrg                    selected = n;
835b8e80941Smrg            }
836b8e80941Smrg            ImGui::TreePop();
837b8e80941Smrg        }
838b8e80941Smrg        if (ImGui::TreeNode("Selection State: Multiple Selection"))
839b8e80941Smrg        {
840b8e80941Smrg            ShowHelpMarker("Hold CTRL and click to select multiple items.");
841b8e80941Smrg            static bool selection[5] = { false, false, false, false, false };
842b8e80941Smrg            for (int n = 0; n < 5; n++)
843b8e80941Smrg            {
844b8e80941Smrg                char buf[32];
845b8e80941Smrg                sprintf(buf, "Object %d", n);
846b8e80941Smrg                if (ImGui::Selectable(buf, selection[n]))
847b8e80941Smrg                {
848b8e80941Smrg                    if (!ImGui::GetIO().KeyCtrl)    // Clear selection when CTRL is not held
849b8e80941Smrg                        memset(selection, 0, sizeof(selection));
850b8e80941Smrg                    selection[n] ^= 1;
851b8e80941Smrg                }
852b8e80941Smrg            }
853b8e80941Smrg            ImGui::TreePop();
854b8e80941Smrg        }
855b8e80941Smrg        if (ImGui::TreeNode("Rendering more text into the same line"))
856b8e80941Smrg        {
857b8e80941Smrg            // Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically.
858b8e80941Smrg            static bool selected[3] = { false, false, false };
859b8e80941Smrg            ImGui::Selectable("main.c",    &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
860b8e80941Smrg            ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
861b8e80941Smrg            ImGui::Selectable("Hello.h",   &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
862b8e80941Smrg            ImGui::TreePop();
863b8e80941Smrg        }
864b8e80941Smrg        if (ImGui::TreeNode("In columns"))
865b8e80941Smrg        {
866b8e80941Smrg            ImGui::Columns(3, NULL, false);
867b8e80941Smrg            static bool selected[16] = { 0 };
868b8e80941Smrg            for (int i = 0; i < 16; i++)
869b8e80941Smrg            {
870b8e80941Smrg                char label[32]; sprintf(label, "Item %d", i);
871b8e80941Smrg                if (ImGui::Selectable(label, &selected[i])) {}
872b8e80941Smrg                ImGui::NextColumn();
873b8e80941Smrg            }
874b8e80941Smrg            ImGui::Columns(1);
875b8e80941Smrg            ImGui::TreePop();
876b8e80941Smrg        }
877b8e80941Smrg        if (ImGui::TreeNode("Grid"))
878b8e80941Smrg        {
879b8e80941Smrg            static bool selected[4*4] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
880b8e80941Smrg            for (int i = 0; i < 4*4; i++)
881b8e80941Smrg            {
882b8e80941Smrg                ImGui::PushID(i);
883b8e80941Smrg                if (ImGui::Selectable("Sailor", &selected[i], 0, ImVec2(50,50)))
884b8e80941Smrg                {
885b8e80941Smrg                    // Note: We _unnecessarily_ test for both x/y and i here only to silence some static analyzer. The second part of each test is unnecessary.
886b8e80941Smrg                    int x = i % 4;
887b8e80941Smrg                    int y = i / 4;
888b8e80941Smrg                    if (x > 0)           { selected[i - 1] ^= 1; }
889b8e80941Smrg                    if (x < 3 && i < 15) { selected[i + 1] ^= 1; }
890b8e80941Smrg                    if (y > 0 && i > 3)  { selected[i - 4] ^= 1; }
891b8e80941Smrg                    if (y < 3 && i < 12) { selected[i + 4] ^= 1; }
892b8e80941Smrg                }
893b8e80941Smrg                if ((i % 4) < 3) ImGui::SameLine();
894b8e80941Smrg                ImGui::PopID();
895b8e80941Smrg            }
896b8e80941Smrg            ImGui::TreePop();
897b8e80941Smrg        }
898b8e80941Smrg        if (ImGui::TreeNode("Alignment"))
899b8e80941Smrg        {
900b8e80941Smrg            ShowHelpMarker("Alignment applies when a selectable is larger than its text content.\nBy default, Selectables uses style.SelectableTextAlign but it can be overriden on a per-item basis using PushStyleVar().");
901b8e80941Smrg            static bool selected[3*3] = { true, false, true, false, true, false, true, false, true };
902b8e80941Smrg            for (int y = 0; y < 3; y++)
903b8e80941Smrg            {
904b8e80941Smrg                for (int x = 0; x < 3; x++)
905b8e80941Smrg                {
906b8e80941Smrg                    ImVec2 alignment = ImVec2((float)x / 2.0f, (float)y / 2.0f);
907b8e80941Smrg                    char name[32];
908b8e80941Smrg                    sprintf(name, "(%.1f,%.1f)", alignment.x, alignment.y);
909b8e80941Smrg                    if (x > 0) ImGui::SameLine();
910b8e80941Smrg                    ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, alignment);
911b8e80941Smrg                    ImGui::Selectable(name, &selected[3*y+x], ImGuiSelectableFlags_None, ImVec2(80,80));
912b8e80941Smrg                    ImGui::PopStyleVar();
913b8e80941Smrg                }
914b8e80941Smrg            }
915b8e80941Smrg            ImGui::TreePop();
916b8e80941Smrg        }
917b8e80941Smrg        ImGui::TreePop();
918b8e80941Smrg    }
919b8e80941Smrg
920b8e80941Smrg    if (ImGui::TreeNode("Filtered Text Input"))
921b8e80941Smrg    {
922b8e80941Smrg        static char buf1[64] = ""; ImGui::InputText("default", buf1, 64);
923b8e80941Smrg        static char buf2[64] = ""; ImGui::InputText("decimal", buf2, 64, ImGuiInputTextFlags_CharsDecimal);
924b8e80941Smrg        static char buf3[64] = ""; ImGui::InputText("hexadecimal", buf3, 64, ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase);
925b8e80941Smrg        static char buf4[64] = ""; ImGui::InputText("uppercase", buf4, 64, ImGuiInputTextFlags_CharsUppercase);
926b8e80941Smrg        static char buf5[64] = ""; ImGui::InputText("no blank", buf5, 64, ImGuiInputTextFlags_CharsNoBlank);
927b8e80941Smrg        struct TextFilters { static int FilterImGuiLetters(ImGuiInputTextCallbackData* data) { if (data->EventChar < 256 && strchr("imgui", (char)data->EventChar)) return 0; return 1; } };
928b8e80941Smrg        static char buf6[64] = ""; ImGui::InputText("\"imgui\" letters", buf6, 64, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::FilterImGuiLetters);
929b8e80941Smrg
930b8e80941Smrg        ImGui::Text("Password input");
931b8e80941Smrg        static char bufpass[64] = "password123";
932b8e80941Smrg        ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
933b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
934b8e80941Smrg        ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
935b8e80941Smrg
936b8e80941Smrg        ImGui::TreePop();
937b8e80941Smrg    }
938b8e80941Smrg
939b8e80941Smrg    if (ImGui::TreeNode("Multi-line Text Input"))
940b8e80941Smrg    {
941b8e80941Smrg        // Note: we are using a fixed-sized buffer for simplicity here. See ImGuiInputTextFlags_CallbackResize
942b8e80941Smrg        // and the code in misc/cpp/imgui_stdlib.h for how to setup InputText() for dynamically resizing strings.
943b8e80941Smrg        static bool read_only = false;
944b8e80941Smrg        static char text[1024*16] =
945b8e80941Smrg            "/*\n"
946b8e80941Smrg            " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
947b8e80941Smrg            " the hexadecimal encoding of one offending instruction,\n"
948b8e80941Smrg            " more formally, the invalid operand with locked CMPXCHG8B\n"
949b8e80941Smrg            " instruction bug, is a design flaw in the majority of\n"
950b8e80941Smrg            " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
951b8e80941Smrg            " processors (all in the P5 microarchitecture).\n"
952b8e80941Smrg            "*/\n\n"
953b8e80941Smrg            "label:\n"
954b8e80941Smrg            "\tlock cmpxchg8b eax\n";
955b8e80941Smrg
956b8e80941Smrg        ShowHelpMarker("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)");
957b8e80941Smrg        ImGui::Checkbox("Read-only", &read_only);
958b8e80941Smrg        ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput | (read_only ? ImGuiInputTextFlags_ReadOnly : 0);
959b8e80941Smrg        ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-1.0f, ImGui::GetTextLineHeight() * 16), flags);
960b8e80941Smrg        ImGui::TreePop();
961b8e80941Smrg    }
962b8e80941Smrg
963b8e80941Smrg    if (ImGui::TreeNode("Plots Widgets"))
964b8e80941Smrg    {
965b8e80941Smrg        static bool animate = true;
966b8e80941Smrg        ImGui::Checkbox("Animate", &animate);
967b8e80941Smrg
968b8e80941Smrg        static float arr[] = { 0.6f, 0.1f, 1.0f, 0.5f, 0.92f, 0.1f, 0.2f };
969b8e80941Smrg        ImGui::PlotLines("Frame Times", arr, IM_ARRAYSIZE(arr));
970b8e80941Smrg
971b8e80941Smrg        // Create a dummy array of contiguous float values to plot
972b8e80941Smrg        // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter.
973b8e80941Smrg        static float values[90] = { 0 };
974b8e80941Smrg        static int values_offset = 0;
975b8e80941Smrg        static double refresh_time = 0.0;
976b8e80941Smrg        if (!animate || refresh_time == 0.0)
977b8e80941Smrg            refresh_time = ImGui::GetTime();
978b8e80941Smrg        while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo
979b8e80941Smrg        {
980b8e80941Smrg            static float phase = 0.0f;
981b8e80941Smrg            values[values_offset] = cosf(phase);
982b8e80941Smrg            values_offset = (values_offset+1) % IM_ARRAYSIZE(values);
983b8e80941Smrg            phase += 0.10f*values_offset;
984b8e80941Smrg            refresh_time += 1.0f/60.0f;
985b8e80941Smrg        }
986b8e80941Smrg        ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80));
987b8e80941Smrg        ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80));
988b8e80941Smrg
989b8e80941Smrg        // Use functions to generate output
990b8e80941Smrg        // FIXME: This is rather awkward because current plot API only pass in indices. We probably want an API passing floats and user provide sample rate/count.
991b8e80941Smrg        struct Funcs
992b8e80941Smrg        {
993b8e80941Smrg            static float Sin(void*, int i) { return sinf(i * 0.1f); }
994b8e80941Smrg            static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; }
995b8e80941Smrg        };
996b8e80941Smrg        static int func_type = 0, display_count = 70;
997b8e80941Smrg        ImGui::Separator();
998b8e80941Smrg        ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type, "Sin\0Saw\0"); ImGui::PopItemWidth();
999b8e80941Smrg        ImGui::SameLine();
1000b8e80941Smrg        ImGui::SliderInt("Sample count", &display_count, 1, 400);
1001b8e80941Smrg        float (*func)(void*, int) = (func_type == 0) ? Funcs::Sin : Funcs::Saw;
1002b8e80941Smrg        ImGui::PlotLines("Lines", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
1003b8e80941Smrg        ImGui::PlotHistogram("Histogram", func, NULL, display_count, 0, NULL, -1.0f, 1.0f, ImVec2(0,80));
1004b8e80941Smrg        ImGui::Separator();
1005b8e80941Smrg
1006b8e80941Smrg        // Animate a simple progress bar
1007b8e80941Smrg        static float progress = 0.0f, progress_dir = 1.0f;
1008b8e80941Smrg        if (animate)
1009b8e80941Smrg        {
1010b8e80941Smrg            progress += progress_dir * 0.4f * ImGui::GetIO().DeltaTime;
1011b8e80941Smrg            if (progress >= +1.1f) { progress = +1.1f; progress_dir *= -1.0f; }
1012b8e80941Smrg            if (progress <= -0.1f) { progress = -0.1f; progress_dir *= -1.0f; }
1013b8e80941Smrg        }
1014b8e80941Smrg
1015b8e80941Smrg        // Typically we would use ImVec2(-1.0f,0.0f) to use all available width, or ImVec2(width,0.0f) for a specified width. ImVec2(0.0f,0.0f) uses ItemWidth.
1016b8e80941Smrg        ImGui::ProgressBar(progress, ImVec2(0.0f,0.0f));
1017b8e80941Smrg        ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
1018b8e80941Smrg        ImGui::Text("Progress Bar");
1019b8e80941Smrg
1020b8e80941Smrg        float progress_saturated = (progress < 0.0f) ? 0.0f : (progress > 1.0f) ? 1.0f : progress;
1021b8e80941Smrg        char buf[32];
1022b8e80941Smrg        sprintf(buf, "%d/%d", (int)(progress_saturated*1753), 1753);
1023b8e80941Smrg        ImGui::ProgressBar(progress, ImVec2(0.f,0.f), buf);
1024b8e80941Smrg        ImGui::TreePop();
1025b8e80941Smrg    }
1026b8e80941Smrg
1027b8e80941Smrg    if (ImGui::TreeNode("Color/Picker Widgets"))
1028b8e80941Smrg    {
1029b8e80941Smrg        static ImVec4 color = ImVec4(114.0f/255.0f, 144.0f/255.0f, 154.0f/255.0f, 200.0f/255.0f);
1030b8e80941Smrg
1031b8e80941Smrg        static bool alpha_preview = true;
1032b8e80941Smrg        static bool alpha_half_preview = false;
1033b8e80941Smrg        static bool drag_and_drop = true;
1034b8e80941Smrg        static bool options_menu = true;
1035b8e80941Smrg        static bool hdr = false;
1036b8e80941Smrg        ImGui::Checkbox("With Alpha Preview", &alpha_preview);
1037b8e80941Smrg        ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview);
1038b8e80941Smrg        ImGui::Checkbox("With Drag and Drop", &drag_and_drop);
1039b8e80941Smrg        ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
1040b8e80941Smrg        ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
1041b8e80941Smrg        int 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);
1042b8e80941Smrg
1043b8e80941Smrg        ImGui::Text("Color widget:");
1044b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
1045b8e80941Smrg        ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags);
1046b8e80941Smrg
1047b8e80941Smrg        ImGui::Text("Color widget HSV with Alpha:");
1048b8e80941Smrg        ImGui::ColorEdit4("MyColor##2", (float*)&color, ImGuiColorEditFlags_HSV | misc_flags);
1049b8e80941Smrg
1050b8e80941Smrg        ImGui::Text("Color widget with Float Display:");
1051b8e80941Smrg        ImGui::ColorEdit4("MyColor##2f", (float*)&color, ImGuiColorEditFlags_Float | misc_flags);
1052b8e80941Smrg
1053b8e80941Smrg        ImGui::Text("Color button with Picker:");
1054b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("With the ImGuiColorEditFlags_NoInputs flag you can hide all the slider/text inputs.\nWith the ImGuiColorEditFlags_NoLabel flag you can pass a non-empty label which will only be used for the tooltip and picker popup.");
1055b8e80941Smrg        ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags);
1056b8e80941Smrg
1057b8e80941Smrg        ImGui::Text("Color button with Custom Picker Popup:");
1058b8e80941Smrg
1059b8e80941Smrg        // Generate a dummy default palette. The palette will persist and can be edited.
1060b8e80941Smrg        static bool saved_palette_init = true;
1061b8e80941Smrg        static ImVec4 saved_palette[32] = { };
1062b8e80941Smrg        if (saved_palette_init)
1063b8e80941Smrg        {
1064b8e80941Smrg            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1065b8e80941Smrg            {
1066b8e80941Smrg                ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z);
1067b8e80941Smrg                saved_palette[n].w = 1.0f; // Alpha
1068b8e80941Smrg            }
1069b8e80941Smrg            saved_palette_init = false;
1070b8e80941Smrg        }
1071b8e80941Smrg
1072b8e80941Smrg        static ImVec4 backup_color;
1073b8e80941Smrg        bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags);
1074b8e80941Smrg        ImGui::SameLine();
1075b8e80941Smrg        open_popup |= ImGui::Button("Palette");
1076b8e80941Smrg        if (open_popup)
1077b8e80941Smrg        {
1078b8e80941Smrg            ImGui::OpenPopup("mypicker");
1079b8e80941Smrg            backup_color = color;
1080b8e80941Smrg        }
1081b8e80941Smrg        if (ImGui::BeginPopup("mypicker"))
1082b8e80941Smrg        {
1083b8e80941Smrg            ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
1084b8e80941Smrg            ImGui::Separator();
1085b8e80941Smrg            ImGui::ColorPicker4("##picker", (float*)&color, misc_flags | ImGuiColorEditFlags_NoSidePreview | ImGuiColorEditFlags_NoSmallPreview);
1086b8e80941Smrg            ImGui::SameLine();
1087b8e80941Smrg
1088b8e80941Smrg            ImGui::BeginGroup(); // Lock X position
1089b8e80941Smrg            ImGui::Text("Current");
1090b8e80941Smrg            ImGui::ColorButton("##current", color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40));
1091b8e80941Smrg            ImGui::Text("Previous");
1092b8e80941Smrg            if (ImGui::ColorButton("##previous", backup_color, ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_AlphaPreviewHalf, ImVec2(60,40)))
1093b8e80941Smrg                color = backup_color;
1094b8e80941Smrg            ImGui::Separator();
1095b8e80941Smrg            ImGui::Text("Palette");
1096b8e80941Smrg            for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++)
1097b8e80941Smrg            {
1098b8e80941Smrg                ImGui::PushID(n);
1099b8e80941Smrg                if ((n % 8) != 0)
1100b8e80941Smrg                    ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y);
1101b8e80941Smrg                if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20)))
1102b8e80941Smrg                    color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha!
1103b8e80941Smrg
1104b8e80941Smrg                // Allow user to drop colors into each palette entry
1105b8e80941Smrg                // (Note that ColorButton is already a drag source by default, unless using ImGuiColorEditFlags_NoDragDrop)
1106b8e80941Smrg                if (ImGui::BeginDragDropTarget())
1107b8e80941Smrg                {
1108b8e80941Smrg                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F))
1109b8e80941Smrg                        memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3);
1110b8e80941Smrg                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F))
1111b8e80941Smrg                        memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4);
1112b8e80941Smrg                    ImGui::EndDragDropTarget();
1113b8e80941Smrg                }
1114b8e80941Smrg
1115b8e80941Smrg                ImGui::PopID();
1116b8e80941Smrg            }
1117b8e80941Smrg            ImGui::EndGroup();
1118b8e80941Smrg            ImGui::EndPopup();
1119b8e80941Smrg        }
1120b8e80941Smrg
1121b8e80941Smrg        ImGui::Text("Color button only:");
1122b8e80941Smrg        ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80));
1123b8e80941Smrg
1124b8e80941Smrg        ImGui::Text("Color picker:");
1125b8e80941Smrg        static bool alpha = true;
1126b8e80941Smrg        static bool alpha_bar = true;
1127b8e80941Smrg        static bool side_preview = true;
1128b8e80941Smrg        static bool ref_color = false;
1129b8e80941Smrg        static ImVec4 ref_color_v(1.0f,0.0f,1.0f,0.5f);
1130b8e80941Smrg        static int inputs_mode = 2;
1131b8e80941Smrg        static int picker_mode = 0;
1132b8e80941Smrg        ImGui::Checkbox("With Alpha", &alpha);
1133b8e80941Smrg        ImGui::Checkbox("With Alpha Bar", &alpha_bar);
1134b8e80941Smrg        ImGui::Checkbox("With Side Preview", &side_preview);
1135b8e80941Smrg        if (side_preview)
1136b8e80941Smrg        {
1137b8e80941Smrg            ImGui::SameLine();
1138b8e80941Smrg            ImGui::Checkbox("With Ref Color", &ref_color);
1139b8e80941Smrg            if (ref_color)
1140b8e80941Smrg            {
1141b8e80941Smrg                ImGui::SameLine();
1142b8e80941Smrg                ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | misc_flags);
1143b8e80941Smrg            }
1144b8e80941Smrg        }
1145b8e80941Smrg        ImGui::Combo("Inputs Mode", &inputs_mode, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
1146b8e80941Smrg        ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
1147b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
1148b8e80941Smrg        ImGuiColorEditFlags flags = misc_flags;
1149b8e80941Smrg        if (!alpha) flags |= ImGuiColorEditFlags_NoAlpha; // This is by default if you call ColorPicker3() instead of ColorPicker4()
1150b8e80941Smrg        if (alpha_bar) flags |= ImGuiColorEditFlags_AlphaBar;
1151b8e80941Smrg        if (!side_preview) flags |= ImGuiColorEditFlags_NoSidePreview;
1152b8e80941Smrg        if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
1153b8e80941Smrg        if (picker_mode == 2) flags |= ImGuiColorEditFlags_PickerHueWheel;
1154b8e80941Smrg        if (inputs_mode == 1) flags |= ImGuiColorEditFlags_NoInputs;
1155b8e80941Smrg        if (inputs_mode == 2) flags |= ImGuiColorEditFlags_RGB;
1156b8e80941Smrg        if (inputs_mode == 3) flags |= ImGuiColorEditFlags_HSV;
1157b8e80941Smrg        if (inputs_mode == 4) flags |= ImGuiColorEditFlags_HEX;
1158b8e80941Smrg        ImGui::ColorPicker4("MyColor##4", (float*)&color, flags, ref_color ? &ref_color_v.x : NULL);
1159b8e80941Smrg
1160b8e80941Smrg        ImGui::Text("Programmatically set defaults:");
1161b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("SetColorEditOptions() is designed to allow you to set boot-time default.\nWe don't have Push/Pop functions because you can force options on a per-widget basis if needed, and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid encouraging you to persistently save values that aren't forward-compatible.");
1162b8e80941Smrg        if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
1163b8e80941Smrg            ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_HSV | ImGuiColorEditFlags_PickerHueBar);
1164b8e80941Smrg        if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
1165b8e80941Smrg            ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
1166b8e80941Smrg
1167b8e80941Smrg        ImGui::TreePop();
1168b8e80941Smrg    }
1169b8e80941Smrg
1170b8e80941Smrg    if (ImGui::TreeNode("Range Widgets"))
1171b8e80941Smrg    {
1172b8e80941Smrg        static float begin = 10, end = 90;
1173b8e80941Smrg        static int begin_i = 100, end_i = 1000;
1174b8e80941Smrg        ImGui::DragFloatRange2("range", &begin, &end, 0.25f, 0.0f, 100.0f, "Min: %.1f %%", "Max: %.1f %%");
1175b8e80941Smrg        ImGui::DragIntRange2("range int (no bounds)", &begin_i, &end_i, 5, 0, 0, "Min: %d units", "Max: %d units");
1176b8e80941Smrg        ImGui::TreePop();
1177b8e80941Smrg    }
1178b8e80941Smrg
1179b8e80941Smrg    if (ImGui::TreeNode("Data Types"))
1180b8e80941Smrg    {
1181b8e80941Smrg        // The DragScalar/InputScalar/SliderScalar functions allow various data types: signed/unsigned int/long long and float/double
1182b8e80941Smrg        // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type,
1183b8e80941Smrg        // and passing all arguments by address.
1184b8e80941Smrg        // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
1185b8e80941Smrg        // In practice, if you frequently use a given type that is not covered by the normal API entry points, you can wrap it
1186b8e80941Smrg        // yourself inside a 1 line function which can take typed argument as value instead of void*, and then pass their address
1187b8e80941Smrg        // to the generic function. For example:
1188b8e80941Smrg        //   bool MySliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld")
1189b8e80941Smrg        //   {
1190b8e80941Smrg        //      return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format);
1191b8e80941Smrg        //   }
1192b8e80941Smrg
1193b8e80941Smrg        // Limits (as helper variables that we can take the address of)
1194b8e80941Smrg        // Note that the SliderScalar function has a maximum usable range of half the natural type maximum, hence the /2 below.
1195b8e80941Smrg        #ifndef LLONG_MIN
1196b8e80941Smrg        ImS64 LLONG_MIN = -9223372036854775807LL - 1;
1197b8e80941Smrg        ImS64 LLONG_MAX = 9223372036854775807LL;
1198b8e80941Smrg        ImU64 ULLONG_MAX = (2ULL * 9223372036854775807LL + 1);
1199b8e80941Smrg        #endif
1200b8e80941Smrg        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;
1201b8e80941Smrg        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;
1202b8e80941Smrg        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;
1203b8e80941Smrg        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;
1204b8e80941Smrg        const float   f32_zero = 0.f, f32_one = 1.f, f32_lo_a = -10000000000.0f, f32_hi_a = +10000000000.0f;
1205b8e80941Smrg        const double  f64_zero = 0.,  f64_one = 1.,  f64_lo_a = -1000000000000000.0, f64_hi_a = +1000000000000000.0;
1206b8e80941Smrg
1207b8e80941Smrg        // State
1208b8e80941Smrg        static ImS32  s32_v = -1;
1209b8e80941Smrg        static ImU32  u32_v = (ImU32)-1;
1210b8e80941Smrg        static ImS64  s64_v = -1;
1211b8e80941Smrg        static ImU64  u64_v = (ImU64)-1;
1212b8e80941Smrg        static float  f32_v = 0.123f;
1213b8e80941Smrg        static double f64_v = 90000.01234567890123456789;
1214b8e80941Smrg
1215b8e80941Smrg        const float drag_speed = 0.2f;
1216b8e80941Smrg        static bool drag_clamp = false;
1217b8e80941Smrg        ImGui::Text("Drags:");
1218b8e80941Smrg        ImGui::Checkbox("Clamp integers to 0..50", &drag_clamp); ImGui::SameLine(); ShowHelpMarker("As with every widgets in dear imgui, we never modify values unless there is a user interaction.\nYou can override the clamping limits by using CTRL+Click to input a value.");
1219b8e80941Smrg        ImGui::DragScalar("drag s32",       ImGuiDataType_S32,    &s32_v, drag_speed, drag_clamp ? &s32_zero : NULL, drag_clamp ? &s32_fifty : NULL);
1220b8e80941Smrg        ImGui::DragScalar("drag u32",       ImGuiDataType_U32,    &u32_v, drag_speed, drag_clamp ? &u32_zero : NULL, drag_clamp ? &u32_fifty : NULL, "%u ms");
1221b8e80941Smrg        ImGui::DragScalar("drag s64",       ImGuiDataType_S64,    &s64_v, drag_speed, drag_clamp ? &s64_zero : NULL, drag_clamp ? &s64_fifty : NULL);
1222b8e80941Smrg        ImGui::DragScalar("drag u64",       ImGuiDataType_U64,    &u64_v, drag_speed, drag_clamp ? &u64_zero : NULL, drag_clamp ? &u64_fifty : NULL);
1223b8e80941Smrg        ImGui::DragScalar("drag float",     ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", 1.0f);
1224b8e80941Smrg        ImGui::DragScalar("drag float ^2",  ImGuiDataType_Float,  &f32_v, 0.005f,  &f32_zero, &f32_one, "%f", 2.0f); ImGui::SameLine(); ShowHelpMarker("You can use the 'power' parameter to increase tweaking precision on one side of the range.");
1225b8e80941Smrg        ImGui::DragScalar("drag double",    ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, NULL,     "%.10f grams", 1.0f);
1226b8e80941Smrg        ImGui::DragScalar("drag double ^2", ImGuiDataType_Double, &f64_v, 0.0005f, &f64_zero, &f64_one, "0 < %.10f < 1", 2.0f);
1227b8e80941Smrg
1228b8e80941Smrg        ImGui::Text("Sliders");
1229b8e80941Smrg        ImGui::SliderScalar("slider s32 low",     ImGuiDataType_S32,    &s32_v, &s32_zero, &s32_fifty,"%d");
1230b8e80941Smrg        ImGui::SliderScalar("slider s32 high",    ImGuiDataType_S32,    &s32_v, &s32_hi_a, &s32_hi_b, "%d");
1231b8e80941Smrg        ImGui::SliderScalar("slider s32 full",    ImGuiDataType_S32,    &s32_v, &s32_min,  &s32_max,  "%d");
1232b8e80941Smrg        ImGui::SliderScalar("slider u32 low",     ImGuiDataType_U32,    &u32_v, &u32_zero, &u32_fifty,"%u");
1233b8e80941Smrg        ImGui::SliderScalar("slider u32 high",    ImGuiDataType_U32,    &u32_v, &u32_hi_a, &u32_hi_b, "%u");
1234b8e80941Smrg        ImGui::SliderScalar("slider u32 full",    ImGuiDataType_U32,    &u32_v, &u32_min,  &u32_max,  "%u");
1235b8e80941Smrg        ImGui::SliderScalar("slider s64 low",     ImGuiDataType_S64,    &s64_v, &s64_zero, &s64_fifty,"%I64d");
1236b8e80941Smrg        ImGui::SliderScalar("slider s64 high",    ImGuiDataType_S64,    &s64_v, &s64_hi_a, &s64_hi_b, "%I64d");
1237b8e80941Smrg        ImGui::SliderScalar("slider s64 full",    ImGuiDataType_S64,    &s64_v, &s64_min,  &s64_max,  "%I64d");
1238b8e80941Smrg        ImGui::SliderScalar("slider u64 low",     ImGuiDataType_U64,    &u64_v, &u64_zero, &u64_fifty,"%I64u ms");
1239b8e80941Smrg        ImGui::SliderScalar("slider u64 high",    ImGuiDataType_U64,    &u64_v, &u64_hi_a, &u64_hi_b, "%I64u ms");
1240b8e80941Smrg        ImGui::SliderScalar("slider u64 full",    ImGuiDataType_U64,    &u64_v, &u64_min,  &u64_max,  "%I64u ms");
1241b8e80941Smrg        ImGui::SliderScalar("slider float low",   ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one);
1242b8e80941Smrg        ImGui::SliderScalar("slider float low^2", ImGuiDataType_Float,  &f32_v, &f32_zero, &f32_one,  "%.10f", 2.0f);
1243b8e80941Smrg        ImGui::SliderScalar("slider float high",  ImGuiDataType_Float,  &f32_v, &f32_lo_a, &f32_hi_a, "%e");
1244b8e80941Smrg        ImGui::SliderScalar("slider double low",  ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f grams", 1.0f);
1245b8e80941Smrg        ImGui::SliderScalar("slider double low^2",ImGuiDataType_Double, &f64_v, &f64_zero, &f64_one,  "%.10f", 2.0f);
1246b8e80941Smrg        ImGui::SliderScalar("slider double high", ImGuiDataType_Double, &f64_v, &f64_lo_a, &f64_hi_a, "%e grams", 1.0f);
1247b8e80941Smrg
1248b8e80941Smrg        static bool inputs_step = true;
1249b8e80941Smrg        ImGui::Text("Inputs");
1250b8e80941Smrg        ImGui::Checkbox("Show step buttons", &inputs_step);
1251b8e80941Smrg        ImGui::InputScalar("input s32",     ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%d");
1252b8e80941Smrg        ImGui::InputScalar("input s32 hex", ImGuiDataType_S32,    &s32_v, inputs_step ? &s32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1253b8e80941Smrg        ImGui::InputScalar("input u32",     ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%u");
1254b8e80941Smrg        ImGui::InputScalar("input u32 hex", ImGuiDataType_U32,    &u32_v, inputs_step ? &u32_one : NULL, NULL, "%08X", ImGuiInputTextFlags_CharsHexadecimal);
1255b8e80941Smrg        ImGui::InputScalar("input s64",     ImGuiDataType_S64,    &s64_v, inputs_step ? &s64_one : NULL);
1256b8e80941Smrg        ImGui::InputScalar("input u64",     ImGuiDataType_U64,    &u64_v, inputs_step ? &u64_one : NULL);
1257b8e80941Smrg        ImGui::InputScalar("input float",   ImGuiDataType_Float,  &f32_v, inputs_step ? &f32_one : NULL);
1258b8e80941Smrg        ImGui::InputScalar("input double",  ImGuiDataType_Double, &f64_v, inputs_step ? &f64_one : NULL);
1259b8e80941Smrg
1260b8e80941Smrg        ImGui::TreePop();
1261b8e80941Smrg    }
1262b8e80941Smrg
1263b8e80941Smrg    if (ImGui::TreeNode("Multi-component Widgets"))
1264b8e80941Smrg    {
1265b8e80941Smrg        static float vec4f[4] = { 0.10f, 0.20f, 0.30f, 0.44f };
1266b8e80941Smrg        static int vec4i[4] = { 1, 5, 100, 255 };
1267b8e80941Smrg
1268b8e80941Smrg        ImGui::InputFloat2("input float2", vec4f);
1269b8e80941Smrg        ImGui::DragFloat2("drag float2", vec4f, 0.01f, 0.0f, 1.0f);
1270b8e80941Smrg        ImGui::SliderFloat2("slider float2", vec4f, 0.0f, 1.0f);
1271b8e80941Smrg        ImGui::InputInt2("input int2", vec4i);
1272b8e80941Smrg        ImGui::DragInt2("drag int2", vec4i, 1, 0, 255);
1273b8e80941Smrg        ImGui::SliderInt2("slider int2", vec4i, 0, 255);
1274b8e80941Smrg        ImGui::Spacing();
1275b8e80941Smrg
1276b8e80941Smrg        ImGui::InputFloat3("input float3", vec4f);
1277b8e80941Smrg        ImGui::DragFloat3("drag float3", vec4f, 0.01f, 0.0f, 1.0f);
1278b8e80941Smrg        ImGui::SliderFloat3("slider float3", vec4f, 0.0f, 1.0f);
1279b8e80941Smrg        ImGui::InputInt3("input int3", vec4i);
1280b8e80941Smrg        ImGui::DragInt3("drag int3", vec4i, 1, 0, 255);
1281b8e80941Smrg        ImGui::SliderInt3("slider int3", vec4i, 0, 255);
1282b8e80941Smrg        ImGui::Spacing();
1283b8e80941Smrg
1284b8e80941Smrg        ImGui::InputFloat4("input float4", vec4f);
1285b8e80941Smrg        ImGui::DragFloat4("drag float4", vec4f, 0.01f, 0.0f, 1.0f);
1286b8e80941Smrg        ImGui::SliderFloat4("slider float4", vec4f, 0.0f, 1.0f);
1287b8e80941Smrg        ImGui::InputInt4("input int4", vec4i);
1288b8e80941Smrg        ImGui::DragInt4("drag int4", vec4i, 1, 0, 255);
1289b8e80941Smrg        ImGui::SliderInt4("slider int4", vec4i, 0, 255);
1290b8e80941Smrg
1291b8e80941Smrg        ImGui::TreePop();
1292b8e80941Smrg    }
1293b8e80941Smrg
1294b8e80941Smrg    if (ImGui::TreeNode("Vertical Sliders"))
1295b8e80941Smrg    {
1296b8e80941Smrg        const float spacing = 4;
1297b8e80941Smrg        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(spacing, spacing));
1298b8e80941Smrg
1299b8e80941Smrg        static int int_value = 0;
1300b8e80941Smrg        ImGui::VSliderInt("##int", ImVec2(18,160), &int_value, 0, 5);
1301b8e80941Smrg        ImGui::SameLine();
1302b8e80941Smrg
1303b8e80941Smrg        static float values[7] = { 0.0f, 0.60f, 0.35f, 0.9f, 0.70f, 0.20f, 0.0f };
1304b8e80941Smrg        ImGui::PushID("set1");
1305b8e80941Smrg        for (int i = 0; i < 7; i++)
1306b8e80941Smrg        {
1307b8e80941Smrg            if (i > 0) ImGui::SameLine();
1308b8e80941Smrg            ImGui::PushID(i);
1309b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_FrameBg, (ImVec4)ImColor::HSV(i/7.0f, 0.5f, 0.5f));
1310b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, (ImVec4)ImColor::HSV(i/7.0f, 0.6f, 0.5f));
1311b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_FrameBgActive, (ImVec4)ImColor::HSV(i/7.0f, 0.7f, 0.5f));
1312b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_SliderGrab, (ImVec4)ImColor::HSV(i/7.0f, 0.9f, 0.9f));
1313b8e80941Smrg            ImGui::VSliderFloat("##v", ImVec2(18,160), &values[i], 0.0f, 1.0f, "");
1314b8e80941Smrg            if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1315b8e80941Smrg                ImGui::SetTooltip("%.3f", values[i]);
1316b8e80941Smrg            ImGui::PopStyleColor(4);
1317b8e80941Smrg            ImGui::PopID();
1318b8e80941Smrg        }
1319b8e80941Smrg        ImGui::PopID();
1320b8e80941Smrg
1321b8e80941Smrg        ImGui::SameLine();
1322b8e80941Smrg        ImGui::PushID("set2");
1323b8e80941Smrg        static float values2[4] = { 0.20f, 0.80f, 0.40f, 0.25f };
1324b8e80941Smrg        const int rows = 3;
1325b8e80941Smrg        const ImVec2 small_slider_size(18, (160.0f-(rows-1)*spacing)/rows);
1326b8e80941Smrg        for (int nx = 0; nx < 4; nx++)
1327b8e80941Smrg        {
1328b8e80941Smrg            if (nx > 0) ImGui::SameLine();
1329b8e80941Smrg            ImGui::BeginGroup();
1330b8e80941Smrg            for (int ny = 0; ny < rows; ny++)
1331b8e80941Smrg            {
1332b8e80941Smrg                ImGui::PushID(nx*rows+ny);
1333b8e80941Smrg                ImGui::VSliderFloat("##v", small_slider_size, &values2[nx], 0.0f, 1.0f, "");
1334b8e80941Smrg                if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1335b8e80941Smrg                    ImGui::SetTooltip("%.3f", values2[nx]);
1336b8e80941Smrg                ImGui::PopID();
1337b8e80941Smrg            }
1338b8e80941Smrg            ImGui::EndGroup();
1339b8e80941Smrg        }
1340b8e80941Smrg        ImGui::PopID();
1341b8e80941Smrg
1342b8e80941Smrg        ImGui::SameLine();
1343b8e80941Smrg        ImGui::PushID("set3");
1344b8e80941Smrg        for (int i = 0; i < 4; i++)
1345b8e80941Smrg        {
1346b8e80941Smrg            if (i > 0) ImGui::SameLine();
1347b8e80941Smrg            ImGui::PushID(i);
1348b8e80941Smrg            ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize, 40);
1349b8e80941Smrg            ImGui::VSliderFloat("##v", ImVec2(40,160), &values[i], 0.0f, 1.0f, "%.2f\nsec");
1350b8e80941Smrg            ImGui::PopStyleVar();
1351b8e80941Smrg            ImGui::PopID();
1352b8e80941Smrg        }
1353b8e80941Smrg        ImGui::PopID();
1354b8e80941Smrg        ImGui::PopStyleVar();
1355b8e80941Smrg        ImGui::TreePop();
1356b8e80941Smrg    }
1357b8e80941Smrg
1358b8e80941Smrg    if (ImGui::TreeNode("Drag and Drop"))
1359b8e80941Smrg    {
1360b8e80941Smrg        {
1361b8e80941Smrg            // ColorEdit widgets automatically act as drag source and drag target.
1362b8e80941Smrg            // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets
1363b8e80941Smrg            // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo.
1364b8e80941Smrg            ImGui::BulletText("Drag and drop in standard widgets");
1365b8e80941Smrg            ImGui::Indent();
1366b8e80941Smrg            static float col1[3] = { 1.0f,0.0f,0.2f };
1367b8e80941Smrg            static float col2[4] = { 0.4f,0.7f,0.0f,0.5f };
1368b8e80941Smrg            ImGui::ColorEdit3("color 1", col1);
1369b8e80941Smrg            ImGui::ColorEdit4("color 2", col2);
1370b8e80941Smrg            ImGui::Unindent();
1371b8e80941Smrg        }
1372b8e80941Smrg
1373b8e80941Smrg        {
1374b8e80941Smrg            ImGui::BulletText("Drag and drop to copy/swap items");
1375b8e80941Smrg            ImGui::Indent();
1376b8e80941Smrg            enum Mode
1377b8e80941Smrg            {
1378b8e80941Smrg                Mode_Copy,
1379b8e80941Smrg                Mode_Move,
1380b8e80941Smrg                Mode_Swap
1381b8e80941Smrg            };
1382b8e80941Smrg            static int mode = 0;
1383b8e80941Smrg            if (ImGui::RadioButton("Copy", mode == Mode_Copy)) { mode = Mode_Copy; } ImGui::SameLine();
1384b8e80941Smrg            if (ImGui::RadioButton("Move", mode == Mode_Move)) { mode = Mode_Move; } ImGui::SameLine();
1385b8e80941Smrg            if (ImGui::RadioButton("Swap", mode == Mode_Swap)) { mode = Mode_Swap; }
1386b8e80941Smrg            static const char* names[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", "Bibi", "Blaine", "Bryn" };
1387b8e80941Smrg            for (int n = 0; n < IM_ARRAYSIZE(names); n++)
1388b8e80941Smrg            {
1389b8e80941Smrg                ImGui::PushID(n);
1390b8e80941Smrg                if ((n % 3) != 0)
1391b8e80941Smrg                    ImGui::SameLine();
1392b8e80941Smrg                ImGui::Button(names[n], ImVec2(60,60));
1393b8e80941Smrg
1394b8e80941Smrg                // Our buttons are both drag sources and drag targets here!
1395b8e80941Smrg                if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
1396b8e80941Smrg                {
1397b8e80941Smrg                    ImGui::SetDragDropPayload("DND_DEMO_CELL", &n, sizeof(int));        // Set payload to carry the index of our item (could be anything)
1398b8e80941Smrg                    if (mode == Mode_Copy) { ImGui::Text("Copy %s", names[n]); }        // Display preview (could be anything, e.g. when dragging an image we could decide to display the filename and a small preview of the image, etc.)
1399b8e80941Smrg                    if (mode == Mode_Move) { ImGui::Text("Move %s", names[n]); }
1400b8e80941Smrg                    if (mode == Mode_Swap) { ImGui::Text("Swap %s", names[n]); }
1401b8e80941Smrg                    ImGui::EndDragDropSource();
1402b8e80941Smrg                }
1403b8e80941Smrg                if (ImGui::BeginDragDropTarget())
1404b8e80941Smrg                {
1405b8e80941Smrg                    if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
1406b8e80941Smrg                    {
1407b8e80941Smrg                        IM_ASSERT(payload->DataSize == sizeof(int));
1408b8e80941Smrg                        int payload_n = *(const int*)payload->Data;
1409b8e80941Smrg                        if (mode == Mode_Copy)
1410b8e80941Smrg                        {
1411b8e80941Smrg                            names[n] = names[payload_n];
1412b8e80941Smrg                        }
1413b8e80941Smrg                        if (mode == Mode_Move)
1414b8e80941Smrg                        {
1415b8e80941Smrg                            names[n] = names[payload_n];
1416b8e80941Smrg                            names[payload_n] = "";
1417b8e80941Smrg                        }
1418b8e80941Smrg                        if (mode == Mode_Swap)
1419b8e80941Smrg                        {
1420b8e80941Smrg                            const char* tmp = names[n];
1421b8e80941Smrg                            names[n] = names[payload_n];
1422b8e80941Smrg                            names[payload_n] = tmp;
1423b8e80941Smrg                        }
1424b8e80941Smrg                    }
1425b8e80941Smrg                    ImGui::EndDragDropTarget();
1426b8e80941Smrg                }
1427b8e80941Smrg                ImGui::PopID();
1428b8e80941Smrg            }
1429b8e80941Smrg            ImGui::Unindent();
1430b8e80941Smrg        }
1431b8e80941Smrg
1432b8e80941Smrg        ImGui::TreePop();
1433b8e80941Smrg    }
1434b8e80941Smrg
1435b8e80941Smrg    if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)"))
1436b8e80941Smrg    {
1437b8e80941Smrg        // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined.
1438b8e80941Smrg        // (because BulletText is an item itself and that would affect the output of IsItemHovered() we pass all state in a single call to simplify the code).
1439b8e80941Smrg        static int item_type = 1;
1440b8e80941Smrg        static bool b = false;
1441b8e80941Smrg        static float col4f[4] = { 1.0f, 0.5, 0.0f, 1.0f };
1442b8e80941Smrg        ImGui::RadioButton("Text", &item_type, 0);
1443b8e80941Smrg        ImGui::RadioButton("Button", &item_type, 1);
1444b8e80941Smrg        ImGui::RadioButton("Checkbox", &item_type, 2);
1445b8e80941Smrg        ImGui::RadioButton("SliderFloat", &item_type, 3);
1446b8e80941Smrg        ImGui::RadioButton("ColorEdit4", &item_type, 4);
1447b8e80941Smrg        ImGui::RadioButton("ListBox", &item_type, 5);
1448b8e80941Smrg        ImGui::Separator();
1449b8e80941Smrg        bool ret = false;
1450b8e80941Smrg        if (item_type == 0) { ImGui::Text("ITEM: Text"); }                                              // Testing text items with no identifier/interaction
1451b8e80941Smrg        if (item_type == 1) { ret = ImGui::Button("ITEM: Button"); }                                    // Testing button
1452b8e80941Smrg        if (item_type == 2) { ret = ImGui::Checkbox("ITEM: Checkbox", &b); }                            // Testing checkbox
1453b8e80941Smrg        if (item_type == 3) { ret = ImGui::SliderFloat("ITEM: SliderFloat", &col4f[0], 0.0f, 1.0f); }   // Testing basic item
1454b8e80941Smrg        if (item_type == 4) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); }                     // Testing multi-component items (IsItemXXX flags are reported merged)
1455b8e80941Smrg        if (item_type == 5) { const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
1456b8e80941Smrg        ImGui::BulletText(
1457b8e80941Smrg            "Return value = %d\n"
1458b8e80941Smrg            "IsItemFocused() = %d\n"
1459b8e80941Smrg            "IsItemHovered() = %d\n"
1460b8e80941Smrg            "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
1461b8e80941Smrg            "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1462b8e80941Smrg            "IsItemHovered(_AllowWhenOverlapped) = %d\n"
1463b8e80941Smrg            "IsItemHovered(_RectOnly) = %d\n"
1464b8e80941Smrg            "IsItemActive() = %d\n"
1465b8e80941Smrg            "IsItemEdited() = %d\n"
1466b8e80941Smrg            "IsItemActivated() = %d\n"
1467b8e80941Smrg            "IsItemDeactivated() = %d\n"
1468b8e80941Smrg            "IsItemDeactivatedEdit() = %d\n"
1469b8e80941Smrg            "IsItemVisible() = %d\n"
1470b8e80941Smrg            "GetItemRectMin() = (%.1f, %.1f)\n"
1471b8e80941Smrg            "GetItemRectMax() = (%.1f, %.1f)\n"
1472b8e80941Smrg            "GetItemRectSize() = (%.1f, %.1f)",
1473b8e80941Smrg            ret,
1474b8e80941Smrg            ImGui::IsItemFocused(),
1475b8e80941Smrg            ImGui::IsItemHovered(),
1476b8e80941Smrg            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1477b8e80941Smrg            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1478b8e80941Smrg            ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped),
1479b8e80941Smrg            ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly),
1480b8e80941Smrg            ImGui::IsItemActive(),
1481b8e80941Smrg            ImGui::IsItemEdited(),
1482b8e80941Smrg            ImGui::IsItemActivated(),
1483b8e80941Smrg            ImGui::IsItemDeactivated(),
1484b8e80941Smrg            ImGui::IsItemDeactivatedAfterEdit(),
1485b8e80941Smrg            ImGui::IsItemVisible(),
1486b8e80941Smrg            ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y,
1487b8e80941Smrg            ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y,
1488b8e80941Smrg            ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y
1489b8e80941Smrg        );
1490b8e80941Smrg
1491b8e80941Smrg        static bool embed_all_inside_a_child_window = false;
1492b8e80941Smrg        ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
1493b8e80941Smrg        if (embed_all_inside_a_child_window)
1494b8e80941Smrg            ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true);
1495b8e80941Smrg
1496b8e80941Smrg        // Testing IsWindowFocused() function with its various flags. Note that the flags can be combined.
1497b8e80941Smrg        ImGui::BulletText(
1498b8e80941Smrg            "IsWindowFocused() = %d\n"
1499b8e80941Smrg            "IsWindowFocused(_ChildWindows) = %d\n"
1500b8e80941Smrg            "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
1501b8e80941Smrg            "IsWindowFocused(_RootWindow) = %d\n"
1502b8e80941Smrg            "IsWindowFocused(_AnyWindow) = %d\n",
1503b8e80941Smrg            ImGui::IsWindowFocused(),
1504b8e80941Smrg            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
1505b8e80941Smrg            ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
1506b8e80941Smrg            ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
1507b8e80941Smrg            ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
1508b8e80941Smrg
1509b8e80941Smrg        // Testing IsWindowHovered() function with its various flags. Note that the flags can be combined.
1510b8e80941Smrg        ImGui::BulletText(
1511b8e80941Smrg            "IsWindowHovered() = %d\n"
1512b8e80941Smrg            "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
1513b8e80941Smrg            "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1514b8e80941Smrg            "IsWindowHovered(_ChildWindows) = %d\n"
1515b8e80941Smrg            "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
1516b8e80941Smrg            "IsWindowHovered(_RootWindow) = %d\n"
1517b8e80941Smrg            "IsWindowHovered(_AnyWindow) = %d\n",
1518b8e80941Smrg            ImGui::IsWindowHovered(),
1519b8e80941Smrg            ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
1520b8e80941Smrg            ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
1521b8e80941Smrg            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
1522b8e80941Smrg            ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
1523b8e80941Smrg            ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
1524b8e80941Smrg            ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
1525b8e80941Smrg
1526b8e80941Smrg        ImGui::BeginChild("child", ImVec2(0, 50), true);
1527b8e80941Smrg        ImGui::Text("This is another child window for testing the _ChildWindows flag.");
1528b8e80941Smrg        ImGui::EndChild();
1529b8e80941Smrg        if (embed_all_inside_a_child_window)
1530b8e80941Smrg            ImGui::EndChild();
1531b8e80941Smrg
1532b8e80941Smrg        // Calling IsItemHovered() after begin returns the hovered status of the title bar.
1533b8e80941Smrg        // This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window.
1534b8e80941Smrg        static bool test_window = false;
1535b8e80941Smrg        ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
1536b8e80941Smrg        if (test_window)
1537b8e80941Smrg        {
1538b8e80941Smrg            ImGui::Begin("Title bar Hovered/Active tests", &test_window);
1539b8e80941Smrg            if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
1540b8e80941Smrg            {
1541b8e80941Smrg                if (ImGui::MenuItem("Close")) { test_window = false; }
1542b8e80941Smrg                ImGui::EndPopup();
1543b8e80941Smrg            }
1544b8e80941Smrg            ImGui::Text(
1545b8e80941Smrg                "IsItemHovered() after begin = %d (== is title bar hovered)\n"
1546b8e80941Smrg                "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
1547b8e80941Smrg                ImGui::IsItemHovered(), ImGui::IsItemActive());
1548b8e80941Smrg            ImGui::End();
1549b8e80941Smrg        }
1550b8e80941Smrg
1551b8e80941Smrg        ImGui::TreePop();
1552b8e80941Smrg    }
1553b8e80941Smrg}
1554b8e80941Smrg
1555b8e80941Smrgstatic void ShowDemoWindowLayout()
1556b8e80941Smrg{
1557b8e80941Smrg    if (!ImGui::CollapsingHeader("Layout"))
1558b8e80941Smrg        return;
1559b8e80941Smrg
1560b8e80941Smrg    if (ImGui::TreeNode("Child windows"))
1561b8e80941Smrg    {
1562b8e80941Smrg        ShowHelpMarker("Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window.");
1563b8e80941Smrg        static bool disable_mouse_wheel = false;
1564b8e80941Smrg        static bool disable_menu = false;
1565b8e80941Smrg        ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel);
1566b8e80941Smrg        ImGui::Checkbox("Disable Menu", &disable_menu);
1567b8e80941Smrg
1568b8e80941Smrg        static int line = 50;
1569b8e80941Smrg        bool goto_line = ImGui::Button("Goto");
1570b8e80941Smrg        ImGui::SameLine();
1571b8e80941Smrg        ImGui::PushItemWidth(100);
1572b8e80941Smrg        goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue);
1573b8e80941Smrg        ImGui::PopItemWidth();
1574b8e80941Smrg
1575b8e80941Smrg        // Child 1: no border, enable horizontal scrollbar
1576b8e80941Smrg        {
1577b8e80941Smrg            ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0);
1578b8e80941Smrg            ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags);
1579b8e80941Smrg            for (int i = 0; i < 100; i++)
1580b8e80941Smrg            {
1581b8e80941Smrg                ImGui::Text("%04d: scrollable region", i);
1582b8e80941Smrg                if (goto_line && line == i)
1583b8e80941Smrg                    ImGui::SetScrollHereY();
1584b8e80941Smrg            }
1585b8e80941Smrg            if (goto_line && line >= 100)
1586b8e80941Smrg                ImGui::SetScrollHereY();
1587b8e80941Smrg            ImGui::EndChild();
1588b8e80941Smrg        }
1589b8e80941Smrg
1590b8e80941Smrg        ImGui::SameLine();
1591b8e80941Smrg
1592b8e80941Smrg        // Child 2: rounded border
1593b8e80941Smrg        {
1594b8e80941Smrg            ImGuiWindowFlags window_flags = (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar);
1595b8e80941Smrg            ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
1596b8e80941Smrg            ImGui::BeginChild("Child2", ImVec2(0, 260), true, window_flags);
1597b8e80941Smrg            if (!disable_menu && ImGui::BeginMenuBar())
1598b8e80941Smrg            {
1599b8e80941Smrg                if (ImGui::BeginMenu("Menu"))
1600b8e80941Smrg                {
1601b8e80941Smrg                    ShowExampleMenuFile();
1602b8e80941Smrg                    ImGui::EndMenu();
1603b8e80941Smrg                }
1604b8e80941Smrg                ImGui::EndMenuBar();
1605b8e80941Smrg            }
1606b8e80941Smrg            ImGui::Columns(2);
1607b8e80941Smrg            for (int i = 0; i < 100; i++)
1608b8e80941Smrg            {
1609b8e80941Smrg                char buf[32];
1610b8e80941Smrg                sprintf(buf, "%03d", i);
1611b8e80941Smrg                ImGui::Button(buf, ImVec2(-1.0f, 0.0f));
1612b8e80941Smrg                ImGui::NextColumn();
1613b8e80941Smrg            }
1614b8e80941Smrg            ImGui::EndChild();
1615b8e80941Smrg            ImGui::PopStyleVar();
1616b8e80941Smrg        }
1617b8e80941Smrg
1618b8e80941Smrg        ImGui::Separator();
1619b8e80941Smrg
1620b8e80941Smrg        // Demonstrate a few extra things
1621b8e80941Smrg        // - Changing ImGuiCol_ChildBg (which is transparent black in default styles)
1622b8e80941Smrg        // - Using SetCursorPos() to position the child window (because the child window is an item from the POV of the parent window)
1623b8e80941Smrg        //   You can also call SetNextWindowPos() to position the child window. The parent window will effectively layout from this position.
1624b8e80941Smrg        // - Using ImGui::GetItemRectMin/Max() to query the "item" state (because the child window is an item from the POV of the parent window)
1625b8e80941Smrg        //   See "Widgets" -> "Querying Status (Active/Focused/Hovered etc.)" section for more details about this.
1626b8e80941Smrg        {
1627b8e80941Smrg            ImGui::SetCursorPosX(50);
1628b8e80941Smrg            ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
1629b8e80941Smrg            ImGui::BeginChild("blah", ImVec2(200, 100), true, ImGuiWindowFlags_None);
1630b8e80941Smrg            for (int n = 0; n < 50; n++)
1631b8e80941Smrg                ImGui::Text("Some test %d", n);
1632b8e80941Smrg            ImGui::EndChild();
1633b8e80941Smrg            ImVec2 child_rect_min = ImGui::GetItemRectMin();
1634b8e80941Smrg            ImVec2 child_rect_max = ImGui::GetItemRectMax();
1635b8e80941Smrg            ImGui::PopStyleColor();
1636b8e80941Smrg            ImGui::Text("Rect of child window is: (%.0f,%.0f) (%.0f,%.0f)", child_rect_min.x, child_rect_min.y, child_rect_max.x, child_rect_max.y);
1637b8e80941Smrg        }
1638b8e80941Smrg
1639b8e80941Smrg        ImGui::TreePop();
1640b8e80941Smrg    }
1641b8e80941Smrg
1642b8e80941Smrg    if (ImGui::TreeNode("Widgets Width"))
1643b8e80941Smrg    {
1644b8e80941Smrg        static float f = 0.0f;
1645b8e80941Smrg        ImGui::Text("PushItemWidth(100)");
1646b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("Fixed width.");
1647b8e80941Smrg        ImGui::PushItemWidth(100);
1648b8e80941Smrg        ImGui::DragFloat("float##1", &f);
1649b8e80941Smrg        ImGui::PopItemWidth();
1650b8e80941Smrg
1651b8e80941Smrg        ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
1652b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("Half of window width.");
1653b8e80941Smrg        ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f);
1654b8e80941Smrg        ImGui::DragFloat("float##2", &f);
1655b8e80941Smrg        ImGui::PopItemWidth();
1656b8e80941Smrg
1657b8e80941Smrg        ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
1658b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
1659b8e80941Smrg        ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f);
1660b8e80941Smrg        ImGui::DragFloat("float##3", &f);
1661b8e80941Smrg        ImGui::PopItemWidth();
1662b8e80941Smrg
1663b8e80941Smrg        ImGui::Text("PushItemWidth(-100)");
1664b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
1665b8e80941Smrg        ImGui::PushItemWidth(-100);
1666b8e80941Smrg        ImGui::DragFloat("float##4", &f);
1667b8e80941Smrg        ImGui::PopItemWidth();
1668b8e80941Smrg
1669b8e80941Smrg        ImGui::Text("PushItemWidth(-1)");
1670b8e80941Smrg        ImGui::SameLine(); ShowHelpMarker("Align to right edge");
1671b8e80941Smrg        ImGui::PushItemWidth(-1);
1672b8e80941Smrg        ImGui::DragFloat("float##5", &f);
1673b8e80941Smrg        ImGui::PopItemWidth();
1674b8e80941Smrg
1675b8e80941Smrg        ImGui::TreePop();
1676b8e80941Smrg    }
1677b8e80941Smrg
1678b8e80941Smrg    if (ImGui::TreeNode("Basic Horizontal Layout"))
1679b8e80941Smrg    {
1680b8e80941Smrg        ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1681b8e80941Smrg
1682b8e80941Smrg        // Text
1683b8e80941Smrg        ImGui::Text("Two items: Hello"); ImGui::SameLine();
1684b8e80941Smrg        ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1685b8e80941Smrg
1686b8e80941Smrg        // Adjust spacing
1687b8e80941Smrg        ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
1688b8e80941Smrg        ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1689b8e80941Smrg
1690b8e80941Smrg        // Button
1691b8e80941Smrg        ImGui::AlignTextToFramePadding();
1692b8e80941Smrg        ImGui::Text("Normal buttons"); ImGui::SameLine();
1693b8e80941Smrg        ImGui::Button("Banana"); ImGui::SameLine();
1694b8e80941Smrg        ImGui::Button("Apple"); ImGui::SameLine();
1695b8e80941Smrg        ImGui::Button("Corniflower");
1696b8e80941Smrg
1697b8e80941Smrg        // Button
1698b8e80941Smrg        ImGui::Text("Small buttons"); ImGui::SameLine();
1699b8e80941Smrg        ImGui::SmallButton("Like this one"); ImGui::SameLine();
1700b8e80941Smrg        ImGui::Text("can fit within a text block.");
1701b8e80941Smrg
1702b8e80941Smrg        // Aligned to arbitrary position. Easy/cheap column.
1703b8e80941Smrg        ImGui::Text("Aligned");
1704b8e80941Smrg        ImGui::SameLine(150); ImGui::Text("x=150");
1705b8e80941Smrg        ImGui::SameLine(300); ImGui::Text("x=300");
1706b8e80941Smrg        ImGui::Text("Aligned");
1707b8e80941Smrg        ImGui::SameLine(150); ImGui::SmallButton("x=150");
1708b8e80941Smrg        ImGui::SameLine(300); ImGui::SmallButton("x=300");
1709b8e80941Smrg
1710b8e80941Smrg        // Checkbox
1711b8e80941Smrg        static bool c1 = false, c2 = false, c3 = false, c4 = false;
1712b8e80941Smrg        ImGui::Checkbox("My", &c1); ImGui::SameLine();
1713b8e80941Smrg        ImGui::Checkbox("Tailor", &c2); ImGui::SameLine();
1714b8e80941Smrg        ImGui::Checkbox("Is", &c3); ImGui::SameLine();
1715b8e80941Smrg        ImGui::Checkbox("Rich", &c4);
1716b8e80941Smrg
1717b8e80941Smrg        // Various
1718b8e80941Smrg        static float f0 = 1.0f, f1 = 2.0f, f2 = 3.0f;
1719b8e80941Smrg        ImGui::PushItemWidth(80);
1720b8e80941Smrg        const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
1721b8e80941Smrg        static int item = -1;
1722b8e80941Smrg        ImGui::Combo("Combo", &item, items, IM_ARRAYSIZE(items)); ImGui::SameLine();
1723b8e80941Smrg        ImGui::SliderFloat("X", &f0, 0.0f, 5.0f); ImGui::SameLine();
1724b8e80941Smrg        ImGui::SliderFloat("Y", &f1, 0.0f, 5.0f); ImGui::SameLine();
1725b8e80941Smrg        ImGui::SliderFloat("Z", &f2, 0.0f, 5.0f);
1726b8e80941Smrg        ImGui::PopItemWidth();
1727b8e80941Smrg
1728b8e80941Smrg        ImGui::PushItemWidth(80);
1729b8e80941Smrg        ImGui::Text("Lists:");
1730b8e80941Smrg        static int selection[4] = { 0, 1, 2, 3 };
1731b8e80941Smrg        for (int i = 0; i < 4; i++)
1732b8e80941Smrg        {
1733b8e80941Smrg            if (i > 0) ImGui::SameLine();
1734b8e80941Smrg            ImGui::PushID(i);
1735b8e80941Smrg            ImGui::ListBox("", &selection[i], items, IM_ARRAYSIZE(items));
1736b8e80941Smrg            ImGui::PopID();
1737b8e80941Smrg            //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
1738b8e80941Smrg        }
1739b8e80941Smrg        ImGui::PopItemWidth();
1740b8e80941Smrg
1741b8e80941Smrg        // Dummy
1742b8e80941Smrg        ImVec2 button_sz(40, 40);
1743b8e80941Smrg        ImGui::Button("A", button_sz); ImGui::SameLine();
1744b8e80941Smrg        ImGui::Dummy(button_sz); ImGui::SameLine();
1745b8e80941Smrg        ImGui::Button("B", button_sz);
1746b8e80941Smrg
1747b8e80941Smrg        // Manually wrapping (we should eventually provide this as an automatic layout feature, but for now you can do it manually)
1748b8e80941Smrg        ImGui::Text("Manually wrapping:");
1749b8e80941Smrg        ImGuiStyle& style = ImGui::GetStyle();
1750b8e80941Smrg        int buttons_count = 20;
1751b8e80941Smrg        float window_visible_x2 = ImGui::GetWindowPos().x + ImGui::GetWindowContentRegionMax().x;
1752b8e80941Smrg        for (int n = 0; n < buttons_count; n++)
1753b8e80941Smrg        {
1754b8e80941Smrg            ImGui::PushID(n);
1755b8e80941Smrg            ImGui::Button("Box", button_sz);
1756b8e80941Smrg            float last_button_x2 = ImGui::GetItemRectMax().x;
1757b8e80941Smrg            float next_button_x2 = last_button_x2 + style.ItemSpacing.x + button_sz.x; // Expected position if next button was on same line
1758b8e80941Smrg            if (n + 1 < buttons_count && next_button_x2 < window_visible_x2)
1759b8e80941Smrg                ImGui::SameLine();
1760b8e80941Smrg            ImGui::PopID();
1761b8e80941Smrg        }
1762b8e80941Smrg
1763b8e80941Smrg        ImGui::TreePop();
1764b8e80941Smrg    }
1765b8e80941Smrg
1766b8e80941Smrg    if (ImGui::TreeNode("Tabs"))
1767b8e80941Smrg    {
1768b8e80941Smrg        if (ImGui::TreeNode("Basic"))
1769b8e80941Smrg        {
1770b8e80941Smrg            ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None;
1771b8e80941Smrg            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1772b8e80941Smrg            {
1773b8e80941Smrg                if (ImGui::BeginTabItem("Avocado"))
1774b8e80941Smrg                {
1775b8e80941Smrg                    ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah");
1776b8e80941Smrg                    ImGui::EndTabItem();
1777b8e80941Smrg                }
1778b8e80941Smrg                if (ImGui::BeginTabItem("Broccoli"))
1779b8e80941Smrg                {
1780b8e80941Smrg                    ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah");
1781b8e80941Smrg                    ImGui::EndTabItem();
1782b8e80941Smrg                }
1783b8e80941Smrg                if (ImGui::BeginTabItem("Cucumber"))
1784b8e80941Smrg                {
1785b8e80941Smrg                    ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah");
1786b8e80941Smrg                    ImGui::EndTabItem();
1787b8e80941Smrg                }
1788b8e80941Smrg                ImGui::EndTabBar();
1789b8e80941Smrg            }
1790b8e80941Smrg            ImGui::Separator();
1791b8e80941Smrg            ImGui::TreePop();
1792b8e80941Smrg        }
1793b8e80941Smrg
1794b8e80941Smrg        if (ImGui::TreeNode("Advanced & Close Button"))
1795b8e80941Smrg        {
1796b8e80941Smrg            // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0).
1797b8e80941Smrg            static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable;
1798b8e80941Smrg            ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_Reorderable);
1799b8e80941Smrg            ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs);
1800b8e80941Smrg            ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton);
1801b8e80941Smrg            ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton);
1802b8e80941Smrg            if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
1803b8e80941Smrg                tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_;
1804b8e80941Smrg            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown))
1805b8e80941Smrg                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown);
1806b8e80941Smrg            if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", (unsigned int*)&tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll))
1807b8e80941Smrg                tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll);
1808b8e80941Smrg
1809b8e80941Smrg            // Tab Bar
1810b8e80941Smrg            const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" };
1811b8e80941Smrg            static bool opened[4] = { true, true, true, true }; // Persistent user state
1812b8e80941Smrg            for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1813b8e80941Smrg            {
1814b8e80941Smrg                if (n > 0) { ImGui::SameLine(); }
1815b8e80941Smrg                ImGui::Checkbox(names[n], &opened[n]);
1816b8e80941Smrg            }
1817b8e80941Smrg
1818b8e80941Smrg            // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): the underlying bool will be set to false when the tab is closed.
1819b8e80941Smrg            if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags))
1820b8e80941Smrg            {
1821b8e80941Smrg                for (int n = 0; n < IM_ARRAYSIZE(opened); n++)
1822b8e80941Smrg                    if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n]))
1823b8e80941Smrg                    {
1824b8e80941Smrg                        ImGui::Text("This is the %s tab!", names[n]);
1825b8e80941Smrg                        if (n & 1)
1826b8e80941Smrg                            ImGui::Text("I am an odd tab.");
1827b8e80941Smrg                        ImGui::EndTabItem();
1828b8e80941Smrg                    }
1829b8e80941Smrg                ImGui::EndTabBar();
1830b8e80941Smrg            }
1831b8e80941Smrg            ImGui::Separator();
1832b8e80941Smrg            ImGui::TreePop();
1833b8e80941Smrg        }
1834b8e80941Smrg        ImGui::TreePop();
1835b8e80941Smrg    }
1836b8e80941Smrg
1837b8e80941Smrg    if (ImGui::TreeNode("Groups"))
1838b8e80941Smrg    {
1839b8e80941Smrg        ShowHelpMarker("Using ImGui::BeginGroup()/EndGroup() to layout items. BeginGroup() basically locks the horizontal position. EndGroup() bundles the whole group so that you can use functions such as IsItemHovered() on it.");
1840b8e80941Smrg        ImGui::BeginGroup();
1841b8e80941Smrg        {
1842b8e80941Smrg            ImGui::BeginGroup();
1843b8e80941Smrg            ImGui::Button("AAA");
1844b8e80941Smrg            ImGui::SameLine();
1845b8e80941Smrg            ImGui::Button("BBB");
1846b8e80941Smrg            ImGui::SameLine();
1847b8e80941Smrg            ImGui::BeginGroup();
1848b8e80941Smrg            ImGui::Button("CCC");
1849b8e80941Smrg            ImGui::Button("DDD");
1850b8e80941Smrg            ImGui::EndGroup();
1851b8e80941Smrg            ImGui::SameLine();
1852b8e80941Smrg            ImGui::Button("EEE");
1853b8e80941Smrg            ImGui::EndGroup();
1854b8e80941Smrg            if (ImGui::IsItemHovered())
1855b8e80941Smrg                ImGui::SetTooltip("First group hovered");
1856b8e80941Smrg        }
1857b8e80941Smrg        // Capture the group size and create widgets using the same size
1858b8e80941Smrg        ImVec2 size = ImGui::GetItemRectSize();
1859b8e80941Smrg        const float values[5] = { 0.5f, 0.20f, 0.80f, 0.60f, 0.25f };
1860b8e80941Smrg        ImGui::PlotHistogram("##values", values, IM_ARRAYSIZE(values), 0, NULL, 0.0f, 1.0f, size);
1861b8e80941Smrg
1862b8e80941Smrg        ImGui::Button("ACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
1863b8e80941Smrg        ImGui::SameLine();
1864b8e80941Smrg        ImGui::Button("REACTION", ImVec2((size.x - ImGui::GetStyle().ItemSpacing.x)*0.5f, size.y));
1865b8e80941Smrg        ImGui::EndGroup();
1866b8e80941Smrg        ImGui::SameLine();
1867b8e80941Smrg
1868b8e80941Smrg        ImGui::Button("LEVERAGE\nBUZZWORD", size);
1869b8e80941Smrg        ImGui::SameLine();
1870b8e80941Smrg
1871b8e80941Smrg        if (ImGui::ListBoxHeader("List", size))
1872b8e80941Smrg        {
1873b8e80941Smrg            ImGui::Selectable("Selected", true);
1874b8e80941Smrg            ImGui::Selectable("Not Selected", false);
1875b8e80941Smrg            ImGui::ListBoxFooter();
1876b8e80941Smrg        }
1877b8e80941Smrg
1878b8e80941Smrg        ImGui::TreePop();
1879b8e80941Smrg    }
1880b8e80941Smrg
1881b8e80941Smrg    if (ImGui::TreeNode("Text Baseline Alignment"))
1882b8e80941Smrg    {
1883b8e80941Smrg        ShowHelpMarker("This is testing the vertical alignment that gets applied on text to keep it aligned with widgets. Lines only composed of text or \"small\" widgets fit in less vertical spaces than lines with normal widgets.");
1884b8e80941Smrg
1885b8e80941Smrg        ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
1886b8e80941Smrg        ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1887b8e80941Smrg        ImGui::Text("Banana");
1888b8e80941Smrg
1889b8e80941Smrg        ImGui::Text("Banana"); ImGui::SameLine();
1890b8e80941Smrg        ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1891b8e80941Smrg        ImGui::Text("One\nTwo\nThree");
1892b8e80941Smrg
1893b8e80941Smrg        ImGui::Button("HOP##1"); ImGui::SameLine();
1894b8e80941Smrg        ImGui::Text("Banana"); ImGui::SameLine();
1895b8e80941Smrg        ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1896b8e80941Smrg        ImGui::Text("Banana");
1897b8e80941Smrg
1898b8e80941Smrg        ImGui::Button("HOP##2"); ImGui::SameLine();
1899b8e80941Smrg        ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1900b8e80941Smrg        ImGui::Text("Banana");
1901b8e80941Smrg
1902b8e80941Smrg        ImGui::Button("TEST##1"); ImGui::SameLine();
1903b8e80941Smrg        ImGui::Text("TEST"); ImGui::SameLine();
1904b8e80941Smrg        ImGui::SmallButton("TEST##2");
1905b8e80941Smrg
1906b8e80941Smrg        ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets.
1907b8e80941Smrg        ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
1908b8e80941Smrg        ImGui::Button("Widget##1"); ImGui::SameLine();
1909b8e80941Smrg        ImGui::Text("Widget"); ImGui::SameLine();
1910b8e80941Smrg        ImGui::SmallButton("Widget##2"); ImGui::SameLine();
1911b8e80941Smrg        ImGui::Button("Widget##3");
1912b8e80941Smrg
1913b8e80941Smrg        // Tree
1914b8e80941Smrg        const float spacing = ImGui::GetStyle().ItemInnerSpacing.x;
1915b8e80941Smrg        ImGui::Button("Button##1");
1916b8e80941Smrg        ImGui::SameLine(0.0f, spacing);
1917b8e80941Smrg        if (ImGui::TreeNode("Node##1")) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }    // Dummy tree data
1918b8e80941Smrg
1919b8e80941Smrg        ImGui::AlignTextToFramePadding();         // Vertically align text node a bit lower so it'll be vertically centered with upcoming widget. Otherwise you can use SmallButton (smaller fit).
1920b8e80941Smrg        bool node_open = ImGui::TreeNode("Node##2");  // Common mistake to avoid: if we want to SameLine after TreeNode we need to do it before we add child content.
1921b8e80941Smrg        ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##2");
1922b8e80941Smrg        if (node_open) { for (int i = 0; i < 6; i++) ImGui::BulletText("Item %d..", i); ImGui::TreePop(); }   // Dummy tree data
1923b8e80941Smrg
1924b8e80941Smrg        // Bullet
1925b8e80941Smrg        ImGui::Button("Button##3");
1926b8e80941Smrg        ImGui::SameLine(0.0f, spacing);
1927b8e80941Smrg        ImGui::BulletText("Bullet text");
1928b8e80941Smrg
1929b8e80941Smrg        ImGui::AlignTextToFramePadding();
1930b8e80941Smrg        ImGui::BulletText("Node");
1931b8e80941Smrg        ImGui::SameLine(0.0f, spacing); ImGui::Button("Button##4");
1932b8e80941Smrg
1933b8e80941Smrg        ImGui::TreePop();
1934b8e80941Smrg    }
1935b8e80941Smrg
1936b8e80941Smrg    if (ImGui::TreeNode("Scrolling"))
1937b8e80941Smrg    {
1938b8e80941Smrg        ShowHelpMarker("Use SetScrollHereY() or SetScrollFromPosY() to scroll to a given position.");
1939b8e80941Smrg
1940b8e80941Smrg        static bool track = true;
1941b8e80941Smrg        static int track_line = 50, scroll_to_px = 200;
1942b8e80941Smrg        ImGui::Checkbox("Track", &track);
1943b8e80941Smrg        ImGui::PushItemWidth(100);
1944b8e80941Smrg        ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 99, "Line = %d");
1945b8e80941Smrg        bool scroll_to = ImGui::Button("Scroll To Pos");
1946b8e80941Smrg        ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "Y = %d px");
1947b8e80941Smrg        ImGui::PopItemWidth();
1948b8e80941Smrg        if (scroll_to) track = false;
1949b8e80941Smrg
1950b8e80941Smrg        for (int i = 0; i < 5; i++)
1951b8e80941Smrg        {
1952b8e80941Smrg            if (i > 0) ImGui::SameLine();
1953b8e80941Smrg            ImGui::BeginGroup();
1954b8e80941Smrg            ImGui::Text("%s", i == 0 ? "Top" : i == 1 ? "25%" : i == 2 ? "Center" : i == 3 ? "75%" : "Bottom");
1955b8e80941Smrg            ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i), ImVec2(ImGui::GetWindowWidth() * 0.17f, 200.0f), true);
1956b8e80941Smrg            if (scroll_to)
1957b8e80941Smrg                ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.25f);
1958b8e80941Smrg            for (int line = 0; line < 100; line++)
1959b8e80941Smrg            {
1960b8e80941Smrg                if (track && line == track_line)
1961b8e80941Smrg                {
1962b8e80941Smrg                    ImGui::TextColored(ImVec4(1,1,0,1), "Line %d", line);
1963b8e80941Smrg                    ImGui::SetScrollHereY(i * 0.25f); // 0.0f:top, 0.5f:center, 1.0f:bottom
1964b8e80941Smrg                }
1965b8e80941Smrg                else
1966b8e80941Smrg                {
1967b8e80941Smrg                    ImGui::Text("Line %d", line);
1968b8e80941Smrg                }
1969b8e80941Smrg            }
1970b8e80941Smrg            float scroll_y = ImGui::GetScrollY(), scroll_max_y = ImGui::GetScrollMaxY();
1971b8e80941Smrg            ImGui::EndChild();
1972b8e80941Smrg            ImGui::Text("%.0f/%0.f", scroll_y, scroll_max_y);
1973b8e80941Smrg            ImGui::EndGroup();
1974b8e80941Smrg        }
1975b8e80941Smrg        ImGui::TreePop();
1976b8e80941Smrg    }
1977b8e80941Smrg
1978b8e80941Smrg    if (ImGui::TreeNode("Horizontal Scrolling"))
1979b8e80941Smrg    {
1980b8e80941Smrg        ShowHelpMarker("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.\n\nYou may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
1981b8e80941Smrg        static int lines = 7;
1982b8e80941Smrg        ImGui::SliderInt("Lines", &lines, 1, 15);
1983b8e80941Smrg        ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
1984b8e80941Smrg        ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
1985b8e80941Smrg        ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar);
1986b8e80941Smrg        for (int line = 0; line < lines; line++)
1987b8e80941Smrg        {
1988b8e80941Smrg            // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off
1989b8e80941Smrg            // manipulating the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets yourself. You may also want to use the lower-level ImDrawList API)
1990b8e80941Smrg            int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
1991b8e80941Smrg            for (int n = 0; n < num_buttons; n++)
1992b8e80941Smrg            {
1993b8e80941Smrg                if (n > 0) ImGui::SameLine();
1994b8e80941Smrg                ImGui::PushID(n + line * 1000);
1995b8e80941Smrg                char num_buf[16];
1996b8e80941Smrg                sprintf(num_buf, "%d", n);
1997b8e80941Smrg                const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf;
1998b8e80941Smrg                float hue = n*0.05f;
1999b8e80941Smrg                ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
2000b8e80941Smrg                ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
2001b8e80941Smrg                ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
2002b8e80941Smrg                ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
2003b8e80941Smrg                ImGui::PopStyleColor(3);
2004b8e80941Smrg                ImGui::PopID();
2005b8e80941Smrg            }
2006b8e80941Smrg        }
2007b8e80941Smrg        float scroll_x = ImGui::GetScrollX(), scroll_max_x = ImGui::GetScrollMaxX();
2008b8e80941Smrg        ImGui::EndChild();
2009b8e80941Smrg        ImGui::PopStyleVar(2);
2010b8e80941Smrg        float scroll_x_delta = 0.0f;
2011b8e80941Smrg        ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) { scroll_x_delta = -ImGui::GetIO().DeltaTime * 1000.0f; } ImGui::SameLine();
2012b8e80941Smrg        ImGui::Text("Scroll from code"); ImGui::SameLine();
2013b8e80941Smrg        ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) { scroll_x_delta = +ImGui::GetIO().DeltaTime * 1000.0f; } ImGui::SameLine();
2014b8e80941Smrg        ImGui::Text("%.0f/%.0f", scroll_x, scroll_max_x);
2015b8e80941Smrg        if (scroll_x_delta != 0.0f)
2016b8e80941Smrg        {
2017b8e80941Smrg            ImGui::BeginChild("scrolling"); // Demonstrate a trick: you can use Begin to set yourself in the context of another window (here we are already out of your child window)
2018b8e80941Smrg            ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
2019b8e80941Smrg            ImGui::EndChild();
2020b8e80941Smrg        }
2021b8e80941Smrg        ImGui::TreePop();
2022b8e80941Smrg    }
2023b8e80941Smrg
2024b8e80941Smrg    if (ImGui::TreeNode("Clipping"))
2025b8e80941Smrg    {
2026b8e80941Smrg        static ImVec2 size(100, 100), offset(50, 20);
2027b8e80941Smrg        ImGui::TextWrapped("On a per-widget basis we are occasionally clipping text CPU-side if it won't fit in its frame. Otherwise we are doing coarser clipping + passing a scissor rectangle to the renderer. The system is designed to try minimizing both execution and CPU/GPU rendering cost.");
2028b8e80941Smrg        ImGui::DragFloat2("size", (float*)&size, 0.5f, 1.0f, 200.0f, "%.0f");
2029b8e80941Smrg        ImGui::TextWrapped("(Click and drag)");
2030b8e80941Smrg        ImVec2 pos = ImGui::GetCursorScreenPos();
2031b8e80941Smrg        ImVec4 clip_rect(pos.x, pos.y, pos.x + size.x, pos.y + size.y);
2032b8e80941Smrg        ImGui::InvisibleButton("##dummy", size);
2033b8e80941Smrg        if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; }
2034b8e80941Smrg        ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x + size.x, pos.y + size.y), IM_COL32(90, 90, 120, 255));
2035b8e80941Smrg        ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x + offset.x, pos.y + offset.y), IM_COL32(255, 255, 255, 255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect);
2036b8e80941Smrg        ImGui::TreePop();
2037b8e80941Smrg    }
2038b8e80941Smrg}
2039b8e80941Smrg
2040b8e80941Smrgstatic void ShowDemoWindowPopups()
2041b8e80941Smrg{
2042b8e80941Smrg    if (!ImGui::CollapsingHeader("Popups & Modal windows"))
2043b8e80941Smrg        return;
2044b8e80941Smrg
2045b8e80941Smrg    // The properties of popups windows are:
2046b8e80941Smrg    // - They block normal mouse hovering detection outside them. (*)
2047b8e80941Smrg    // - Unless modal, they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
2048b8e80941Smrg    // - Their visibility state (~bool) is held internally by imgui instead of being held by the programmer as we are used to with regular Begin() calls.
2049b8e80941Smrg    //   User can manipulate the visibility state by calling OpenPopup().
2050b8e80941Smrg    // (*) One can use IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup) to bypass it and detect hovering even when normally blocked by a popup.
2051b8e80941Smrg    // Those three properties are connected. The library needs to hold their visibility state because it can close popups at any time.
2052b8e80941Smrg
2053b8e80941Smrg    // Typical use for regular windows:
2054b8e80941Smrg    //   bool my_tool_is_active = false; if (ImGui::Button("Open")) my_tool_is_active = true; [...] if (my_tool_is_active) Begin("My Tool", &my_tool_is_active) { [...] } End();
2055b8e80941Smrg    // Typical use for popups:
2056b8e80941Smrg    //   if (ImGui::Button("Open")) ImGui::OpenPopup("MyPopup"); if (ImGui::BeginPopup("MyPopup") { [...] EndPopup(); }
2057b8e80941Smrg
2058b8e80941Smrg    // With popups we have to go through a library call (here OpenPopup) to manipulate the visibility state.
2059b8e80941Smrg    // This may be a bit confusing at first but it should quickly make sense. Follow on the examples below.
2060b8e80941Smrg
2061b8e80941Smrg    if (ImGui::TreeNode("Popups"))
2062b8e80941Smrg    {
2063b8e80941Smrg        ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
2064b8e80941Smrg
2065b8e80941Smrg        static int selected_fish = -1;
2066b8e80941Smrg        const char* names[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
2067b8e80941Smrg        static bool toggles[] = { true, false, false, false, false };
2068b8e80941Smrg
2069b8e80941Smrg        // Simple selection popup
2070b8e80941Smrg        // (If you want to show the current selection inside the Button itself, you may want to build a string using the "###" operator to preserve a constant ID with a variable label)
2071b8e80941Smrg        if (ImGui::Button("Select.."))
2072b8e80941Smrg            ImGui::OpenPopup("my_select_popup");
2073b8e80941Smrg        ImGui::SameLine();
2074b8e80941Smrg        ImGui::TextUnformatted(selected_fish == -1 ? "<None>" : names[selected_fish]);
2075b8e80941Smrg        if (ImGui::BeginPopup("my_select_popup"))
2076b8e80941Smrg        {
2077b8e80941Smrg            ImGui::Text("Aquarium");
2078b8e80941Smrg            ImGui::Separator();
2079b8e80941Smrg            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
2080b8e80941Smrg                if (ImGui::Selectable(names[i]))
2081b8e80941Smrg                    selected_fish = i;
2082b8e80941Smrg            ImGui::EndPopup();
2083b8e80941Smrg        }
2084b8e80941Smrg
2085b8e80941Smrg        // Showing a menu with toggles
2086b8e80941Smrg        if (ImGui::Button("Toggle.."))
2087b8e80941Smrg            ImGui::OpenPopup("my_toggle_popup");
2088b8e80941Smrg        if (ImGui::BeginPopup("my_toggle_popup"))
2089b8e80941Smrg        {
2090b8e80941Smrg            for (int i = 0; i < IM_ARRAYSIZE(names); i++)
2091b8e80941Smrg                ImGui::MenuItem(names[i], "", &toggles[i]);
2092b8e80941Smrg            if (ImGui::BeginMenu("Sub-menu"))
2093b8e80941Smrg            {
2094b8e80941Smrg                ImGui::MenuItem("Click me");
2095b8e80941Smrg                ImGui::EndMenu();
2096b8e80941Smrg            }
2097b8e80941Smrg
2098b8e80941Smrg            ImGui::Separator();
2099b8e80941Smrg            ImGui::Text("Tooltip here");
2100b8e80941Smrg            if (ImGui::IsItemHovered())
2101b8e80941Smrg                ImGui::SetTooltip("I am a tooltip over a popup");
2102b8e80941Smrg
2103b8e80941Smrg            if (ImGui::Button("Stacked Popup"))
2104b8e80941Smrg                ImGui::OpenPopup("another popup");
2105b8e80941Smrg            if (ImGui::BeginPopup("another popup"))
2106b8e80941Smrg            {
2107b8e80941Smrg                for (int i = 0; i < IM_ARRAYSIZE(names); i++)
2108b8e80941Smrg                    ImGui::MenuItem(names[i], "", &toggles[i]);
2109b8e80941Smrg                if (ImGui::BeginMenu("Sub-menu"))
2110b8e80941Smrg                {
2111b8e80941Smrg                    ImGui::MenuItem("Click me");
2112b8e80941Smrg                    ImGui::EndMenu();
2113b8e80941Smrg                }
2114b8e80941Smrg                ImGui::EndPopup();
2115b8e80941Smrg            }
2116b8e80941Smrg            ImGui::EndPopup();
2117b8e80941Smrg        }
2118b8e80941Smrg
2119b8e80941Smrg        // Call the more complete ShowExampleMenuFile which we use in various places of this demo
2120b8e80941Smrg        if (ImGui::Button("File Menu.."))
2121b8e80941Smrg            ImGui::OpenPopup("my_file_popup");
2122b8e80941Smrg        if (ImGui::BeginPopup("my_file_popup"))
2123b8e80941Smrg        {
2124b8e80941Smrg            ShowExampleMenuFile();
2125b8e80941Smrg            ImGui::EndPopup();
2126b8e80941Smrg        }
2127b8e80941Smrg
2128b8e80941Smrg        ImGui::TreePop();
2129b8e80941Smrg    }
2130b8e80941Smrg
2131b8e80941Smrg    if (ImGui::TreeNode("Context menus"))
2132b8e80941Smrg    {
2133b8e80941Smrg        // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
2134b8e80941Smrg        //    if (IsItemHovered() && IsMouseReleased(0))
2135b8e80941Smrg        //       OpenPopup(id);
2136b8e80941Smrg        //    return BeginPopup(id);
2137b8e80941Smrg        // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
2138b8e80941Smrg        static float value = 0.5f;
2139b8e80941Smrg        ImGui::Text("Value = %.3f (<-- right-click here)", value);
2140b8e80941Smrg        if (ImGui::BeginPopupContextItem("item context menu"))
2141b8e80941Smrg        {
2142b8e80941Smrg            if (ImGui::Selectable("Set to zero")) value = 0.0f;
2143b8e80941Smrg            if (ImGui::Selectable("Set to PI")) value = 3.1415f;
2144b8e80941Smrg            ImGui::PushItemWidth(-1);
2145b8e80941Smrg            ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
2146b8e80941Smrg            ImGui::PopItemWidth();
2147b8e80941Smrg            ImGui::EndPopup();
2148b8e80941Smrg        }
2149b8e80941Smrg
2150b8e80941Smrg        // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the Begin call.
2151b8e80941Smrg        // So here we will make it that clicking on the text field with the right mouse button (1) will toggle the visibility of the popup above.
2152b8e80941Smrg        ImGui::Text("(You can also right-click me to the same popup as above.)");
2153b8e80941Smrg        ImGui::OpenPopupOnItemClick("item context menu", 1);
2154b8e80941Smrg
2155b8e80941Smrg        // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
2156b8e80941Smrg        // BeginPopupContextItem() will use the last item ID as the popup ID.
2157b8e80941Smrg        // In addition here, we want to include your editable label inside the button label. We use the ### operator to override the ID (read FAQ about ID for details)
2158b8e80941Smrg        static char name[32] = "Label1";
2159b8e80941Smrg        char buf[64]; sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
2160b8e80941Smrg        ImGui::Button(buf);
2161b8e80941Smrg        if (ImGui::BeginPopupContextItem())
2162b8e80941Smrg        {
2163b8e80941Smrg            ImGui::Text("Edit name:");
2164b8e80941Smrg            ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
2165b8e80941Smrg            if (ImGui::Button("Close"))
2166b8e80941Smrg                ImGui::CloseCurrentPopup();
2167b8e80941Smrg            ImGui::EndPopup();
2168b8e80941Smrg        }
2169b8e80941Smrg        ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
2170b8e80941Smrg
2171b8e80941Smrg        ImGui::TreePop();
2172b8e80941Smrg    }
2173b8e80941Smrg
2174b8e80941Smrg    if (ImGui::TreeNode("Modals"))
2175b8e80941Smrg    {
2176b8e80941Smrg        ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
2177b8e80941Smrg
2178b8e80941Smrg        if (ImGui::Button("Delete.."))
2179b8e80941Smrg            ImGui::OpenPopup("Delete?");
2180b8e80941Smrg
2181b8e80941Smrg        if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize))
2182b8e80941Smrg        {
2183b8e80941Smrg            ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
2184b8e80941Smrg            ImGui::Separator();
2185b8e80941Smrg
2186b8e80941Smrg            //static int dummy_i = 0;
2187b8e80941Smrg            //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
2188b8e80941Smrg
2189b8e80941Smrg            static bool dont_ask_me_next_time = false;
2190b8e80941Smrg            ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
2191b8e80941Smrg            ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time);
2192b8e80941Smrg            ImGui::PopStyleVar();
2193b8e80941Smrg
2194b8e80941Smrg            if (ImGui::Button("OK", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
2195b8e80941Smrg            ImGui::SetItemDefaultFocus();
2196b8e80941Smrg            ImGui::SameLine();
2197b8e80941Smrg            if (ImGui::Button("Cancel", ImVec2(120, 0))) { ImGui::CloseCurrentPopup(); }
2198b8e80941Smrg            ImGui::EndPopup();
2199b8e80941Smrg        }
2200b8e80941Smrg
2201b8e80941Smrg        if (ImGui::Button("Stacked modals.."))
2202b8e80941Smrg            ImGui::OpenPopup("Stacked 1");
2203b8e80941Smrg        if (ImGui::BeginPopupModal("Stacked 1", NULL, ImGuiWindowFlags_MenuBar))
2204b8e80941Smrg        {
2205b8e80941Smrg            if (ImGui::BeginMenuBar())
2206b8e80941Smrg            {
2207b8e80941Smrg                if (ImGui::BeginMenu("File"))
2208b8e80941Smrg                {
2209b8e80941Smrg                    if (ImGui::MenuItem("Dummy menu item")) {}
2210b8e80941Smrg                    ImGui::EndMenu();
2211b8e80941Smrg                }
2212b8e80941Smrg                ImGui::EndMenuBar();
2213b8e80941Smrg            }
2214b8e80941Smrg            ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
2215b8e80941Smrg
2216b8e80941Smrg            // Testing behavior of widgets stacking their own regular popups over the modal.
2217b8e80941Smrg            static int item = 1;
2218b8e80941Smrg            static float color[4] = { 0.4f,0.7f,0.0f,0.5f };
2219b8e80941Smrg            ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
2220b8e80941Smrg            ImGui::ColorEdit4("color", color);
2221b8e80941Smrg
2222b8e80941Smrg            if (ImGui::Button("Add another modal.."))
2223b8e80941Smrg                ImGui::OpenPopup("Stacked 2");
2224b8e80941Smrg
2225b8e80941Smrg            // Also demonstrate passing a bool* to BeginPopupModal(), this will create a regular close button which will close the popup.
2226b8e80941Smrg            // Note that the visibility state of popups is owned by imgui, so the input value of the bool actually doesn't matter here.
2227b8e80941Smrg            bool dummy_open = true;
2228b8e80941Smrg            if (ImGui::BeginPopupModal("Stacked 2", &dummy_open))
2229b8e80941Smrg            {
2230b8e80941Smrg                ImGui::Text("Hello from Stacked The Second!");
2231b8e80941Smrg                if (ImGui::Button("Close"))
2232b8e80941Smrg                    ImGui::CloseCurrentPopup();
2233b8e80941Smrg                ImGui::EndPopup();
2234b8e80941Smrg            }
2235b8e80941Smrg
2236b8e80941Smrg            if (ImGui::Button("Close"))
2237b8e80941Smrg                ImGui::CloseCurrentPopup();
2238b8e80941Smrg            ImGui::EndPopup();
2239b8e80941Smrg        }
2240b8e80941Smrg
2241b8e80941Smrg        ImGui::TreePop();
2242b8e80941Smrg    }
2243b8e80941Smrg
2244b8e80941Smrg    if (ImGui::TreeNode("Menus inside a regular window"))
2245b8e80941Smrg    {
2246b8e80941Smrg        ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
2247b8e80941Smrg        ImGui::Separator();
2248b8e80941Smrg        // NB: As a quirk in this very specific example, we want to differentiate the parent of this menu from the parent of the various popup menus above.
2249b8e80941Smrg        // To do so we are encloding the items in a PushID()/PopID() block to make them two different menusets. If we don't, opening any popup above and hovering our menu here
2250b8e80941Smrg        // would open it. This is because once a menu is active, we allow to switch to a sibling menu by just hovering on it, which is the desired behavior for regular menus.
2251b8e80941Smrg        ImGui::PushID("foo");
2252b8e80941Smrg        ImGui::MenuItem("Menu item", "CTRL+M");
2253b8e80941Smrg        if (ImGui::BeginMenu("Menu inside a regular window"))
2254b8e80941Smrg        {
2255b8e80941Smrg            ShowExampleMenuFile();
2256b8e80941Smrg            ImGui::EndMenu();
2257b8e80941Smrg        }
2258b8e80941Smrg        ImGui::PopID();
2259b8e80941Smrg        ImGui::Separator();
2260b8e80941Smrg        ImGui::TreePop();
2261b8e80941Smrg    }
2262b8e80941Smrg}
2263b8e80941Smrg
2264b8e80941Smrgstatic void ShowDemoWindowColumns()
2265b8e80941Smrg{
2266b8e80941Smrg    if (!ImGui::CollapsingHeader("Columns"))
2267b8e80941Smrg        return;
2268b8e80941Smrg
2269b8e80941Smrg    ImGui::PushID("Columns");
2270b8e80941Smrg
2271b8e80941Smrg    // Basic columns
2272b8e80941Smrg    if (ImGui::TreeNode("Basic"))
2273b8e80941Smrg    {
2274b8e80941Smrg        ImGui::Text("Without border:");
2275b8e80941Smrg        ImGui::Columns(3, "mycolumns3", false);  // 3-ways, no border
2276b8e80941Smrg        ImGui::Separator();
2277b8e80941Smrg        for (int n = 0; n < 14; n++)
2278b8e80941Smrg        {
2279b8e80941Smrg            char label[32];
2280b8e80941Smrg            sprintf(label, "Item %d", n);
2281b8e80941Smrg            if (ImGui::Selectable(label)) {}
2282b8e80941Smrg            //if (ImGui::Button(label, ImVec2(-1,0))) {}
2283b8e80941Smrg            ImGui::NextColumn();
2284b8e80941Smrg        }
2285b8e80941Smrg        ImGui::Columns(1);
2286b8e80941Smrg        ImGui::Separator();
2287b8e80941Smrg
2288b8e80941Smrg        ImGui::Text("With border:");
2289b8e80941Smrg        ImGui::Columns(4, "mycolumns"); // 4-ways, with border
2290b8e80941Smrg        ImGui::Separator();
2291b8e80941Smrg        ImGui::Text("ID"); ImGui::NextColumn();
2292b8e80941Smrg        ImGui::Text("Name"); ImGui::NextColumn();
2293b8e80941Smrg        ImGui::Text("Path"); ImGui::NextColumn();
2294b8e80941Smrg        ImGui::Text("Hovered"); ImGui::NextColumn();
2295b8e80941Smrg        ImGui::Separator();
2296b8e80941Smrg        const char* names[3] = { "One", "Two", "Three" };
2297b8e80941Smrg        const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
2298b8e80941Smrg        static int selected = -1;
2299b8e80941Smrg        for (int i = 0; i < 3; i++)
2300b8e80941Smrg        {
2301b8e80941Smrg            char label[32];
2302b8e80941Smrg            sprintf(label, "%04d", i);
2303b8e80941Smrg            if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
2304b8e80941Smrg                selected = i;
2305b8e80941Smrg            bool hovered = ImGui::IsItemHovered();
2306b8e80941Smrg            ImGui::NextColumn();
2307b8e80941Smrg            ImGui::Text(names[i]); ImGui::NextColumn();
2308b8e80941Smrg            ImGui::Text(paths[i]); ImGui::NextColumn();
2309b8e80941Smrg            ImGui::Text("%d", hovered); ImGui::NextColumn();
2310b8e80941Smrg        }
2311b8e80941Smrg        ImGui::Columns(1);
2312b8e80941Smrg        ImGui::Separator();
2313b8e80941Smrg        ImGui::TreePop();
2314b8e80941Smrg    }
2315b8e80941Smrg
2316b8e80941Smrg    // Create multiple items in a same cell before switching to next column
2317b8e80941Smrg    if (ImGui::TreeNode("Mixed items"))
2318b8e80941Smrg    {
2319b8e80941Smrg        ImGui::Columns(3, "mixed");
2320b8e80941Smrg        ImGui::Separator();
2321b8e80941Smrg
2322b8e80941Smrg        ImGui::Text("Hello");
2323b8e80941Smrg        ImGui::Button("Banana");
2324b8e80941Smrg        ImGui::NextColumn();
2325b8e80941Smrg
2326b8e80941Smrg        ImGui::Text("ImGui");
2327b8e80941Smrg        ImGui::Button("Apple");
2328b8e80941Smrg        static float foo = 1.0f;
2329b8e80941Smrg        ImGui::InputFloat("red", &foo, 0.05f, 0, "%.3f");
2330b8e80941Smrg        ImGui::Text("An extra line here.");
2331b8e80941Smrg        ImGui::NextColumn();
2332b8e80941Smrg
2333b8e80941Smrg        ImGui::Text("Sailor");
2334b8e80941Smrg        ImGui::Button("Corniflower");
2335b8e80941Smrg        static float bar = 1.0f;
2336b8e80941Smrg        ImGui::InputFloat("blue", &bar, 0.05f, 0, "%.3f");
2337b8e80941Smrg        ImGui::NextColumn();
2338b8e80941Smrg
2339b8e80941Smrg        if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2340b8e80941Smrg        if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2341b8e80941Smrg        if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2342b8e80941Smrg        ImGui::Columns(1);
2343b8e80941Smrg        ImGui::Separator();
2344b8e80941Smrg        ImGui::TreePop();
2345b8e80941Smrg    }
2346b8e80941Smrg
2347b8e80941Smrg    // Word wrapping
2348b8e80941Smrg    if (ImGui::TreeNode("Word-wrapping"))
2349b8e80941Smrg    {
2350b8e80941Smrg        ImGui::Columns(2, "word-wrapping");
2351b8e80941Smrg        ImGui::Separator();
2352b8e80941Smrg        ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2353b8e80941Smrg        ImGui::TextWrapped("Hello Left");
2354b8e80941Smrg        ImGui::NextColumn();
2355b8e80941Smrg        ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2356b8e80941Smrg        ImGui::TextWrapped("Hello Right");
2357b8e80941Smrg        ImGui::Columns(1);
2358b8e80941Smrg        ImGui::Separator();
2359b8e80941Smrg        ImGui::TreePop();
2360b8e80941Smrg    }
2361b8e80941Smrg
2362b8e80941Smrg    if (ImGui::TreeNode("Borders"))
2363b8e80941Smrg    {
2364b8e80941Smrg        // NB: Future columns API should allow automatic horizontal borders.
2365b8e80941Smrg        static bool h_borders = true;
2366b8e80941Smrg        static bool v_borders = true;
2367b8e80941Smrg        ImGui::Checkbox("horizontal", &h_borders);
2368b8e80941Smrg        ImGui::SameLine();
2369b8e80941Smrg        ImGui::Checkbox("vertical", &v_borders);
2370b8e80941Smrg        ImGui::Columns(4, NULL, v_borders);
2371b8e80941Smrg        for (int i = 0; i < 4*3; i++)
2372b8e80941Smrg        {
2373b8e80941Smrg            if (h_borders && ImGui::GetColumnIndex() == 0)
2374b8e80941Smrg                ImGui::Separator();
2375b8e80941Smrg            ImGui::Text("%c%c%c", 'a'+i, 'a'+i, 'a'+i);
2376b8e80941Smrg            ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
2377b8e80941Smrg            ImGui::NextColumn();
2378b8e80941Smrg        }
2379b8e80941Smrg        ImGui::Columns(1);
2380b8e80941Smrg        if (h_borders)
2381b8e80941Smrg            ImGui::Separator();
2382b8e80941Smrg        ImGui::TreePop();
2383b8e80941Smrg    }
2384b8e80941Smrg
2385b8e80941Smrg    // Scrolling columns
2386b8e80941Smrg    /*
2387b8e80941Smrg    if (ImGui::TreeNode("Vertical Scrolling"))
2388b8e80941Smrg    {
2389b8e80941Smrg        ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
2390b8e80941Smrg        ImGui::Columns(3);
2391b8e80941Smrg        ImGui::Text("ID"); ImGui::NextColumn();
2392b8e80941Smrg        ImGui::Text("Name"); ImGui::NextColumn();
2393b8e80941Smrg        ImGui::Text("Path"); ImGui::NextColumn();
2394b8e80941Smrg        ImGui::Columns(1);
2395b8e80941Smrg        ImGui::Separator();
2396b8e80941Smrg        ImGui::EndChild();
2397b8e80941Smrg        ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
2398b8e80941Smrg        ImGui::Columns(3);
2399b8e80941Smrg        for (int i = 0; i < 10; i++)
2400b8e80941Smrg        {
2401b8e80941Smrg            ImGui::Text("%04d", i); ImGui::NextColumn();
2402b8e80941Smrg            ImGui::Text("Foobar"); ImGui::NextColumn();
2403b8e80941Smrg            ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
2404b8e80941Smrg        }
2405b8e80941Smrg        ImGui::Columns(1);
2406b8e80941Smrg        ImGui::EndChild();
2407b8e80941Smrg        ImGui::TreePop();
2408b8e80941Smrg    }
2409b8e80941Smrg    */
2410b8e80941Smrg
2411b8e80941Smrg    if (ImGui::TreeNode("Horizontal Scrolling"))
2412b8e80941Smrg    {
2413b8e80941Smrg        ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
2414b8e80941Smrg        ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar);
2415b8e80941Smrg        ImGui::Columns(10);
2416b8e80941Smrg        int ITEMS_COUNT = 2000;
2417b8e80941Smrg        ImGuiListClipper clipper(ITEMS_COUNT);  // Also demonstrate using the clipper for large list
2418b8e80941Smrg        while (clipper.Step())
2419b8e80941Smrg        {
2420b8e80941Smrg            for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
2421b8e80941Smrg                for (int j = 0; j < 10; j++)
2422b8e80941Smrg                {
2423b8e80941Smrg                    ImGui::Text("Line %d Column %d...", i, j);
2424b8e80941Smrg                    ImGui::NextColumn();
2425b8e80941Smrg                }
2426b8e80941Smrg        }
2427b8e80941Smrg        ImGui::Columns(1);
2428b8e80941Smrg        ImGui::EndChild();
2429b8e80941Smrg        ImGui::TreePop();
2430b8e80941Smrg    }
2431b8e80941Smrg
2432b8e80941Smrg    bool node_open = ImGui::TreeNode("Tree within single cell");
2433b8e80941Smrg    ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
2434b8e80941Smrg    if (node_open)
2435b8e80941Smrg    {
2436b8e80941Smrg        ImGui::Columns(2, "tree items");
2437b8e80941Smrg        ImGui::Separator();
2438b8e80941Smrg        if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
2439b8e80941Smrg        if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
2440b8e80941Smrg        ImGui::Columns(1);
2441b8e80941Smrg        ImGui::Separator();
2442b8e80941Smrg        ImGui::TreePop();
2443b8e80941Smrg    }
2444b8e80941Smrg    ImGui::PopID();
2445b8e80941Smrg}
2446b8e80941Smrg
2447b8e80941Smrgstatic void ShowDemoWindowMisc()
2448b8e80941Smrg{
2449b8e80941Smrg    if (ImGui::CollapsingHeader("Filtering"))
2450b8e80941Smrg    {
2451b8e80941Smrg        static ImGuiTextFilter filter;
2452b8e80941Smrg        ImGui::Text("Filter usage:\n"
2453b8e80941Smrg                    "  \"\"         display all lines\n"
2454b8e80941Smrg                    "  \"xxx\"      display lines containing \"xxx\"\n"
2455b8e80941Smrg                    "  \"xxx,yyy\"  display lines containing \"xxx\" or \"yyy\"\n"
2456b8e80941Smrg                    "  \"-xxx\"     hide lines containing \"xxx\"");
2457b8e80941Smrg        filter.Draw();
2458b8e80941Smrg        const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
2459b8e80941Smrg        for (int i = 0; i < IM_ARRAYSIZE(lines); i++)
2460b8e80941Smrg            if (filter.PassFilter(lines[i]))
2461b8e80941Smrg                ImGui::BulletText("%s", lines[i]);
2462b8e80941Smrg    }
2463b8e80941Smrg
2464b8e80941Smrg    if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
2465b8e80941Smrg    {
2466b8e80941Smrg        ImGuiIO& io = ImGui::GetIO();
2467b8e80941Smrg
2468b8e80941Smrg        ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse);
2469b8e80941Smrg        ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard);
2470b8e80941Smrg        ImGui::Text("WantTextInput: %d", io.WantTextInput);
2471b8e80941Smrg        ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos);
2472b8e80941Smrg        ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible);
2473b8e80941Smrg
2474b8e80941Smrg        if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
2475b8e80941Smrg        {
2476b8e80941Smrg            if (ImGui::IsMousePosValid())
2477b8e80941Smrg                ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y);
2478b8e80941Smrg            else
2479b8e80941Smrg                ImGui::Text("Mouse pos: <INVALID>");
2480b8e80941Smrg            ImGui::Text("Mouse delta: (%g, %g)", io.MouseDelta.x, io.MouseDelta.y);
2481b8e80941Smrg            ImGui::Text("Mouse down:");     for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); }
2482b8e80941Smrg            ImGui::Text("Mouse clicked:");  for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i))          { ImGui::SameLine(); ImGui::Text("b%d", i); }
2483b8e80941Smrg            ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); }
2484b8e80941Smrg            ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i))         { ImGui::SameLine(); ImGui::Text("b%d", i); }
2485b8e80941Smrg            ImGui::Text("Mouse wheel: %.1f", io.MouseWheel);
2486b8e80941Smrg
2487b8e80941Smrg            ImGui::Text("Keys down:");      for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f)     { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }
2488b8e80941Smrg            ImGui::Text("Keys pressed:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i))             { ImGui::SameLine(); ImGui::Text("%d", i); }
2489b8e80941Smrg            ImGui::Text("Keys release:");   for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i))            { ImGui::SameLine(); ImGui::Text("%d", i); }
2490b8e80941Smrg            ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
2491b8e80941Smrg
2492b8e80941Smrg            ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f)                    { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); }
2493b8e80941Smrg            ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f)    { ImGui::SameLine(); ImGui::Text("[%d]", i); }
2494b8e80941Smrg            ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f)   { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); }
2495b8e80941Smrg
2496b8e80941Smrg            ImGui::Button("Hovering me sets the\nkeyboard capture flag");
2497b8e80941Smrg            if (ImGui::IsItemHovered())
2498b8e80941Smrg                ImGui::CaptureKeyboardFromApp(true);
2499b8e80941Smrg            ImGui::SameLine();
2500b8e80941Smrg            ImGui::Button("Holding me clears the\nthe keyboard capture flag");
2501b8e80941Smrg            if (ImGui::IsItemActive())
2502b8e80941Smrg                ImGui::CaptureKeyboardFromApp(false);
2503b8e80941Smrg
2504b8e80941Smrg            ImGui::TreePop();
2505b8e80941Smrg        }
2506b8e80941Smrg
2507b8e80941Smrg        if (ImGui::TreeNode("Tabbing"))
2508b8e80941Smrg        {
2509b8e80941Smrg            ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
2510b8e80941Smrg            static char buf[32] = "dummy";
2511b8e80941Smrg            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
2512b8e80941Smrg            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
2513b8e80941Smrg            ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
2514b8e80941Smrg            ImGui::PushAllowKeyboardFocus(false);
2515b8e80941Smrg            ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
2516b8e80941Smrg            //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
2517b8e80941Smrg            ImGui::PopAllowKeyboardFocus();
2518b8e80941Smrg            ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
2519b8e80941Smrg            ImGui::TreePop();
2520b8e80941Smrg        }
2521b8e80941Smrg
2522b8e80941Smrg        if (ImGui::TreeNode("Focus from code"))
2523b8e80941Smrg        {
2524b8e80941Smrg            bool focus_1 = ImGui::Button("Focus on 1"); ImGui::SameLine();
2525b8e80941Smrg            bool focus_2 = ImGui::Button("Focus on 2"); ImGui::SameLine();
2526b8e80941Smrg            bool focus_3 = ImGui::Button("Focus on 3");
2527b8e80941Smrg            int has_focus = 0;
2528b8e80941Smrg            static char buf[128] = "click on a button to set focus";
2529b8e80941Smrg
2530b8e80941Smrg            if (focus_1) ImGui::SetKeyboardFocusHere();
2531b8e80941Smrg            ImGui::InputText("1", buf, IM_ARRAYSIZE(buf));
2532b8e80941Smrg            if (ImGui::IsItemActive()) has_focus = 1;
2533b8e80941Smrg
2534b8e80941Smrg            if (focus_2) ImGui::SetKeyboardFocusHere();
2535b8e80941Smrg            ImGui::InputText("2", buf, IM_ARRAYSIZE(buf));
2536b8e80941Smrg            if (ImGui::IsItemActive()) has_focus = 2;
2537b8e80941Smrg
2538b8e80941Smrg            ImGui::PushAllowKeyboardFocus(false);
2539b8e80941Smrg            if (focus_3) ImGui::SetKeyboardFocusHere();
2540b8e80941Smrg            ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
2541b8e80941Smrg            if (ImGui::IsItemActive()) has_focus = 3;
2542b8e80941Smrg            ImGui::PopAllowKeyboardFocus();
2543b8e80941Smrg
2544b8e80941Smrg            if (has_focus)
2545b8e80941Smrg                ImGui::Text("Item with focus: %d", has_focus);
2546b8e80941Smrg            else
2547b8e80941Smrg                ImGui::Text("Item with focus: <none>");
2548b8e80941Smrg
2549b8e80941Smrg            // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
2550b8e80941Smrg            static float f3[3] = { 0.0f, 0.0f, 0.0f };
2551b8e80941Smrg            int focus_ahead = -1;
2552b8e80941Smrg            if (ImGui::Button("Focus on X")) { focus_ahead = 0; } ImGui::SameLine();
2553b8e80941Smrg            if (ImGui::Button("Focus on Y")) { focus_ahead = 1; } ImGui::SameLine();
2554b8e80941Smrg            if (ImGui::Button("Focus on Z")) { focus_ahead = 2; }
2555b8e80941Smrg            if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead);
2556b8e80941Smrg            ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f);
2557b8e80941Smrg
2558b8e80941Smrg            ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
2559b8e80941Smrg            ImGui::TreePop();
2560b8e80941Smrg        }
2561b8e80941Smrg
2562b8e80941Smrg        if (ImGui::TreeNode("Dragging"))
2563b8e80941Smrg        {
2564b8e80941Smrg            ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
2565b8e80941Smrg            for (int button = 0; button < 3; button++)
2566b8e80941Smrg                ImGui::Text("IsMouseDragging(%d):\n  w/ default threshold: %d,\n  w/ zero threshold: %d\n  w/ large threshold: %d",
2567b8e80941Smrg                    button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f));
2568b8e80941Smrg            ImGui::Button("Drag Me");
2569b8e80941Smrg            if (ImGui::IsItemActive())
2570b8e80941Smrg            {
2571b8e80941Smrg                // Draw a line between the button and the mouse cursor
2572b8e80941Smrg                ImDrawList* draw_list = ImGui::GetWindowDrawList();
2573b8e80941Smrg                draw_list->PushClipRectFullScreen();
2574b8e80941Smrg                draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f);
2575b8e80941Smrg                draw_list->PopClipRect();
2576b8e80941Smrg
2577b8e80941Smrg                // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
2578b8e80941Smrg                // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
2579b8e80941Smrg                ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f);
2580b8e80941Smrg                ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0);
2581b8e80941Smrg                ImVec2 mouse_delta = io.MouseDelta;
2582b8e80941Smrg                ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y);
2583b8e80941Smrg            }
2584b8e80941Smrg            ImGui::TreePop();
2585b8e80941Smrg        }
2586b8e80941Smrg
2587b8e80941Smrg        if (ImGui::TreeNode("Mouse cursors"))
2588b8e80941Smrg        {
2589b8e80941Smrg            const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" };
2590b8e80941Smrg            IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT);
2591b8e80941Smrg
2592b8e80941Smrg            ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]);
2593b8e80941Smrg            ImGui::Text("Hover to see mouse cursors:");
2594b8e80941Smrg            ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it.");
2595b8e80941Smrg            for (int i = 0; i < ImGuiMouseCursor_COUNT; i++)
2596b8e80941Smrg            {
2597b8e80941Smrg                char label[32];
2598b8e80941Smrg                sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]);
2599b8e80941Smrg                ImGui::Bullet(); ImGui::Selectable(label, false);
2600b8e80941Smrg                if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
2601b8e80941Smrg                    ImGui::SetMouseCursor(i);
2602b8e80941Smrg            }
2603b8e80941Smrg            ImGui::TreePop();
2604b8e80941Smrg        }
2605b8e80941Smrg    }
2606b8e80941Smrg}
2607b8e80941Smrg
2608b8e80941Smrg//-----------------------------------------------------------------------------
2609b8e80941Smrg// [SECTION] About Window / ShowAboutWindow()
2610b8e80941Smrg// Access from ImGui Demo -> Help -> About
2611b8e80941Smrg//-----------------------------------------------------------------------------
2612b8e80941Smrg
2613b8e80941Smrgvoid ImGui::ShowAboutWindow(bool* p_open)
2614b8e80941Smrg{
2615b8e80941Smrg    if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
2616b8e80941Smrg    {
2617b8e80941Smrg        ImGui::End();
2618b8e80941Smrg        return;
2619b8e80941Smrg    }
2620b8e80941Smrg    ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
2621b8e80941Smrg    ImGui::Separator();
2622b8e80941Smrg    ImGui::Text("By Omar Cornut and all dear imgui contributors.");
2623b8e80941Smrg    ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
2624b8e80941Smrg
2625b8e80941Smrg    static bool show_config_info = false;
2626b8e80941Smrg    ImGui::Checkbox("Config/Build Information", &show_config_info);
2627b8e80941Smrg    if (show_config_info)
2628b8e80941Smrg    {
2629b8e80941Smrg        ImGuiIO& io = ImGui::GetIO();
2630b8e80941Smrg        ImGuiStyle& style = ImGui::GetStyle();
2631b8e80941Smrg
2632b8e80941Smrg        bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
2633b8e80941Smrg        ImGui::BeginChildFrame(ImGui::GetID("cfginfos"), ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18), ImGuiWindowFlags_NoMove);
2634b8e80941Smrg        if (copy_to_clipboard)
2635b8e80941Smrg            ImGui::LogToClipboard();
2636b8e80941Smrg
2637b8e80941Smrg        ImGui::Text("Dear ImGui %s (%d)", IMGUI_VERSION, IMGUI_VERSION_NUM);
2638b8e80941Smrg        ImGui::Separator();
2639b8e80941Smrg        ImGui::Text("sizeof(size_t): %d, sizeof(ImDrawIdx): %d, sizeof(ImDrawVert): %d", (int)sizeof(size_t), (int)sizeof(ImDrawIdx), (int)sizeof(ImDrawVert));
2640b8e80941Smrg        ImGui::Text("define: __cplusplus=%d", (int)__cplusplus);
2641b8e80941Smrg#ifdef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
2642b8e80941Smrg        ImGui::Text("define: IMGUI_DISABLE_OBSOLETE_FUNCTIONS");
2643b8e80941Smrg#endif
2644b8e80941Smrg#ifdef IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS
2645b8e80941Smrg        ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS");
2646b8e80941Smrg#endif
2647b8e80941Smrg#ifdef IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS
2648b8e80941Smrg        ImGui::Text("define: IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS");
2649b8e80941Smrg#endif
2650b8e80941Smrg#ifdef IMGUI_DISABLE_WIN32_FUNCTIONS
2651b8e80941Smrg        ImGui::Text("define: IMGUI_DISABLE_WIN32_FUNCTIONS");
2652b8e80941Smrg#endif
2653b8e80941Smrg#ifdef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS
2654b8e80941Smrg        ImGui::Text("define: IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS");
2655b8e80941Smrg#endif
2656b8e80941Smrg#ifdef IMGUI_DISABLE_MATH_FUNCTIONS
2657b8e80941Smrg        ImGui::Text("define: IMGUI_DISABLE_MATH_FUNCTIONS");
2658b8e80941Smrg#endif
2659b8e80941Smrg#ifdef IMGUI_DISABLE_DEFAULT_ALLOCATORS
2660b8e80941Smrg        ImGui::Text("define: IMGUI_DISABLE_DEFAULT_ALLOCATORS");
2661b8e80941Smrg#endif
2662b8e80941Smrg#ifdef IMGUI_USE_BGRA_PACKED_COLOR
2663b8e80941Smrg        ImGui::Text("define: IMGUI_USE_BGRA_PACKED_COLOR");
2664b8e80941Smrg#endif
2665b8e80941Smrg#ifdef _WIN32
2666b8e80941Smrg        ImGui::Text("define: _WIN32");
2667b8e80941Smrg#endif
2668b8e80941Smrg#ifdef _WIN64
2669b8e80941Smrg        ImGui::Text("define: _WIN64");
2670b8e80941Smrg#endif
2671b8e80941Smrg#ifdef __linux__
2672b8e80941Smrg        ImGui::Text("define: __linux__");
2673b8e80941Smrg#endif
2674b8e80941Smrg#ifdef __APPLE__
2675b8e80941Smrg        ImGui::Text("define: __APPLE__");
2676b8e80941Smrg#endif
2677b8e80941Smrg#ifdef _MSC_VER
2678b8e80941Smrg        ImGui::Text("define: _MSC_VER=%d", _MSC_VER);
2679b8e80941Smrg#endif
2680b8e80941Smrg#ifdef __MINGW32__
2681b8e80941Smrg        ImGui::Text("define: __MINGW32__");
2682b8e80941Smrg#endif
2683b8e80941Smrg#ifdef __MINGW64__
2684b8e80941Smrg        ImGui::Text("define: __MINGW64__");
2685b8e80941Smrg#endif
2686b8e80941Smrg#ifdef __GNUC__
2687b8e80941Smrg        ImGui::Text("define: __GNUC__=%d", (int)__GNUC__);
2688b8e80941Smrg#endif
2689b8e80941Smrg#ifdef __clang_version__
2690b8e80941Smrg        ImGui::Text("define: __clang_version__=%s", __clang_version__);
2691b8e80941Smrg#endif
2692b8e80941Smrg        ImGui::Separator();
2693b8e80941Smrg        ImGui::Text("io.BackendPlatformName: %s", io.BackendPlatformName ? io.BackendPlatformName : "NULL");
2694b8e80941Smrg        ImGui::Text("io.BackendRendererName: %s", io.BackendRendererName ? io.BackendRendererName : "NULL");
2695b8e80941Smrg        ImGui::Text("io.ConfigFlags: 0x%08X", io.ConfigFlags);
2696b8e80941Smrg        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard)        ImGui::Text(" NavEnableKeyboard");
2697b8e80941Smrg        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad)         ImGui::Text(" NavEnableGamepad");
2698b8e80941Smrg        if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)     ImGui::Text(" NavEnableSetMousePos");
2699b8e80941Smrg        if (io.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)     ImGui::Text(" NavNoCaptureKeyboard");
2700b8e80941Smrg        if (io.ConfigFlags & ImGuiConfigFlags_NoMouse)                  ImGui::Text(" NoMouse");
2701b8e80941Smrg        if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)      ImGui::Text(" NoMouseCursorChange");
2702b8e80941Smrg        if (io.MouseDrawCursor)                                         ImGui::Text("io.MouseDrawCursor");
2703b8e80941Smrg        if (io.ConfigMacOSXBehaviors)                                   ImGui::Text("io.ConfigMacOSXBehaviors");
2704b8e80941Smrg        if (io.ConfigInputTextCursorBlink)                              ImGui::Text("io.ConfigInputTextCursorBlink");
2705b8e80941Smrg        if (io.ConfigWindowsResizeFromEdges)                            ImGui::Text("io.ConfigWindowsResizeFromEdges");
2706b8e80941Smrg        if (io.ConfigWindowsMoveFromTitleBarOnly)                       ImGui::Text("io.ConfigWindowsMoveFromTitleBarOnly");
2707b8e80941Smrg        ImGui::Text("io.BackendFlags: 0x%08X", io.BackendFlags);
2708b8e80941Smrg        if (io.BackendFlags & ImGuiBackendFlags_HasGamepad)             ImGui::Text(" HasGamepad");
2709b8e80941Smrg        if (io.BackendFlags & ImGuiBackendFlags_HasMouseCursors)        ImGui::Text(" HasMouseCursors");
2710b8e80941Smrg        if (io.BackendFlags & ImGuiBackendFlags_HasSetMousePos)         ImGui::Text(" HasSetMousePos");
2711b8e80941Smrg        ImGui::Separator();
2712b8e80941Smrg        ImGui::Text("io.Fonts: %d fonts, Flags: 0x%08X, TexSize: %d,%d", io.Fonts->Fonts.Size, io.Fonts->Flags, io.Fonts->TexWidth, io.Fonts->TexHeight);
2713b8e80941Smrg        ImGui::Text("io.DisplaySize: %.2f,%.2f", io.DisplaySize.x, io.DisplaySize.y);
2714b8e80941Smrg        ImGui::Text("io.DisplayFramebufferScale: %.2f,%.2f", io.DisplayFramebufferScale.x, io.DisplayFramebufferScale.y);
2715b8e80941Smrg        ImGui::Separator();
2716b8e80941Smrg        ImGui::Text("style.WindowPadding: %.2f,%.2f", style.WindowPadding.x, style.WindowPadding.y);
2717b8e80941Smrg        ImGui::Text("style.WindowBorderSize: %.2f", style.WindowBorderSize);
2718b8e80941Smrg        ImGui::Text("style.FramePadding: %.2f,%.2f", style.FramePadding.x, style.FramePadding.y);
2719b8e80941Smrg        ImGui::Text("style.FrameRounding: %.2f", style.FrameRounding);
2720b8e80941Smrg        ImGui::Text("style.FrameBorderSize: %.2f", style.FrameBorderSize);
2721b8e80941Smrg        ImGui::Text("style.ItemSpacing: %.2f,%.2f", style.ItemSpacing.x, style.ItemSpacing.y);
2722b8e80941Smrg        ImGui::Text("style.ItemInnerSpacing: %.2f,%.2f", style.ItemInnerSpacing.x, style.ItemInnerSpacing.y);
2723b8e80941Smrg
2724b8e80941Smrg        if (copy_to_clipboard)
2725b8e80941Smrg            ImGui::LogFinish();
2726b8e80941Smrg        ImGui::EndChildFrame();
2727b8e80941Smrg    }
2728b8e80941Smrg    ImGui::End();
2729b8e80941Smrg}
2730b8e80941Smrg
2731b8e80941Smrg//-----------------------------------------------------------------------------
2732b8e80941Smrg// [SECTION] Style Editor / ShowStyleEditor()
2733b8e80941Smrg//-----------------------------------------------------------------------------
2734b8e80941Smrg
2735b8e80941Smrg// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
2736b8e80941Smrg// Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally.
2737b8e80941Smrgbool ImGui::ShowStyleSelector(const char* label)
2738b8e80941Smrg{
2739b8e80941Smrg    static int style_idx = -1;
2740b8e80941Smrg    if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0"))
2741b8e80941Smrg    {
2742b8e80941Smrg        switch (style_idx)
2743b8e80941Smrg        {
2744b8e80941Smrg        case 0: ImGui::StyleColorsClassic(); break;
2745b8e80941Smrg        case 1: ImGui::StyleColorsDark(); break;
2746b8e80941Smrg        case 2: ImGui::StyleColorsLight(); break;
2747b8e80941Smrg        }
2748b8e80941Smrg        return true;
2749b8e80941Smrg    }
2750b8e80941Smrg    return false;
2751b8e80941Smrg}
2752b8e80941Smrg
2753b8e80941Smrg// Demo helper function to select among loaded fonts.
2754b8e80941Smrg// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
2755b8e80941Smrgvoid ImGui::ShowFontSelector(const char* label)
2756b8e80941Smrg{
2757b8e80941Smrg    ImGuiIO& io = ImGui::GetIO();
2758b8e80941Smrg    ImFont* font_current = ImGui::GetFont();
2759b8e80941Smrg    if (ImGui::BeginCombo(label, font_current->GetDebugName()))
2760b8e80941Smrg    {
2761b8e80941Smrg        for (int n = 0; n < io.Fonts->Fonts.Size; n++)
2762b8e80941Smrg        {
2763b8e80941Smrg            ImFont* font = io.Fonts->Fonts[n];
2764b8e80941Smrg            ImGui::PushID((void*)font);
2765b8e80941Smrg            if (ImGui::Selectable(font->GetDebugName(), font == font_current))
2766b8e80941Smrg                io.FontDefault = font;
2767b8e80941Smrg            ImGui::PopID();
2768b8e80941Smrg        }
2769b8e80941Smrg        ImGui::EndCombo();
2770b8e80941Smrg    }
2771b8e80941Smrg    ImGui::SameLine();
2772b8e80941Smrg    ShowHelpMarker(
2773b8e80941Smrg        "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
2774b8e80941Smrg        "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
2775b8e80941Smrg        "- Read FAQ and documentation in misc/fonts/ for more details.\n"
2776b8e80941Smrg        "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
2777b8e80941Smrg}
2778b8e80941Smrg
2779b8e80941Smrgvoid ImGui::ShowStyleEditor(ImGuiStyle* ref)
2780b8e80941Smrg{
2781b8e80941Smrg    // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
2782b8e80941Smrg    ImGuiStyle& style = ImGui::GetStyle();
2783b8e80941Smrg    static ImGuiStyle ref_saved_style;
2784b8e80941Smrg
2785b8e80941Smrg    // Default to using internal storage as reference
2786b8e80941Smrg    static bool init = true;
2787b8e80941Smrg    if (init && ref == NULL)
2788b8e80941Smrg        ref_saved_style = style;
2789b8e80941Smrg    init = false;
2790b8e80941Smrg    if (ref == NULL)
2791b8e80941Smrg        ref = &ref_saved_style;
2792b8e80941Smrg
2793b8e80941Smrg    ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
2794b8e80941Smrg
2795b8e80941Smrg    if (ImGui::ShowStyleSelector("Colors##Selector"))
2796b8e80941Smrg        ref_saved_style = style;
2797b8e80941Smrg    ImGui::ShowFontSelector("Fonts##Selector");
2798b8e80941Smrg
2799b8e80941Smrg    // Simplified Settings
2800b8e80941Smrg    if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f"))
2801b8e80941Smrg        style.GrabRounding = style.FrameRounding; // Make GrabRounding always the same value as FrameRounding
2802b8e80941Smrg    { bool window_border = (style.WindowBorderSize > 0.0f); if (ImGui::Checkbox("WindowBorder", &window_border)) style.WindowBorderSize = window_border ? 1.0f : 0.0f; }
2803b8e80941Smrg    ImGui::SameLine();
2804b8e80941Smrg    { bool frame_border = (style.FrameBorderSize > 0.0f); if (ImGui::Checkbox("FrameBorder", &frame_border)) style.FrameBorderSize = frame_border ? 1.0f : 0.0f; }
2805b8e80941Smrg    ImGui::SameLine();
2806b8e80941Smrg    { bool popup_border = (style.PopupBorderSize > 0.0f); if (ImGui::Checkbox("PopupBorder", &popup_border)) style.PopupBorderSize = popup_border ? 1.0f : 0.0f; }
2807b8e80941Smrg
2808b8e80941Smrg    // Save/Revert button
2809b8e80941Smrg    if (ImGui::Button("Save Ref"))
2810b8e80941Smrg        *ref = ref_saved_style = style;
2811b8e80941Smrg    ImGui::SameLine();
2812b8e80941Smrg    if (ImGui::Button("Revert Ref"))
2813b8e80941Smrg        style = *ref;
2814b8e80941Smrg    ImGui::SameLine();
2815b8e80941Smrg    ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
2816b8e80941Smrg
2817b8e80941Smrg    ImGui::Separator();
2818b8e80941Smrg
2819b8e80941Smrg    if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None))
2820b8e80941Smrg    {
2821b8e80941Smrg        if (ImGui::BeginTabItem("Sizes"))
2822b8e80941Smrg        {
2823b8e80941Smrg            ImGui::Text("Main");
2824b8e80941Smrg            ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f, 20.0f, "%.0f");
2825b8e80941Smrg            ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f, 20.0f, "%.0f");
2826b8e80941Smrg            ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f, 20.0f, "%.0f");
2827b8e80941Smrg            ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing, 0.0f, 20.0f, "%.0f");
2828b8e80941Smrg            ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding, 0.0f, 10.0f, "%.0f");
2829b8e80941Smrg            ImGui::SliderFloat("IndentSpacing", &style.IndentSpacing, 0.0f, 30.0f, "%.0f");
2830b8e80941Smrg            ImGui::SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
2831b8e80941Smrg            ImGui::SliderFloat("GrabMinSize", &style.GrabMinSize, 1.0f, 20.0f, "%.0f");
2832b8e80941Smrg            ImGui::Text("Borders");
2833b8e80941Smrg            ImGui::SliderFloat("WindowBorderSize", &style.WindowBorderSize, 0.0f, 1.0f, "%.0f");
2834b8e80941Smrg            ImGui::SliderFloat("ChildBorderSize", &style.ChildBorderSize, 0.0f, 1.0f, "%.0f");
2835b8e80941Smrg            ImGui::SliderFloat("PopupBorderSize", &style.PopupBorderSize, 0.0f, 1.0f, "%.0f");
2836b8e80941Smrg            ImGui::SliderFloat("FrameBorderSize", &style.FrameBorderSize, 0.0f, 1.0f, "%.0f");
2837b8e80941Smrg            ImGui::SliderFloat("TabBorderSize", &style.TabBorderSize, 0.0f, 1.0f, "%.0f");
2838b8e80941Smrg            ImGui::Text("Rounding");
2839b8e80941Smrg            ImGui::SliderFloat("WindowRounding", &style.WindowRounding, 0.0f, 12.0f, "%.0f");
2840b8e80941Smrg            ImGui::SliderFloat("ChildRounding", &style.ChildRounding, 0.0f, 12.0f, "%.0f");
2841b8e80941Smrg            ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
2842b8e80941Smrg            ImGui::SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
2843b8e80941Smrg            ImGui::SliderFloat("ScrollbarRounding", &style.ScrollbarRounding, 0.0f, 12.0f, "%.0f");
2844b8e80941Smrg            ImGui::SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
2845b8e80941Smrg            ImGui::SliderFloat("TabRounding", &style.TabRounding, 0.0f, 12.0f, "%.0f");
2846b8e80941Smrg            ImGui::Text("Alignment");
2847b8e80941Smrg            ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign, 0.0f, 1.0f, "%.2f");
2848b8e80941Smrg            ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a button is larger than its text content.");
2849b8e80941Smrg            ImGui::SliderFloat2("SelectableTextAlign", (float*)&style.SelectableTextAlign, 0.0f, 1.0f, "%.2f"); ImGui::SameLine(); ShowHelpMarker("Alignment applies when a selectable is larger than its text content.");
2850b8e80941Smrg            ImGui::Text("Safe Area Padding"); ImGui::SameLine(); ShowHelpMarker("Adjust if you cannot see the edges of your screen (e.g. on a TV where scaling has not been configured).");
2851b8e80941Smrg            ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f, "%.0f");
2852b8e80941Smrg            ImGui::EndTabItem();
2853b8e80941Smrg        }
2854b8e80941Smrg
2855b8e80941Smrg        if (ImGui::BeginTabItem("Colors"))
2856b8e80941Smrg        {
2857b8e80941Smrg            static int output_dest = 0;
2858b8e80941Smrg            static bool output_only_modified = true;
2859b8e80941Smrg            if (ImGui::Button("Export Unsaved"))
2860b8e80941Smrg            {
2861b8e80941Smrg                if (output_dest == 0)
2862b8e80941Smrg                    ImGui::LogToClipboard();
2863b8e80941Smrg                else
2864b8e80941Smrg                    ImGui::LogToTTY();
2865b8e80941Smrg                ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
2866b8e80941Smrg                for (int i = 0; i < ImGuiCol_COUNT; i++)
2867b8e80941Smrg                {
2868b8e80941Smrg                    const ImVec4& col = style.Colors[i];
2869b8e80941Smrg                    const char* name = ImGui::GetStyleColorName(i);
2870b8e80941Smrg                    if (!output_only_modified || memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
2871b8e80941Smrg                        ImGui::LogText("colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, %.2ff);" IM_NEWLINE, name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
2872b8e80941Smrg                }
2873b8e80941Smrg                ImGui::LogFinish();
2874b8e80941Smrg            }
2875b8e80941Smrg            ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
2876b8e80941Smrg            ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified);
2877b8e80941Smrg
2878b8e80941Smrg            static ImGuiTextFilter filter;
2879b8e80941Smrg            filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
2880b8e80941Smrg
2881b8e80941Smrg            static ImGuiColorEditFlags alpha_flags = 0;
2882b8e80941Smrg            ImGui::RadioButton("Opaque", &alpha_flags, 0); ImGui::SameLine();
2883b8e80941Smrg            ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine();
2884b8e80941Smrg            ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf); ImGui::SameLine();
2885b8e80941Smrg            ShowHelpMarker("In the color list:\nLeft-click on colored square to open color picker,\nRight-click to open edit options menu.");
2886b8e80941Smrg
2887b8e80941Smrg            ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
2888b8e80941Smrg            ImGui::PushItemWidth(-160);
2889b8e80941Smrg            for (int i = 0; i < ImGuiCol_COUNT; i++)
2890b8e80941Smrg            {
2891b8e80941Smrg                const char* name = ImGui::GetStyleColorName(i);
2892b8e80941Smrg                if (!filter.PassFilter(name))
2893b8e80941Smrg                    continue;
2894b8e80941Smrg                ImGui::PushID(i);
2895b8e80941Smrg                ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
2896b8e80941Smrg                if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
2897b8e80941Smrg                {
2898b8e80941Smrg                    // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons.
2899b8e80941Smrg                    // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
2900b8e80941Smrg                    ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i];
2901b8e80941Smrg                    ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i];
2902b8e80941Smrg                }
2903b8e80941Smrg                ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
2904b8e80941Smrg                ImGui::TextUnformatted(name);
2905b8e80941Smrg                ImGui::PopID();
2906b8e80941Smrg            }
2907b8e80941Smrg            ImGui::PopItemWidth();
2908b8e80941Smrg            ImGui::EndChild();
2909b8e80941Smrg
2910b8e80941Smrg            ImGui::EndTabItem();
2911b8e80941Smrg        }
2912b8e80941Smrg
2913b8e80941Smrg        if (ImGui::BeginTabItem("Fonts"))
2914b8e80941Smrg        {
2915b8e80941Smrg            ImGuiIO& io = ImGui::GetIO();
2916b8e80941Smrg            ImFontAtlas* atlas = io.Fonts;
2917b8e80941Smrg            ShowHelpMarker("Read FAQ and misc/fonts/README.txt for details on font loading.");
2918b8e80941Smrg            ImGui::PushItemWidth(120);
2919b8e80941Smrg            for (int i = 0; i < atlas->Fonts.Size; i++)
2920b8e80941Smrg            {
2921b8e80941Smrg                ImFont* font = atlas->Fonts[i];
2922b8e80941Smrg                ImGui::PushID(font);
2923b8e80941Smrg                bool font_details_opened = ImGui::TreeNode(font, "Font %d: \"%s\"\n%.2f px, %d glyphs, %d file(s)", i, font->ConfigData ? font->ConfigData[0].Name : "", font->FontSize, font->Glyphs.Size, font->ConfigDataCount);
2924b8e80941Smrg                ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) { io.FontDefault = font; }
2925b8e80941Smrg                if (font_details_opened)
2926b8e80941Smrg                {
2927b8e80941Smrg                    ImGui::PushFont(font);
2928b8e80941Smrg                    ImGui::Text("The quick brown fox jumps over the lazy dog");
2929b8e80941Smrg                    ImGui::PopFont();
2930b8e80941Smrg                    ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f");   // Scale only this font
2931b8e80941Smrg                    ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)");
2932b8e80941Smrg                    ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, "%.0f");
2933b8e80941Smrg                    ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent);
2934b8e80941Smrg                    ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar);
2935b8e80941Smrg                    const float surface_sqrt = sqrtf((float)font->MetricsTotalSurface);
2936b8e80941Smrg                    ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)surface_sqrt, (int)surface_sqrt);
2937b8e80941Smrg                    for (int config_i = 0; config_i < font->ConfigDataCount; config_i++)
2938b8e80941Smrg                        if (const ImFontConfig* cfg = &font->ConfigData[config_i])
2939b8e80941Smrg                            ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH);
2940b8e80941Smrg                    if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
2941b8e80941Smrg                    {
2942b8e80941Smrg                        // Display all glyphs of the fonts in separate pages of 256 characters
2943b8e80941Smrg                        for (int base = 0; base < 0x10000; base += 256)
2944b8e80941Smrg                        {
2945b8e80941Smrg                            int count = 0;
2946b8e80941Smrg                            for (int n = 0; n < 256; n++)
2947b8e80941Smrg                                count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0;
2948b8e80941Smrg                            if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base + 255, count, count > 1 ? "glyphs" : "glyph"))
2949b8e80941Smrg                            {
2950b8e80941Smrg                                float cell_size = font->FontSize * 1;
2951b8e80941Smrg                                float cell_spacing = style.ItemSpacing.y;
2952b8e80941Smrg                                ImVec2 base_pos = ImGui::GetCursorScreenPos();
2953b8e80941Smrg                                ImDrawList* draw_list = ImGui::GetWindowDrawList();
2954b8e80941Smrg                                for (int n = 0; n < 256; n++)
2955b8e80941Smrg                                {
2956b8e80941Smrg                                    ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing));
2957b8e80941Smrg                                    ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size);
2958b8e80941Smrg                                    const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base + n));
2959b8e80941Smrg                                    draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255, 255, 255, 100) : IM_COL32(255, 255, 255, 50));
2960b8e80941Smrg                                    if (glyph)
2961b8e80941Smrg                                        font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base + n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string.
2962b8e80941Smrg                                    if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2))
2963b8e80941Smrg                                    {
2964b8e80941Smrg                                        ImGui::BeginTooltip();
2965b8e80941Smrg                                        ImGui::Text("Codepoint: U+%04X", base + n);
2966b8e80941Smrg                                        ImGui::Separator();
2967b8e80941Smrg                                        ImGui::Text("AdvanceX: %.1f", glyph->AdvanceX);
2968b8e80941Smrg                                        ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph->X0, glyph->Y0, glyph->X1, glyph->Y1);
2969b8e80941Smrg                                        ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph->U0, glyph->V0, glyph->U1, glyph->V1);
2970b8e80941Smrg                                        ImGui::EndTooltip();
2971b8e80941Smrg                                    }
2972b8e80941Smrg                                }
2973b8e80941Smrg                                ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16));
2974b8e80941Smrg                                ImGui::TreePop();
2975b8e80941Smrg                            }
2976b8e80941Smrg                        }
2977b8e80941Smrg                        ImGui::TreePop();
2978b8e80941Smrg                    }
2979b8e80941Smrg                    ImGui::TreePop();
2980b8e80941Smrg                }
2981b8e80941Smrg                ImGui::PopID();
2982b8e80941Smrg            }
2983b8e80941Smrg            if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
2984b8e80941Smrg            {
2985b8e80941Smrg                ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), ImColor(255, 255, 255, 255), ImColor(255, 255, 255, 128));
2986b8e80941Smrg                ImGui::TreePop();
2987b8e80941Smrg            }
2988b8e80941Smrg
2989b8e80941Smrg            static float window_scale = 1.0f;
2990b8e80941Smrg            if (ImGui::DragFloat("this window scale", &window_scale, 0.005f, 0.3f, 2.0f, "%.2f"))   // scale only this window
2991b8e80941Smrg                ImGui::SetWindowFontScale(window_scale);
2992b8e80941Smrg            ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, 0.3f, 2.0f, "%.2f");      // scale everything
2993b8e80941Smrg            ImGui::PopItemWidth();
2994b8e80941Smrg
2995b8e80941Smrg            ImGui::EndTabItem();
2996b8e80941Smrg        }
2997b8e80941Smrg
2998b8e80941Smrg        if (ImGui::BeginTabItem("Rendering"))
2999b8e80941Smrg        {
3000b8e80941Smrg            ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well.");
3001b8e80941Smrg            ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
3002b8e80941Smrg            ImGui::PushItemWidth(100);
3003b8e80941Smrg            ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, "%.2f", 2.0f);
3004b8e80941Smrg            if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
3005b8e80941Smrg            ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
3006b8e80941Smrg            ImGui::PopItemWidth();
3007b8e80941Smrg
3008b8e80941Smrg            ImGui::EndTabItem();
3009b8e80941Smrg        }
3010b8e80941Smrg
3011b8e80941Smrg        ImGui::EndTabBar();
3012b8e80941Smrg    }
3013b8e80941Smrg
3014b8e80941Smrg    ImGui::PopItemWidth();
3015b8e80941Smrg}
3016b8e80941Smrg
3017b8e80941Smrg//-----------------------------------------------------------------------------
3018b8e80941Smrg// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
3019b8e80941Smrg//-----------------------------------------------------------------------------
3020b8e80941Smrg
3021b8e80941Smrg// Demonstrate creating a fullscreen menu bar and populating it.
3022b8e80941Smrgstatic void ShowExampleAppMainMenuBar()
3023b8e80941Smrg{
3024b8e80941Smrg    if (ImGui::BeginMainMenuBar())
3025b8e80941Smrg    {
3026b8e80941Smrg        if (ImGui::BeginMenu("File"))
3027b8e80941Smrg        {
3028b8e80941Smrg            ShowExampleMenuFile();
3029b8e80941Smrg            ImGui::EndMenu();
3030b8e80941Smrg        }
3031b8e80941Smrg        if (ImGui::BeginMenu("Edit"))
3032b8e80941Smrg        {
3033b8e80941Smrg            if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
3034b8e80941Smrg            if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {}  // Disabled item
3035b8e80941Smrg            ImGui::Separator();
3036b8e80941Smrg            if (ImGui::MenuItem("Cut", "CTRL+X")) {}
3037b8e80941Smrg            if (ImGui::MenuItem("Copy", "CTRL+C")) {}
3038b8e80941Smrg            if (ImGui::MenuItem("Paste", "CTRL+V")) {}
3039b8e80941Smrg            ImGui::EndMenu();
3040b8e80941Smrg        }
3041b8e80941Smrg        ImGui::EndMainMenuBar();
3042b8e80941Smrg    }
3043b8e80941Smrg}
3044b8e80941Smrg
3045b8e80941Smrgstatic void ShowExampleMenuFile()
3046b8e80941Smrg{
3047b8e80941Smrg    ImGui::MenuItem("(dummy menu)", NULL, false, false);
3048b8e80941Smrg    if (ImGui::MenuItem("New")) {}
3049b8e80941Smrg    if (ImGui::MenuItem("Open", "Ctrl+O")) {}
3050b8e80941Smrg    if (ImGui::BeginMenu("Open Recent"))
3051b8e80941Smrg    {
3052b8e80941Smrg        ImGui::MenuItem("fish_hat.c");
3053b8e80941Smrg        ImGui::MenuItem("fish_hat.inl");
3054b8e80941Smrg        ImGui::MenuItem("fish_hat.h");
3055b8e80941Smrg        if (ImGui::BeginMenu("More.."))
3056b8e80941Smrg        {
3057b8e80941Smrg            ImGui::MenuItem("Hello");
3058b8e80941Smrg            ImGui::MenuItem("Sailor");
3059b8e80941Smrg            if (ImGui::BeginMenu("Recurse.."))
3060b8e80941Smrg            {
3061b8e80941Smrg                ShowExampleMenuFile();
3062b8e80941Smrg                ImGui::EndMenu();
3063b8e80941Smrg            }
3064b8e80941Smrg            ImGui::EndMenu();
3065b8e80941Smrg        }
3066b8e80941Smrg        ImGui::EndMenu();
3067b8e80941Smrg    }
3068b8e80941Smrg    if (ImGui::MenuItem("Save", "Ctrl+S")) {}
3069b8e80941Smrg    if (ImGui::MenuItem("Save As..")) {}
3070b8e80941Smrg    ImGui::Separator();
3071b8e80941Smrg    if (ImGui::BeginMenu("Options"))
3072b8e80941Smrg    {
3073b8e80941Smrg        static bool enabled = true;
3074b8e80941Smrg        ImGui::MenuItem("Enabled", "", &enabled);
3075b8e80941Smrg        ImGui::BeginChild("child", ImVec2(0, 60), true);
3076b8e80941Smrg        for (int i = 0; i < 10; i++)
3077b8e80941Smrg            ImGui::Text("Scrolling Text %d", i);
3078b8e80941Smrg        ImGui::EndChild();
3079b8e80941Smrg        static float f = 0.5f;
3080b8e80941Smrg        static int n = 0;
3081b8e80941Smrg        static bool b = true;
3082b8e80941Smrg        ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
3083b8e80941Smrg        ImGui::InputFloat("Input", &f, 0.1f);
3084b8e80941Smrg        ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0");
3085b8e80941Smrg        ImGui::Checkbox("Check", &b);
3086b8e80941Smrg        ImGui::EndMenu();
3087b8e80941Smrg    }
3088b8e80941Smrg    if (ImGui::BeginMenu("Colors"))
3089b8e80941Smrg    {
3090b8e80941Smrg        float sz = ImGui::GetTextLineHeight();
3091b8e80941Smrg        for (int i = 0; i < ImGuiCol_COUNT; i++)
3092b8e80941Smrg        {
3093b8e80941Smrg            const char* name = ImGui::GetStyleColorName((ImGuiCol)i);
3094b8e80941Smrg            ImVec2 p = ImGui::GetCursorScreenPos();
3095b8e80941Smrg            ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i));
3096b8e80941Smrg            ImGui::Dummy(ImVec2(sz, sz));
3097b8e80941Smrg            ImGui::SameLine();
3098b8e80941Smrg            ImGui::MenuItem(name);
3099b8e80941Smrg        }
3100b8e80941Smrg        ImGui::EndMenu();
3101b8e80941Smrg    }
3102b8e80941Smrg    if (ImGui::BeginMenu("Disabled", false)) // Disabled
3103b8e80941Smrg    {
3104b8e80941Smrg        IM_ASSERT(0);
3105b8e80941Smrg    }
3106b8e80941Smrg    if (ImGui::MenuItem("Checked", NULL, true)) {}
3107b8e80941Smrg    if (ImGui::MenuItem("Quit", "Alt+F4")) {}
3108b8e80941Smrg}
3109b8e80941Smrg
3110b8e80941Smrg//-----------------------------------------------------------------------------
3111b8e80941Smrg// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
3112b8e80941Smrg//-----------------------------------------------------------------------------
3113b8e80941Smrg
3114b8e80941Smrg// Demonstrate creating a simple console window, with scrolling, filtering, completion and history.
3115b8e80941Smrg// For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
3116b8e80941Smrgstruct ExampleAppConsole
3117b8e80941Smrg{
3118b8e80941Smrg    char                  InputBuf[256];
3119b8e80941Smrg    ImVector<char*>       Items;
3120b8e80941Smrg    ImVector<const char*> Commands;
3121b8e80941Smrg    ImVector<char*>       History;
3122b8e80941Smrg    int                   HistoryPos;    // -1: new line, 0..History.Size-1 browsing history.
3123b8e80941Smrg    ImGuiTextFilter       Filter;
3124b8e80941Smrg    bool                  AutoScroll;
3125b8e80941Smrg    bool                  ScrollToBottom;
3126b8e80941Smrg
3127b8e80941Smrg    ExampleAppConsole()
3128b8e80941Smrg    {
3129b8e80941Smrg        ClearLog();
3130b8e80941Smrg        memset(InputBuf, 0, sizeof(InputBuf));
3131b8e80941Smrg        HistoryPos = -1;
3132b8e80941Smrg        Commands.push_back("HELP");
3133b8e80941Smrg        Commands.push_back("HISTORY");
3134b8e80941Smrg        Commands.push_back("CLEAR");
3135b8e80941Smrg        Commands.push_back("CLASSIFY");  // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
3136b8e80941Smrg        AutoScroll = true;
3137b8e80941Smrg        ScrollToBottom = true;
3138b8e80941Smrg        AddLog("Welcome to Dear ImGui!");
3139b8e80941Smrg    }
3140b8e80941Smrg    ~ExampleAppConsole()
3141b8e80941Smrg    {
3142b8e80941Smrg        ClearLog();
3143b8e80941Smrg        for (int i = 0; i < History.Size; i++)
3144b8e80941Smrg            free(History[i]);
3145b8e80941Smrg    }
3146b8e80941Smrg
3147b8e80941Smrg    // Portable helpers
3148b8e80941Smrg    static int   Stricmp(const char* str1, const char* str2)         { int d; while ((d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; } return d; }
3149b8e80941Smrg    static int   Strnicmp(const char* str1, const char* str2, int n) { int d = 0; while (n > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; n--; } return d; }
3150b8e80941Smrg    static char* Strdup(const char *str)                             { size_t len = strlen(str) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)str, len); }
3151b8e80941Smrg    static void  Strtrim(char* str)                                  { char* str_end = str + strlen(str); while (str_end > str && str_end[-1] == ' ') str_end--; *str_end = 0; }
3152b8e80941Smrg
3153b8e80941Smrg    void    ClearLog()
3154b8e80941Smrg    {
3155b8e80941Smrg        for (int i = 0; i < Items.Size; i++)
3156b8e80941Smrg            free(Items[i]);
3157b8e80941Smrg        Items.clear();
3158b8e80941Smrg        ScrollToBottom = true;
3159b8e80941Smrg    }
3160b8e80941Smrg
3161b8e80941Smrg    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
3162b8e80941Smrg    {
3163b8e80941Smrg        // FIXME-OPT
3164b8e80941Smrg        char buf[1024];
3165b8e80941Smrg        va_list args;
3166b8e80941Smrg        va_start(args, fmt);
3167b8e80941Smrg        vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
3168b8e80941Smrg        buf[IM_ARRAYSIZE(buf)-1] = 0;
3169b8e80941Smrg        va_end(args);
3170b8e80941Smrg        Items.push_back(Strdup(buf));
3171b8e80941Smrg        if (AutoScroll)
3172b8e80941Smrg            ScrollToBottom = true;
3173b8e80941Smrg    }
3174b8e80941Smrg
3175b8e80941Smrg    void    Draw(const char* title, bool* p_open)
3176b8e80941Smrg    {
3177b8e80941Smrg        ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
3178b8e80941Smrg        if (!ImGui::Begin(title, p_open))
3179b8e80941Smrg        {
3180b8e80941Smrg            ImGui::End();
3181b8e80941Smrg            return;
3182b8e80941Smrg        }
3183b8e80941Smrg
3184b8e80941Smrg        // As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
3185b8e80941Smrg        // Here we create a context menu only available from the title bar.
3186b8e80941Smrg        if (ImGui::BeginPopupContextItem())
3187b8e80941Smrg        {
3188b8e80941Smrg            if (ImGui::MenuItem("Close Console"))
3189b8e80941Smrg                *p_open = false;
3190b8e80941Smrg            ImGui::EndPopup();
3191b8e80941Smrg        }
3192b8e80941Smrg
3193b8e80941Smrg        ImGui::TextWrapped("This example implements a console with basic coloring, completion and history. A more elaborate implementation may want to store entries along with extra data such as timestamp, emitter, etc.");
3194b8e80941Smrg        ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
3195b8e80941Smrg
3196b8e80941Smrg        // TODO: display items starting from the bottom
3197b8e80941Smrg
3198b8e80941Smrg        if (ImGui::SmallButton("Add Dummy Text"))  { AddLog("%d some text", Items.Size); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
3199b8e80941Smrg        if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
3200b8e80941Smrg        if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
3201b8e80941Smrg        bool copy_to_clipboard = ImGui::SmallButton("Copy"); ImGui::SameLine();
3202b8e80941Smrg        if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom = true;
3203b8e80941Smrg        //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
3204b8e80941Smrg
3205b8e80941Smrg        ImGui::Separator();
3206b8e80941Smrg
3207b8e80941Smrg        // Options menu
3208b8e80941Smrg        if (ImGui::BeginPopup("Options"))
3209b8e80941Smrg        {
3210b8e80941Smrg            if (ImGui::Checkbox("Auto-scroll", &AutoScroll))
3211b8e80941Smrg                if (AutoScroll)
3212b8e80941Smrg                    ScrollToBottom = true;
3213b8e80941Smrg            ImGui::EndPopup();
3214b8e80941Smrg        }
3215b8e80941Smrg
3216b8e80941Smrg        // Options, Filter
3217b8e80941Smrg        if (ImGui::Button("Options"))
3218b8e80941Smrg            ImGui::OpenPopup("Options");
3219b8e80941Smrg        ImGui::SameLine();
3220b8e80941Smrg        Filter.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
3221b8e80941Smrg        ImGui::Separator();
3222b8e80941Smrg
3223b8e80941Smrg        const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
3224b8e80941Smrg        ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText
3225b8e80941Smrg        if (ImGui::BeginPopupContextWindow())
3226b8e80941Smrg        {
3227b8e80941Smrg            if (ImGui::Selectable("Clear")) ClearLog();
3228b8e80941Smrg            ImGui::EndPopup();
3229b8e80941Smrg        }
3230b8e80941Smrg
3231b8e80941Smrg        // Display every line as a separate entry so we can change their color or add custom widgets. If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
3232b8e80941Smrg        // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
3233b8e80941Smrg        // You can seek and display only the lines that are visible using the ImGuiListClipper helper, if your elements are evenly spaced and you have cheap random access to the elements.
3234b8e80941Smrg        // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
3235b8e80941Smrg        //     ImGuiListClipper clipper(Items.Size);
3236b8e80941Smrg        //     while (clipper.Step())
3237b8e80941Smrg        //         for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
3238b8e80941Smrg        // However, note that you can not use this code as is if a filter is active because it breaks the 'cheap random-access' property. We would need random-access on the post-filtered list.
3239b8e80941Smrg        // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices that passed the filtering test, recomputing this array when user changes the filter,
3240b8e80941Smrg        // and appending newly elements as they are inserted. This is left as a task to the user until we can manage to improve this example code!
3241b8e80941Smrg        // If your items are of variable size you may want to implement code similar to what ImGuiListClipper does. Or split your data into fixed height items to allow random-seeking into your list.
3242b8e80941Smrg        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing
3243b8e80941Smrg        if (copy_to_clipboard)
3244b8e80941Smrg            ImGui::LogToClipboard();
3245b8e80941Smrg        for (int i = 0; i < Items.Size; i++)
3246b8e80941Smrg        {
3247b8e80941Smrg            const char* item = Items[i];
3248b8e80941Smrg            if (!Filter.PassFilter(item))
3249b8e80941Smrg                continue;
3250b8e80941Smrg
3251b8e80941Smrg            // Normally you would store more information in your item (e.g. make Items[] an array of structure, store color/type etc.)
3252b8e80941Smrg            bool pop_color = false;
3253b8e80941Smrg            if (strstr(item, "[error]"))            { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.4f, 0.4f, 1.0f)); pop_color = true; }
3254b8e80941Smrg            else if (strncmp(item, "# ", 2) == 0)   { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.8f, 0.6f, 1.0f)); pop_color = true; }
3255b8e80941Smrg            ImGui::TextUnformatted(item);
3256b8e80941Smrg            if (pop_color)
3257b8e80941Smrg                ImGui::PopStyleColor();
3258b8e80941Smrg        }
3259b8e80941Smrg        if (copy_to_clipboard)
3260b8e80941Smrg            ImGui::LogFinish();
3261b8e80941Smrg        if (ScrollToBottom)
3262b8e80941Smrg            ImGui::SetScrollHereY(1.0f);
3263b8e80941Smrg        ScrollToBottom = false;
3264b8e80941Smrg        ImGui::PopStyleVar();
3265b8e80941Smrg        ImGui::EndChild();
3266b8e80941Smrg        ImGui::Separator();
3267b8e80941Smrg
3268b8e80941Smrg        // Command-line
3269b8e80941Smrg        bool reclaim_focus = false;
3270b8e80941Smrg        if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this))
3271b8e80941Smrg        {
3272b8e80941Smrg            char* s = InputBuf;
3273b8e80941Smrg            Strtrim(s);
3274b8e80941Smrg            if (s[0])
3275b8e80941Smrg                ExecCommand(s);
3276b8e80941Smrg            strcpy(s, "");
3277b8e80941Smrg            reclaim_focus = true;
3278b8e80941Smrg        }
3279b8e80941Smrg
3280b8e80941Smrg        // Auto-focus on window apparition
3281b8e80941Smrg        ImGui::SetItemDefaultFocus();
3282b8e80941Smrg        if (reclaim_focus)
3283b8e80941Smrg            ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
3284b8e80941Smrg
3285b8e80941Smrg        ImGui::End();
3286b8e80941Smrg    }
3287b8e80941Smrg
3288b8e80941Smrg    void    ExecCommand(const char* command_line)
3289b8e80941Smrg    {
3290b8e80941Smrg        AddLog("# %s\n", command_line);
3291b8e80941Smrg
3292b8e80941Smrg        // Insert into history. First find match and delete it so it can be pushed to the back. This isn't trying to be smart or optimal.
3293b8e80941Smrg        HistoryPos = -1;
3294b8e80941Smrg        for (int i = History.Size-1; i >= 0; i--)
3295b8e80941Smrg            if (Stricmp(History[i], command_line) == 0)
3296b8e80941Smrg            {
3297b8e80941Smrg                free(History[i]);
3298b8e80941Smrg                History.erase(History.begin() + i);
3299b8e80941Smrg                break;
3300b8e80941Smrg            }
3301b8e80941Smrg        History.push_back(Strdup(command_line));
3302b8e80941Smrg
3303b8e80941Smrg        // Process command
3304b8e80941Smrg        if (Stricmp(command_line, "CLEAR") == 0)
3305b8e80941Smrg        {
3306b8e80941Smrg            ClearLog();
3307b8e80941Smrg        }
3308b8e80941Smrg        else if (Stricmp(command_line, "HELP") == 0)
3309b8e80941Smrg        {
3310b8e80941Smrg            AddLog("Commands:");
3311b8e80941Smrg            for (int i = 0; i < Commands.Size; i++)
3312b8e80941Smrg                AddLog("- %s", Commands[i]);
3313b8e80941Smrg        }
3314b8e80941Smrg        else if (Stricmp(command_line, "HISTORY") == 0)
3315b8e80941Smrg        {
3316b8e80941Smrg            int first = History.Size - 10;
3317b8e80941Smrg            for (int i = first > 0 ? first : 0; i < History.Size; i++)
3318b8e80941Smrg                AddLog("%3d: %s\n", i, History[i]);
3319b8e80941Smrg        }
3320b8e80941Smrg        else
3321b8e80941Smrg        {
3322b8e80941Smrg            AddLog("Unknown command: '%s'\n", command_line);
3323b8e80941Smrg        }
3324b8e80941Smrg
3325b8e80941Smrg        // On commad input, we scroll to bottom even if AutoScroll==false
3326b8e80941Smrg        ScrollToBottom = true;
3327b8e80941Smrg    }
3328b8e80941Smrg
3329b8e80941Smrg    static int TextEditCallbackStub(ImGuiInputTextCallbackData* data) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
3330b8e80941Smrg    {
3331b8e80941Smrg        ExampleAppConsole* console = (ExampleAppConsole*)data->UserData;
3332b8e80941Smrg        return console->TextEditCallback(data);
3333b8e80941Smrg    }
3334b8e80941Smrg
3335b8e80941Smrg    int     TextEditCallback(ImGuiInputTextCallbackData* data)
3336b8e80941Smrg    {
3337b8e80941Smrg        //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
3338b8e80941Smrg        switch (data->EventFlag)
3339b8e80941Smrg        {
3340b8e80941Smrg        case ImGuiInputTextFlags_CallbackCompletion:
3341b8e80941Smrg            {
3342b8e80941Smrg                // Example of TEXT COMPLETION
3343b8e80941Smrg
3344b8e80941Smrg                // Locate beginning of current word
3345b8e80941Smrg                const char* word_end = data->Buf + data->CursorPos;
3346b8e80941Smrg                const char* word_start = word_end;
3347b8e80941Smrg                while (word_start > data->Buf)
3348b8e80941Smrg                {
3349b8e80941Smrg                    const char c = word_start[-1];
3350b8e80941Smrg                    if (c == ' ' || c == '\t' || c == ',' || c == ';')
3351b8e80941Smrg                        break;
3352b8e80941Smrg                    word_start--;
3353b8e80941Smrg                }
3354b8e80941Smrg
3355b8e80941Smrg                // Build a list of candidates
3356b8e80941Smrg                ImVector<const char*> candidates;
3357b8e80941Smrg                for (int i = 0; i < Commands.Size; i++)
3358b8e80941Smrg                    if (Strnicmp(Commands[i], word_start, (int)(word_end-word_start)) == 0)
3359b8e80941Smrg                        candidates.push_back(Commands[i]);
3360b8e80941Smrg
3361b8e80941Smrg                if (candidates.Size == 0)
3362b8e80941Smrg                {
3363b8e80941Smrg                    // No match
3364b8e80941Smrg                    AddLog("No match for \"%.*s\"!\n", (int)(word_end-word_start), word_start);
3365b8e80941Smrg                }
3366b8e80941Smrg                else if (candidates.Size == 1)
3367b8e80941Smrg                {
3368b8e80941Smrg                    // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
3369b8e80941Smrg                    data->DeleteChars((int)(word_start-data->Buf), (int)(word_end-word_start));
3370b8e80941Smrg                    data->InsertChars(data->CursorPos, candidates[0]);
3371b8e80941Smrg                    data->InsertChars(data->CursorPos, " ");
3372b8e80941Smrg                }
3373b8e80941Smrg                else
3374b8e80941Smrg                {
3375b8e80941Smrg                    // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
3376b8e80941Smrg                    int match_len = (int)(word_end - word_start);
3377b8e80941Smrg                    for (;;)
3378b8e80941Smrg                    {
3379b8e80941Smrg                        int c = 0;
3380b8e80941Smrg                        bool all_candidates_matches = true;
3381b8e80941Smrg                        for (int i = 0; i < candidates.Size && all_candidates_matches; i++)
3382b8e80941Smrg                            if (i == 0)
3383b8e80941Smrg                                c = toupper(candidates[i][match_len]);
3384b8e80941Smrg                            else if (c == 0 || c != toupper(candidates[i][match_len]))
3385b8e80941Smrg                                all_candidates_matches = false;
3386b8e80941Smrg                        if (!all_candidates_matches)
3387b8e80941Smrg                            break;
3388b8e80941Smrg                        match_len++;
3389b8e80941Smrg                    }
3390b8e80941Smrg
3391b8e80941Smrg                    if (match_len > 0)
3392b8e80941Smrg                    {
3393b8e80941Smrg                        data->DeleteChars((int)(word_start - data->Buf), (int)(word_end-word_start));
3394b8e80941Smrg                        data->InsertChars(data->CursorPos, candidates[0], candidates[0] + match_len);
3395b8e80941Smrg                    }
3396b8e80941Smrg
3397b8e80941Smrg                    // List matches
3398b8e80941Smrg                    AddLog("Possible matches:\n");
3399b8e80941Smrg                    for (int i = 0; i < candidates.Size; i++)
3400b8e80941Smrg                        AddLog("- %s\n", candidates[i]);
3401b8e80941Smrg                }
3402b8e80941Smrg
3403b8e80941Smrg                break;
3404b8e80941Smrg            }
3405b8e80941Smrg        case ImGuiInputTextFlags_CallbackHistory:
3406b8e80941Smrg            {
3407b8e80941Smrg                // Example of HISTORY
3408b8e80941Smrg                const int prev_history_pos = HistoryPos;
3409b8e80941Smrg                if (data->EventKey == ImGuiKey_UpArrow)
3410b8e80941Smrg                {
3411b8e80941Smrg                    if (HistoryPos == -1)
3412b8e80941Smrg                        HistoryPos = History.Size - 1;
3413b8e80941Smrg                    else if (HistoryPos > 0)
3414b8e80941Smrg                        HistoryPos--;
3415b8e80941Smrg                }
3416b8e80941Smrg                else if (data->EventKey == ImGuiKey_DownArrow)
3417b8e80941Smrg                {
3418b8e80941Smrg                    if (HistoryPos != -1)
3419b8e80941Smrg                        if (++HistoryPos >= History.Size)
3420b8e80941Smrg                            HistoryPos = -1;
3421b8e80941Smrg                }
3422b8e80941Smrg
3423b8e80941Smrg                // A better implementation would preserve the data on the current input line along with cursor position.
3424b8e80941Smrg                if (prev_history_pos != HistoryPos)
3425b8e80941Smrg                {
3426b8e80941Smrg                    const char* history_str = (HistoryPos >= 0) ? History[HistoryPos] : "";
3427b8e80941Smrg                    data->DeleteChars(0, data->BufTextLen);
3428b8e80941Smrg                    data->InsertChars(0, history_str);
3429b8e80941Smrg                }
3430b8e80941Smrg            }
3431b8e80941Smrg        }
3432b8e80941Smrg        return 0;
3433b8e80941Smrg    }
3434b8e80941Smrg};
3435b8e80941Smrg
3436b8e80941Smrgstatic void ShowExampleAppConsole(bool* p_open)
3437b8e80941Smrg{
3438b8e80941Smrg    static ExampleAppConsole console;
3439b8e80941Smrg    console.Draw("Example: Console", p_open);
3440b8e80941Smrg}
3441b8e80941Smrg
3442b8e80941Smrg//-----------------------------------------------------------------------------
3443b8e80941Smrg// [SECTION] Example App: Debug Log / ShowExampleAppLog()
3444b8e80941Smrg//-----------------------------------------------------------------------------
3445b8e80941Smrg
3446b8e80941Smrg// Usage:
3447b8e80941Smrg//  static ExampleAppLog my_log;
3448b8e80941Smrg//  my_log.AddLog("Hello %d world\n", 123);
3449b8e80941Smrg//  my_log.Draw("title");
3450b8e80941Smrgstruct ExampleAppLog
3451b8e80941Smrg{
3452b8e80941Smrg    ImGuiTextBuffer     Buf;
3453b8e80941Smrg    ImGuiTextFilter     Filter;
3454b8e80941Smrg    ImVector<int>       LineOffsets;        // Index to lines offset. We maintain this with AddLog() calls, allowing us to have a random access on lines
3455b8e80941Smrg    bool                AutoScroll;
3456b8e80941Smrg    bool                ScrollToBottom;
3457b8e80941Smrg
3458b8e80941Smrg    ExampleAppLog()
3459b8e80941Smrg    {
3460b8e80941Smrg        AutoScroll = true;
3461b8e80941Smrg        ScrollToBottom = false;
3462b8e80941Smrg        Clear();
3463b8e80941Smrg    }
3464b8e80941Smrg
3465b8e80941Smrg    void    Clear()
3466b8e80941Smrg    {
3467b8e80941Smrg        Buf.clear();
3468b8e80941Smrg        LineOffsets.clear();
3469b8e80941Smrg        LineOffsets.push_back(0);
3470b8e80941Smrg    }
3471b8e80941Smrg
3472b8e80941Smrg    void    AddLog(const char* fmt, ...) IM_FMTARGS(2)
3473b8e80941Smrg    {
3474b8e80941Smrg        int old_size = Buf.size();
3475b8e80941Smrg        va_list args;
3476b8e80941Smrg        va_start(args, fmt);
3477b8e80941Smrg        Buf.appendfv(fmt, args);
3478b8e80941Smrg        va_end(args);
3479b8e80941Smrg        for (int new_size = Buf.size(); old_size < new_size; old_size++)
3480b8e80941Smrg            if (Buf[old_size] == '\n')
3481b8e80941Smrg                LineOffsets.push_back(old_size + 1);
3482b8e80941Smrg        if (AutoScroll)
3483b8e80941Smrg            ScrollToBottom = true;
3484b8e80941Smrg    }
3485b8e80941Smrg
3486b8e80941Smrg    void    Draw(const char* title, bool* p_open = NULL)
3487b8e80941Smrg    {
3488b8e80941Smrg        if (!ImGui::Begin(title, p_open))
3489b8e80941Smrg        {
3490b8e80941Smrg            ImGui::End();
3491b8e80941Smrg            return;
3492b8e80941Smrg        }
3493b8e80941Smrg
3494b8e80941Smrg        // Options menu
3495b8e80941Smrg        if (ImGui::BeginPopup("Options"))
3496b8e80941Smrg        {
3497b8e80941Smrg            if (ImGui::Checkbox("Auto-scroll", &AutoScroll))
3498b8e80941Smrg                if (AutoScroll)
3499b8e80941Smrg                    ScrollToBottom = true;
3500b8e80941Smrg            ImGui::EndPopup();
3501b8e80941Smrg        }
3502b8e80941Smrg
3503b8e80941Smrg        // Main window
3504b8e80941Smrg        if (ImGui::Button("Options"))
3505b8e80941Smrg            ImGui::OpenPopup("Options");
3506b8e80941Smrg        ImGui::SameLine();
3507b8e80941Smrg        bool clear = ImGui::Button("Clear");
3508b8e80941Smrg        ImGui::SameLine();
3509b8e80941Smrg        bool copy = ImGui::Button("Copy");
3510b8e80941Smrg        ImGui::SameLine();
3511b8e80941Smrg        Filter.Draw("Filter", -100.0f);
3512b8e80941Smrg
3513b8e80941Smrg        ImGui::Separator();
3514b8e80941Smrg        ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar);
3515b8e80941Smrg
3516b8e80941Smrg        if (clear)
3517b8e80941Smrg            Clear();
3518b8e80941Smrg        if (copy)
3519b8e80941Smrg            ImGui::LogToClipboard();
3520b8e80941Smrg
3521b8e80941Smrg        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
3522b8e80941Smrg        const char* buf = Buf.begin();
3523b8e80941Smrg        const char* buf_end = Buf.end();
3524b8e80941Smrg        if (Filter.IsActive())
3525b8e80941Smrg        {
3526b8e80941Smrg            // In this example we don't use the clipper when Filter is enabled.
3527b8e80941Smrg            // This is because we don't have a random access on the result on our filter.
3528b8e80941Smrg            // A real application processing logs with ten of thousands of entries may want to store the result of search/filter.
3529b8e80941Smrg            // especially if the filtering function is not trivial (e.g. reg-exp).
3530b8e80941Smrg            for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
3531b8e80941Smrg            {
3532b8e80941Smrg                const char* line_start = buf + LineOffsets[line_no];
3533b8e80941Smrg                const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
3534b8e80941Smrg                if (Filter.PassFilter(line_start, line_end))
3535b8e80941Smrg                    ImGui::TextUnformatted(line_start, line_end);
3536b8e80941Smrg            }
3537b8e80941Smrg        }
3538b8e80941Smrg        else
3539b8e80941Smrg        {
3540b8e80941Smrg            // The simplest and easy way to display the entire buffer:
3541b8e80941Smrg            //   ImGui::TextUnformatted(buf_begin, buf_end);
3542b8e80941Smrg            // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward to skip non-visible lines.
3543b8e80941Smrg            // Here we instead demonstrate using the clipper to only process lines that are within the visible area.
3544b8e80941Smrg            // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them on your side is recommended.
3545b8e80941Smrg            // Using ImGuiListClipper requires A) random access into your data, and B) items all being the  same height,
3546b8e80941Smrg            // both of which we can handle since we an array pointing to the beginning of each line of text.
3547b8e80941Smrg            // When using the filter (in the block of code above) we don't have random access into the data to display anymore, which is why we don't use the clipper.
3548b8e80941Smrg            // Storing or skimming through the search result would make it possible (and would be recommended if you want to search through tens of thousands of entries)
3549b8e80941Smrg            ImGuiListClipper clipper;
3550b8e80941Smrg            clipper.Begin(LineOffsets.Size);
3551b8e80941Smrg            while (clipper.Step())
3552b8e80941Smrg            {
3553b8e80941Smrg                for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
3554b8e80941Smrg                {
3555b8e80941Smrg                    const char* line_start = buf + LineOffsets[line_no];
3556b8e80941Smrg                    const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
3557b8e80941Smrg                    ImGui::TextUnformatted(line_start, line_end);
3558b8e80941Smrg                }
3559b8e80941Smrg            }
3560b8e80941Smrg            clipper.End();
3561b8e80941Smrg        }
3562b8e80941Smrg        ImGui::PopStyleVar();
3563b8e80941Smrg
3564b8e80941Smrg        if (ScrollToBottom)
3565b8e80941Smrg            ImGui::SetScrollHereY(1.0f);
3566b8e80941Smrg        ScrollToBottom = false;
3567b8e80941Smrg        ImGui::EndChild();
3568b8e80941Smrg        ImGui::End();
3569b8e80941Smrg    }
3570b8e80941Smrg};
3571b8e80941Smrg
3572b8e80941Smrg// Demonstrate creating a simple log window with basic filtering.
3573b8e80941Smrgstatic void ShowExampleAppLog(bool* p_open)
3574b8e80941Smrg{
3575b8e80941Smrg    static ExampleAppLog log;
3576b8e80941Smrg
3577b8e80941Smrg    // For the demo: add a debug button _BEFORE_ the normal log window contents
3578b8e80941Smrg    // We take advantage of the fact that multiple calls to Begin()/End() are appending to the same window.
3579b8e80941Smrg    // Most of the contents of the window will be added by the log.Draw() call.
3580b8e80941Smrg    ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
3581b8e80941Smrg    ImGui::Begin("Example: Log", p_open);
3582b8e80941Smrg    if (ImGui::SmallButton("[Debug] Add 5 entries"))
3583b8e80941Smrg    {
3584b8e80941Smrg        static int counter = 0;
3585b8e80941Smrg        for (int n = 0; n < 5; n++)
3586b8e80941Smrg        {
3587b8e80941Smrg            const char* categories[3] = { "info", "warn", "error" };
3588b8e80941Smrg            const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
3589b8e80941Smrg            log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
3590b8e80941Smrg                ImGui::GetFrameCount(), categories[counter % IM_ARRAYSIZE(categories)], ImGui::GetTime(), words[counter % IM_ARRAYSIZE(words)]);
3591b8e80941Smrg            counter++;
3592b8e80941Smrg        }
3593b8e80941Smrg    }
3594b8e80941Smrg    ImGui::End();
3595b8e80941Smrg
3596b8e80941Smrg    log.Draw("Example: Log", p_open);
3597b8e80941Smrg}
3598b8e80941Smrg
3599b8e80941Smrg//-----------------------------------------------------------------------------
3600b8e80941Smrg// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
3601b8e80941Smrg//-----------------------------------------------------------------------------
3602b8e80941Smrg
3603b8e80941Smrg// Demonstrate create a window with multiple child windows.
3604b8e80941Smrgstatic void ShowExampleAppLayout(bool* p_open)
3605b8e80941Smrg{
3606b8e80941Smrg    ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
3607b8e80941Smrg    if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
3608b8e80941Smrg    {
3609b8e80941Smrg        if (ImGui::BeginMenuBar())
3610b8e80941Smrg        {
3611b8e80941Smrg            if (ImGui::BeginMenu("File"))
3612b8e80941Smrg            {
3613b8e80941Smrg                if (ImGui::MenuItem("Close")) *p_open = false;
3614b8e80941Smrg                ImGui::EndMenu();
3615b8e80941Smrg            }
3616b8e80941Smrg            ImGui::EndMenuBar();
3617b8e80941Smrg        }
3618b8e80941Smrg
3619b8e80941Smrg        // left
3620b8e80941Smrg        static int selected = 0;
3621b8e80941Smrg        ImGui::BeginChild("left pane", ImVec2(150, 0), true);
3622b8e80941Smrg        for (int i = 0; i < 100; i++)
3623b8e80941Smrg        {
3624b8e80941Smrg            char label[128];
3625b8e80941Smrg            sprintf(label, "MyObject %d", i);
3626b8e80941Smrg            if (ImGui::Selectable(label, selected == i))
3627b8e80941Smrg                selected = i;
3628b8e80941Smrg        }
3629b8e80941Smrg        ImGui::EndChild();
3630b8e80941Smrg        ImGui::SameLine();
3631b8e80941Smrg
3632b8e80941Smrg        // right
3633b8e80941Smrg        ImGui::BeginGroup();
3634b8e80941Smrg            ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
3635b8e80941Smrg                ImGui::Text("MyObject: %d", selected);
3636b8e80941Smrg                ImGui::Separator();
3637b8e80941Smrg                if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
3638b8e80941Smrg                {
3639b8e80941Smrg                    if (ImGui::BeginTabItem("Description"))
3640b8e80941Smrg                    {
3641b8e80941Smrg                        ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
3642b8e80941Smrg                        ImGui::EndTabItem();
3643b8e80941Smrg                    }
3644b8e80941Smrg                    if (ImGui::BeginTabItem("Details"))
3645b8e80941Smrg                    {
3646b8e80941Smrg                        ImGui::Text("ID: 0123456789");
3647b8e80941Smrg                        ImGui::EndTabItem();
3648b8e80941Smrg                    }
3649b8e80941Smrg                    ImGui::EndTabBar();
3650b8e80941Smrg                }
3651b8e80941Smrg            ImGui::EndChild();
3652b8e80941Smrg            if (ImGui::Button("Revert")) {}
3653b8e80941Smrg            ImGui::SameLine();
3654b8e80941Smrg            if (ImGui::Button("Save")) {}
3655b8e80941Smrg        ImGui::EndGroup();
3656b8e80941Smrg    }
3657b8e80941Smrg    ImGui::End();
3658b8e80941Smrg}
3659b8e80941Smrg
3660b8e80941Smrg//-----------------------------------------------------------------------------
3661b8e80941Smrg// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
3662b8e80941Smrg//-----------------------------------------------------------------------------
3663b8e80941Smrg
3664b8e80941Smrg// Demonstrate create a simple property editor.
3665b8e80941Smrgstatic void ShowExampleAppPropertyEditor(bool* p_open)
3666b8e80941Smrg{
3667b8e80941Smrg    ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver);
3668b8e80941Smrg    if (!ImGui::Begin("Example: Property editor", p_open))
3669b8e80941Smrg    {
3670b8e80941Smrg        ImGui::End();
3671b8e80941Smrg        return;
3672b8e80941Smrg    }
3673b8e80941Smrg
3674b8e80941Smrg    ShowHelpMarker("This example shows how you may implement a property editor using two columns.\nAll objects/fields data are dummies here.\nRemember that in many simple cases, you can use ImGui::SameLine(xxx) to position\nyour cursor horizontally instead of using the Columns() API.");
3675b8e80941Smrg
3676b8e80941Smrg    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2,2));
3677b8e80941Smrg    ImGui::Columns(2);
3678b8e80941Smrg    ImGui::Separator();
3679b8e80941Smrg
3680b8e80941Smrg    struct funcs
3681b8e80941Smrg    {
3682b8e80941Smrg        static void ShowDummyObject(const char* prefix, int uid)
3683b8e80941Smrg        {
3684b8e80941Smrg            ImGui::PushID(uid);                      // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
3685b8e80941Smrg            ImGui::AlignTextToFramePadding();  // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
3686b8e80941Smrg            bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
3687b8e80941Smrg            ImGui::NextColumn();
3688b8e80941Smrg            ImGui::AlignTextToFramePadding();
3689b8e80941Smrg            ImGui::Text("my sailor is rich");
3690b8e80941Smrg            ImGui::NextColumn();
3691b8e80941Smrg            if (node_open)
3692b8e80941Smrg            {
3693b8e80941Smrg                static float dummy_members[8] = { 0.0f,0.0f,1.0f,3.1416f,100.0f,999.0f };
3694b8e80941Smrg                for (int i = 0; i < 8; i++)
3695b8e80941Smrg                {
3696b8e80941Smrg                    ImGui::PushID(i); // Use field index as identifier.
3697b8e80941Smrg                    if (i < 2)
3698b8e80941Smrg                    {
3699b8e80941Smrg                        ShowDummyObject("Child", 424242);
3700b8e80941Smrg                    }
3701b8e80941Smrg                    else
3702b8e80941Smrg                    {
3703b8e80941Smrg                        // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
3704b8e80941Smrg                        ImGui::AlignTextToFramePadding();
3705b8e80941Smrg                        ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet, "Field_%d", i);
3706b8e80941Smrg                        ImGui::NextColumn();
3707b8e80941Smrg                        ImGui::PushItemWidth(-1);
3708b8e80941Smrg                        if (i >= 5)
3709b8e80941Smrg                            ImGui::InputFloat("##value", &dummy_members[i], 1.0f);
3710b8e80941Smrg                        else
3711b8e80941Smrg                            ImGui::DragFloat("##value", &dummy_members[i], 0.01f);
3712b8e80941Smrg                        ImGui::PopItemWidth();
3713b8e80941Smrg                        ImGui::NextColumn();
3714b8e80941Smrg                    }
3715b8e80941Smrg                    ImGui::PopID();
3716b8e80941Smrg                }
3717b8e80941Smrg                ImGui::TreePop();
3718b8e80941Smrg            }
3719b8e80941Smrg            ImGui::PopID();
3720b8e80941Smrg        }
3721b8e80941Smrg    };
3722b8e80941Smrg
3723b8e80941Smrg    // Iterate dummy objects with dummy members (all the same data)
3724b8e80941Smrg    for (int obj_i = 0; obj_i < 3; obj_i++)
3725b8e80941Smrg        funcs::ShowDummyObject("Object", obj_i);
3726b8e80941Smrg
3727b8e80941Smrg    ImGui::Columns(1);
3728b8e80941Smrg    ImGui::Separator();
3729b8e80941Smrg    ImGui::PopStyleVar();
3730b8e80941Smrg    ImGui::End();
3731b8e80941Smrg}
3732b8e80941Smrg
3733b8e80941Smrg//-----------------------------------------------------------------------------
3734b8e80941Smrg// [SECTION] Example App: Long Text / ShowExampleAppLongText()
3735b8e80941Smrg//-----------------------------------------------------------------------------
3736b8e80941Smrg
3737b8e80941Smrg// Demonstrate/test rendering huge amount of text, and the incidence of clipping.
3738b8e80941Smrgstatic void ShowExampleAppLongText(bool* p_open)
3739b8e80941Smrg{
3740b8e80941Smrg    ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver);
3741b8e80941Smrg    if (!ImGui::Begin("Example: Long text display", p_open))
3742b8e80941Smrg    {
3743b8e80941Smrg        ImGui::End();
3744b8e80941Smrg        return;
3745b8e80941Smrg    }
3746b8e80941Smrg
3747b8e80941Smrg    static int test_type = 0;
3748b8e80941Smrg    static ImGuiTextBuffer log;
3749b8e80941Smrg    static int lines = 0;
3750b8e80941Smrg    ImGui::Text("Printing unusually long amount of text.");
3751b8e80941Smrg    ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
3752b8e80941Smrg    ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
3753b8e80941Smrg    if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
3754b8e80941Smrg    ImGui::SameLine();
3755b8e80941Smrg    if (ImGui::Button("Add 1000 lines"))
3756b8e80941Smrg    {
3757b8e80941Smrg        for (int i = 0; i < 1000; i++)
3758b8e80941Smrg            log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines+i);
3759b8e80941Smrg        lines += 1000;
3760b8e80941Smrg    }
3761b8e80941Smrg    ImGui::BeginChild("Log");
3762b8e80941Smrg    switch (test_type)
3763b8e80941Smrg    {
3764b8e80941Smrg    case 0:
3765b8e80941Smrg        // Single call to TextUnformatted() with a big buffer
3766b8e80941Smrg        ImGui::TextUnformatted(log.begin(), log.end());
3767b8e80941Smrg        break;
3768b8e80941Smrg    case 1:
3769b8e80941Smrg        {
3770b8e80941Smrg            // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
3771b8e80941Smrg            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
3772b8e80941Smrg            ImGuiListClipper clipper(lines);
3773b8e80941Smrg            while (clipper.Step())
3774b8e80941Smrg                for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
3775b8e80941Smrg                    ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
3776b8e80941Smrg            ImGui::PopStyleVar();
3777b8e80941Smrg            break;
3778b8e80941Smrg        }
3779b8e80941Smrg    case 2:
3780b8e80941Smrg        // Multiple calls to Text(), not clipped (slow)
3781b8e80941Smrg        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
3782b8e80941Smrg        for (int i = 0; i < lines; i++)
3783b8e80941Smrg            ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
3784b8e80941Smrg        ImGui::PopStyleVar();
3785b8e80941Smrg        break;
3786b8e80941Smrg    }
3787b8e80941Smrg    ImGui::EndChild();
3788b8e80941Smrg    ImGui::End();
3789b8e80941Smrg}
3790b8e80941Smrg
3791b8e80941Smrg//-----------------------------------------------------------------------------
3792b8e80941Smrg// [SECTION] Example App: Auto Resize / ShowExampleAppAutoResize()
3793b8e80941Smrg//-----------------------------------------------------------------------------
3794b8e80941Smrg
3795b8e80941Smrg// Demonstrate creating a window which gets auto-resized according to its content.
3796b8e80941Smrgstatic void ShowExampleAppAutoResize(bool* p_open)
3797b8e80941Smrg{
3798b8e80941Smrg    if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
3799b8e80941Smrg    {
3800b8e80941Smrg        ImGui::End();
3801b8e80941Smrg        return;
3802b8e80941Smrg    }
3803b8e80941Smrg
3804b8e80941Smrg    static int lines = 10;
3805b8e80941Smrg    ImGui::Text("Window will resize every-frame to the size of its content.\nNote that you probably don't want to query the window size to\noutput your content because that would create a feedback loop.");
3806b8e80941Smrg    ImGui::SliderInt("Number of lines", &lines, 1, 20);
3807b8e80941Smrg    for (int i = 0; i < lines; i++)
3808b8e80941Smrg        ImGui::Text("%*sThis is line %d", i * 4, "", i); // Pad with space to extend size horizontally
3809b8e80941Smrg    ImGui::End();
3810b8e80941Smrg}
3811b8e80941Smrg
3812b8e80941Smrg//-----------------------------------------------------------------------------
3813b8e80941Smrg// [SECTION] Example App: Constrained Resize / ShowExampleAppConstrainedResize()
3814b8e80941Smrg//-----------------------------------------------------------------------------
3815b8e80941Smrg
3816b8e80941Smrg// Demonstrate creating a window with custom resize constraints.
3817b8e80941Smrgstatic void ShowExampleAppConstrainedResize(bool* p_open)
3818b8e80941Smrg{
3819b8e80941Smrg    struct CustomConstraints // Helper functions to demonstrate programmatic constraints
3820b8e80941Smrg    {
3821b8e80941Smrg        static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); }
3822b8e80941Smrg        static void Step(ImGuiSizeCallbackData* data)   { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); }
3823b8e80941Smrg    };
3824b8e80941Smrg
3825b8e80941Smrg    static bool auto_resize = false;
3826b8e80941Smrg    static int type = 0;
3827b8e80941Smrg    static int display_lines = 10;
3828b8e80941Smrg    if (type == 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0),    ImVec2(-1, FLT_MAX));      // Vertical only
3829b8e80941Smrg    if (type == 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1),    ImVec2(FLT_MAX, -1));      // Horizontal only
3830b8e80941Smrg    if (type == 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX, FLT_MAX)); // Width > 100, Height > 100
3831b8e80941Smrg    if (type == 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1),  ImVec2(500, -1));          // Width 400-500
3832b8e80941Smrg    if (type == 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400),  ImVec2(-1, 500));          // Height 400-500
3833b8e80941Smrg    if (type == 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Square);                     // Always Square
3834b8e80941Smrg    if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0),     ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
3835b8e80941Smrg
3836b8e80941Smrg    ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
3837b8e80941Smrg    if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
3838b8e80941Smrg    {
3839b8e80941Smrg        const char* desc[] =
3840b8e80941Smrg        {
3841b8e80941Smrg            "Resize vertical only",
3842b8e80941Smrg            "Resize horizontal only",
3843b8e80941Smrg            "Width > 100, Height > 100",
3844b8e80941Smrg            "Width 400-500",
3845b8e80941Smrg            "Height 400-500",
3846b8e80941Smrg            "Custom: Always Square",
3847b8e80941Smrg            "Custom: Fixed Steps (100)",
3848b8e80941Smrg        };
3849b8e80941Smrg        if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
3850b8e80941Smrg        if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
3851b8e80941Smrg        if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
3852b8e80941Smrg        ImGui::PushItemWidth(200);
3853b8e80941Smrg        ImGui::Combo("Constraint", &type, desc, IM_ARRAYSIZE(desc));
3854b8e80941Smrg        ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
3855b8e80941Smrg        ImGui::PopItemWidth();
3856b8e80941Smrg        ImGui::Checkbox("Auto-resize", &auto_resize);
3857b8e80941Smrg        for (int i = 0; i < display_lines; i++)
3858b8e80941Smrg            ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
3859b8e80941Smrg    }
3860b8e80941Smrg    ImGui::End();
3861b8e80941Smrg}
3862b8e80941Smrg
3863b8e80941Smrg//-----------------------------------------------------------------------------
3864b8e80941Smrg// [SECTION] Example App: Simple Overlay / ShowExampleAppSimpleOverlay()
3865b8e80941Smrg//-----------------------------------------------------------------------------
3866b8e80941Smrg
3867b8e80941Smrg// Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
3868b8e80941Smrgstatic void ShowExampleAppSimpleOverlay(bool* p_open)
3869b8e80941Smrg{
3870b8e80941Smrg    const float DISTANCE = 10.0f;
3871b8e80941Smrg    static int corner = 0;
3872b8e80941Smrg    ImGuiIO& io = ImGui::GetIO();
3873b8e80941Smrg    if (corner != -1)
3874b8e80941Smrg    {
3875b8e80941Smrg        ImVec2 window_pos = ImVec2((corner & 1) ? io.DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? io.DisplaySize.y - DISTANCE : DISTANCE);
3876b8e80941Smrg        ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f);
3877b8e80941Smrg        ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
3878b8e80941Smrg    }
3879b8e80941Smrg    ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background
3880b8e80941Smrg    if (ImGui::Begin("Example: Simple overlay", p_open, (corner != -1 ? ImGuiWindowFlags_NoMove : 0) | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav))
3881b8e80941Smrg    {
3882b8e80941Smrg        ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
3883b8e80941Smrg        ImGui::Separator();
3884b8e80941Smrg        if (ImGui::IsMousePosValid())
3885b8e80941Smrg            ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
3886b8e80941Smrg        else
3887b8e80941Smrg            ImGui::Text("Mouse Position: <invalid>");
3888b8e80941Smrg        if (ImGui::BeginPopupContextWindow())
3889b8e80941Smrg        {
3890b8e80941Smrg            if (ImGui::MenuItem("Custom",       NULL, corner == -1)) corner = -1;
3891b8e80941Smrg            if (ImGui::MenuItem("Top-left",     NULL, corner == 0)) corner = 0;
3892b8e80941Smrg            if (ImGui::MenuItem("Top-right",    NULL, corner == 1)) corner = 1;
3893b8e80941Smrg            if (ImGui::MenuItem("Bottom-left",  NULL, corner == 2)) corner = 2;
3894b8e80941Smrg            if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
3895b8e80941Smrg            if (p_open && ImGui::MenuItem("Close")) *p_open = false;
3896b8e80941Smrg            ImGui::EndPopup();
3897b8e80941Smrg        }
3898b8e80941Smrg    }
3899b8e80941Smrg    ImGui::End();
3900b8e80941Smrg}
3901b8e80941Smrg
3902b8e80941Smrg//-----------------------------------------------------------------------------
3903b8e80941Smrg// [SECTION] Example App: Manipulating Window Titles / ShowExampleAppWindowTitles()
3904b8e80941Smrg//-----------------------------------------------------------------------------
3905b8e80941Smrg
3906b8e80941Smrg// Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
3907b8e80941Smrg// This apply to all regular items as well. Read FAQ section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." for details.
3908b8e80941Smrgstatic void ShowExampleAppWindowTitles(bool*)
3909b8e80941Smrg{
3910b8e80941Smrg    // By default, Windows are uniquely identified by their title.
3911b8e80941Smrg    // You can use the "##" and "###" markers to manipulate the display/ID.
3912b8e80941Smrg
3913b8e80941Smrg    // Using "##" to display same title but have unique identifier.
3914b8e80941Smrg    ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
3915b8e80941Smrg    ImGui::Begin("Same title as another window##1");
3916b8e80941Smrg    ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
3917b8e80941Smrg    ImGui::End();
3918b8e80941Smrg
3919b8e80941Smrg    ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
3920b8e80941Smrg    ImGui::Begin("Same title as another window##2");
3921b8e80941Smrg    ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
3922b8e80941Smrg    ImGui::End();
3923b8e80941Smrg
3924b8e80941Smrg    // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
3925b8e80941Smrg    char buf[128];
3926b8e80941Smrg    sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
3927b8e80941Smrg    ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
3928b8e80941Smrg    ImGui::Begin(buf);
3929b8e80941Smrg    ImGui::Text("This window has a changing title.");
3930b8e80941Smrg    ImGui::End();
3931b8e80941Smrg}
3932b8e80941Smrg
3933b8e80941Smrg//-----------------------------------------------------------------------------
3934b8e80941Smrg// [SECTION] Example App: Custom Rendering using ImDrawList API / ShowExampleAppCustomRendering()
3935b8e80941Smrg//-----------------------------------------------------------------------------
3936b8e80941Smrg
3937b8e80941Smrg// Demonstrate using the low-level ImDrawList to draw custom shapes.
3938b8e80941Smrgstatic void ShowExampleAppCustomRendering(bool* p_open)
3939b8e80941Smrg{
3940b8e80941Smrg    ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver);
3941b8e80941Smrg    if (!ImGui::Begin("Example: Custom rendering", p_open))
3942b8e80941Smrg    {
3943b8e80941Smrg        ImGui::End();
3944b8e80941Smrg        return;
3945b8e80941Smrg    }
3946b8e80941Smrg
3947b8e80941Smrg    // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
3948b8e80941Smrg    // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
3949b8e80941Smrg    // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
3950b8e80941Smrg    // In this example we are not using the maths operators!
3951b8e80941Smrg    ImDrawList* draw_list = ImGui::GetWindowDrawList();
3952b8e80941Smrg
3953b8e80941Smrg    // Primitives
3954b8e80941Smrg    ImGui::Text("Primitives");
3955b8e80941Smrg    static float sz = 36.0f;
3956b8e80941Smrg    static float thickness = 4.0f;
3957b8e80941Smrg    static ImVec4 col = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
3958b8e80941Smrg    ImGui::DragFloat("Size", &sz, 0.2f, 2.0f, 72.0f, "%.0f");
3959b8e80941Smrg    ImGui::DragFloat("Thickness", &thickness, 0.05f, 1.0f, 8.0f, "%.02f");
3960b8e80941Smrg    ImGui::ColorEdit4("Color", &col.x);
3961b8e80941Smrg    {
3962b8e80941Smrg        const ImVec2 p = ImGui::GetCursorScreenPos();
3963b8e80941Smrg        const ImU32 col32 = ImColor(col);
3964b8e80941Smrg        float x = p.x + 4.0f, y = p.y + 4.0f, spacing = 8.0f;
3965b8e80941Smrg        for (int n = 0; n < 2; n++)
3966b8e80941Smrg        {
3967b8e80941Smrg            // First line uses a thickness of 1.0, second line uses the configurable thickness
3968b8e80941Smrg            float th = (n == 0) ? 1.0f : thickness;
3969b8e80941Smrg            draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6, th); x += sz+spacing;     // Hexagon
3970b8e80941Smrg            draw_list->AddCircle(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 20, th); x += sz+spacing;    // Circle
3971b8e80941Smrg            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 0.0f,  ImDrawCornerFlags_All, th); x += sz+spacing;
3972b8e80941Smrg            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_All, th); x += sz+spacing;
3973b8e80941Smrg            draw_list->AddRect(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight, th); x += sz+spacing;
3974b8e80941Smrg            draw_list->AddTriangle(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32, th); x += sz+spacing;
3975b8e80941Smrg            draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y   ), col32, th); x += sz+spacing;               // Horizontal line (note: drawing a filled rectangle will be faster!)
3976b8e80941Smrg            draw_list->AddLine(ImVec2(x, y), ImVec2(x,    y+sz), col32, th); x += spacing;                  // Vertical line (note: drawing a filled rectangle will be faster!)
3977b8e80941Smrg            draw_list->AddLine(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, th); x += sz+spacing;               // Diagonal line
3978b8e80941Smrg            draw_list->AddBezierCurve(ImVec2(x, y), ImVec2(x+sz*1.3f,y+sz*0.3f), ImVec2(x+sz-sz*1.3f,y+sz-sz*0.3f), ImVec2(x+sz, y+sz), col32, th);
3979b8e80941Smrg            x = p.x + 4;
3980b8e80941Smrg            y += sz+spacing;
3981b8e80941Smrg        }
3982b8e80941Smrg        draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 6); x += sz+spacing;       // Hexagon
3983b8e80941Smrg        draw_list->AddCircleFilled(ImVec2(x+sz*0.5f, y+sz*0.5f), sz*0.5f, col32, 32); x += sz+spacing;      // Circle
3984b8e80941Smrg        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32); x += sz+spacing;
3985b8e80941Smrg        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing;
3986b8e80941Smrg        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing;
3987b8e80941Smrg        draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing;
3988b8e80941Smrg        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+thickness), col32); x += sz+spacing;          // Horizontal line (faster than AddLine, but only handle integer thickness)
3989b8e80941Smrg        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+thickness, y+sz), col32); x += spacing+spacing;     // Vertical line (faster than AddLine, but only handle integer thickness)
3990b8e80941Smrg        draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+1, y+1), col32);          x += sz;                  // Pixel (faster than AddLine)
3991b8e80941Smrg        draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), IM_COL32(0,0,0,255), IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255));
3992b8e80941Smrg        ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3));
3993b8e80941Smrg    }
3994b8e80941Smrg    ImGui::Separator();
3995b8e80941Smrg    {
3996b8e80941Smrg        static ImVector<ImVec2> points;
3997b8e80941Smrg        static bool adding_line = false;
3998b8e80941Smrg        ImGui::Text("Canvas example");
3999b8e80941Smrg        if (ImGui::Button("Clear")) points.clear();
4000b8e80941Smrg        if (points.Size >= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points.pop_back(); points.pop_back(); } }
4001b8e80941Smrg        ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
4002b8e80941Smrg
4003b8e80941Smrg        // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
4004b8e80941Smrg        // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
4005b8e80941Smrg        // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
4006b8e80941Smrg        ImVec2 canvas_pos = ImGui::GetCursorScreenPos();            // ImDrawList API uses screen coordinates!
4007b8e80941Smrg        ImVec2 canvas_size = ImGui::GetContentRegionAvail();        // Resize canvas to what's available
4008b8e80941Smrg        if (canvas_size.x < 50.0f) canvas_size.x = 50.0f;
4009b8e80941Smrg        if (canvas_size.y < 50.0f) canvas_size.y = 50.0f;
4010b8e80941Smrg        draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50, 50, 50, 255), IM_COL32(50, 50, 60, 255), IM_COL32(60, 60, 70, 255), IM_COL32(50, 50, 60, 255));
4011b8e80941Smrg        draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255, 255, 255, 255));
4012b8e80941Smrg
4013b8e80941Smrg        bool adding_preview = false;
4014b8e80941Smrg        ImGui::InvisibleButton("canvas", canvas_size);
4015b8e80941Smrg        ImVec2 mouse_pos_in_canvas = ImVec2(ImGui::GetIO().MousePos.x - canvas_pos.x, ImGui::GetIO().MousePos.y - canvas_pos.y);
4016b8e80941Smrg        if (adding_line)
4017b8e80941Smrg        {
4018b8e80941Smrg            adding_preview = true;
4019b8e80941Smrg            points.push_back(mouse_pos_in_canvas);
4020b8e80941Smrg            if (!ImGui::IsMouseDown(0))
4021b8e80941Smrg                adding_line = adding_preview = false;
4022b8e80941Smrg        }
4023b8e80941Smrg        if (ImGui::IsItemHovered())
4024b8e80941Smrg        {
4025b8e80941Smrg            if (!adding_line && ImGui::IsMouseClicked(0))
4026b8e80941Smrg            {
4027b8e80941Smrg                points.push_back(mouse_pos_in_canvas);
4028b8e80941Smrg                adding_line = true;
4029b8e80941Smrg            }
4030b8e80941Smrg            if (ImGui::IsMouseClicked(1) && !points.empty())
4031b8e80941Smrg            {
4032b8e80941Smrg                adding_line = adding_preview = false;
4033b8e80941Smrg                points.pop_back();
4034b8e80941Smrg                points.pop_back();
4035b8e80941Smrg            }
4036b8e80941Smrg        }
4037b8e80941Smrg        draw_list->PushClipRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), true);      // clip lines within the canvas (if we resize it, etc.)
4038b8e80941Smrg        for (int i = 0; i < points.Size - 1; i += 2)
4039b8e80941Smrg            draw_list->AddLine(ImVec2(canvas_pos.x + points[i].x, canvas_pos.y + points[i].y), ImVec2(canvas_pos.x + points[i + 1].x, canvas_pos.y + points[i + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
4040b8e80941Smrg        draw_list->PopClipRect();
4041b8e80941Smrg        if (adding_preview)
4042b8e80941Smrg            points.pop_back();
4043b8e80941Smrg    }
4044b8e80941Smrg    ImGui::End();
4045b8e80941Smrg}
4046b8e80941Smrg
4047b8e80941Smrg//-----------------------------------------------------------------------------
4048b8e80941Smrg// [SECTION] Example App: Documents Handling / ShowExampleAppDocuments()
4049b8e80941Smrg//-----------------------------------------------------------------------------
4050b8e80941Smrg
4051b8e80941Smrg// Simplified structure to mimic a Document model
4052b8e80941Smrgstruct MyDocument
4053b8e80941Smrg{
4054b8e80941Smrg    const char* Name;           // Document title
4055b8e80941Smrg    bool        Open;           // Set when the document is open (in this demo, we keep an array of all available documents to simplify the demo)
4056b8e80941Smrg    bool        OpenPrev;       // Copy of Open from last update.
4057b8e80941Smrg    bool        Dirty;          // Set when the document has been modified
4058b8e80941Smrg    bool        WantClose;      // Set when the document
4059b8e80941Smrg    ImVec4      Color;          // An arbitrary variable associated to the document
4060b8e80941Smrg
4061b8e80941Smrg    MyDocument(const char* name, bool open = true, const ImVec4& color = ImVec4(1.0f,1.0f,1.0f,1.0f))
4062b8e80941Smrg    {
4063b8e80941Smrg        Name = name;
4064b8e80941Smrg        Open = OpenPrev = open;
4065b8e80941Smrg        Dirty = false;
4066b8e80941Smrg        WantClose = false;
4067b8e80941Smrg        Color = color;
4068b8e80941Smrg    }
4069b8e80941Smrg    void DoOpen()       { Open = true; }
4070b8e80941Smrg    void DoQueueClose() { WantClose = true; }
4071b8e80941Smrg    void DoForceClose() { Open = false; Dirty = false; }
4072b8e80941Smrg    void DoSave()       { Dirty = false; }
4073b8e80941Smrg
4074b8e80941Smrg    // Display dummy contents for the Document
4075b8e80941Smrg    static void DisplayContents(MyDocument* doc)
4076b8e80941Smrg    {
4077b8e80941Smrg        ImGui::PushID(doc);
4078b8e80941Smrg        ImGui::Text("Document \"%s\"", doc->Name);
4079b8e80941Smrg        ImGui::PushStyleColor(ImGuiCol_Text, doc->Color);
4080b8e80941Smrg        ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.");
4081b8e80941Smrg        ImGui::PopStyleColor();
4082b8e80941Smrg        if (ImGui::Button("Modify", ImVec2(100, 0)))
4083b8e80941Smrg            doc->Dirty = true;
4084b8e80941Smrg        ImGui::SameLine();
4085b8e80941Smrg        if (ImGui::Button("Save", ImVec2(100, 0)))
4086b8e80941Smrg            doc->DoSave();
4087b8e80941Smrg        ImGui::ColorEdit3("color", &doc->Color.x);  // Useful to test drag and drop and hold-dragged-to-open-tab behavior.
4088b8e80941Smrg        ImGui::PopID();
4089b8e80941Smrg    }
4090b8e80941Smrg
4091b8e80941Smrg    // Display context menu for the Document
4092b8e80941Smrg    static void DisplayContextMenu(MyDocument* doc)
4093b8e80941Smrg    {
4094b8e80941Smrg        if (!ImGui::BeginPopupContextItem())
4095b8e80941Smrg            return;
4096b8e80941Smrg
4097b8e80941Smrg        char buf[256];
4098b8e80941Smrg        sprintf(buf, "Save %s", doc->Name);
4099b8e80941Smrg        if (ImGui::MenuItem(buf, "CTRL+S", false, doc->Open))
4100b8e80941Smrg            doc->DoSave();
4101b8e80941Smrg        if (ImGui::MenuItem("Close", "CTRL+W", false, doc->Open))
4102b8e80941Smrg            doc->DoQueueClose();
4103b8e80941Smrg        ImGui::EndPopup();
4104b8e80941Smrg    }
4105b8e80941Smrg};
4106b8e80941Smrg
4107b8e80941Smrgstruct ExampleAppDocuments
4108b8e80941Smrg{
4109b8e80941Smrg    ImVector<MyDocument> Documents;
4110b8e80941Smrg
4111b8e80941Smrg    ExampleAppDocuments()
4112b8e80941Smrg    {
4113b8e80941Smrg        Documents.push_back(MyDocument("Lettuce",             true,  ImVec4(0.4f, 0.8f, 0.4f, 1.0f)));
4114b8e80941Smrg        Documents.push_back(MyDocument("Eggplant",            true,  ImVec4(0.8f, 0.5f, 1.0f, 1.0f)));
4115b8e80941Smrg        Documents.push_back(MyDocument("Carrot",              true,  ImVec4(1.0f, 0.8f, 0.5f, 1.0f)));
4116b8e80941Smrg        Documents.push_back(MyDocument("Tomato",              false, ImVec4(1.0f, 0.3f, 0.4f, 1.0f)));
4117b8e80941Smrg        Documents.push_back(MyDocument("A Rather Long Title", false));
4118b8e80941Smrg        Documents.push_back(MyDocument("Some Document",       false));
4119b8e80941Smrg    }
4120b8e80941Smrg};
4121b8e80941Smrg
4122b8e80941Smrg// [Optional] Notify the system of Tabs/Windows closure that happened outside the regular tab interface.
4123b8e80941Smrg// If a tab has been closed programmatically (aka closed from another source such as the Checkbox() in the demo, as opposed
4124b8e80941Smrg// to clicking on the regular tab closing button) and stops being submitted, it will take a frame for the tab bar to notice its absence.
4125b8e80941Smrg// During this frame there will be a gap in the tab bar, and if the tab that has disappeared was the selected one, the tab bar
4126b8e80941Smrg// will report no selected tab during the frame. This will effectively give the impression of a flicker for one frame.
4127b8e80941Smrg// We call SetTabItemClosed() to manually notify the Tab Bar or Docking system of removed tabs to avoid this glitch.
4128b8e80941Smrg// Note that this completely optional, and only affect tab bars with the ImGuiTabBarFlags_Reorderable flag.
4129b8e80941Smrgstatic void NotifyOfDocumentsClosedElsewhere(ExampleAppDocuments& app)
4130b8e80941Smrg{
4131b8e80941Smrg    for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4132b8e80941Smrg    {
4133b8e80941Smrg        MyDocument* doc = &app.Documents[doc_n];
4134b8e80941Smrg        if (!doc->Open && doc->OpenPrev)
4135b8e80941Smrg            ImGui::SetTabItemClosed(doc->Name);
4136b8e80941Smrg        doc->OpenPrev = doc->Open;
4137b8e80941Smrg    }
4138b8e80941Smrg}
4139b8e80941Smrg
4140b8e80941Smrgvoid ShowExampleAppDocuments(bool* p_open)
4141b8e80941Smrg{
4142b8e80941Smrg    static ExampleAppDocuments app;
4143b8e80941Smrg
4144b8e80941Smrg    if (!ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar))
4145b8e80941Smrg    {
4146b8e80941Smrg        ImGui::End();
4147b8e80941Smrg        return;
4148b8e80941Smrg    }
4149b8e80941Smrg
4150b8e80941Smrg    // Options
4151b8e80941Smrg    static bool opt_reorderable = true;
4152b8e80941Smrg    static ImGuiTabBarFlags opt_fitting_flags = ImGuiTabBarFlags_FittingPolicyDefault_;
4153b8e80941Smrg
4154b8e80941Smrg    // Menu
4155b8e80941Smrg    if (ImGui::BeginMenuBar())
4156b8e80941Smrg    {
4157b8e80941Smrg        if (ImGui::BeginMenu("File"))
4158b8e80941Smrg        {
4159b8e80941Smrg            int open_count = 0;
4160b8e80941Smrg            for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4161b8e80941Smrg                open_count += app.Documents[doc_n].Open ? 1 : 0;
4162b8e80941Smrg
4163b8e80941Smrg            if (ImGui::BeginMenu("Open", open_count < app.Documents.Size))
4164b8e80941Smrg            {
4165b8e80941Smrg                for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4166b8e80941Smrg                {
4167b8e80941Smrg                    MyDocument* doc = &app.Documents[doc_n];
4168b8e80941Smrg                    if (!doc->Open)
4169b8e80941Smrg                        if (ImGui::MenuItem(doc->Name))
4170b8e80941Smrg                            doc->DoOpen();
4171b8e80941Smrg                }
4172b8e80941Smrg                ImGui::EndMenu();
4173b8e80941Smrg            }
4174b8e80941Smrg            if (ImGui::MenuItem("Close All Documents", NULL, false, open_count > 0))
4175b8e80941Smrg                for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4176b8e80941Smrg                    app.Documents[doc_n].DoQueueClose();
4177b8e80941Smrg            if (ImGui::MenuItem("Exit", "Alt+F4")) {}
4178b8e80941Smrg            ImGui::EndMenu();
4179b8e80941Smrg        }
4180b8e80941Smrg        ImGui::EndMenuBar();
4181b8e80941Smrg    }
4182b8e80941Smrg
4183b8e80941Smrg    // [Debug] List documents with one checkbox for each
4184b8e80941Smrg    for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4185b8e80941Smrg    {
4186b8e80941Smrg        MyDocument* doc = &app.Documents[doc_n];
4187b8e80941Smrg        if (doc_n > 0)
4188b8e80941Smrg            ImGui::SameLine();
4189b8e80941Smrg        ImGui::PushID(doc);
4190b8e80941Smrg        if (ImGui::Checkbox(doc->Name, &doc->Open))
4191b8e80941Smrg            if (!doc->Open)
4192b8e80941Smrg                doc->DoForceClose();
4193b8e80941Smrg        ImGui::PopID();
4194b8e80941Smrg    }
4195b8e80941Smrg
4196b8e80941Smrg    ImGui::Separator();
4197b8e80941Smrg
4198b8e80941Smrg    // Submit Tab Bar and Tabs
4199b8e80941Smrg    {
4200b8e80941Smrg        ImGuiTabBarFlags tab_bar_flags = (opt_fitting_flags) | (opt_reorderable ? ImGuiTabBarFlags_Reorderable : 0);
4201b8e80941Smrg        if (ImGui::BeginTabBar("##tabs", tab_bar_flags))
4202b8e80941Smrg        {
4203b8e80941Smrg            if (opt_reorderable)
4204b8e80941Smrg                NotifyOfDocumentsClosedElsewhere(app);
4205b8e80941Smrg
4206b8e80941Smrg            // [DEBUG] Stress tests
4207b8e80941Smrg            //if ((ImGui::GetFrameCount() % 30) == 0) docs[1].Open ^= 1;            // [DEBUG] Automatically show/hide a tab. Test various interactions e.g. dragging with this on.
4208b8e80941Smrg            //if (ImGui::GetIO().KeyCtrl) ImGui::SetTabItemSelected(docs[1].Name);  // [DEBUG] Test SetTabItemSelected(), probably not very useful as-is anyway..
4209b8e80941Smrg
4210b8e80941Smrg            // Submit Tabs
4211b8e80941Smrg            for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4212b8e80941Smrg            {
4213b8e80941Smrg                MyDocument* doc = &app.Documents[doc_n];
4214b8e80941Smrg                if (!doc->Open)
4215b8e80941Smrg                    continue;
4216b8e80941Smrg
4217b8e80941Smrg                ImGuiTabItemFlags tab_flags = (doc->Dirty ? ImGuiTabItemFlags_UnsavedDocument : 0);
4218b8e80941Smrg                bool visible = ImGui::BeginTabItem(doc->Name, &doc->Open, tab_flags);
4219b8e80941Smrg
4220b8e80941Smrg                // Cancel attempt to close when unsaved add to save queue so we can display a popup.
4221b8e80941Smrg                if (!doc->Open && doc->Dirty)
4222b8e80941Smrg                {
4223b8e80941Smrg                    doc->Open = true;
4224b8e80941Smrg                    doc->DoQueueClose();
4225b8e80941Smrg                }
4226b8e80941Smrg
4227b8e80941Smrg                MyDocument::DisplayContextMenu(doc);
4228b8e80941Smrg                if (visible)
4229b8e80941Smrg                {
4230b8e80941Smrg                    MyDocument::DisplayContents(doc);
4231b8e80941Smrg                    ImGui::EndTabItem();
4232b8e80941Smrg                }
4233b8e80941Smrg            }
4234b8e80941Smrg
4235b8e80941Smrg            ImGui::EndTabBar();
4236b8e80941Smrg        }
4237b8e80941Smrg    }
4238b8e80941Smrg
4239b8e80941Smrg    // Update closing queue
4240b8e80941Smrg    static ImVector<MyDocument*> close_queue;
4241b8e80941Smrg    if (close_queue.empty())
4242b8e80941Smrg    {
4243b8e80941Smrg        // Close queue is locked once we started a popup
4244b8e80941Smrg        for (int doc_n = 0; doc_n < app.Documents.Size; doc_n++)
4245b8e80941Smrg        {
4246b8e80941Smrg            MyDocument* doc = &app.Documents[doc_n];
4247b8e80941Smrg            if (doc->WantClose)
4248b8e80941Smrg            {
4249b8e80941Smrg                doc->WantClose = false;
4250b8e80941Smrg                close_queue.push_back(doc);
4251b8e80941Smrg            }
4252b8e80941Smrg        }
4253b8e80941Smrg    }
4254b8e80941Smrg
4255b8e80941Smrg    // Display closing confirmation UI
4256b8e80941Smrg    if (!close_queue.empty())
4257b8e80941Smrg    {
4258b8e80941Smrg        int close_queue_unsaved_documents = 0;
4259b8e80941Smrg        for (int n = 0; n < close_queue.Size; n++)
4260b8e80941Smrg            if (close_queue[n]->Dirty)
4261b8e80941Smrg                close_queue_unsaved_documents++;
4262b8e80941Smrg
4263b8e80941Smrg        if (close_queue_unsaved_documents == 0)
4264b8e80941Smrg        {
4265b8e80941Smrg            // Close documents when all are unsaved
4266b8e80941Smrg            for (int n = 0; n < close_queue.Size; n++)
4267b8e80941Smrg                close_queue[n]->DoForceClose();
4268b8e80941Smrg            close_queue.clear();
4269b8e80941Smrg        }
4270b8e80941Smrg        else
4271b8e80941Smrg        {
4272b8e80941Smrg            if (!ImGui::IsPopupOpen("Save?"))
4273b8e80941Smrg                ImGui::OpenPopup("Save?");
4274b8e80941Smrg            if (ImGui::BeginPopupModal("Save?"))
4275b8e80941Smrg            {
4276b8e80941Smrg                ImGui::Text("Save change to the following items?");
4277b8e80941Smrg                ImGui::PushItemWidth(-1.0f);
4278b8e80941Smrg                ImGui::ListBoxHeader("##", close_queue_unsaved_documents, 6);
4279b8e80941Smrg                for (int n = 0; n < close_queue.Size; n++)
4280b8e80941Smrg                    if (close_queue[n]->Dirty)
4281b8e80941Smrg                        ImGui::Text("%s", close_queue[n]->Name);
4282b8e80941Smrg                ImGui::ListBoxFooter();
4283b8e80941Smrg
4284b8e80941Smrg                if (ImGui::Button("Yes", ImVec2(80, 0)))
4285b8e80941Smrg                {
4286b8e80941Smrg                    for (int n = 0; n < close_queue.Size; n++)
4287b8e80941Smrg                    {
4288b8e80941Smrg                        if (close_queue[n]->Dirty)
4289b8e80941Smrg                            close_queue[n]->DoSave();
4290b8e80941Smrg                        close_queue[n]->DoForceClose();
4291b8e80941Smrg                    }
4292b8e80941Smrg                    close_queue.clear();
4293b8e80941Smrg                    ImGui::CloseCurrentPopup();
4294b8e80941Smrg                }
4295b8e80941Smrg                ImGui::SameLine();
4296b8e80941Smrg                if (ImGui::Button("No", ImVec2(80, 0)))
4297b8e80941Smrg                {
4298b8e80941Smrg                    for (int n = 0; n < close_queue.Size; n++)
4299b8e80941Smrg                        close_queue[n]->DoForceClose();
4300b8e80941Smrg                    close_queue.clear();
4301b8e80941Smrg                    ImGui::CloseCurrentPopup();
4302b8e80941Smrg                }
4303b8e80941Smrg                ImGui::SameLine();
4304b8e80941Smrg                if (ImGui::Button("Cancel", ImVec2(80, 0)))
4305b8e80941Smrg                {
4306b8e80941Smrg                    close_queue.clear();
4307b8e80941Smrg                    ImGui::CloseCurrentPopup();
4308b8e80941Smrg                }
4309b8e80941Smrg                ImGui::EndPopup();
4310b8e80941Smrg            }
4311b8e80941Smrg        }
4312b8e80941Smrg    }
4313b8e80941Smrg
4314b8e80941Smrg    ImGui::End();
4315b8e80941Smrg}
4316b8e80941Smrg
4317b8e80941Smrg// End of Demo code
4318b8e80941Smrg#else
4319b8e80941Smrg
4320b8e80941Smrgvoid ImGui::ShowAboutWindow(bool*) {}
4321b8e80941Smrgvoid ImGui::ShowDemoWindow(bool*) {}
4322b8e80941Smrgvoid ImGui::ShowUserGuide() {}
4323b8e80941Smrgvoid ImGui::ShowStyleEditor(ImGuiStyle*) {}
4324b8e80941Smrg
4325b8e80941Smrg#endif
4326