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