1 // dear imgui, v1.63 WIP
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.
13 // -Your beloved friend, imgui_demo.cpp (that you won't delete)
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.
21 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
22 #define _CRT_SECURE_NO_WARNINGS
26 #include <ctype.h> // toupper, isprint
27 #include <limits.h> // INT_MIN, INT_MAX
28 #include <math.h> // sqrtf, powf, cosf, sinf, floorf, ceilf
29 #include <stdio.h> // vsnprintf, sscanf, printf
30 #include <stdlib.h> // NULL, malloc, free, atoi
31 #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
32 #include <stddef.h> // intptr_t
34 #include <stdint.h> // intptr_t
38 #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
39 #define snprintf _snprintf
42 #pragma clang diagnostic ignored "-Wold-style-cast" // warning : use of old-style cast // yes, they are more terse.
43 #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)
44 #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int'
45 #pragma clang diagnostic ignored "-Wformat-security" // warning : warning: format string is not a string literal
46 #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.
47 #if __has_warning("-Wreserved-id-macro")
48 #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier //
50 #elif defined(__GNUC__)
51 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size
52 #pragma GCC diagnostic ignored "-Wformat-security" // warning : format string is not a string literal (potentially insecure)
53 #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function
54 #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value
56 #pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub.
60 // Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n.
62 #define IM_NEWLINE "\r\n"
64 #define IM_NEWLINE "\n"
67 #define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B))
69 //-----------------------------------------------------------------------------
71 //-----------------------------------------------------------------------------
73 #if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Obsolete name since 1.53, TEST->DEMO
74 #define IMGUI_DISABLE_DEMO_WINDOWS
77 #if !defined(IMGUI_DISABLE_DEMO_WINDOWS)
79 // Forward Declarations
80 static void ShowExampleAppMainMenuBar();
81 static void ShowExampleAppConsole(bool* p_open
);
82 static void ShowExampleAppLog(bool* p_open
);
83 static void ShowExampleAppLayout(bool* p_open
);
84 static void ShowExampleAppPropertyEditor(bool* p_open
);
85 static void ShowExampleAppLongText(bool* p_open
);
86 static void ShowExampleAppAutoResize(bool* p_open
);
87 static void ShowExampleAppConstrainedResize(bool* p_open
);
88 static void ShowExampleAppSimpleOverlay(bool* p_open
);
89 static void ShowExampleAppWindowTitles(bool* p_open
);
90 static void ShowExampleAppCustomRendering(bool* p_open
);
91 static void ShowExampleMenuFile();
93 // Helper to display a little (?) mark which shows a tooltip when hovered.
94 static void ShowHelpMarker(const char* desc
)
96 ImGui::TextDisabled("(?)");
97 if (ImGui::IsItemHovered())
99 ImGui::BeginTooltip();
100 ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f
);
101 ImGui::TextUnformatted(desc
);
102 ImGui::PopTextWrapPos();
107 // Helper to display basic user controls.
108 void ImGui::ShowUserGuide()
110 ImGui::BulletText("Double-click on title bar to collapse window.");
111 ImGui::BulletText("Click and drag on lower right corner to resize window\n(double-click to auto fit window to its contents).");
112 ImGui::BulletText("Click and drag on any empty space to move window.");
113 ImGui::BulletText("TAB/SHIFT+TAB to cycle through keyboard editable fields.");
114 ImGui::BulletText("CTRL+Click on a slider or drag box to input value as text.");
115 if (ImGui::GetIO().FontAllowUserScaling
)
116 ImGui::BulletText("CTRL+Mouse Wheel to zoom window contents.");
117 ImGui::BulletText("Mouse Wheel to scroll.");
118 ImGui::BulletText("While editing text:\n");
120 ImGui::BulletText("Hold SHIFT or use mouse to select text.");
121 ImGui::BulletText("CTRL+Left/Right to word jump.");
122 ImGui::BulletText("CTRL+A or double-click to select all.");
123 ImGui::BulletText("CTRL+X,CTRL+C,CTRL+V to use clipboard.");
124 ImGui::BulletText("CTRL+Z,CTRL+Y to undo/redo.");
125 ImGui::BulletText("ESCAPE to revert.");
126 ImGui::BulletText("You can apply arithmetic operators +,*,/ on numerical values.\nUse +- to subtract.");
130 // Demonstrate most Dear ImGui features (this is big function!)
131 // 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.
132 void ImGui::ShowDemoWindow(bool* p_open
)
134 // Examples Apps (accessible from the "Examples" menu)
135 static bool show_app_main_menu_bar
= false;
136 static bool show_app_console
= false;
137 static bool show_app_log
= false;
138 static bool show_app_layout
= false;
139 static bool show_app_property_editor
= false;
140 static bool show_app_long_text
= false;
141 static bool show_app_auto_resize
= false;
142 static bool show_app_constrained_resize
= false;
143 static bool show_app_simple_overlay
= false;
144 static bool show_app_window_titles
= false;
145 static bool show_app_custom_rendering
= false;
147 if (show_app_main_menu_bar
) ShowExampleAppMainMenuBar();
148 if (show_app_console
) ShowExampleAppConsole(&show_app_console
);
149 if (show_app_log
) ShowExampleAppLog(&show_app_log
);
150 if (show_app_layout
) ShowExampleAppLayout(&show_app_layout
);
151 if (show_app_property_editor
) ShowExampleAppPropertyEditor(&show_app_property_editor
);
152 if (show_app_long_text
) ShowExampleAppLongText(&show_app_long_text
);
153 if (show_app_auto_resize
) ShowExampleAppAutoResize(&show_app_auto_resize
);
154 if (show_app_constrained_resize
) ShowExampleAppConstrainedResize(&show_app_constrained_resize
);
155 if (show_app_simple_overlay
) ShowExampleAppSimpleOverlay(&show_app_simple_overlay
);
156 if (show_app_window_titles
) ShowExampleAppWindowTitles(&show_app_window_titles
);
157 if (show_app_custom_rendering
) ShowExampleAppCustomRendering(&show_app_custom_rendering
);
159 // Dear ImGui Apps (accessible from the "Help" menu)
160 static bool show_app_metrics
= false;
161 static bool show_app_style_editor
= false;
162 static bool show_app_about
= false;
164 if (show_app_metrics
) { ImGui::ShowMetricsWindow(&show_app_metrics
); }
165 if (show_app_style_editor
) { ImGui::Begin("Style Editor", &show_app_style_editor
); ImGui::ShowStyleEditor(); ImGui::End(); }
168 ImGui::Begin("About Dear ImGui", &show_app_about
, ImGuiWindowFlags_AlwaysAutoResize
);
169 ImGui::Text("Dear ImGui, %s", ImGui::GetVersion());
171 ImGui::Text("By Omar Cornut and all dear imgui contributors.");
172 ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information.");
176 // Demonstrate the various window flags. Typically you would just use the default!
177 static bool no_titlebar
= false;
178 static bool no_scrollbar
= false;
179 static bool no_menu
= false;
180 static bool no_move
= false;
181 static bool no_resize
= false;
182 static bool no_collapse
= false;
183 static bool no_close
= false;
184 static bool no_nav
= false;
186 ImGuiWindowFlags window_flags
= 0;
187 if (no_titlebar
) window_flags
|= ImGuiWindowFlags_NoTitleBar
;
188 if (no_scrollbar
) window_flags
|= ImGuiWindowFlags_NoScrollbar
;
189 if (!no_menu
) window_flags
|= ImGuiWindowFlags_MenuBar
;
190 if (no_move
) window_flags
|= ImGuiWindowFlags_NoMove
;
191 if (no_resize
) window_flags
|= ImGuiWindowFlags_NoResize
;
192 if (no_collapse
) window_flags
|= ImGuiWindowFlags_NoCollapse
;
193 if (no_nav
) window_flags
|= ImGuiWindowFlags_NoNav
;
194 if (no_close
) p_open
= NULL
; // Don't pass our bool* to Begin
196 // 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.
197 ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver
);
198 ImGui::SetNextWindowSize(ImVec2(550, 680), ImGuiCond_FirstUseEver
);
200 // Main body of the Demo window starts here.
201 if (!ImGui::Begin("ImGui Demo", p_open
, window_flags
))
203 // Early out if the window is collapsed, as an optimization.
207 ImGui::Text("dear imgui says hello. (%s)", IMGUI_VERSION
);
209 // Most "big" widgets share a common width settings by default.
210 //ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.65f); // Use 2/3 of the space for widgets and 1/3 for labels (default)
211 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.
214 if (ImGui::BeginMenuBar())
216 if (ImGui::BeginMenu("Menu"))
218 ShowExampleMenuFile();
221 if (ImGui::BeginMenu("Examples"))
223 ImGui::MenuItem("Main menu bar", NULL
, &show_app_main_menu_bar
);
224 ImGui::MenuItem("Console", NULL
, &show_app_console
);
225 ImGui::MenuItem("Log", NULL
, &show_app_log
);
226 ImGui::MenuItem("Simple layout", NULL
, &show_app_layout
);
227 ImGui::MenuItem("Property editor", NULL
, &show_app_property_editor
);
228 ImGui::MenuItem("Long text display", NULL
, &show_app_long_text
);
229 ImGui::MenuItem("Auto-resizing window", NULL
, &show_app_auto_resize
);
230 ImGui::MenuItem("Constrained-resizing window", NULL
, &show_app_constrained_resize
);
231 ImGui::MenuItem("Simple overlay", NULL
, &show_app_simple_overlay
);
232 ImGui::MenuItem("Manipulating window titles", NULL
, &show_app_window_titles
);
233 ImGui::MenuItem("Custom rendering", NULL
, &show_app_custom_rendering
);
236 if (ImGui::BeginMenu("Help"))
238 ImGui::MenuItem("Metrics", NULL
, &show_app_metrics
);
239 ImGui::MenuItem("Style Editor", NULL
, &show_app_style_editor
);
240 ImGui::MenuItem("About Dear ImGui", NULL
, &show_app_about
);
247 if (ImGui::CollapsingHeader("Help"))
249 ImGui::TextWrapped("This window is being created by the ShowDemoWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n");
250 ImGui::Text("USER GUIDE:");
251 ImGui::ShowUserGuide();
254 if (ImGui::CollapsingHeader("Window options"))
256 ImGui::Checkbox("No titlebar", &no_titlebar
); ImGui::SameLine(150);
257 ImGui::Checkbox("No scrollbar", &no_scrollbar
); ImGui::SameLine(300);
258 ImGui::Checkbox("No menu", &no_menu
);
259 ImGui::Checkbox("No move", &no_move
); ImGui::SameLine(150);
260 ImGui::Checkbox("No resize", &no_resize
); ImGui::SameLine(300);
261 ImGui::Checkbox("No collapse", &no_collapse
);
262 ImGui::Checkbox("No close", &no_close
); ImGui::SameLine(150);
263 ImGui::Checkbox("No nav", &no_nav
);
265 if (ImGui::TreeNode("Style"))
267 ImGui::ShowStyleEditor();
271 if (ImGui::TreeNode("Capture/Logging"))
273 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. You can also call ImGui::LogText() to output directly to the log without a visual output.");
279 if (ImGui::CollapsingHeader("Widgets"))
281 if (ImGui::TreeNode("Basic"))
283 static int clicked
= 0;
284 if (ImGui::Button("Button"))
289 ImGui::Text("Thanks for clicking me!");
292 static bool check
= true;
293 ImGui::Checkbox("checkbox", &check
);
296 ImGui::RadioButton("radio a", &e
, 0); ImGui::SameLine();
297 ImGui::RadioButton("radio b", &e
, 1); ImGui::SameLine();
298 ImGui::RadioButton("radio c", &e
, 2);
300 // Color buttons, demonstrate using PushID() to add unique identifier in the ID stack, and changing style.
301 for (int i
= 0; i
< 7; i
++)
303 if (i
> 0) ImGui::SameLine();
305 ImGui::PushStyleColor(ImGuiCol_Button
, (ImVec4
)ImColor::HSV(i
/7.0f
, 0.6f
, 0.6f
));
306 ImGui::PushStyleColor(ImGuiCol_ButtonHovered
, (ImVec4
)ImColor::HSV(i
/7.0f
, 0.7f
, 0.7f
));
307 ImGui::PushStyleColor(ImGuiCol_ButtonActive
, (ImVec4
)ImColor::HSV(i
/7.0f
, 0.8f
, 0.8f
));
308 ImGui::Button("Click");
309 ImGui::PopStyleColor(3);
314 static int counter
= 0;
315 float spacing
= ImGui::GetStyle().ItemInnerSpacing
.x
;
316 ImGui::PushButtonRepeat(true);
317 if (ImGui::ArrowButton("##left", ImGuiDir_Left
)) { counter
--; }
318 ImGui::SameLine(0.0f
, spacing
);
319 if (ImGui::ArrowButton("##right", ImGuiDir_Right
)) { counter
++; }
320 ImGui::PopButtonRepeat();
322 ImGui::Text("%d", counter
);
324 ImGui::Text("Hover over me");
325 if (ImGui::IsItemHovered())
326 ImGui::SetTooltip("I am a tooltip");
329 ImGui::Text("- or me");
330 if (ImGui::IsItemHovered())
332 ImGui::BeginTooltip();
333 ImGui::Text("I am a fancy tooltip");
334 static float arr
[] = { 0.6f
, 0.1f
, 1.0f
, 0.5f
, 0.92f
, 0.1f
, 0.2f
};
335 ImGui::PlotLines("Curve", arr
, IM_ARRAYSIZE(arr
));
341 ImGui::LabelText("label", "Value");
344 // Using the _simplified_ one-liner Combo() api here
345 // See "Combo" section for examples of how to use the more complete BeginCombo()/EndCombo() api.
346 const char* items
[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
347 static int item_current
= 0;
348 ImGui::Combo("combo", &item_current
, items
, IM_ARRAYSIZE(items
));
349 ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n");
353 static char str0
[128] = "Hello, world!";
355 ImGui::InputText("input text", str0
, IM_ARRAYSIZE(str0
));
356 ImGui::SameLine(); ShowHelpMarker("Hold 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");
358 ImGui::InputInt("input int", &i0
);
359 ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n");
361 static float f0
= 0.001f
;
362 ImGui::InputFloat("input float", &f0
, 0.01f
, 1.0f
);
364 static double d0
= 999999.00000001;
365 ImGui::InputDouble("input double", &d0
, 0.01f
, 1.0f
, "%.8f");
367 static float f1
= 1.e10f
;
368 ImGui::InputFloat("input scientific", &f1
, 0.0f
, 0.0f
, "%e");
369 ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n e.g. \"1e+8\" becomes \"100000000\".\n");
371 static float vec4a
[4] = { 0.10f
, 0.20f
, 0.30f
, 0.44f
};
372 ImGui::InputFloat3("input float3", vec4a
);
376 static int i1
= 50, i2
= 42;
377 ImGui::DragInt("drag int", &i1
, 1);
378 ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value.");
380 ImGui::DragInt("drag int 0..100", &i2
, 1, 0, 100, "%d%%");
382 static float f1
=1.00f
, f2
=0.0067f
;
383 ImGui::DragFloat("drag float", &f1
, 0.005f
);
384 ImGui::DragFloat("drag small float", &f2
, 0.0001f
, 0.0f
, 0.0f
, "%.06f ns");
389 ImGui::SliderInt("slider int", &i1
, -1, 3);
390 ImGui::SameLine(); ShowHelpMarker("CTRL+click to input value.");
392 static float f1
=0.123f
, f2
=0.0f
;
393 ImGui::SliderFloat("slider float", &f1
, 0.0f
, 1.0f
, "ratio = %.3f");
394 ImGui::SliderFloat("slider float (curve)", &f2
, -10.0f
, 10.0f
, "%.4f", 2.0f
);
395 static float angle
= 0.0f
;
396 ImGui::SliderAngle("slider angle", &angle
);
400 static float col1
[3] = { 1.0f
,0.0f
,0.2f
};
401 static float col2
[4] = { 0.4f
,0.7f
,0.0f
,0.5f
};
402 ImGui::ColorEdit3("color 1", col1
);
403 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");
405 ImGui::ColorEdit4("color 2", col2
);
410 const char* listbox_items
[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" };
411 static int listbox_item_current
= 1;
412 ImGui::ListBox("listbox\n(single select)", &listbox_item_current
, listbox_items
, IM_ARRAYSIZE(listbox_items
), 4);
414 //static int listbox_item_current2 = 2;
415 //ImGui::PushItemWidth(-1);
416 //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4);
417 //ImGui::PopItemWidth();
423 // Testing ImGuiOnceUponAFrame helper.
424 //static ImGuiOnceUponAFrame once;
425 //for (int i = 0; i < 5; i++)
427 // ImGui::Text("This will be displayed only once.");
429 if (ImGui::TreeNode("Trees"))
431 if (ImGui::TreeNode("Basic trees"))
433 for (int i
= 0; i
< 5; i
++)
434 if (ImGui::TreeNode((void*)(intptr_t)i
, "Child %d", i
))
436 ImGui::Text("blah blah");
438 if (ImGui::SmallButton("button")) { };
444 if (ImGui::TreeNode("Advanced, with Selectable nodes"))
446 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.");
447 static bool align_label_with_current_x_position
= false;
448 ImGui::Checkbox("Align label with current X position)", &align_label_with_current_x_position
);
449 ImGui::Text("Hello!");
450 if (align_label_with_current_x_position
)
451 ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
453 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.
454 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.
455 ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing
, ImGui::GetFontSize()*3); // Increase spacing to differentiate leaves from expanded contents.
456 for (int i
= 0; i
< 6; i
++)
458 // Disable the default open on single-click behavior and pass in Selected flag according to our selection state.
459 ImGuiTreeNodeFlags node_flags
= ImGuiTreeNodeFlags_OpenOnArrow
| ImGuiTreeNodeFlags_OpenOnDoubleClick
| ((selection_mask
& (1 << i
)) ? ImGuiTreeNodeFlags_Selected
: 0);
463 bool node_open
= ImGui::TreeNodeEx((void*)(intptr_t)i
, node_flags
, "Selectable Node %d", i
);
464 if (ImGui::IsItemClicked())
468 ImGui::Text("Blah blah\nBlah Blah");
474 // 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().
475 node_flags
|= ImGuiTreeNodeFlags_Leaf
| ImGuiTreeNodeFlags_NoTreePushOnOpen
; // ImGuiTreeNodeFlags_Bullet
476 ImGui::TreeNodeEx((void*)(intptr_t)i
, node_flags
, "Selectable Leaf %d", i
);
477 if (ImGui::IsItemClicked())
481 if (node_clicked
!= -1)
483 // Update selection state. Process outside of tree loop to avoid visual inconsistencies during the clicking-frame.
484 if (ImGui::GetIO().KeyCtrl
)
485 selection_mask
^= (1 << node_clicked
); // CTRL+click to toggle
486 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
487 selection_mask
= (1 << node_clicked
); // Click to single-select
489 ImGui::PopStyleVar();
490 if (align_label_with_current_x_position
)
491 ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
497 if (ImGui::TreeNode("Collapsing Headers"))
499 static bool closable_group
= true;
500 ImGui::Checkbox("Enable extra group", &closable_group
);
501 if (ImGui::CollapsingHeader("Header"))
503 ImGui::Text("IsItemHovered: %d", IsItemHovered());
504 for (int i
= 0; i
< 5; i
++)
505 ImGui::Text("Some content %d", i
);
507 if (ImGui::CollapsingHeader("Header with a close button", &closable_group
))
509 ImGui::Text("IsItemHovered: %d", IsItemHovered());
510 for (int i
= 0; i
< 5; i
++)
511 ImGui::Text("More content %d", i
);
516 if (ImGui::TreeNode("Bullets"))
518 ImGui::BulletText("Bullet point 1");
519 ImGui::BulletText("Bullet point 2\nOn multiple lines");
520 ImGui::Bullet(); ImGui::Text("Bullet point 3 (two calls)");
521 ImGui::Bullet(); ImGui::SmallButton("Button");
525 if (ImGui::TreeNode("Text"))
527 if (ImGui::TreeNode("Colored Text"))
529 // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility.
530 ImGui::TextColored(ImVec4(1.0f
,0.0f
,1.0f
,1.0f
), "Pink");
531 ImGui::TextColored(ImVec4(1.0f
,1.0f
,0.0f
,1.0f
), "Yellow");
532 ImGui::TextDisabled("Disabled");
533 ImGui::SameLine(); ShowHelpMarker("The TextDisabled color is stored in ImGuiStyle.");
537 if (ImGui::TreeNode("Word Wrapping"))
539 // Using shortcut. You can use PushTextWrapPos()/PopTextWrapPos() for more flexibility.
540 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.");
543 static float wrap_width
= 200.0f
;
544 ImGui::SliderFloat("Wrap width", &wrap_width
, -20, 600, "%.0f");
546 ImGui::Text("Test paragraph 1:");
547 ImVec2 pos
= ImGui::GetCursorScreenPos();
548 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));
549 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x
+ wrap_width
);
550 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
);
551 ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
552 ImGui::PopTextWrapPos();
554 ImGui::Text("Test paragraph 2:");
555 pos
= ImGui::GetCursorScreenPos();
556 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));
557 ImGui::PushTextWrapPos(ImGui::GetCursorPos().x
+ wrap_width
);
558 ImGui::Text("aaaaaaaa bbbbbbbb, c cccccccc,dddddddd. d eeeeeeee ffffffff. gggggggg!hhhhhhhh");
559 ImGui::GetWindowDrawList()->AddRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax(), IM_COL32(255,255,0,255));
560 ImGui::PopTextWrapPos();
565 if (ImGui::TreeNode("UTF-8 Text"))
567 // UTF-8 test with Japanese characters
568 // (Needs a suitable font, try Noto, or Arial Unicode, or M+ fonts. Read misc/fonts/README.txt for details.)
569 // - From C++11 you can use the u8"my text" syntax to encode literal strings as UTF-8
570 // - 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')
571 // - FOR THIS DEMO FILE ONLY, BECAUSE WE WANT TO SUPPORT OLD COMPILERS, WE ARE *NOT* INCLUDING RAW UTF-8 CHARACTERS IN THIS SOURCE FILE.
572 // Instead we are encoding a few strings with hexadecimal constants. Don't do this in your application!
573 // Please use u8"text in any language" in your application!
574 // 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.
575 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.");
576 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.
577 ImGui::Text("Kanjis: \xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e (nihongo)");
578 static char buf
[32] = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e";
579 //static char buf[32] = u8"NIHONGO"; // <- this is how you would write it with C++11, using real kanjis
580 ImGui::InputText("UTF-8 input", buf
, IM_ARRAYSIZE(buf
));
586 if (ImGui::TreeNode("Images"))
588 ImGuiIO
& io
= ImGui::GetIO();
589 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!");
591 // Here we are grabbing the font texture because that's the only one we have access to inside the demo code.
592 // 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.
593 // 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.
594 // (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.)
595 // 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.
596 // 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.
597 // Consider using the lower-level ImDrawList::AddImage() API, via ImGui::GetWindowDrawList()->AddImage().
598 ImTextureID my_tex_id
= io
.Fonts
->TexID
;
599 float my_tex_w
= (float)io
.Fonts
->TexWidth
;
600 float my_tex_h
= (float)io
.Fonts
->TexHeight
;
602 ImGui::Text("%.0fx%.0f", my_tex_w
, my_tex_h
);
603 ImVec2 pos
= ImGui::GetCursorScreenPos();
604 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));
605 if (ImGui::IsItemHovered())
607 ImGui::BeginTooltip();
608 float region_sz
= 32.0f
;
609 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
;
610 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
;
612 ImGui::Text("Min: (%.2f, %.2f)", region_x
, region_y
);
613 ImGui::Text("Max: (%.2f, %.2f)", region_x
+ region_sz
, region_y
+ region_sz
);
614 ImVec2 uv0
= ImVec2((region_x
) / my_tex_w
, (region_y
) / my_tex_h
);
615 ImVec2 uv1
= ImVec2((region_x
+ region_sz
) / my_tex_w
, (region_y
+ region_sz
) / my_tex_h
);
616 ImGui::Image(my_tex_id
, ImVec2(region_sz
* zoom
, region_sz
* zoom
), uv0
, uv1
, ImColor(255,255,255,255), ImColor(255,255,255,128));
619 ImGui::TextWrapped("And now some textured buttons..");
620 static int pressed_count
= 0;
621 for (int i
= 0; i
< 8; i
++)
624 int frame_padding
= -1 + i
; // -1 = uses default padding
625 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)))
631 ImGui::Text("Pressed %d times.", pressed_count
);
635 if (ImGui::TreeNode("Combo"))
637 // Expose flags as checkbox for the demo
638 static ImGuiComboFlags flags
= 0;
639 ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags
, ImGuiComboFlags_PopupAlignLeft
);
640 if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags
, ImGuiComboFlags_NoArrowButton
))
641 flags
&= ~ImGuiComboFlags_NoPreview
; // Clear the other flag, as we cannot combine both
642 if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags
, ImGuiComboFlags_NoPreview
))
643 flags
&= ~ImGuiComboFlags_NoArrowButton
; // Clear the other flag, as we cannot combine both
645 // General BeginCombo() API, you have full control over your selection data and display type.
646 // (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.)
647 const char* items
[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" };
648 static const char* item_current
= items
[0]; // Here our selection is a single pointer stored outside the object.
649 if (ImGui::BeginCombo("combo 1", item_current
, flags
)) // The second parameter is the label previewed before opening the combo.
651 for (int n
= 0; n
< IM_ARRAYSIZE(items
); n
++)
653 bool is_selected
= (item_current
== items
[n
]);
654 if (ImGui::Selectable(items
[n
], is_selected
))
655 item_current
= items
[n
];
657 ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch)
662 // Simplified one-liner Combo() API, using values packed in a single constant string
663 static int item_current_2
= 0;
664 ImGui::Combo("combo 2 (one-liner)", &item_current_2
, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
666 // Simplified one-liner Combo() using an array of const char*
667 static int item_current_3
= -1; // If the selection isn't within 0..count, Combo won't display a preview
668 ImGui::Combo("combo 3 (array)", &item_current_3
, items
, IM_ARRAYSIZE(items
));
670 // Simplified one-liner Combo() using an accessor function
671 struct FuncHolder
{ static bool ItemGetter(void* data
, int idx
, const char** out_str
) { *out_str
= ((const char**)data
)[idx
]; return true; } };
672 static int item_current_4
= 0;
673 ImGui::Combo("combo 4 (function)", &item_current_4
, &FuncHolder::ItemGetter
, items
, IM_ARRAYSIZE(items
));
678 if (ImGui::TreeNode("Selectables"))
680 // Selectable() has 2 overloads:
681 // - 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.
682 // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases)
683 // 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).
684 if (ImGui::TreeNode("Basic"))
686 static bool selection
[5] = { false, true, false, false, false };
687 ImGui::Selectable("1. I am selectable", &selection
[0]);
688 ImGui::Selectable("2. I am selectable", &selection
[1]);
689 ImGui::Text("3. I am not selectable");
690 ImGui::Selectable("4. I am selectable", &selection
[3]);
691 if (ImGui::Selectable("5. I am double clickable", selection
[4], ImGuiSelectableFlags_AllowDoubleClick
))
692 if (ImGui::IsMouseDoubleClicked(0))
693 selection
[4] = !selection
[4];
696 if (ImGui::TreeNode("Selection State: Single Selection"))
698 static int selected
= -1;
699 for (int n
= 0; n
< 5; n
++)
702 sprintf(buf
, "Object %d", n
);
703 if (ImGui::Selectable(buf
, selected
== n
))
708 if (ImGui::TreeNode("Selection State: Multiple Selection"))
710 ShowHelpMarker("Hold CTRL and click to select multiple items.");
711 static bool selection
[5] = { false, false, false, false, false };
712 for (int n
= 0; n
< 5; n
++)
715 sprintf(buf
, "Object %d", n
);
716 if (ImGui::Selectable(buf
, selection
[n
]))
718 if (!ImGui::GetIO().KeyCtrl
) // Clear selection when CTRL is not held
719 memset(selection
, 0, sizeof(selection
));
725 if (ImGui::TreeNode("Rendering more text into the same line"))
727 // Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically.
728 static bool selected
[3] = { false, false, false };
729 ImGui::Selectable("main.c", &selected
[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
730 ImGui::Selectable("Hello.cpp", &selected
[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes");
731 ImGui::Selectable("Hello.h", &selected
[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes");
734 if (ImGui::TreeNode("In columns"))
736 ImGui::Columns(3, NULL
, false);
737 static bool selected
[16] = { 0 };
738 for (int i
= 0; i
< 16; i
++)
740 char label
[32]; sprintf(label
, "Item %d", i
);
741 if (ImGui::Selectable(label
, &selected
[i
])) {}
747 if (ImGui::TreeNode("Grid"))
749 static bool selected
[16] = { true, false, false, false, false, true, false, false, false, false, true, false, false, false, false, true };
750 for (int i
= 0; i
< 16; i
++)
753 if (ImGui::Selectable("Sailor", &selected
[i
], 0, ImVec2(50,50)))
755 int x
= i
% 4, y
= i
/ 4;
756 if (x
> 0) selected
[i
- 1] ^= 1;
757 if (x
< 3) selected
[i
+ 1] ^= 1;
758 if (y
> 0) selected
[i
- 4] ^= 1;
759 if (y
< 3) selected
[i
+ 4] ^= 1;
761 if ((i
% 4) < 3) ImGui::SameLine();
769 if (ImGui::TreeNode("Filtered Text Input"))
771 static char buf1
[64] = ""; ImGui::InputText("default", buf1
, 64);
772 static char buf2
[64] = ""; ImGui::InputText("decimal", buf2
, 64, ImGuiInputTextFlags_CharsDecimal
);
773 static char buf3
[64] = ""; ImGui::InputText("hexadecimal", buf3
, 64, ImGuiInputTextFlags_CharsHexadecimal
| ImGuiInputTextFlags_CharsUppercase
);
774 static char buf4
[64] = ""; ImGui::InputText("uppercase", buf4
, 64, ImGuiInputTextFlags_CharsUppercase
);
775 static char buf5
[64] = ""; ImGui::InputText("no blank", buf5
, 64, ImGuiInputTextFlags_CharsNoBlank
);
776 struct TextFilters
{ static int FilterImGuiLetters(ImGuiTextEditCallbackData
* data
) { if (data
->EventChar
< 256 && strchr("imgui", (char)data
->EventChar
)) return 0; return 1; } };
777 static char buf6
[64] = ""; ImGui::InputText("\"imgui\" letters", buf6
, 64, ImGuiInputTextFlags_CallbackCharFilter
, TextFilters::FilterImGuiLetters
);
779 ImGui::Text("Password input");
780 static char bufpass
[64] = "password123";
781 ImGui::InputText("password", bufpass
, 64, ImGuiInputTextFlags_Password
| ImGuiInputTextFlags_CharsNoBlank
);
782 ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
783 ImGui::InputText("password (clear)", bufpass
, 64, ImGuiInputTextFlags_CharsNoBlank
);
788 if (ImGui::TreeNode("Multi-line Text Input"))
790 static bool read_only
= false;
791 static char text
[1024*16] =
793 " The Pentium F00F bug, shorthand for F0 0F C7 C8,\n"
794 " the hexadecimal encoding of one offending instruction,\n"
795 " more formally, the invalid operand with locked CMPXCHG8B\n"
796 " instruction bug, is a design flaw in the majority of\n"
797 " Intel Pentium, Pentium MMX, and Pentium OverDrive\n"
798 " processors (all in the P5 microarchitecture).\n"
801 "\tlock cmpxchg8b eax\n";
803 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding
, ImVec2(0,0));
804 ImGui::Checkbox("Read-only", &read_only
);
805 ImGui::PopStyleVar();
806 ImGui::InputTextMultiline("##source", text
, IM_ARRAYSIZE(text
), ImVec2(-1.0f
, ImGui::GetTextLineHeight() * 16), ImGuiInputTextFlags_AllowTabInput
| (read_only
? ImGuiInputTextFlags_ReadOnly
: 0));
810 if (ImGui::TreeNode("Plots Widgets"))
812 static bool animate
= true;
813 ImGui::Checkbox("Animate", &animate
);
815 static float arr
[] = { 0.6f
, 0.1f
, 1.0f
, 0.5f
, 0.92f
, 0.1f
, 0.2f
};
816 ImGui::PlotLines("Frame Times", arr
, IM_ARRAYSIZE(arr
));
818 // Create a dummy array of contiguous float values to plot
819 // 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.
820 static float values
[90] = { 0 };
821 static int values_offset
= 0;
822 static double refresh_time
= 0.0;
823 if (!animate
|| refresh_time
== 0.0f
)
824 refresh_time
= ImGui::GetTime();
825 while (refresh_time
< ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo
827 static float phase
= 0.0f
;
828 values
[values_offset
] = cosf(phase
);
829 values_offset
= (values_offset
+1) % IM_ARRAYSIZE(values
);
830 phase
+= 0.10f
*values_offset
;
831 refresh_time
+= 1.0f
/60.0f
;
833 ImGui::PlotLines("Lines", values
, IM_ARRAYSIZE(values
), values_offset
, "avg 0.0", -1.0f
, 1.0f
, ImVec2(0,80));
834 ImGui::PlotHistogram("Histogram", arr
, IM_ARRAYSIZE(arr
), 0, NULL
, 0.0f
, 1.0f
, ImVec2(0,80));
836 // Use functions to generate output
837 // 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.
840 static float Sin(void*, int i
) { return sinf(i
* 0.1f
); }
841 static float Saw(void*, int i
) { return (i
& 1) ? 1.0f
: -1.0f
; }
843 static int func_type
= 0, display_count
= 70;
845 ImGui::PushItemWidth(100); ImGui::Combo("func", &func_type
, "Sin\0Saw\0"); ImGui::PopItemWidth();
847 ImGui::SliderInt("Sample count", &display_count
, 1, 400);
848 float (*func
)(void*, int) = (func_type
== 0) ? Funcs::Sin
: Funcs::Saw
;
849 ImGui::PlotLines("Lines", func
, NULL
, display_count
, 0, NULL
, -1.0f
, 1.0f
, ImVec2(0,80));
850 ImGui::PlotHistogram("Histogram", func
, NULL
, display_count
, 0, NULL
, -1.0f
, 1.0f
, ImVec2(0,80));
853 // Animate a simple progress bar
854 static float progress
= 0.0f
, progress_dir
= 1.0f
;
857 progress
+= progress_dir
* 0.4f
* ImGui::GetIO().DeltaTime
;
858 if (progress
>= +1.1f
) { progress
= +1.1f
; progress_dir
*= -1.0f
; }
859 if (progress
<= -0.1f
) { progress
= -0.1f
; progress_dir
*= -1.0f
; }
862 // 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.
863 ImGui::ProgressBar(progress
, ImVec2(0.0f
,0.0f
));
864 ImGui::SameLine(0.0f
, ImGui::GetStyle().ItemInnerSpacing
.x
);
865 ImGui::Text("Progress Bar");
867 float progress_saturated
= (progress
< 0.0f
) ? 0.0f
: (progress
> 1.0f
) ? 1.0f
: progress
;
869 sprintf(buf
, "%d/%d", (int)(progress_saturated
*1753), 1753);
870 ImGui::ProgressBar(progress
, ImVec2(0.f
,0.f
), buf
);
874 if (ImGui::TreeNode("Color/Picker Widgets"))
876 static ImVec4 color
= ImColor(114, 144, 154, 200);
878 static bool alpha_preview
= true;
879 static bool alpha_half_preview
= false;
880 static bool drag_and_drop
= true;
881 static bool options_menu
= true;
882 static bool hdr
= false;
883 ImGui::Checkbox("With Alpha Preview", &alpha_preview
);
884 ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview
);
885 ImGui::Checkbox("With Drag and Drop", &drag_and_drop
);
886 ImGui::Checkbox("With Options Menu", &options_menu
); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options.");
887 ImGui::Checkbox("With HDR", &hdr
); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets.");
888 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
);
890 ImGui::Text("Color widget:");
891 ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nCTRL+click on individual component to input value.\n");
892 ImGui::ColorEdit3("MyColor##1", (float*)&color
, misc_flags
);
894 ImGui::Text("Color widget HSV with Alpha:");
895 ImGui::ColorEdit4("MyColor##2", (float*)&color
, ImGuiColorEditFlags_HSV
| misc_flags
);
897 ImGui::Text("Color widget with Float Display:");
898 ImGui::ColorEdit4("MyColor##2f", (float*)&color
, ImGuiColorEditFlags_Float
| misc_flags
);
900 ImGui::Text("Color button with Picker:");
901 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.");
902 ImGui::ColorEdit4("MyColor##3", (float*)&color
, ImGuiColorEditFlags_NoInputs
| ImGuiColorEditFlags_NoLabel
| misc_flags
);
904 ImGui::Text("Color button with Custom Picker Popup:");
906 // Generate a dummy palette
907 static bool saved_palette_inited
= false;
908 static ImVec4 saved_palette
[32];
909 if (!saved_palette_inited
)
910 for (int n
= 0; n
< IM_ARRAYSIZE(saved_palette
); n
++)
912 ImGui::ColorConvertHSVtoRGB(n
/ 31.0f
, 0.8f
, 0.8f
, saved_palette
[n
].x
, saved_palette
[n
].y
, saved_palette
[n
].z
);
913 saved_palette
[n
].w
= 1.0f
; // Alpha
915 saved_palette_inited
= true;
917 static ImVec4 backup_color
;
918 bool open_popup
= ImGui::ColorButton("MyColor##3b", color
, misc_flags
);
920 open_popup
|= ImGui::Button("Palette");
923 ImGui::OpenPopup("mypicker");
924 backup_color
= color
;
926 if (ImGui::BeginPopup("mypicker"))
928 // FIXME: Adding a drag and drop example here would be perfect!
929 ImGui::Text("MY CUSTOM COLOR PICKER WITH AN AMAZING PALETTE!");
931 ImGui::ColorPicker4("##picker", (float*)&color
, misc_flags
| ImGuiColorEditFlags_NoSidePreview
| ImGuiColorEditFlags_NoSmallPreview
);
934 ImGui::Text("Current");
935 ImGui::ColorButton("##current", color
, ImGuiColorEditFlags_NoPicker
| ImGuiColorEditFlags_AlphaPreviewHalf
, ImVec2(60,40));
936 ImGui::Text("Previous");
937 if (ImGui::ColorButton("##previous", backup_color
, ImGuiColorEditFlags_NoPicker
| ImGuiColorEditFlags_AlphaPreviewHalf
, ImVec2(60,40)))
938 color
= backup_color
;
940 ImGui::Text("Palette");
941 for (int n
= 0; n
< IM_ARRAYSIZE(saved_palette
); n
++)
945 ImGui::SameLine(0.0f
, ImGui::GetStyle().ItemSpacing
.y
);
946 if (ImGui::ColorButton("##palette", saved_palette
[n
], ImGuiColorEditFlags_NoAlpha
| ImGuiColorEditFlags_NoPicker
| ImGuiColorEditFlags_NoTooltip
, ImVec2(20,20)))
947 color
= ImVec4(saved_palette
[n
].x
, saved_palette
[n
].y
, saved_palette
[n
].z
, color
.w
); // Preserve alpha!
949 if (ImGui::BeginDragDropTarget())
951 if (const ImGuiPayload
* payload
= AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F
))
952 memcpy((float*)&saved_palette
[n
], payload
->Data
, sizeof(float) * 3);
953 if (const ImGuiPayload
* payload
= AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F
))
954 memcpy((float*)&saved_palette
[n
], payload
->Data
, sizeof(float) * 4);
964 ImGui::Text("Color button only:");
965 ImGui::ColorButton("MyColor##3c", *(ImVec4
*)&color
, misc_flags
, ImVec2(80,80));
967 ImGui::Text("Color picker:");
968 static bool alpha
= true;
969 static bool alpha_bar
= true;
970 static bool side_preview
= true;
971 static bool ref_color
= false;
972 static ImVec4
ref_color_v(1.0f
,0.0f
,1.0f
,0.5f
);
973 static int inputs_mode
= 2;
974 static int picker_mode
= 0;
975 ImGui::Checkbox("With Alpha", &alpha
);
976 ImGui::Checkbox("With Alpha Bar", &alpha_bar
);
977 ImGui::Checkbox("With Side Preview", &side_preview
);
981 ImGui::Checkbox("With Ref Color", &ref_color
);
985 ImGui::ColorEdit4("##RefColor", &ref_color_v
.x
, ImGuiColorEditFlags_NoInputs
| misc_flags
);
988 ImGui::Combo("Inputs Mode", &inputs_mode
, "All Inputs\0No Inputs\0RGB Input\0HSV Input\0HEX Input\0");
989 ImGui::Combo("Picker Mode", &picker_mode
, "Auto/Current\0Hue bar + SV rect\0Hue wheel + SV triangle\0");
990 ImGui::SameLine(); ShowHelpMarker("User can right-click the picker to change mode.");
991 ImGuiColorEditFlags flags
= misc_flags
;
992 if (!alpha
) flags
|= ImGuiColorEditFlags_NoAlpha
; // This is by default if you call ColorPicker3() instead of ColorPicker4()
993 if (alpha_bar
) flags
|= ImGuiColorEditFlags_AlphaBar
;
994 if (!side_preview
) flags
|= ImGuiColorEditFlags_NoSidePreview
;
995 if (picker_mode
== 1) flags
|= ImGuiColorEditFlags_PickerHueBar
;
996 if (picker_mode
== 2) flags
|= ImGuiColorEditFlags_PickerHueWheel
;
997 if (inputs_mode
== 1) flags
|= ImGuiColorEditFlags_NoInputs
;
998 if (inputs_mode
== 2) flags
|= ImGuiColorEditFlags_RGB
;
999 if (inputs_mode
== 3) flags
|= ImGuiColorEditFlags_HSV
;
1000 if (inputs_mode
== 4) flags
|= ImGuiColorEditFlags_HEX
;
1001 ImGui::ColorPicker4("MyColor##4", (float*)&color
, flags
, ref_color
? &ref_color_v
.x
: NULL
);
1003 ImGui::Text("Programmatically set defaults:");
1004 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.");
1005 if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
1006 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8
| ImGuiColorEditFlags_HSV
| ImGuiColorEditFlags_PickerHueBar
);
1007 if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
1008 ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float
| ImGuiColorEditFlags_HDR
| ImGuiColorEditFlags_PickerHueWheel
);
1013 if (ImGui::TreeNode("Range Widgets"))
1015 static float begin
= 10, end
= 90;
1016 static int begin_i
= 100, end_i
= 1000;
1017 ImGui::DragFloatRange2("range", &begin
, &end
, 0.25f
, 0.0f
, 100.0f
, "Min: %.1f %%", "Max: %.1f %%");
1018 ImGui::DragIntRange2("range int (no bounds)", &begin_i
, &end_i
, 5, 0, 0, "Min: %d units", "Max: %d units");
1022 if (ImGui::TreeNode("Data Types"))
1024 // The DragScalar, InputScalar, SliderScalar functions allow manipulating most common data types: signed/unsigned int/long long and float/double
1025 // To avoid polluting the public API with all possible combinations, we use the ImGuiDataType enum to pass the type, and argument-by-values are turned into argument-by-address.
1026 // This is the reason the test code below creates local variables to hold "zero" "one" etc. for each types.
1027 // In practice, if you frequently use a given type that is not covered by the normal API entry points, you may want to wrap it yourself inside a 1 line function
1028 // which can take typed values argument instead of void*, and then pass their address to the generic function. For example:
1029 // bool SliderU64(const char *label, u64* value, u64 min = 0, u64 max = 0, const char* format = "%lld") { return SliderScalar(label, ImGuiDataType_U64, value, &min, &max, format); }
1030 // Below are helper variables we can take the address of to work-around this:
1031 // Note that the SliderScalar function has a maximum usable range of half the natural type maximum, hence the /2 below.
1032 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;
1033 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;
1034 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;
1035 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;
1036 const float f32_zero
= 0.f
, f32_one
= 1.f
, f32_lo_a
= -10000000000.0f
, f32_hi_a
= +10000000000.0f
;
1037 const double f64_zero
= 0., f64_one
= 1., f64_lo_a
= -1000000000000000, f64_hi_a
= +1000000000000000;
1040 static ImS32 s32_v
= -1;
1041 static ImU32 u32_v
= (ImU32
)-1;
1042 static ImS64 s64_v
= -1;
1043 static ImU64 u64_v
= (ImU64
)-1;
1044 static float f32_v
= 0.123f
;
1045 static double f64_v
= 90000.01234567890123456789;
1047 const float drag_speed
= 0.2f
;
1048 static bool drag_clamp
= false;
1049 ImGui::Text("Drags:");
1050 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.");
1051 ImGui::DragScalar("drag s32", ImGuiDataType_S32
, &s32_v
, drag_speed
, drag_clamp
? &s32_zero
: NULL
, drag_clamp
? &s32_fifty
: NULL
);
1052 ImGui::DragScalar("drag u32", ImGuiDataType_U32
, &u32_v
, drag_speed
, drag_clamp
? &u32_zero
: NULL
, drag_clamp
? &u32_fifty
: NULL
, "%u ms");
1053 ImGui::DragScalar("drag s64", ImGuiDataType_S64
, &s64_v
, drag_speed
, drag_clamp
? &s64_zero
: NULL
, drag_clamp
? &s64_fifty
: NULL
);
1054 ImGui::DragScalar("drag u64", ImGuiDataType_U64
, &u64_v
, drag_speed
, drag_clamp
? &u64_zero
: NULL
, drag_clamp
? &u64_fifty
: NULL
);
1055 ImGui::DragScalar("drag float", ImGuiDataType_Float
, &f32_v
, 0.005f
, &f32_zero
, &f32_one
, "%f", 1.0f
);
1056 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.");
1057 ImGui::DragScalar("drag double", ImGuiDataType_Double
, &f64_v
, 0.0005f
, &f64_zero
, NULL
, "%.10f grams", 1.0f
);
1058 ImGui::DragScalar("drag double ^2", ImGuiDataType_Double
, &f64_v
, 0.0005f
, &f64_zero
, &f64_one
, "0 < %.10f < 1", 2.0f
);
1060 ImGui::Text("Sliders");
1061 ImGui::SliderScalar("slider s32 low", ImGuiDataType_S32
, &s32_v
, &s32_zero
, &s32_fifty
,"%d");
1062 ImGui::SliderScalar("slider s32 high", ImGuiDataType_S32
, &s32_v
, &s32_hi_a
, &s32_hi_b
, "%d");
1063 ImGui::SliderScalar("slider s32 full", ImGuiDataType_S32
, &s32_v
, &s32_min
, &s32_max
, "%d");
1064 ImGui::SliderScalar("slider u32 low", ImGuiDataType_U32
, &u32_v
, &u32_zero
, &u32_fifty
,"%u");
1065 ImGui::SliderScalar("slider u32 high", ImGuiDataType_U32
, &u32_v
, &u32_hi_a
, &u32_hi_b
, "%u");
1066 ImGui::SliderScalar("slider u32 full", ImGuiDataType_U32
, &u32_v
, &u32_min
, &u32_max
, "%u");
1067 ImGui::SliderScalar("slider s64 low", ImGuiDataType_S64
, &s64_v
, &s64_zero
, &s64_fifty
,"%I64d");
1068 ImGui::SliderScalar("slider s64 high", ImGuiDataType_S64
, &s64_v
, &s64_hi_a
, &s64_hi_b
, "%I64d");
1069 ImGui::SliderScalar("slider s64 full", ImGuiDataType_S64
, &s64_v
, &s64_min
, &s64_max
, "%I64d");
1070 ImGui::SliderScalar("slider u64 low", ImGuiDataType_U64
, &u64_v
, &u64_zero
, &u64_fifty
,"%I64u ms");
1071 ImGui::SliderScalar("slider u64 high", ImGuiDataType_U64
, &u64_v
, &u64_hi_a
, &u64_hi_b
, "%I64u ms");
1072 ImGui::SliderScalar("slider u64 full", ImGuiDataType_U64
, &u64_v
, &u64_min
, &u64_max
, "%I64u ms");
1073 ImGui::SliderScalar("slider float low", ImGuiDataType_Float
, &f32_v
, &f32_zero
, &f32_one
);
1074 ImGui::SliderScalar("slider float low^2", ImGuiDataType_Float
, &f32_v
, &f32_zero
, &f32_one
, "%.10f", 2.0f
);
1075 ImGui::SliderScalar("slider float high", ImGuiDataType_Float
, &f32_v
, &f32_lo_a
, &f32_hi_a
, "%e");
1076 ImGui::SliderScalar("slider double low", ImGuiDataType_Double
, &f64_v
, &f64_zero
, &f64_one
, "%.10f grams", 1.0f
);
1077 ImGui::SliderScalar("slider double low^2",ImGuiDataType_Double
, &f64_v
, &f64_zero
, &f64_one
, "%.10f", 2.0f
);
1078 ImGui::SliderScalar("slider double high", ImGuiDataType_Double
, &f64_v
, &f64_lo_a
, &f64_hi_a
, "%e grams", 1.0f
);
1080 static bool inputs_step
= true;
1081 ImGui::Text("Inputs");
1082 ImGui::Checkbox("Show step buttons", &inputs_step
);
1083 ImGui::InputScalar("input s32", ImGuiDataType_S32
, &s32_v
, inputs_step
? &s32_one
: NULL
, NULL
, "%d");
1084 ImGui::InputScalar("input s32 hex", ImGuiDataType_S32
, &s32_v
, inputs_step
? &s32_one
: NULL
, NULL
, "%08X", ImGuiInputTextFlags_CharsHexadecimal
);
1085 ImGui::InputScalar("input u32", ImGuiDataType_U32
, &u32_v
, inputs_step
? &u32_one
: NULL
, NULL
, "%u");
1086 ImGui::InputScalar("input u32 hex", ImGuiDataType_U32
, &u32_v
, inputs_step
? &u32_one
: NULL
, NULL
, "%08X", ImGuiInputTextFlags_CharsHexadecimal
);
1087 ImGui::InputScalar("input s64", ImGuiDataType_S64
, &s64_v
, inputs_step
? &s64_one
: NULL
);
1088 ImGui::InputScalar("input u64", ImGuiDataType_U64
, &u64_v
, inputs_step
? &u64_one
: NULL
);
1089 ImGui::InputScalar("input float", ImGuiDataType_Float
, &f32_v
, inputs_step
? &f32_one
: NULL
);
1090 ImGui::InputScalar("input double", ImGuiDataType_Double
, &f64_v
, inputs_step
? &f64_one
: NULL
);
1095 if (ImGui::TreeNode("Multi-component Widgets"))
1097 static float vec4f
[4] = { 0.10f
, 0.20f
, 0.30f
, 0.44f
};
1098 static int vec4i
[4] = { 1, 5, 100, 255 };
1100 ImGui::InputFloat2("input float2", vec4f
);
1101 ImGui::DragFloat2("drag float2", vec4f
, 0.01f
, 0.0f
, 1.0f
);
1102 ImGui::SliderFloat2("slider float2", vec4f
, 0.0f
, 1.0f
);
1103 ImGui::InputInt2("input int2", vec4i
);
1104 ImGui::DragInt2("drag int2", vec4i
, 1, 0, 255);
1105 ImGui::SliderInt2("slider int2", vec4i
, 0, 255);
1108 ImGui::InputFloat3("input float3", vec4f
);
1109 ImGui::DragFloat3("drag float3", vec4f
, 0.01f
, 0.0f
, 1.0f
);
1110 ImGui::SliderFloat3("slider float3", vec4f
, 0.0f
, 1.0f
);
1111 ImGui::InputInt3("input int3", vec4i
);
1112 ImGui::DragInt3("drag int3", vec4i
, 1, 0, 255);
1113 ImGui::SliderInt3("slider int3", vec4i
, 0, 255);
1116 ImGui::InputFloat4("input float4", vec4f
);
1117 ImGui::DragFloat4("drag float4", vec4f
, 0.01f
, 0.0f
, 1.0f
);
1118 ImGui::SliderFloat4("slider float4", vec4f
, 0.0f
, 1.0f
);
1119 ImGui::InputInt4("input int4", vec4i
);
1120 ImGui::DragInt4("drag int4", vec4i
, 1, 0, 255);
1121 ImGui::SliderInt4("slider int4", vec4i
, 0, 255);
1126 if (ImGui::TreeNode("Vertical Sliders"))
1128 const float spacing
= 4;
1129 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing
, ImVec2(spacing
, spacing
));
1131 static int int_value
= 0;
1132 ImGui::VSliderInt("##int", ImVec2(18,160), &int_value
, 0, 5);
1135 static float values
[7] = { 0.0f
, 0.60f
, 0.35f
, 0.9f
, 0.70f
, 0.20f
, 0.0f
};
1136 ImGui::PushID("set1");
1137 for (int i
= 0; i
< 7; i
++)
1139 if (i
> 0) ImGui::SameLine();
1141 ImGui::PushStyleColor(ImGuiCol_FrameBg
, (ImVec4
)ImColor::HSV(i
/7.0f
, 0.5f
, 0.5f
));
1142 ImGui::PushStyleColor(ImGuiCol_FrameBgHovered
, (ImVec4
)ImColor::HSV(i
/7.0f
, 0.6f
, 0.5f
));
1143 ImGui::PushStyleColor(ImGuiCol_FrameBgActive
, (ImVec4
)ImColor::HSV(i
/7.0f
, 0.7f
, 0.5f
));
1144 ImGui::PushStyleColor(ImGuiCol_SliderGrab
, (ImVec4
)ImColor::HSV(i
/7.0f
, 0.9f
, 0.9f
));
1145 ImGui::VSliderFloat("##v", ImVec2(18,160), &values
[i
], 0.0f
, 1.0f
, "");
1146 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1147 ImGui::SetTooltip("%.3f", values
[i
]);
1148 ImGui::PopStyleColor(4);
1154 ImGui::PushID("set2");
1155 static float values2
[4] = { 0.20f
, 0.80f
, 0.40f
, 0.25f
};
1157 const ImVec2
small_slider_size(18, (160.0f
-(rows
-1)*spacing
)/rows
);
1158 for (int nx
= 0; nx
< 4; nx
++)
1160 if (nx
> 0) ImGui::SameLine();
1161 ImGui::BeginGroup();
1162 for (int ny
= 0; ny
< rows
; ny
++)
1164 ImGui::PushID(nx
*rows
+ny
);
1165 ImGui::VSliderFloat("##v", small_slider_size
, &values2
[nx
], 0.0f
, 1.0f
, "");
1166 if (ImGui::IsItemActive() || ImGui::IsItemHovered())
1167 ImGui::SetTooltip("%.3f", values2
[nx
]);
1175 ImGui::PushID("set3");
1176 for (int i
= 0; i
< 4; i
++)
1178 if (i
> 0) ImGui::SameLine();
1180 ImGui::PushStyleVar(ImGuiStyleVar_GrabMinSize
, 40);
1181 ImGui::VSliderFloat("##v", ImVec2(40,160), &values
[i
], 0.0f
, 1.0f
, "%.2f\nsec");
1182 ImGui::PopStyleVar();
1186 ImGui::PopStyleVar();
1190 if (ImGui::TreeNode("Drag and Drop"))
1193 // ColorEdit widgets automatically act as drag source and drag target.
1194 // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F to allow your own widgets
1195 // to use colors in their drag and drop interaction. Also see the demo in Color Picker -> Palette demo.
1196 ImGui::BulletText("Drag and drop in standard widgets");
1198 static float col1
[3] = { 1.0f
,0.0f
,0.2f
};
1199 static float col2
[4] = { 0.4f
,0.7f
,0.0f
,0.5f
};
1200 ImGui::ColorEdit3("color 1", col1
);
1201 ImGui::ColorEdit4("color 2", col2
);
1206 ImGui::BulletText("Drag and drop to copy/swap items");
1214 static int mode
= 0;
1215 if (ImGui::RadioButton("Copy", mode
== Mode_Copy
)) { mode
= Mode_Copy
; } ImGui::SameLine();
1216 if (ImGui::RadioButton("Move", mode
== Mode_Move
)) { mode
= Mode_Move
; } ImGui::SameLine();
1217 if (ImGui::RadioButton("Swap", mode
== Mode_Swap
)) { mode
= Mode_Swap
; }
1218 static const char* names
[9] = { "Bobby", "Beatrice", "Betty", "Brianna", "Barry", "Bernard", "Bibi", "Blaine", "Bryn" };
1219 for (int n
= 0; n
< IM_ARRAYSIZE(names
); n
++)
1224 ImGui::Button(names
[n
], ImVec2(60,60));
1226 // Our buttons are both drag sources and drag targets here!
1227 if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None
))
1229 ImGui::SetDragDropPayload("DND_DEMO_CELL", &n
, sizeof(int)); // Set payload to carry the index of our item (could be anything)
1230 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.)
1231 if (mode
== Mode_Move
) { ImGui::Text("Move %s", names
[n
]); }
1232 if (mode
== Mode_Swap
) { ImGui::Text("Swap %s", names
[n
]); }
1233 ImGui::EndDragDropSource();
1235 if (ImGui::BeginDragDropTarget())
1237 if (const ImGuiPayload
* payload
= ImGui::AcceptDragDropPayload("DND_DEMO_CELL"))
1239 IM_ASSERT(payload
->DataSize
== sizeof(int));
1240 int payload_n
= *(const int*)payload
->Data
;
1241 if (mode
== Mode_Copy
)
1243 names
[n
] = names
[payload_n
];
1245 if (mode
== Mode_Move
)
1247 names
[n
] = names
[payload_n
];
1248 names
[payload_n
] = "";
1250 if (mode
== Mode_Swap
)
1252 const char* tmp
= names
[n
];
1253 names
[n
] = names
[payload_n
];
1254 names
[payload_n
] = tmp
;
1257 ImGui::EndDragDropTarget();
1267 if (ImGui::TreeNode("Active, Focused, Hovered & Focused Tests"))
1269 // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined.
1270 // (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).
1271 static int item_type
= 1;
1272 static bool b
= false;
1273 static float col4f
[4] = { 1.0f
, 0.5, 0.0f
, 1.0f
};
1274 ImGui::RadioButton("Text", &item_type
, 0); ImGui::SameLine();
1275 ImGui::RadioButton("Button", &item_type
, 1); ImGui::SameLine();
1276 ImGui::RadioButton("CheckBox", &item_type
, 2); ImGui::SameLine();
1277 ImGui::RadioButton("SliderFloat", &item_type
, 3); ImGui::SameLine();
1278 ImGui::RadioButton("ColorEdit4", &item_type
, 4); ImGui::SameLine();
1279 ImGui::RadioButton("ListBox", &item_type
, 5);
1281 if (item_type
== 0) { ImGui::Text("ITEM: Text"); } // Testing text items with no identifier/interaction
1282 if (item_type
== 1) { ret
= ImGui::Button("ITEM: Button"); } // Testing button
1283 if (item_type
== 2) { ret
= ImGui::Checkbox("ITEM: CheckBox", &b
); } // Testing checkbox
1284 if (item_type
== 3) { ret
= ImGui::SliderFloat("ITEM: SliderFloat", &col4f
[0], 0.0f
, 1.0f
); } // Testing basic item
1285 if (item_type
== 4) { ret
= ImGui::ColorEdit4("ITEM: ColorEdit4", col4f
); } // Testing multi-component items (IsItemXXX flags are reported merged)
1286 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
)); }
1288 "Return value = %d\n"
1289 "IsItemFocused() = %d\n"
1290 "IsItemHovered() = %d\n"
1291 "IsItemHovered(_AllowWhenBlockedByPopup) = %d\n"
1292 "IsItemHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1293 "IsItemHovered(_AllowWhenOverlapped) = %d\n"
1294 "IsItemHovered(_RectOnly) = %d\n"
1295 "IsItemActive() = %d\n"
1296 "IsItemDeactivated() = %d\n"
1297 "IsItemDeactivatedAfterChange() = %d\n"
1298 "IsItemVisible() = %d\n",
1300 ImGui::IsItemFocused(),
1301 ImGui::IsItemHovered(),
1302 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup
),
1303 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
),
1304 ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped
),
1305 ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly
),
1306 ImGui::IsItemActive(),
1307 ImGui::IsItemDeactivated(),
1308 ImGui::IsItemDeactivatedAfterChange(),
1309 ImGui::IsItemVisible()
1312 static bool embed_all_inside_a_child_window
= false;
1313 ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window
);
1314 if (embed_all_inside_a_child_window
)
1315 ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20), true);
1317 // Testing IsWindowFocused() function with its various flags. Note that the flags can be combined.
1319 "IsWindowFocused() = %d\n"
1320 "IsWindowFocused(_ChildWindows) = %d\n"
1321 "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
1322 "IsWindowFocused(_RootWindow) = %d\n"
1323 "IsWindowFocused(_AnyWindow) = %d\n",
1324 ImGui::IsWindowFocused(),
1325 ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows
),
1326 ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows
| ImGuiFocusedFlags_RootWindow
),
1327 ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow
),
1328 ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow
));
1330 // Testing IsWindowHovered() function with its various flags. Note that the flags can be combined.
1332 "IsWindowHovered() = %d\n"
1333 "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
1334 "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
1335 "IsWindowHovered(_ChildWindows) = %d\n"
1336 "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
1337 "IsWindowHovered(_RootWindow) = %d\n"
1338 "IsWindowHovered(_AnyWindow) = %d\n",
1339 ImGui::IsWindowHovered(),
1340 ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup
),
1341 ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem
),
1342 ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows
),
1343 ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows
| ImGuiHoveredFlags_RootWindow
),
1344 ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow
),
1345 ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow
));
1347 ImGui::BeginChild("child", ImVec2(0, 50), true);
1348 ImGui::Text("This is another child window for testing with the _ChildWindows flag.");
1350 if (embed_all_inside_a_child_window
)
1353 // Calling IsItemHovered() after begin returns the hovered status of the title bar.
1354 // This is useful in particular if you want to create a context menu (with BeginPopupContextItem) associated to the title bar of a window.
1355 static bool test_window
= false;
1356 ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window
);
1359 ImGui::Begin("Title bar Hovered/Active tests", &test_window
);
1360 if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
1362 if (ImGui::MenuItem("Close")) { test_window
= false; }
1366 "IsItemHovered() after begin = %d (== is title bar hovered)\n"
1367 "IsItemActive() after begin = %d (== is window being clicked/moved)\n",
1368 ImGui::IsItemHovered(), ImGui::IsItemActive());
1376 if (ImGui::CollapsingHeader("Layout"))
1378 if (ImGui::TreeNode("Child regions"))
1380 static bool disable_mouse_wheel
= false;
1381 static bool disable_menu
= false;
1382 ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel
);
1383 ImGui::Checkbox("Disable Menu", &disable_menu
);
1385 static int line
= 50;
1386 bool goto_line
= ImGui::Button("Goto");
1388 ImGui::PushItemWidth(100);
1389 goto_line
|= ImGui::InputInt("##Line", &line
, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue
);
1390 ImGui::PopItemWidth();
1392 // Child 1: no border, enable horizontal scrollbar
1394 ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f
, 300), false, ImGuiWindowFlags_HorizontalScrollbar
| (disable_mouse_wheel
? ImGuiWindowFlags_NoScrollWithMouse
: 0));
1395 for (int i
= 0; i
< 100; i
++)
1397 ImGui::Text("%04d: scrollable region", i
);
1398 if (goto_line
&& line
== i
)
1399 ImGui::SetScrollHere();
1401 if (goto_line
&& line
>= 100)
1402 ImGui::SetScrollHere();
1408 // Child 2: rounded border
1410 ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding
, 5.0f
);
1411 ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel
? ImGuiWindowFlags_NoScrollWithMouse
: 0) | (disable_menu
? 0 : ImGuiWindowFlags_MenuBar
));
1412 if (!disable_menu
&& ImGui::BeginMenuBar())
1414 if (ImGui::BeginMenu("Menu"))
1416 ShowExampleMenuFile();
1419 ImGui::EndMenuBar();
1422 for (int i
= 0; i
< 100; i
++)
1425 sprintf(buf
, "%03d", i
);
1426 ImGui::Button(buf
, ImVec2(-1.0f
, 0.0f
));
1427 ImGui::NextColumn();
1430 ImGui::PopStyleVar();
1436 if (ImGui::TreeNode("Widgets Width"))
1438 static float f
= 0.0f
;
1439 ImGui::Text("PushItemWidth(100)");
1440 ImGui::SameLine(); ShowHelpMarker("Fixed width.");
1441 ImGui::PushItemWidth(100);
1442 ImGui::DragFloat("float##1", &f
);
1443 ImGui::PopItemWidth();
1445 ImGui::Text("PushItemWidth(GetWindowWidth() * 0.5f)");
1446 ImGui::SameLine(); ShowHelpMarker("Half of window width.");
1447 ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f
);
1448 ImGui::DragFloat("float##2", &f
);
1449 ImGui::PopItemWidth();
1451 ImGui::Text("PushItemWidth(GetContentRegionAvailWidth() * 0.5f)");
1452 ImGui::SameLine(); ShowHelpMarker("Half of available width.\n(~ right-cursor_pos)\n(works within a column set)");
1453 ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() * 0.5f
);
1454 ImGui::DragFloat("float##3", &f
);
1455 ImGui::PopItemWidth();
1457 ImGui::Text("PushItemWidth(-100)");
1458 ImGui::SameLine(); ShowHelpMarker("Align to right edge minus 100");
1459 ImGui::PushItemWidth(-100);
1460 ImGui::DragFloat("float##4", &f
);
1461 ImGui::PopItemWidth();
1463 ImGui::Text("PushItemWidth(-1)");
1464 ImGui::SameLine(); ShowHelpMarker("Align to right edge");
1465 ImGui::PushItemWidth(-1);
1466 ImGui::DragFloat("float##5", &f
);
1467 ImGui::PopItemWidth();
1472 if (ImGui::TreeNode("Basic Horizontal Layout"))
1474 ImGui::TextWrapped("(Use ImGui::SameLine() to keep adding items to the right of the preceding item)");
1477 ImGui::Text("Two items: Hello"); ImGui::SameLine();
1478 ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1481 ImGui::Text("More spacing: Hello"); ImGui::SameLine(0, 20);
1482 ImGui::TextColored(ImVec4(1,1,0,1), "Sailor");
1485 ImGui::AlignTextToFramePadding();
1486 ImGui::Text("Normal buttons"); ImGui::SameLine();
1487 ImGui::Button("Banana"); ImGui::SameLine();
1488 ImGui::Button("Apple"); ImGui::SameLine();
1489 ImGui::Button("Corniflower");
1492 ImGui::Text("Small buttons"); ImGui::SameLine();
1493 ImGui::SmallButton("Like this one"); ImGui::SameLine();
1494 ImGui::Text("can fit within a text block.");
1496 // Aligned to arbitrary position. Easy/cheap column.
1497 ImGui::Text("Aligned");
1498 ImGui::SameLine(150); ImGui::Text("x=150");
1499 ImGui::SameLine(300); ImGui::Text("x=300");
1500 ImGui::Text("Aligned");
1501 ImGui::SameLine(150); ImGui::SmallButton("x=150");
1502 ImGui::SameLine(300); ImGui::SmallButton("x=300");
1505 static bool c1
=false,c2
=false,c3
=false,c4
=false;
1506 ImGui::Checkbox("My", &c1
); ImGui::SameLine();
1507 ImGui::Checkbox("Tailor", &c2
); ImGui::SameLine();
1508 ImGui::Checkbox("Is", &c3
); ImGui::SameLine();
1509 ImGui::Checkbox("Rich", &c4
);
1512 static float f0
=1.0f
, f1
=2.0f
, f2
=3.0f
;
1513 ImGui::PushItemWidth(80);
1514 const char* items
[] = { "AAAA", "BBBB", "CCCC", "DDDD" };
1515 static int item
= -1;
1516 ImGui::Combo("Combo", &item
, items
, IM_ARRAYSIZE(items
)); ImGui::SameLine();
1517 ImGui::SliderFloat("X", &f0
, 0.0f
,5.0f
); ImGui::SameLine();
1518 ImGui::SliderFloat("Y", &f1
, 0.0f
,5.0f
); ImGui::SameLine();
1519 ImGui::SliderFloat("Z", &f2
, 0.0f
,5.0f
);
1520 ImGui::PopItemWidth();
1522 ImGui::PushItemWidth(80);
1523 ImGui::Text("Lists:");
1524 static int selection
[4] = { 0, 1, 2, 3 };
1525 for (int i
= 0; i
< 4; i
++)
1527 if (i
> 0) ImGui::SameLine();
1529 ImGui::ListBox("", &selection
[i
], items
, IM_ARRAYSIZE(items
));
1531 //if (ImGui::IsItemHovered()) ImGui::SetTooltip("ListBox %d hovered", i);
1533 ImGui::PopItemWidth();
1537 ImGui::Button("A", sz
); ImGui::SameLine();
1538 ImGui::Dummy(sz
); ImGui::SameLine();
1539 ImGui::Button("B", sz
);
1544 if (ImGui::TreeNode("Groups"))
1546 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.)");
1547 ImGui::BeginGroup();
1549 ImGui::BeginGroup();
1550 ImGui::Button("AAA");
1552 ImGui::Button("BBB");
1554 ImGui::BeginGroup();
1555 ImGui::Button("CCC");
1556 ImGui::Button("DDD");
1559 ImGui::Button("EEE");
1561 if (ImGui::IsItemHovered())
1562 ImGui::SetTooltip("First group hovered");
1564 // Capture the group size and create widgets using the same size
1565 ImVec2 size
= ImGui::GetItemRectSize();
1566 const float values
[5] = { 0.5f
, 0.20f
, 0.80f
, 0.60f
, 0.25f
};
1567 ImGui::PlotHistogram("##values", values
, IM_ARRAYSIZE(values
), 0, NULL
, 0.0f
, 1.0f
, size
);
1569 ImGui::Button("ACTION", ImVec2((size
.x
- ImGui::GetStyle().ItemSpacing
.x
)*0.5f
,size
.y
));
1571 ImGui::Button("REACTION", ImVec2((size
.x
- ImGui::GetStyle().ItemSpacing
.x
)*0.5f
,size
.y
));
1575 ImGui::Button("LEVERAGE\nBUZZWORD", size
);
1578 if (ImGui::ListBoxHeader("List", size
))
1580 ImGui::Selectable("Selected", true);
1581 ImGui::Selectable("Not Selected", false);
1582 ImGui::ListBoxFooter();
1588 if (ImGui::TreeNode("Text Baseline Alignment"))
1590 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)");
1592 ImGui::Text("One\nTwo\nThree"); ImGui::SameLine();
1593 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1594 ImGui::Text("Banana");
1596 ImGui::Text("Banana"); ImGui::SameLine();
1597 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1598 ImGui::Text("One\nTwo\nThree");
1600 ImGui::Button("HOP##1"); ImGui::SameLine();
1601 ImGui::Text("Banana"); ImGui::SameLine();
1602 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1603 ImGui::Text("Banana");
1605 ImGui::Button("HOP##2"); ImGui::SameLine();
1606 ImGui::Text("Hello\nWorld"); ImGui::SameLine();
1607 ImGui::Text("Banana");
1609 ImGui::Button("TEST##1"); ImGui::SameLine();
1610 ImGui::Text("TEST"); ImGui::SameLine();
1611 ImGui::SmallButton("TEST##2");
1613 ImGui::AlignTextToFramePadding(); // If your line starts with text, call this to align it to upcoming widgets.
1614 ImGui::Text("Text aligned to Widget"); ImGui::SameLine();
1615 ImGui::Button("Widget##1"); ImGui::SameLine();
1616 ImGui::Text("Widget"); ImGui::SameLine();
1617 ImGui::SmallButton("Widget##2"); ImGui::SameLine();
1618 ImGui::Button("Widget##3");
1621 const float spacing
= ImGui::GetStyle().ItemInnerSpacing
.x
;
1622 ImGui::Button("Button##1");
1623 ImGui::SameLine(0.0f
, spacing
);
1624 if (ImGui::TreeNode("Node##1")) { for (int i
= 0; i
< 6; i
++) ImGui::BulletText("Item %d..", i
); ImGui::TreePop(); } // Dummy tree data
1626 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).
1627 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.
1628 ImGui::SameLine(0.0f
, spacing
); ImGui::Button("Button##2");
1629 if (node_open
) { for (int i
= 0; i
< 6; i
++) ImGui::BulletText("Item %d..", i
); ImGui::TreePop(); } // Dummy tree data
1632 ImGui::Button("Button##3");
1633 ImGui::SameLine(0.0f
, spacing
);
1634 ImGui::BulletText("Bullet text");
1636 ImGui::AlignTextToFramePadding();
1637 ImGui::BulletText("Node");
1638 ImGui::SameLine(0.0f
, spacing
); ImGui::Button("Button##4");
1643 if (ImGui::TreeNode("Scrolling"))
1645 ImGui::TextWrapped("(Use SetScrollHere() or SetScrollFromPosY() to scroll to a given position.)");
1646 static bool track
= true;
1647 static int track_line
= 50, scroll_to_px
= 200;
1648 ImGui::Checkbox("Track", &track
);
1649 ImGui::PushItemWidth(100);
1650 ImGui::SameLine(130); track
|= ImGui::DragInt("##line", &track_line
, 0.25f
, 0, 99, "Line = %d");
1651 bool scroll_to
= ImGui::Button("Scroll To Pos");
1652 ImGui::SameLine(130); scroll_to
|= ImGui::DragInt("##pos_y", &scroll_to_px
, 1.00f
, 0, 9999, "Y = %d px");
1653 ImGui::PopItemWidth();
1654 if (scroll_to
) track
= false;
1656 for (int i
= 0; i
< 5; i
++)
1658 if (i
> 0) ImGui::SameLine();
1659 ImGui::BeginGroup();
1660 ImGui::Text("%s", i
== 0 ? "Top" : i
== 1 ? "25%" : i
== 2 ? "Center" : i
== 3 ? "75%" : "Bottom");
1661 ImGui::BeginChild(ImGui::GetID((void*)(intptr_t)i
), ImVec2(ImGui::GetWindowWidth() * 0.17f
, 200.0f
), true);
1663 ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y
+ scroll_to_px
, i
* 0.25f
);
1664 for (int line
= 0; line
< 100; line
++)
1666 if (track
&& line
== track_line
)
1668 ImGui::TextColored(ImColor(255,255,0), "Line %d", line
);
1669 ImGui::SetScrollHere(i
* 0.25f
); // 0.0f:top, 0.5f:center, 1.0f:bottom
1673 ImGui::Text("Line %d", line
);
1676 float scroll_y
= ImGui::GetScrollY(), scroll_max_y
= ImGui::GetScrollMaxY();
1678 ImGui::Text("%.0f/%0.f", scroll_y
, scroll_max_y
);
1684 if (ImGui::TreeNode("Horizontal Scrolling"))
1686 ImGui::Bullet(); ImGui::TextWrapped("Horizontal scrolling for a window has to be enabled explicitly via the ImGuiWindowFlags_HorizontalScrollbar flag.");
1687 ImGui::Bullet(); ImGui::TextWrapped("You may want to explicitly specify content width by calling SetNextWindowContentWidth() before Begin().");
1688 static int lines
= 7;
1689 ImGui::SliderInt("Lines", &lines
, 1, 15);
1690 ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding
, 3.0f
);
1691 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding
, ImVec2(2.0f
, 1.0f
));
1692 ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar
);
1693 for (int line
= 0; line
< lines
; line
++)
1695 // 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
1696 // 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)
1697 int num_buttons
= 10 + ((line
& 1) ? line
* 9 : line
* 3);
1698 for (int n
= 0; n
< num_buttons
; n
++)
1700 if (n
> 0) ImGui::SameLine();
1701 ImGui::PushID(n
+ line
* 1000);
1703 sprintf(num_buf
, "%d", n
);
1704 const char* label
= (!(n
%15)) ? "FizzBuzz" : (!(n
%3)) ? "Fizz" : (!(n
%5)) ? "Buzz" : num_buf
;
1705 float hue
= n
*0.05f
;
1706 ImGui::PushStyleColor(ImGuiCol_Button
, (ImVec4
)ImColor::HSV(hue
, 0.6f
, 0.6f
));
1707 ImGui::PushStyleColor(ImGuiCol_ButtonHovered
, (ImVec4
)ImColor::HSV(hue
, 0.7f
, 0.7f
));
1708 ImGui::PushStyleColor(ImGuiCol_ButtonActive
, (ImVec4
)ImColor::HSV(hue
, 0.8f
, 0.8f
));
1709 ImGui::Button(label
, ImVec2(40.0f
+ sinf((float)(line
+ n
)) * 20.0f
, 0.0f
));
1710 ImGui::PopStyleColor(3);
1714 float scroll_x
= ImGui::GetScrollX(), scroll_max_x
= ImGui::GetScrollMaxX();
1716 ImGui::PopStyleVar(2);
1717 float scroll_x_delta
= 0.0f
;
1718 ImGui::SmallButton("<<"); if (ImGui::IsItemActive()) scroll_x_delta
= -ImGui::GetIO().DeltaTime
* 1000.0f
; ImGui::SameLine();
1719 ImGui::Text("Scroll from code"); ImGui::SameLine();
1720 ImGui::SmallButton(">>"); if (ImGui::IsItemActive()) scroll_x_delta
= +ImGui::GetIO().DeltaTime
* 1000.0f
; ImGui::SameLine();
1721 ImGui::Text("%.0f/%.0f", scroll_x
, scroll_max_x
);
1722 if (scroll_x_delta
!= 0.0f
)
1724 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)
1725 ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta
);
1731 if (ImGui::TreeNode("Clipping"))
1733 static ImVec2
size(100, 100), offset(50, 20);
1734 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.");
1735 ImGui::DragFloat2("size", (float*)&size
, 0.5f
, 0.0f
, 200.0f
, "%.0f");
1736 ImGui::TextWrapped("(Click and drag)");
1737 ImVec2 pos
= ImGui::GetCursorScreenPos();
1738 ImVec4
clip_rect(pos
.x
, pos
.y
, pos
.x
+size
.x
, pos
.y
+size
.y
);
1739 ImGui::InvisibleButton("##dummy", size
);
1740 if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset
.x
+= ImGui::GetIO().MouseDelta
.x
; offset
.y
+= ImGui::GetIO().MouseDelta
.y
; }
1741 ImGui::GetWindowDrawList()->AddRectFilled(pos
, ImVec2(pos
.x
+size
.x
,pos
.y
+size
.y
), IM_COL32(90,90,120,255));
1742 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
);
1747 if (ImGui::CollapsingHeader("Popups & Modal windows"))
1749 if (ImGui::TreeNode("Popups"))
1751 ImGui::TextWrapped("When a popup is active, it inhibits interacting with windows that are behind the popup. Clicking outside the popup closes it.");
1753 static int selected_fish
= -1;
1754 const char* names
[] = { "Bream", "Haddock", "Mackerel", "Pollock", "Tilefish" };
1755 static bool toggles
[] = { true, false, false, false, false };
1757 // Simple selection popup
1758 // (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)
1759 if (ImGui::Button("Select.."))
1760 ImGui::OpenPopup("select");
1762 ImGui::TextUnformatted(selected_fish
== -1 ? "<None>" : names
[selected_fish
]);
1763 if (ImGui::BeginPopup("select"))
1765 ImGui::Text("Aquarium");
1767 for (int i
= 0; i
< IM_ARRAYSIZE(names
); i
++)
1768 if (ImGui::Selectable(names
[i
]))
1773 // Showing a menu with toggles
1774 if (ImGui::Button("Toggle.."))
1775 ImGui::OpenPopup("toggle");
1776 if (ImGui::BeginPopup("toggle"))
1778 for (int i
= 0; i
< IM_ARRAYSIZE(names
); i
++)
1779 ImGui::MenuItem(names
[i
], "", &toggles
[i
]);
1780 if (ImGui::BeginMenu("Sub-menu"))
1782 ImGui::MenuItem("Click me");
1787 ImGui::Text("Tooltip here");
1788 if (ImGui::IsItemHovered())
1789 ImGui::SetTooltip("I am a tooltip over a popup");
1791 if (ImGui::Button("Stacked Popup"))
1792 ImGui::OpenPopup("another popup");
1793 if (ImGui::BeginPopup("another popup"))
1795 for (int i
= 0; i
< IM_ARRAYSIZE(names
); i
++)
1796 ImGui::MenuItem(names
[i
], "", &toggles
[i
]);
1797 if (ImGui::BeginMenu("Sub-menu"))
1799 ImGui::MenuItem("Click me");
1807 if (ImGui::Button("Popup Menu.."))
1808 ImGui::OpenPopup("FilePopup");
1809 if (ImGui::BeginPopup("FilePopup"))
1811 ShowExampleMenuFile();
1818 if (ImGui::TreeNode("Context menus"))
1820 // BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
1821 // if (IsItemHovered() && IsMouseClicked(0))
1823 // return BeginPopup(id);
1824 // For more advanced uses you may want to replicate and cuztomize this code. This the comments inside BeginPopupContextItem() implementation.
1825 static float value
= 0.5f
;
1826 ImGui::Text("Value = %.3f (<-- right-click here)", value
);
1827 if (ImGui::BeginPopupContextItem("item context menu"))
1829 if (ImGui::Selectable("Set to zero")) value
= 0.0f
;
1830 if (ImGui::Selectable("Set to PI")) value
= 3.1415f
;
1831 ImGui::PushItemWidth(-1);
1832 ImGui::DragFloat("##Value", &value
, 0.1f
, 0.0f
, 0.0f
);
1833 ImGui::PopItemWidth();
1837 static char name
[32] = "Label1";
1838 char buf
[64]; sprintf(buf
, "Button: %s###Button", name
); // ### operator override ID ignoring the preceding label
1840 if (ImGui::BeginPopupContextItem()) // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
1842 ImGui::Text("Edit name:");
1843 ImGui::InputText("##edit", name
, IM_ARRAYSIZE(name
));
1844 if (ImGui::Button("Close"))
1845 ImGui::CloseCurrentPopup();
1848 ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
1853 if (ImGui::TreeNode("Modals"))
1855 ImGui::TextWrapped("Modal windows are like popups but the user cannot close them by clicking outside the window.");
1857 if (ImGui::Button("Delete.."))
1858 ImGui::OpenPopup("Delete?");
1859 if (ImGui::BeginPopupModal("Delete?", NULL
, ImGuiWindowFlags_AlwaysAutoResize
))
1861 ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n");
1864 //static int dummy_i = 0;
1865 //ImGui::Combo("Combo", &dummy_i, "Delete\0Delete harder\0");
1867 static bool dont_ask_me_next_time
= false;
1868 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding
, ImVec2(0,0));
1869 ImGui::Checkbox("Don't ask me next time", &dont_ask_me_next_time
);
1870 ImGui::PopStyleVar();
1872 if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
1873 ImGui::SetItemDefaultFocus();
1875 if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); }
1879 if (ImGui::Button("Stacked modals.."))
1880 ImGui::OpenPopup("Stacked 1");
1881 if (ImGui::BeginPopupModal("Stacked 1"))
1883 ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDimBg] behind it.");
1884 static int item
= 1;
1885 ImGui::Combo("Combo", &item
, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0");
1886 static float color
[4] = { 0.4f
,0.7f
,0.0f
,0.5f
};
1887 ImGui::ColorEdit4("color", color
); // This is to test behavior of stacked regular popups over a modal
1889 if (ImGui::Button("Add another modal.."))
1890 ImGui::OpenPopup("Stacked 2");
1891 if (ImGui::BeginPopupModal("Stacked 2"))
1893 ImGui::Text("Hello from Stacked The Second!");
1894 if (ImGui::Button("Close"))
1895 ImGui::CloseCurrentPopup();
1899 if (ImGui::Button("Close"))
1900 ImGui::CloseCurrentPopup();
1907 if (ImGui::TreeNode("Menus inside a regular window"))
1909 ImGui::TextWrapped("Below we are testing adding menu items to a regular window. It's rather unusual but should work!");
1911 // 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.
1912 // 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
1913 // 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.
1914 ImGui::PushID("foo");
1915 ImGui::MenuItem("Menu item", "CTRL+M");
1916 if (ImGui::BeginMenu("Menu inside a regular window"))
1918 ShowExampleMenuFile();
1927 if (ImGui::CollapsingHeader("Columns"))
1929 ImGui::PushID("Columns");
1932 if (ImGui::TreeNode("Basic"))
1934 ImGui::Text("Without border:");
1935 ImGui::Columns(3, "mycolumns3", false); // 3-ways, no border
1937 for (int n
= 0; n
< 14; n
++)
1940 sprintf(label
, "Item %d", n
);
1941 if (ImGui::Selectable(label
)) {}
1942 //if (ImGui::Button(label, ImVec2(-1,0))) {}
1943 ImGui::NextColumn();
1948 ImGui::Text("With border:");
1949 ImGui::Columns(4, "mycolumns"); // 4-ways, with border
1951 ImGui::Text("ID"); ImGui::NextColumn();
1952 ImGui::Text("Name"); ImGui::NextColumn();
1953 ImGui::Text("Path"); ImGui::NextColumn();
1954 ImGui::Text("Hovered"); ImGui::NextColumn();
1956 const char* names
[3] = { "One", "Two", "Three" };
1957 const char* paths
[3] = { "/path/one", "/path/two", "/path/three" };
1958 static int selected
= -1;
1959 for (int i
= 0; i
< 3; i
++)
1962 sprintf(label
, "%04d", i
);
1963 if (ImGui::Selectable(label
, selected
== i
, ImGuiSelectableFlags_SpanAllColumns
))
1965 bool hovered
= ImGui::IsItemHovered();
1966 ImGui::NextColumn();
1967 ImGui::Text(names
[i
]); ImGui::NextColumn();
1968 ImGui::Text(paths
[i
]); ImGui::NextColumn();
1969 ImGui::Text("%d", hovered
); ImGui::NextColumn();
1976 // Create multiple items in a same cell before switching to next column
1977 if (ImGui::TreeNode("Mixed items"))
1979 ImGui::Columns(3, "mixed");
1982 ImGui::Text("Hello");
1983 ImGui::Button("Banana");
1984 ImGui::NextColumn();
1986 ImGui::Text("ImGui");
1987 ImGui::Button("Apple");
1988 static float foo
= 1.0f
;
1989 ImGui::InputFloat("red", &foo
, 0.05f
, 0, "%.3f");
1990 ImGui::Text("An extra line here.");
1991 ImGui::NextColumn();
1993 ImGui::Text("Sailor");
1994 ImGui::Button("Corniflower");
1995 static float bar
= 1.0f
;
1996 ImGui::InputFloat("blue", &bar
, 0.05f
, 0, "%.3f");
1997 ImGui::NextColumn();
1999 if (ImGui::CollapsingHeader("Category A")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2000 if (ImGui::CollapsingHeader("Category B")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2001 if (ImGui::CollapsingHeader("Category C")) { ImGui::Text("Blah blah blah"); } ImGui::NextColumn();
2008 if (ImGui::TreeNode("Word-wrapping"))
2010 ImGui::Columns(2, "word-wrapping");
2012 ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2013 ImGui::TextWrapped("Hello Left");
2014 ImGui::NextColumn();
2015 ImGui::TextWrapped("The quick brown fox jumps over the lazy dog.");
2016 ImGui::TextWrapped("Hello Right");
2022 if (ImGui::TreeNode("Borders"))
2024 // NB: Future columns API should allow automatic horizontal borders.
2025 static bool h_borders
= true;
2026 static bool v_borders
= true;
2027 ImGui::Checkbox("horizontal", &h_borders
);
2029 ImGui::Checkbox("vertical", &v_borders
);
2030 ImGui::Columns(4, NULL
, v_borders
);
2031 for (int i
= 0; i
< 4*3; i
++)
2033 if (h_borders
&& ImGui::GetColumnIndex() == 0)
2035 ImGui::Text("%c%c%c", 'a'+i
, 'a'+i
, 'a'+i
);
2036 ImGui::Text("Width %.2f\nOffset %.2f", ImGui::GetColumnWidth(), ImGui::GetColumnOffset());
2037 ImGui::NextColumn();
2045 // Scrolling columns
2047 if (ImGui::TreeNode("Vertical Scrolling"))
2049 ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
2051 ImGui::Text("ID"); ImGui::NextColumn();
2052 ImGui::Text("Name"); ImGui::NextColumn();
2053 ImGui::Text("Path"); ImGui::NextColumn();
2057 ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
2059 for (int i = 0; i < 10; i++)
2061 ImGui::Text("%04d", i); ImGui::NextColumn();
2062 ImGui::Text("Foobar"); ImGui::NextColumn();
2063 ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
2071 if (ImGui::TreeNode("Horizontal Scrolling"))
2073 ImGui::SetNextWindowContentSize(ImVec2(1500.0f
, 0.0f
));
2074 ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar
);
2076 int ITEMS_COUNT
= 2000;
2077 ImGuiListClipper
clipper(ITEMS_COUNT
); // Also demonstrate using the clipper for large list
2078 while (clipper
.Step())
2080 for (int i
= clipper
.DisplayStart
; i
< clipper
.DisplayEnd
; i
++)
2081 for (int j
= 0; j
< 10; j
++)
2083 ImGui::Text("Line %d Column %d...", i
, j
);
2084 ImGui::NextColumn();
2092 bool node_open
= ImGui::TreeNode("Tree within single cell");
2093 ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell.");
2096 ImGui::Columns(2, "tree items");
2098 if (ImGui::TreeNode("Hello")) { ImGui::BulletText("Sailor"); ImGui::TreePop(); } ImGui::NextColumn();
2099 if (ImGui::TreeNode("Bonjour")) { ImGui::BulletText("Marin"); ImGui::TreePop(); } ImGui::NextColumn();
2107 if (ImGui::CollapsingHeader("Filtering"))
2109 static ImGuiTextFilter filter
;
2110 ImGui::Text("Filter usage:\n"
2111 " \"\" display all lines\n"
2112 " \"xxx\" display lines containing \"xxx\"\n"
2113 " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n"
2114 " \"-xxx\" hide lines containing \"xxx\"");
2116 const char* lines
[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
2117 for (int i
= 0; i
< IM_ARRAYSIZE(lines
); i
++)
2118 if (filter
.PassFilter(lines
[i
]))
2119 ImGui::BulletText("%s", lines
[i
]);
2122 if (ImGui::CollapsingHeader("Inputs, Navigation & Focus"))
2124 ImGuiIO
& io
= ImGui::GetIO();
2126 ImGui::Text("WantCaptureMouse: %d", io
.WantCaptureMouse
);
2127 ImGui::Text("WantCaptureKeyboard: %d", io
.WantCaptureKeyboard
);
2128 ImGui::Text("WantTextInput: %d", io
.WantTextInput
);
2129 ImGui::Text("WantSetMousePos: %d", io
.WantSetMousePos
);
2130 ImGui::Text("NavActive: %d, NavVisible: %d", io
.NavActive
, io
.NavVisible
);
2132 ImGui::Checkbox("io.MouseDrawCursor", &io
.MouseDrawCursor
);
2133 ImGui::SameLine(); ShowHelpMarker("Instruct ImGui to render a mouse cursor for you in software. 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).");
2135 ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad [beta]", (unsigned int *)&io
.ConfigFlags
, ImGuiConfigFlags_NavEnableGamepad
);
2136 ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard [beta]", (unsigned int *)&io
.ConfigFlags
, ImGuiConfigFlags_NavEnableKeyboard
);
2137 ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io
.ConfigFlags
, ImGuiConfigFlags_NavEnableSetMousePos
);
2138 ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos.");
2139 ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io
.ConfigFlags
, ImGuiConfigFlags_NoMouseCursorChange
);
2140 ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility.");
2142 if (ImGui::TreeNode("Keyboard, Mouse & Navigation State"))
2144 if (ImGui::IsMousePosValid())
2145 ImGui::Text("Mouse pos: (%g, %g)", io
.MousePos
.x
, io
.MousePos
.y
);
2147 ImGui::Text("Mouse pos: <INVALID>");
2148 ImGui::Text("Mouse delta: (%g, %g)", io
.MouseDelta
.x
, io
.MouseDelta
.y
);
2149 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
]); }
2150 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
); }
2151 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
); }
2152 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
); }
2153 ImGui::Text("Mouse wheel: %.1f", io
.MouseWheel
);
2155 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
]); }
2156 ImGui::Text("Keys pressed:"); for (int i
= 0; i
< IM_ARRAYSIZE(io
.KeysDown
); i
++) if (ImGui::IsKeyPressed(i
)) { ImGui::SameLine(); ImGui::Text("%d", i
); }
2157 ImGui::Text("Keys release:"); for (int i
= 0; i
< IM_ARRAYSIZE(io
.KeysDown
); i
++) if (ImGui::IsKeyReleased(i
)) { ImGui::SameLine(); ImGui::Text("%d", i
); }
2158 ImGui::Text("Keys mods: %s%s%s%s", io
.KeyCtrl
? "CTRL " : "", io
.KeyShift
? "SHIFT " : "", io
.KeyAlt
? "ALT " : "", io
.KeySuper
? "SUPER " : "");
2160 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
]); }
2161 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
); }
2162 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
]); }
2164 ImGui::Button("Hovering me sets the\nkeyboard capture flag");
2165 if (ImGui::IsItemHovered())
2166 ImGui::CaptureKeyboardFromApp(true);
2168 ImGui::Button("Holding me clears the\nthe keyboard capture flag");
2169 if (ImGui::IsItemActive())
2170 ImGui::CaptureKeyboardFromApp(false);
2175 if (ImGui::TreeNode("Tabbing"))
2177 ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields.");
2178 static char buf
[32] = "dummy";
2179 ImGui::InputText("1", buf
, IM_ARRAYSIZE(buf
));
2180 ImGui::InputText("2", buf
, IM_ARRAYSIZE(buf
));
2181 ImGui::InputText("3", buf
, IM_ARRAYSIZE(buf
));
2182 ImGui::PushAllowKeyboardFocus(false);
2183 ImGui::InputText("4 (tab skip)", buf
, IM_ARRAYSIZE(buf
));
2184 //ImGui::SameLine(); ShowHelperMarker("Use ImGui::PushAllowKeyboardFocus(bool)\nto disable tabbing through certain widgets.");
2185 ImGui::PopAllowKeyboardFocus();
2186 ImGui::InputText("5", buf
, IM_ARRAYSIZE(buf
));
2190 if (ImGui::TreeNode("Focus from code"))
2192 bool focus_1
= ImGui::Button("Focus on 1"); ImGui::SameLine();
2193 bool focus_2
= ImGui::Button("Focus on 2"); ImGui::SameLine();
2194 bool focus_3
= ImGui::Button("Focus on 3");
2196 static char buf
[128] = "click on a button to set focus";
2198 if (focus_1
) ImGui::SetKeyboardFocusHere();
2199 ImGui::InputText("1", buf
, IM_ARRAYSIZE(buf
));
2200 if (ImGui::IsItemActive()) has_focus
= 1;
2202 if (focus_2
) ImGui::SetKeyboardFocusHere();
2203 ImGui::InputText("2", buf
, IM_ARRAYSIZE(buf
));
2204 if (ImGui::IsItemActive()) has_focus
= 2;
2206 ImGui::PushAllowKeyboardFocus(false);
2207 if (focus_3
) ImGui::SetKeyboardFocusHere();
2208 ImGui::InputText("3 (tab skip)", buf
, IM_ARRAYSIZE(buf
));
2209 if (ImGui::IsItemActive()) has_focus
= 3;
2210 ImGui::PopAllowKeyboardFocus();
2213 ImGui::Text("Item with focus: %d", has_focus
);
2215 ImGui::Text("Item with focus: <none>");
2217 // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item
2218 static float f3
[3] = { 0.0f
, 0.0f
, 0.0f
};
2219 int focus_ahead
= -1;
2220 if (ImGui::Button("Focus on X")) focus_ahead
= 0; ImGui::SameLine();
2221 if (ImGui::Button("Focus on Y")) focus_ahead
= 1; ImGui::SameLine();
2222 if (ImGui::Button("Focus on Z")) focus_ahead
= 2;
2223 if (focus_ahead
!= -1) ImGui::SetKeyboardFocusHere(focus_ahead
);
2224 ImGui::SliderFloat3("Float3", &f3
[0], 0.0f
, 1.0f
);
2226 ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code.");
2230 if (ImGui::TreeNode("Dragging"))
2232 ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget.");
2233 for (int button
= 0; button
< 3; button
++)
2234 ImGui::Text("IsMouseDragging(%d):\n w/ default threshold: %d,\n w/ zero threshold: %d\n w/ large threshold: %d",
2235 button
, ImGui::IsMouseDragging(button
), ImGui::IsMouseDragging(button
, 0.0f
), ImGui::IsMouseDragging(button
, 20.0f
));
2236 ImGui::Button("Drag Me");
2237 if (ImGui::IsItemActive())
2239 // Draw a line between the button and the mouse cursor
2240 ImDrawList
* draw_list
= ImGui::GetWindowDrawList();
2241 draw_list
->PushClipRectFullScreen();
2242 draw_list
->AddLine(io
.MouseClickedPos
[0], io
.MousePos
, ImGui::GetColorU32(ImGuiCol_Button
), 4.0f
);
2243 draw_list
->PopClipRect();
2245 // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold)
2246 // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta()
2247 ImVec2 value_raw
= ImGui::GetMouseDragDelta(0, 0.0f
);
2248 ImVec2 value_with_lock_threshold
= ImGui::GetMouseDragDelta(0);
2249 ImVec2 mouse_delta
= io
.MouseDelta
;
2250 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
);
2255 if (ImGui::TreeNode("Mouse cursors"))
2257 const char* mouse_cursors_names
[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE", "Hand" };
2258 IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names
) == ImGuiMouseCursor_COUNT
);
2260 ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names
[ImGui::GetMouseCursor()]);
2261 ImGui::Text("Hover to see mouse cursors:");
2262 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.");
2263 for (int i
= 0; i
< ImGuiMouseCursor_COUNT
; i
++)
2266 sprintf(label
, "Mouse cursor %d: %s", i
, mouse_cursors_names
[i
]);
2267 ImGui::Bullet(); ImGui::Selectable(label
, false);
2268 if (ImGui::IsItemHovered() || ImGui::IsItemFocused())
2269 ImGui::SetMouseCursor(i
);
2275 // End of ShowDemoWindow()
2279 // Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options.
2280 // 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.
2281 bool ImGui::ShowStyleSelector(const char* label
)
2283 static int style_idx
= -1;
2284 if (ImGui::Combo(label
, &style_idx
, "Classic\0Dark\0Light\0"))
2288 case 0: ImGui::StyleColorsClassic(); break;
2289 case 1: ImGui::StyleColorsDark(); break;
2290 case 2: ImGui::StyleColorsLight(); break;
2297 // Demo helper function to select among loaded fonts.
2298 // Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
2299 void ImGui::ShowFontSelector(const char* label
)
2301 ImGuiIO
& io
= ImGui::GetIO();
2302 ImFont
* font_current
= ImGui::GetFont();
2303 if (ImGui::BeginCombo(label
, font_current
->GetDebugName()))
2305 for (int n
= 0; n
< io
.Fonts
->Fonts
.Size
; n
++)
2306 if (ImGui::Selectable(io
.Fonts
->Fonts
[n
]->GetDebugName(), io
.Fonts
->Fonts
[n
] == font_current
))
2307 io
.FontDefault
= io
.Fonts
->Fonts
[n
];
2312 "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n"
2313 "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
2314 "- Read FAQ and documentation in misc/fonts/ for more details.\n"
2315 "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
2318 void ImGui::ShowStyleEditor(ImGuiStyle
* ref
)
2320 // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference)
2321 ImGuiStyle
& style
= ImGui::GetStyle();
2322 static ImGuiStyle ref_saved_style
;
2324 // Default to using internal storage as reference
2325 static bool init
= true;
2326 if (init
&& ref
== NULL
)
2327 ref_saved_style
= style
;
2330 ref
= &ref_saved_style
;
2332 ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f
);
2334 if (ImGui::ShowStyleSelector("Colors##Selector"))
2335 ref_saved_style
= style
;
2336 ImGui::ShowFontSelector("Fonts##Selector");
2338 // Simplified Settings
2339 if (ImGui::SliderFloat("FrameRounding", &style
.FrameRounding
, 0.0f
, 12.0f
, "%.0f"))
2340 style
.GrabRounding
= style
.FrameRounding
; // Make GrabRounding always the same value as FrameRounding
2341 { bool window_border
= (style
.WindowBorderSize
> 0.0f
); if (ImGui::Checkbox("WindowBorder", &window_border
)) style
.WindowBorderSize
= window_border
? 1.0f
: 0.0f
; }
2343 { bool frame_border
= (style
.FrameBorderSize
> 0.0f
); if (ImGui::Checkbox("FrameBorder", &frame_border
)) style
.FrameBorderSize
= frame_border
? 1.0f
: 0.0f
; }
2345 { bool popup_border
= (style
.PopupBorderSize
> 0.0f
); if (ImGui::Checkbox("PopupBorder", &popup_border
)) style
.PopupBorderSize
= popup_border
? 1.0f
: 0.0f
; }
2347 // Save/Revert button
2348 if (ImGui::Button("Save Ref"))
2349 *ref
= ref_saved_style
= style
;
2351 if (ImGui::Button("Revert Ref"))
2354 ShowHelpMarker("Save/Revert in local non-persistent storage. Default Colors definition are not affected. Use \"Export Colors\" below to save them somewhere.");
2356 if (ImGui::TreeNode("Rendering"))
2358 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.");
2359 ImGui::Checkbox("Anti-aliased fill", &style
.AntiAliasedFill
);
2360 ImGui::PushItemWidth(100);
2361 ImGui::DragFloat("Curve Tessellation Tolerance", &style
.CurveTessellationTol
, 0.02f
, 0.10f
, FLT_MAX
, NULL
, 2.0f
);
2362 if (style
.CurveTessellationTol
< 0.0f
) style
.CurveTessellationTol
= 0.10f
;
2363 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.
2364 ImGui::PopItemWidth();
2368 if (ImGui::TreeNode("Settings"))
2370 ImGui::SliderFloat2("WindowPadding", (float*)&style
.WindowPadding
, 0.0f
, 20.0f
, "%.0f");
2371 ImGui::SliderFloat("PopupRounding", &style
.PopupRounding
, 0.0f
, 16.0f
, "%.0f");
2372 ImGui::SliderFloat2("FramePadding", (float*)&style
.FramePadding
, 0.0f
, 20.0f
, "%.0f");
2373 ImGui::SliderFloat2("ItemSpacing", (float*)&style
.ItemSpacing
, 0.0f
, 20.0f
, "%.0f");
2374 ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style
.ItemInnerSpacing
, 0.0f
, 20.0f
, "%.0f");
2375 ImGui::SliderFloat2("TouchExtraPadding", (float*)&style
.TouchExtraPadding
, 0.0f
, 10.0f
, "%.0f");
2376 ImGui::SliderFloat("IndentSpacing", &style
.IndentSpacing
, 0.0f
, 30.0f
, "%.0f");
2377 ImGui::SliderFloat("ScrollbarSize", &style
.ScrollbarSize
, 1.0f
, 20.0f
, "%.0f");
2378 ImGui::SliderFloat("GrabMinSize", &style
.GrabMinSize
, 1.0f
, 20.0f
, "%.0f");
2379 ImGui::Text("BorderSize");
2380 ImGui::SliderFloat("WindowBorderSize", &style
.WindowBorderSize
, 0.0f
, 1.0f
, "%.0f");
2381 ImGui::SliderFloat("ChildBorderSize", &style
.ChildBorderSize
, 0.0f
, 1.0f
, "%.0f");
2382 ImGui::SliderFloat("PopupBorderSize", &style
.PopupBorderSize
, 0.0f
, 1.0f
, "%.0f");
2383 ImGui::SliderFloat("FrameBorderSize", &style
.FrameBorderSize
, 0.0f
, 1.0f
, "%.0f");
2384 ImGui::Text("Rounding");
2385 ImGui::SliderFloat("WindowRounding", &style
.WindowRounding
, 0.0f
, 14.0f
, "%.0f");
2386 ImGui::SliderFloat("ChildRounding", &style
.ChildRounding
, 0.0f
, 16.0f
, "%.0f");
2387 ImGui::SliderFloat("FrameRounding", &style
.FrameRounding
, 0.0f
, 12.0f
, "%.0f");
2388 ImGui::SliderFloat("ScrollbarRounding", &style
.ScrollbarRounding
, 0.0f
, 12.0f
, "%.0f");
2389 ImGui::SliderFloat("GrabRounding", &style
.GrabRounding
, 0.0f
, 12.0f
, "%.0f");
2390 ImGui::Text("Alignment");
2391 ImGui::SliderFloat2("WindowTitleAlign", (float*)&style
.WindowTitleAlign
, 0.0f
, 1.0f
, "%.2f");
2392 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.");
2393 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).");
2394 ImGui::SliderFloat2("DisplaySafeAreaPadding", (float*)&style
.DisplaySafeAreaPadding
, 0.0f
, 30.0f
, "%.0f");
2398 if (ImGui::TreeNode("Colors"))
2400 static int output_dest
= 0;
2401 static bool output_only_modified
= true;
2402 if (ImGui::Button("Export Unsaved"))
2404 if (output_dest
== 0)
2405 ImGui::LogToClipboard();
2408 ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE
);
2409 for (int i
= 0; i
< ImGuiCol_COUNT
; i
++)
2411 const ImVec4
& col
= style
.Colors
[i
];
2412 const char* name
= ImGui::GetStyleColorName(i
);
2413 if (!output_only_modified
|| memcmp(&col
, &ref
->Colors
[i
], sizeof(ImVec4
)) != 0)
2414 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
);
2418 ImGui::SameLine(); ImGui::PushItemWidth(120); ImGui::Combo("##output_type", &output_dest
, "To Clipboard\0To TTY\0"); ImGui::PopItemWidth();
2419 ImGui::SameLine(); ImGui::Checkbox("Only Modified Colors", &output_only_modified
);
2421 ImGui::Text("Tip: Left-click on colored square to open color picker,\nRight-click to open edit options menu.");
2423 static ImGuiTextFilter filter
;
2424 filter
.Draw("Filter colors", 200);
2426 static ImGuiColorEditFlags alpha_flags
= 0;
2427 ImGui::RadioButton("Opaque", &alpha_flags
, 0); ImGui::SameLine();
2428 ImGui::RadioButton("Alpha", &alpha_flags
, ImGuiColorEditFlags_AlphaPreview
); ImGui::SameLine();
2429 ImGui::RadioButton("Both", &alpha_flags
, ImGuiColorEditFlags_AlphaPreviewHalf
);
2431 ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar
| ImGuiWindowFlags_AlwaysHorizontalScrollbar
| ImGuiWindowFlags_NavFlattened
);
2432 ImGui::PushItemWidth(-160);
2433 for (int i
= 0; i
< ImGuiCol_COUNT
; i
++)
2435 const char* name
= ImGui::GetStyleColorName(i
);
2436 if (!filter
.PassFilter(name
))
2439 ImGui::ColorEdit4("##color", (float*)&style
.Colors
[i
], ImGuiColorEditFlags_AlphaBar
| alpha_flags
);
2440 if (memcmp(&style
.Colors
[i
], &ref
->Colors
[i
], sizeof(ImVec4
)) != 0)
2442 // 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.
2443 // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient!
2444 ImGui::SameLine(0.0f
, style
.ItemInnerSpacing
.x
); if (ImGui::Button("Save")) ref
->Colors
[i
] = style
.Colors
[i
];
2445 ImGui::SameLine(0.0f
, style
.ItemInnerSpacing
.x
); if (ImGui::Button("Revert")) style
.Colors
[i
] = ref
->Colors
[i
];
2447 ImGui::SameLine(0.0f
, style
.ItemInnerSpacing
.x
);
2448 ImGui::TextUnformatted(name
);
2451 ImGui::PopItemWidth();
2457 bool fonts_opened
= ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts
->Fonts
.Size
);
2460 ImFontAtlas
* atlas
= ImGui::GetIO().Fonts
;
2461 if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas
->TexWidth
, atlas
->TexHeight
))
2463 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));
2466 ImGui::PushItemWidth(100);
2467 for (int i
= 0; i
< atlas
->Fonts
.Size
; i
++)
2469 ImFont
* font
= atlas
->Fonts
[i
];
2470 ImGui::PushID(font
);
2471 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
);
2472 ImGui::SameLine(); if (ImGui::SmallButton("Set as default")) ImGui::GetIO().FontDefault
= font
;
2473 if (font_details_opened
)
2475 ImGui::PushFont(font
);
2476 ImGui::Text("The quick brown fox jumps over the lazy dog");
2478 ImGui::DragFloat("Font scale", &font
->Scale
, 0.005f
, 0.3f
, 2.0f
, "%.1f"); // Scale only this font
2479 ImGui::InputFloat("Font offset", &font
->DisplayOffset
.y
, 1, 1, 0);
2480 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.)");
2481 ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font
->Ascent
, font
->Descent
, font
->Ascent
- font
->Descent
);
2482 ImGui::Text("Fallback character: '%c' (%d)", font
->FallbackChar
, font
->FallbackChar
);
2483 ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font
->MetricsTotalSurface
, (int)sqrtf((float)font
->MetricsTotalSurface
), (int)sqrtf((float)font
->MetricsTotalSurface
));
2484 for (int config_i
= 0; config_i
< font
->ConfigDataCount
; config_i
++)
2485 if (ImFontConfig
* cfg
= &font
->ConfigData
[config_i
])
2486 ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i
, cfg
->Name
, cfg
->OversampleH
, cfg
->OversampleV
, cfg
->PixelSnapH
);
2487 if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font
->Glyphs
.Size
))
2489 // Display all glyphs of the fonts in separate pages of 256 characters
2490 for (int base
= 0; base
< 0x10000; base
+= 256)
2493 for (int n
= 0; n
< 256; n
++)
2494 count
+= font
->FindGlyphNoFallback((ImWchar
)(base
+ n
)) ? 1 : 0;
2495 if (count
> 0 && ImGui::TreeNode((void*)(intptr_t)base
, "U+%04X..U+%04X (%d %s)", base
, base
+255, count
, count
> 1 ? "glyphs" : "glyph"))
2497 float cell_size
= font
->FontSize
* 1;
2498 float cell_spacing
= style
.ItemSpacing
.y
;
2499 ImVec2 base_pos
= ImGui::GetCursorScreenPos();
2500 ImDrawList
* draw_list
= ImGui::GetWindowDrawList();
2501 for (int n
= 0; n
< 256; n
++)
2503 ImVec2
cell_p1(base_pos
.x
+ (n
% 16) * (cell_size
+ cell_spacing
), base_pos
.y
+ (n
/ 16) * (cell_size
+ cell_spacing
));
2504 ImVec2
cell_p2(cell_p1
.x
+ cell_size
, cell_p1
.y
+ cell_size
);
2505 const ImFontGlyph
* glyph
= font
->FindGlyphNoFallback((ImWchar
)(base
+n
));
2506 draw_list
->AddRect(cell_p1
, cell_p2
, glyph
? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50));
2508 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.
2509 if (glyph
&& ImGui::IsMouseHoveringRect(cell_p1
, cell_p2
))
2511 ImGui::BeginTooltip();
2512 ImGui::Text("Codepoint: U+%04X", base
+n
);
2514 ImGui::Text("AdvanceX: %.1f", glyph
->AdvanceX
);
2515 ImGui::Text("Pos: (%.2f,%.2f)->(%.2f,%.2f)", glyph
->X0
, glyph
->Y0
, glyph
->X1
, glyph
->Y1
);
2516 ImGui::Text("UV: (%.3f,%.3f)->(%.3f,%.3f)", glyph
->U0
, glyph
->V0
, glyph
->U1
, glyph
->V1
);
2517 ImGui::EndTooltip();
2520 ImGui::Dummy(ImVec2((cell_size
+ cell_spacing
) * 16, (cell_size
+ cell_spacing
) * 16));
2530 static float window_scale
= 1.0f
;
2531 ImGui::DragFloat("this window scale", &window_scale
, 0.005f
, 0.3f
, 2.0f
, "%.1f"); // scale only this window
2532 ImGui::DragFloat("global scale", &ImGui::GetIO().FontGlobalScale
, 0.005f
, 0.3f
, 2.0f
, "%.1f"); // scale everything
2533 ImGui::PopItemWidth();
2534 ImGui::SetWindowFontScale(window_scale
);
2538 ImGui::PopItemWidth();
2541 //-----------------------------------------------------------------------------
2542 // EXAMPLE APP CODE: MAIN MENU BAR
2543 //-----------------------------------------------------------------------------
2545 // Demonstrate creating a fullscreen menu bar and populating it.
2546 static void ShowExampleAppMainMenuBar()
2548 if (ImGui::BeginMainMenuBar())
2550 if (ImGui::BeginMenu("File"))
2552 ShowExampleMenuFile();
2555 if (ImGui::BeginMenu("Edit"))
2557 if (ImGui::MenuItem("Undo", "CTRL+Z")) {}
2558 if (ImGui::MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item
2560 if (ImGui::MenuItem("Cut", "CTRL+X")) {}
2561 if (ImGui::MenuItem("Copy", "CTRL+C")) {}
2562 if (ImGui::MenuItem("Paste", "CTRL+V")) {}
2565 ImGui::EndMainMenuBar();
2569 static void ShowExampleMenuFile()
2571 ImGui::MenuItem("(dummy menu)", NULL
, false, false);
2572 if (ImGui::MenuItem("New")) {}
2573 if (ImGui::MenuItem("Open", "Ctrl+O")) {}
2574 if (ImGui::BeginMenu("Open Recent"))
2576 ImGui::MenuItem("fish_hat.c");
2577 ImGui::MenuItem("fish_hat.inl");
2578 ImGui::MenuItem("fish_hat.h");
2579 if (ImGui::BeginMenu("More.."))
2581 ImGui::MenuItem("Hello");
2582 ImGui::MenuItem("Sailor");
2583 if (ImGui::BeginMenu("Recurse.."))
2585 ShowExampleMenuFile();
2592 if (ImGui::MenuItem("Save", "Ctrl+S")) {}
2593 if (ImGui::MenuItem("Save As..")) {}
2595 if (ImGui::BeginMenu("Options"))
2597 static bool enabled
= true;
2598 ImGui::MenuItem("Enabled", "", &enabled
);
2599 ImGui::BeginChild("child", ImVec2(0, 60), true);
2600 for (int i
= 0; i
< 10; i
++)
2601 ImGui::Text("Scrolling Text %d", i
);
2603 static float f
= 0.5f
;
2605 static bool b
= true;
2606 ImGui::SliderFloat("Value", &f
, 0.0f
, 1.0f
);
2607 ImGui::InputFloat("Input", &f
, 0.1f
);
2608 ImGui::Combo("Combo", &n
, "Yes\0No\0Maybe\0\0");
2609 ImGui::Checkbox("Check", &b
);
2612 if (ImGui::BeginMenu("Colors"))
2614 float sz
= ImGui::GetTextLineHeight();
2615 for (int i
= 0; i
< ImGuiCol_COUNT
; i
++)
2617 const char* name
= ImGui::GetStyleColorName((ImGuiCol
)i
);
2618 ImVec2 p
= ImGui::GetCursorScreenPos();
2619 ImGui::GetWindowDrawList()->AddRectFilled(p
, ImVec2(p
.x
+sz
, p
.y
+sz
), ImGui::GetColorU32((ImGuiCol
)i
));
2620 ImGui::Dummy(ImVec2(sz
, sz
));
2622 ImGui::MenuItem(name
);
2626 if (ImGui::BeginMenu("Disabled", false)) // Disabled
2630 if (ImGui::MenuItem("Checked", NULL
, true)) {}
2631 if (ImGui::MenuItem("Quit", "Alt+F4")) {}
2634 //-----------------------------------------------------------------------------
2635 // EXAMPLE APP CODE: CONSOLE
2636 //-----------------------------------------------------------------------------
2638 // Demonstrating creating a simple console window, with scrolling, filtering, completion and history.
2639 // For the console example, here we are using a more C++ like approach of declaring a class to hold the data and the functions.
2640 struct ExampleAppConsole
2643 ImVector
<char*> Items
;
2644 bool ScrollToBottom
;
2645 ImVector
<char*> History
;
2646 int HistoryPos
; // -1: new line, 0..History.Size-1 browsing history.
2647 ImVector
<const char*> Commands
;
2652 memset(InputBuf
, 0, sizeof(InputBuf
));
2654 Commands
.push_back("HELP");
2655 Commands
.push_back("HISTORY");
2656 Commands
.push_back("CLEAR");
2657 Commands
.push_back("CLASSIFY"); // "classify" is only here to provide an example of "C"+[tab] completing to "CL" and displaying matches.
2658 AddLog("Welcome to Dear ImGui!");
2660 ~ExampleAppConsole()
2663 for (int i
= 0; i
< History
.Size
; i
++)
2668 static int Stricmp(const char* str1
, const char* str2
) { int d
; while ((d
= toupper(*str2
) - toupper(*str1
)) == 0 && *str1
) { str1
++; str2
++; } return d
; }
2669 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
; }
2670 static char* Strdup(const char *str
) { size_t len
= strlen(str
) + 1; void* buff
= malloc(len
); return (char*)memcpy(buff
, (const void*)str
, len
); }
2671 static void Strtrim(char* str
) { char* str_end
= str
+ strlen(str
); while (str_end
> str
&& str_end
[-1] == ' ') str_end
--; *str_end
= 0; }
2675 for (int i
= 0; i
< Items
.Size
; i
++)
2678 ScrollToBottom
= true;
2681 void AddLog(const char* fmt
, ...) IM_FMTARGS(2)
2686 va_start(args
, fmt
);
2687 vsnprintf(buf
, IM_ARRAYSIZE(buf
), fmt
, args
);
2688 buf
[IM_ARRAYSIZE(buf
)-1] = 0;
2690 Items
.push_back(Strdup(buf
));
2691 ScrollToBottom
= true;
2694 void Draw(const char* title
, bool* p_open
)
2696 ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver
);
2697 if (!ImGui::Begin(title
, p_open
))
2703 // 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.
2704 // Here we create a context menu only available from the title bar.
2705 if (ImGui::BeginPopupContextItem())
2707 if (ImGui::MenuItem("Close Console"))
2712 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.");
2713 ImGui::TextWrapped("Enter 'HELP' for help, press TAB to use text completion.");
2715 // TODO: display items starting from the bottom
2717 if (ImGui::SmallButton("Add Dummy Text")) { AddLog("%d some text", Items
.Size
); AddLog("some more text"); AddLog("display very important message here!"); } ImGui::SameLine();
2718 if (ImGui::SmallButton("Add Dummy Error")) { AddLog("[error] something went wrong"); } ImGui::SameLine();
2719 if (ImGui::SmallButton("Clear")) { ClearLog(); } ImGui::SameLine();
2720 bool copy_to_clipboard
= ImGui::SmallButton("Copy"); ImGui::SameLine();
2721 if (ImGui::SmallButton("Scroll to bottom")) ScrollToBottom
= true;
2722 //static float t = 0.0f; if (ImGui::GetTime() - t > 0.02f) { t = ImGui::GetTime(); AddLog("Spam %f", t); }
2726 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding
, ImVec2(0,0));
2727 static ImGuiTextFilter filter
;
2728 filter
.Draw("Filter (\"incl,-excl\") (\"error\")", 180);
2729 ImGui::PopStyleVar();
2732 const float footer_height_to_reserve
= ImGui::GetStyle().ItemSpacing
.y
+ ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text
2733 ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve
), false, ImGuiWindowFlags_HorizontalScrollbar
); // Leave room for 1 separator + 1 InputText
2734 if (ImGui::BeginPopupContextWindow())
2736 if (ImGui::Selectable("Clear")) ClearLog();
2740 // 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());
2741 // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping to only process visible items.
2742 // 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.
2743 // To use the clipper we could replace the 'for (int i = 0; i < Items.Size; i++)' loop with:
2744 // ImGuiListClipper clipper(Items.Size);
2745 // while (clipper.Step())
2746 // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
2747 // 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.
2748 // 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,
2749 // 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!
2750 // 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.
2751 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing
, ImVec2(4,1)); // Tighten spacing
2752 if (copy_to_clipboard
)
2753 ImGui::LogToClipboard();
2754 ImVec4 col_default_text
= ImGui::GetStyleColorVec4(ImGuiCol_Text
);
2755 for (int i
= 0; i
< Items
.Size
; i
++)
2757 const char* item
= Items
[i
];
2758 if (!filter
.PassFilter(item
))
2760 ImVec4 col
= col_default_text
;
2761 if (strstr(item
, "[error]")) col
= ImColor(1.0f
,0.4f
,0.4f
,1.0f
);
2762 else if (strncmp(item
, "# ", 2) == 0) col
= ImColor(1.0f
,0.78f
,0.58f
,1.0f
);
2763 ImGui::PushStyleColor(ImGuiCol_Text
, col
);
2764 ImGui::TextUnformatted(item
);
2765 ImGui::PopStyleColor();
2767 if (copy_to_clipboard
)
2770 ImGui::SetScrollHere(1.0f
);
2771 ScrollToBottom
= false;
2772 ImGui::PopStyleVar();
2777 bool reclaim_focus
= false;
2778 if (ImGui::InputText("Input", InputBuf
, IM_ARRAYSIZE(InputBuf
), ImGuiInputTextFlags_EnterReturnsTrue
|ImGuiInputTextFlags_CallbackCompletion
|ImGuiInputTextFlags_CallbackHistory
, &TextEditCallbackStub
, (void*)this))
2782 ExecCommand(InputBuf
);
2783 strcpy(InputBuf
, "");
2784 reclaim_focus
= true;
2787 // Demonstrate keeping focus on the input box
2788 ImGui::SetItemDefaultFocus();
2790 ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget
2795 void ExecCommand(const char* command_line
)
2797 AddLog("# %s\n", command_line
);
2799 // 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.
2801 for (int i
= History
.Size
-1; i
>= 0; i
--)
2802 if (Stricmp(History
[i
], command_line
) == 0)
2805 History
.erase(History
.begin() + i
);
2808 History
.push_back(Strdup(command_line
));
2811 if (Stricmp(command_line
, "CLEAR") == 0)
2815 else if (Stricmp(command_line
, "HELP") == 0)
2817 AddLog("Commands:");
2818 for (int i
= 0; i
< Commands
.Size
; i
++)
2819 AddLog("- %s", Commands
[i
]);
2821 else if (Stricmp(command_line
, "HISTORY") == 0)
2823 int first
= History
.Size
- 10;
2824 for (int i
= first
> 0 ? first
: 0; i
< History
.Size
; i
++)
2825 AddLog("%3d: %s\n", i
, History
[i
]);
2829 AddLog("Unknown command: '%s'\n", command_line
);
2833 static int TextEditCallbackStub(ImGuiTextEditCallbackData
* data
) // In C++11 you are better off using lambdas for this sort of forwarding callbacks
2835 ExampleAppConsole
* console
= (ExampleAppConsole
*)data
->UserData
;
2836 return console
->TextEditCallback(data
);
2839 int TextEditCallback(ImGuiTextEditCallbackData
* data
)
2841 //AddLog("cursor: %d, selection: %d-%d", data->CursorPos, data->SelectionStart, data->SelectionEnd);
2842 switch (data
->EventFlag
)
2844 case ImGuiInputTextFlags_CallbackCompletion
:
2846 // Example of TEXT COMPLETION
2848 // Locate beginning of current word
2849 const char* word_end
= data
->Buf
+ data
->CursorPos
;
2850 const char* word_start
= word_end
;
2851 while (word_start
> data
->Buf
)
2853 const char c
= word_start
[-1];
2854 if (c
== ' ' || c
== '\t' || c
== ',' || c
== ';')
2859 // Build a list of candidates
2860 ImVector
<const char*> candidates
;
2861 for (int i
= 0; i
< Commands
.Size
; i
++)
2862 if (Strnicmp(Commands
[i
], word_start
, (int)(word_end
-word_start
)) == 0)
2863 candidates
.push_back(Commands
[i
]);
2865 if (candidates
.Size
== 0)
2868 AddLog("No match for \"%.*s\"!\n", (int)(word_end
-word_start
), word_start
);
2870 else if (candidates
.Size
== 1)
2872 // Single match. Delete the beginning of the word and replace it entirely so we've got nice casing
2873 data
->DeleteChars((int)(word_start
-data
->Buf
), (int)(word_end
-word_start
));
2874 data
->InsertChars(data
->CursorPos
, candidates
[0]);
2875 data
->InsertChars(data
->CursorPos
, " ");
2879 // Multiple matches. Complete as much as we can, so inputing "C" will complete to "CL" and display "CLEAR" and "CLASSIFY"
2880 int match_len
= (int)(word_end
- word_start
);
2884 bool all_candidates_matches
= true;
2885 for (int i
= 0; i
< candidates
.Size
&& all_candidates_matches
; i
++)
2887 c
= toupper(candidates
[i
][match_len
]);
2888 else if (c
== 0 || c
!= toupper(candidates
[i
][match_len
]))
2889 all_candidates_matches
= false;
2890 if (!all_candidates_matches
)
2897 data
->DeleteChars((int)(word_start
- data
->Buf
), (int)(word_end
-word_start
));
2898 data
->InsertChars(data
->CursorPos
, candidates
[0], candidates
[0] + match_len
);
2902 AddLog("Possible matches:\n");
2903 for (int i
= 0; i
< candidates
.Size
; i
++)
2904 AddLog("- %s\n", candidates
[i
]);
2909 case ImGuiInputTextFlags_CallbackHistory
:
2911 // Example of HISTORY
2912 const int prev_history_pos
= HistoryPos
;
2913 if (data
->EventKey
== ImGuiKey_UpArrow
)
2915 if (HistoryPos
== -1)
2916 HistoryPos
= History
.Size
- 1;
2917 else if (HistoryPos
> 0)
2920 else if (data
->EventKey
== ImGuiKey_DownArrow
)
2922 if (HistoryPos
!= -1)
2923 if (++HistoryPos
>= History
.Size
)
2927 // A better implementation would preserve the data on the current input line along with cursor position.
2928 if (prev_history_pos
!= HistoryPos
)
2930 data
->CursorPos
= data
->SelectionStart
= data
->SelectionEnd
= data
->BufTextLen
= (int)snprintf(data
->Buf
, (size_t)data
->BufSize
, "%s", (HistoryPos
>= 0) ? History
[HistoryPos
] : "");
2931 data
->BufDirty
= true;
2939 static void ShowExampleAppConsole(bool* p_open
)
2941 static ExampleAppConsole console
;
2942 console
.Draw("Example: Console", p_open
);
2945 //-----------------------------------------------------------------------------
2946 // EXAMPLE APP CODE: LOG
2947 //-----------------------------------------------------------------------------
2950 // static ExampleAppLog my_log;
2951 // my_log.AddLog("Hello %d world\n", 123);
2952 // my_log.Draw("title");
2953 struct ExampleAppLog
2955 ImGuiTextBuffer Buf
;
2956 ImGuiTextFilter Filter
;
2957 ImVector
<int> LineOffsets
; // Index to lines offset
2958 bool ScrollToBottom
;
2960 void Clear() { Buf
.clear(); LineOffsets
.clear(); }
2962 void AddLog(const char* fmt
, ...) IM_FMTARGS(2)
2964 int old_size
= Buf
.size();
2966 va_start(args
, fmt
);
2967 Buf
.appendfv(fmt
, args
);
2969 for (int new_size
= Buf
.size(); old_size
< new_size
; old_size
++)
2970 if (Buf
[old_size
] == '\n')
2971 LineOffsets
.push_back(old_size
);
2972 ScrollToBottom
= true;
2975 void Draw(const char* title
, bool* p_open
= NULL
)
2977 ImGui::SetNextWindowSize(ImVec2(500,400), ImGuiCond_FirstUseEver
);
2978 if (!ImGui::Begin(title
, p_open
))
2983 if (ImGui::Button("Clear")) Clear();
2985 bool copy
= ImGui::Button("Copy");
2987 Filter
.Draw("Filter", -100.0f
);
2989 ImGui::BeginChild("scrolling", ImVec2(0,0), false, ImGuiWindowFlags_HorizontalScrollbar
);
2990 if (copy
) ImGui::LogToClipboard();
2992 if (Filter
.IsActive())
2994 const char* buf_begin
= Buf
.begin();
2995 const char* line
= buf_begin
;
2996 for (int line_no
= 0; line
!= NULL
; line_no
++)
2998 const char* line_end
= (line_no
< LineOffsets
.Size
) ? buf_begin
+ LineOffsets
[line_no
] : NULL
;
2999 if (Filter
.PassFilter(line
, line_end
))
3000 ImGui::TextUnformatted(line
, line_end
);
3001 line
= line_end
&& line_end
[1] ? line_end
+ 1 : NULL
;
3006 ImGui::TextUnformatted(Buf
.begin());
3010 ImGui::SetScrollHere(1.0f
);
3011 ScrollToBottom
= false;
3017 // Demonstrate creating a simple log window with basic filtering.
3018 static void ShowExampleAppLog(bool* p_open
)
3020 static ExampleAppLog log
;
3022 // Demo: add random items (unless Ctrl is held)
3023 static double last_time
= -1.0;
3024 double time
= ImGui::GetTime();
3025 if (time
- last_time
>= 0.20f
&& !ImGui::GetIO().KeyCtrl
)
3027 const char* random_words
[] = { "system", "info", "warning", "error", "fatal", "notice", "log" };
3028 log
.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words
[rand() % IM_ARRAYSIZE(random_words
)], time
, ImGui::GetFrameCount());
3032 log
.Draw("Example: Log", p_open
);
3035 //-----------------------------------------------------------------------------
3036 // EXAMPLE APP CODE: SIMPLE LAYOUT
3037 //-----------------------------------------------------------------------------
3039 // Demonstrate create a window with multiple child windows.
3040 static void ShowExampleAppLayout(bool* p_open
)
3042 ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver
);
3043 if (ImGui::Begin("Example: Layout", p_open
, ImGuiWindowFlags_MenuBar
))
3045 if (ImGui::BeginMenuBar())
3047 if (ImGui::BeginMenu("File"))
3049 if (ImGui::MenuItem("Close")) *p_open
= false;
3052 ImGui::EndMenuBar();
3056 static int selected
= 0;
3057 ImGui::BeginChild("left pane", ImVec2(150, 0), true);
3058 for (int i
= 0; i
< 100; i
++)
3061 sprintf(label
, "MyObject %d", i
);
3062 if (ImGui::Selectable(label
, selected
== i
))
3069 ImGui::BeginGroup();
3070 ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
3071 ImGui::Text("MyObject: %d", selected
);
3073 ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ");
3075 if (ImGui::Button("Revert")) {}
3077 if (ImGui::Button("Save")) {}
3083 //-----------------------------------------------------------------------------
3084 // EXAMPLE APP CODE: PROPERTY EDITOR
3085 //-----------------------------------------------------------------------------
3087 // Demonstrate create a simple property editor.
3088 static void ShowExampleAppPropertyEditor(bool* p_open
)
3090 ImGui::SetNextWindowSize(ImVec2(430,450), ImGuiCond_FirstUseEver
);
3091 if (!ImGui::Begin("Example: Property editor", p_open
))
3097 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.");
3099 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding
, ImVec2(2,2));
3105 static void ShowDummyObject(const char* prefix
, int uid
)
3107 ImGui::PushID(uid
); // Use object uid as identifier. Most commonly you could also use the object pointer as a base ID.
3108 ImGui::AlignTextToFramePadding(); // Text and Tree nodes are less high than regular widgets, here we add vertical spacing to make the tree lines equal high.
3109 bool node_open
= ImGui::TreeNode("Object", "%s_%u", prefix
, uid
);
3110 ImGui::NextColumn();
3111 ImGui::AlignTextToFramePadding();
3112 ImGui::Text("my sailor is rich");
3113 ImGui::NextColumn();
3116 static float dummy_members
[8] = { 0.0f
,0.0f
,1.0f
,3.1416f
,100.0f
,999.0f
};
3117 for (int i
= 0; i
< 8; i
++)
3119 ImGui::PushID(i
); // Use field index as identifier.
3122 ShowDummyObject("Child", 424242);
3126 // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
3127 ImGui::AlignTextToFramePadding();
3128 ImGui::TreeNodeEx("Field", ImGuiTreeNodeFlags_Leaf
| ImGuiTreeNodeFlags_NoTreePushOnOpen
| ImGuiTreeNodeFlags_Bullet
, "Field_%d", i
);
3129 ImGui::NextColumn();
3130 ImGui::PushItemWidth(-1);
3132 ImGui::InputFloat("##value", &dummy_members
[i
], 1.0f
);
3134 ImGui::DragFloat("##value", &dummy_members
[i
], 0.01f
);
3135 ImGui::PopItemWidth();
3136 ImGui::NextColumn();
3146 // Iterate dummy objects with dummy members (all the same data)
3147 for (int obj_i
= 0; obj_i
< 3; obj_i
++)
3148 funcs::ShowDummyObject("Object", obj_i
);
3152 ImGui::PopStyleVar();
3156 //-----------------------------------------------------------------------------
3157 // EXAMPLE APP CODE: LONG TEXT
3158 //-----------------------------------------------------------------------------
3160 // Demonstrate/test rendering huge amount of text, and the incidence of clipping.
3161 static void ShowExampleAppLongText(bool* p_open
)
3163 ImGui::SetNextWindowSize(ImVec2(520,600), ImGuiCond_FirstUseEver
);
3164 if (!ImGui::Begin("Example: Long text display", p_open
))
3170 static int test_type
= 0;
3171 static ImGuiTextBuffer log
;
3172 static int lines
= 0;
3173 ImGui::Text("Printing unusually long amount of text.");
3174 ImGui::Combo("Test type", &test_type
, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
3175 ImGui::Text("Buffer contents: %d lines, %d bytes", lines
, log
.size());
3176 if (ImGui::Button("Clear")) { log
.clear(); lines
= 0; }
3178 if (ImGui::Button("Add 1000 lines"))
3180 for (int i
= 0; i
< 1000; i
++)
3181 log
.appendf("%i The quick brown fox jumps over the lazy dog\n", lines
+i
);
3184 ImGui::BeginChild("Log");
3188 // Single call to TextUnformatted() with a big buffer
3189 ImGui::TextUnformatted(log
.begin(), log
.end());
3193 // Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
3194 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing
, ImVec2(0,0));
3195 ImGuiListClipper
clipper(lines
);
3196 while (clipper
.Step())
3197 for (int i
= clipper
.DisplayStart
; i
< clipper
.DisplayEnd
; i
++)
3198 ImGui::Text("%i The quick brown fox jumps over the lazy dog", i
);
3199 ImGui::PopStyleVar();
3203 // Multiple calls to Text(), not clipped (slow)
3204 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing
, ImVec2(0,0));
3205 for (int i
= 0; i
< lines
; i
++)
3206 ImGui::Text("%i The quick brown fox jumps over the lazy dog", i
);
3207 ImGui::PopStyleVar();
3214 //-----------------------------------------------------------------------------
3215 // EXAMPLE APP CODE: AUTO RESIZE
3216 //-----------------------------------------------------------------------------
3218 // Demonstrate creating a window which gets auto-resized according to its content.
3219 static void ShowExampleAppAutoResize(bool* p_open
)
3221 if (!ImGui::Begin("Example: Auto-resizing window", p_open
, ImGuiWindowFlags_AlwaysAutoResize
))
3227 static int lines
= 10;
3228 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.");
3229 ImGui::SliderInt("Number of lines", &lines
, 1, 20);
3230 for (int i
= 0; i
< lines
; i
++)
3231 ImGui::Text("%*sThis is line %d", i
* 4, "", i
); // Pad with space to extend size horizontally
3235 //-----------------------------------------------------------------------------
3236 // EXAMPLE APP CODE: CONSTRAINED RESIZE
3237 //-----------------------------------------------------------------------------
3239 // Demonstrate creating a window with custom resize constraints.
3240 static void ShowExampleAppConstrainedResize(bool* p_open
)
3242 struct CustomConstraints
// Helper functions to demonstrate programmatic constraints
3244 static void Square(ImGuiSizeCallbackData
* data
) { data
->DesiredSize
= ImVec2(IM_MAX(data
->DesiredSize
.x
, data
->DesiredSize
.y
), IM_MAX(data
->DesiredSize
.x
, data
->DesiredSize
.y
)); }
3245 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
); }
3248 static bool auto_resize
= false;
3249 static int type
= 0;
3250 static int display_lines
= 10;
3251 if (type
== 0) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 0), ImVec2(-1, FLT_MAX
)); // Vertical only
3252 if (type
== 1) ImGui::SetNextWindowSizeConstraints(ImVec2(0, -1), ImVec2(FLT_MAX
, -1)); // Horizontal only
3253 if (type
== 2) ImGui::SetNextWindowSizeConstraints(ImVec2(100, 100), ImVec2(FLT_MAX
, FLT_MAX
)); // Width > 100, Height > 100
3254 if (type
== 3) ImGui::SetNextWindowSizeConstraints(ImVec2(400, -1), ImVec2(500, -1)); // Width 400-500
3255 if (type
== 4) ImGui::SetNextWindowSizeConstraints(ImVec2(-1, 400), ImVec2(-1, 500)); // Height 400-500
3256 if (type
== 5) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX
, FLT_MAX
), CustomConstraints::Square
); // Always Square
3257 if (type
== 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX
, FLT_MAX
), CustomConstraints::Step
, (void*)100);// Fixed Step
3259 ImGuiWindowFlags flags
= auto_resize
? ImGuiWindowFlags_AlwaysAutoResize
: 0;
3260 if (ImGui::Begin("Example: Constrained Resize", p_open
, flags
))
3262 const char* desc
[] =
3264 "Resize vertical only",
3265 "Resize horizontal only",
3266 "Width > 100, Height > 100",
3269 "Custom: Always Square",
3270 "Custom: Fixed Steps (100)",
3272 if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
3273 if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
3274 if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
3275 ImGui::PushItemWidth(200);
3276 ImGui::Combo("Constraint", &type
, desc
, IM_ARRAYSIZE(desc
));
3277 ImGui::DragInt("Lines", &display_lines
, 0.2f
, 1, 100);
3278 ImGui::PopItemWidth();
3279 ImGui::Checkbox("Auto-resize", &auto_resize
);
3280 for (int i
= 0; i
< display_lines
; i
++)
3281 ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i
* 4, "");
3286 //-----------------------------------------------------------------------------
3287 // EXAMPLE APP CODE: SIMPLE OVERLAY
3288 //-----------------------------------------------------------------------------
3290 // Demonstrate creating a simple static window with no decoration + a context-menu to choose which corner of the screen to use.
3291 static void ShowExampleAppSimpleOverlay(bool* p_open
)
3293 const float DISTANCE
= 10.0f
;
3294 static int corner
= 0;
3295 ImVec2 window_pos
= ImVec2((corner
& 1) ? ImGui::GetIO().DisplaySize
.x
- DISTANCE
: DISTANCE
, (corner
& 2) ? ImGui::GetIO().DisplaySize
.y
- DISTANCE
: DISTANCE
);
3296 ImVec2 window_pos_pivot
= ImVec2((corner
& 1) ? 1.0f
: 0.0f
, (corner
& 2) ? 1.0f
: 0.0f
);
3298 ImGui::SetNextWindowPos(window_pos
, ImGuiCond_Always
, window_pos_pivot
);
3299 ImGui::SetNextWindowBgAlpha(0.3f
); // Transparent background
3300 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
))
3302 ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
3304 if (ImGui::IsMousePosValid())
3305 ImGui::Text("Mouse Position: (%.1f,%.1f)", ImGui::GetIO().MousePos
.x
, ImGui::GetIO().MousePos
.y
);
3307 ImGui::Text("Mouse Position: <invalid>");
3308 if (ImGui::BeginPopupContextWindow())
3310 if (ImGui::MenuItem("Custom", NULL
, corner
== -1)) corner
= -1;
3311 if (ImGui::MenuItem("Top-left", NULL
, corner
== 0)) corner
= 0;
3312 if (ImGui::MenuItem("Top-right", NULL
, corner
== 1)) corner
= 1;
3313 if (ImGui::MenuItem("Bottom-left", NULL
, corner
== 2)) corner
= 2;
3314 if (ImGui::MenuItem("Bottom-right", NULL
, corner
== 3)) corner
= 3;
3315 if (p_open
&& ImGui::MenuItem("Close")) *p_open
= false;
3322 //-----------------------------------------------------------------------------
3323 // EXAMPLE APP CODE: WINDOW TITLES
3324 //-----------------------------------------------------------------------------
3326 // Demonstrate using "##" and "###" in identifiers to manipulate ID generation.
3327 // 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.
3328 static void ShowExampleAppWindowTitles(bool*)
3330 // By default, Windows are uniquely identified by their title.
3331 // You can use the "##" and "###" markers to manipulate the display/ID.
3333 // Using "##" to display same title but have unique identifier.
3334 ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver
);
3335 ImGui::Begin("Same title as another window##1");
3336 ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
3339 ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver
);
3340 ImGui::Begin("Same title as another window##2");
3341 ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
3344 // Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
3346 sprintf(buf
, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f
) & 3], ImGui::GetFrameCount());
3347 ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver
);
3349 ImGui::Text("This window has a changing title.");
3353 //-----------------------------------------------------------------------------
3354 // EXAMPLE APP CODE: CUSTOM RENDERING
3355 //-----------------------------------------------------------------------------
3357 // Demonstrate using the low-level ImDrawList to draw custom shapes.
3358 static void ShowExampleAppCustomRendering(bool* p_open
)
3360 ImGui::SetNextWindowSize(ImVec2(350, 560), ImGuiCond_FirstUseEver
);
3361 if (!ImGui::Begin("Example: Custom rendering", p_open
))
3367 // Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of overloaded operators, etc.
3368 // Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your types and ImVec2/ImVec4.
3369 // ImGui defines overloaded operators but they are internal to imgui.cpp and not exposed outside (to avoid messing with your types)
3370 // In this example we are not using the maths operators!
3371 ImDrawList
* draw_list
= ImGui::GetWindowDrawList();
3374 ImGui::Text("Primitives");
3375 static float sz
= 36.0f
;
3376 static float thickness
= 4.0f
;
3377 static ImVec4 col
= ImVec4(1.0f
, 1.0f
, 0.4f
, 1.0f
);
3378 ImGui::DragFloat("Size", &sz
, 0.2f
, 2.0f
, 72.0f
, "%.0f");
3379 ImGui::DragFloat("Thickness", &thickness
, 0.05f
, 1.0f
, 8.0f
, "%.02f");
3380 ImGui::ColorEdit3("Color", &col
.x
);
3382 const ImVec2 p
= ImGui::GetCursorScreenPos();
3383 const ImU32 col32
= ImColor(col
);
3384 float x
= p
.x
+ 4.0f
, y
= p
.y
+ 4.0f
, spacing
= 8.0f
;
3385 for (int n
= 0; n
< 2; n
++)
3387 float curr_thickness
= (n
== 0) ? 1.0f
: thickness
;
3388 draw_list
->AddCircle(ImVec2(x
+sz
*0.5f
, y
+sz
*0.5f
), sz
*0.5f
, col32
, 20, curr_thickness
); x
+= sz
+spacing
;
3389 draw_list
->AddRect(ImVec2(x
, y
), ImVec2(x
+sz
, y
+sz
), col32
, 0.0f
, ImDrawCornerFlags_All
, curr_thickness
); x
+= sz
+spacing
;
3390 draw_list
->AddRect(ImVec2(x
, y
), ImVec2(x
+sz
, y
+sz
), col32
, 10.0f
, ImDrawCornerFlags_All
, curr_thickness
); x
+= sz
+spacing
;
3391 draw_list
->AddRect(ImVec2(x
, y
), ImVec2(x
+sz
, y
+sz
), col32
, 10.0f
, ImDrawCornerFlags_TopLeft
|ImDrawCornerFlags_BotRight
, curr_thickness
); x
+= sz
+spacing
;
3392 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
;
3393 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!)
3394 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!)
3395 draw_list
->AddLine(ImVec2(x
, y
), ImVec2(x
+sz
, y
+sz
), col32
, curr_thickness
); x
+= sz
+spacing
; // Diagonal line
3396 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
);
3400 draw_list
->AddCircleFilled(ImVec2(x
+sz
*0.5f
, y
+sz
*0.5f
), sz
*0.5f
, col32
, 32); x
+= sz
+spacing
;
3401 draw_list
->AddRectFilled(ImVec2(x
, y
), ImVec2(x
+sz
, y
+sz
), col32
); x
+= sz
+spacing
;
3402 draw_list
->AddRectFilled(ImVec2(x
, y
), ImVec2(x
+sz
, y
+sz
), col32
, 10.0f
); x
+= sz
+spacing
;
3403 draw_list
->AddRectFilled(ImVec2(x
, y
), ImVec2(x
+sz
, y
+sz
), col32
, 10.0f
, ImDrawCornerFlags_TopLeft
|ImDrawCornerFlags_BotRight
); x
+= sz
+spacing
;
3404 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
;
3405 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)
3406 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)
3407 draw_list
->AddRectFilled(ImVec2(x
, y
), ImVec2(x
+1, y
+1), col32
); x
+= sz
; // Pixel (faster than AddLine)
3408 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));
3409 ImGui::Dummy(ImVec2((sz
+spacing
)*8, (sz
+spacing
)*3));
3413 static ImVector
<ImVec2
> points
;
3414 static bool adding_line
= false;
3415 ImGui::Text("Canvas example");
3416 if (ImGui::Button("Clear")) points
.clear();
3417 if (points
.Size
>= 2) { ImGui::SameLine(); if (ImGui::Button("Undo")) { points
.pop_back(); points
.pop_back(); } }
3418 ImGui::Text("Left-click and drag to add lines,\nRight-click to undo");
3420 // Here we are using InvisibleButton() as a convenience to 1) advance the cursor and 2) allows us to use IsItemHovered()
3421 // But you can also draw directly and poll mouse/keyboard by yourself. You can manipulate the cursor using GetCursorPos() and SetCursorPos().
3422 // If you only use the ImDrawList API, you can notify the owner window of its extends by using SetCursorPos(max).
3423 ImVec2 canvas_pos
= ImGui::GetCursorScreenPos(); // ImDrawList API uses screen coordinates!
3424 ImVec2 canvas_size
= ImGui::GetContentRegionAvail(); // Resize canvas to what's available
3425 if (canvas_size
.x
< 50.0f
) canvas_size
.x
= 50.0f
;
3426 if (canvas_size
.y
< 50.0f
) canvas_size
.y
= 50.0f
;
3427 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));
3428 draw_list
->AddRect(canvas_pos
, ImVec2(canvas_pos
.x
+ canvas_size
.x
, canvas_pos
.y
+ canvas_size
.y
), IM_COL32(255, 255, 255, 255));
3430 bool adding_preview
= false;
3431 ImGui::InvisibleButton("canvas", canvas_size
);
3432 ImVec2 mouse_pos_in_canvas
= ImVec2(ImGui::GetIO().MousePos
.x
- canvas_pos
.x
, ImGui::GetIO().MousePos
.y
- canvas_pos
.y
);
3435 adding_preview
= true;
3436 points
.push_back(mouse_pos_in_canvas
);
3437 if (!ImGui::IsMouseDown(0))
3438 adding_line
= adding_preview
= false;
3440 if (ImGui::IsItemHovered())
3442 if (!adding_line
&& ImGui::IsMouseClicked(0))
3444 points
.push_back(mouse_pos_in_canvas
);
3447 if (ImGui::IsMouseClicked(1) && !points
.empty())
3449 adding_line
= adding_preview
= false;
3454 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.)
3455 for (int i
= 0; i
< points
.Size
- 1; i
+= 2)
3456 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
);
3457 draw_list
->PopClipRect();
3467 void ImGui::ShowDemoWindow(bool*) {}
3468 void ImGui::ShowUserGuide() {}
3469 void ImGui::ShowStyleEditor(ImGuiStyle
*) {}