Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_opengl2.cpp
#	backends/imgui_impl_opengl3.cpp
#	imgui.cpp
docking
ocornut 4 years ago
commit b11518d7d7

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2014-2020 Omar Cornut Copyright (c) 2014-2021 Omar Cornut
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

@ -1,8 +1,8 @@
// dear imgui: Platform Backend for GLUT/FreeGLUT // dear imgui: Platform Backend for GLUT/FreeGLUT
// This needs to be used along with a Renderer (e.g. OpenGL2) // This needs to be used along with a Renderer (e.g. OpenGL2)
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! // !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead! // !!! Nowadays, prefer using GLFW or SDL instead!
// Issues: // Issues:

@ -1,8 +1,8 @@
// dear imgui: Platform Backend for GLUT/FreeGLUT // dear imgui: Platform Backend for GLUT/FreeGLUT
// This needs to be used along with a Renderer (e.g. OpenGL2) // This needs to be used along with a Renderer (e.g. OpenGL2)
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! // !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead! // !!! Nowadays, prefer using GLFW or SDL instead!
// Issues: // Issues:

@ -20,7 +20,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2020-01-23: OpenGL: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. // 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
// 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
// 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
@ -93,23 +94,29 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_LIGHTING); glDisable(GL_LIGHTING);
glDisable(GL_COLOR_MATERIAL); glDisable(GL_COLOR_MATERIAL);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glShadeModel(GL_SMOOTH);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
// you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function: // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
// GLint last_program; // (DO NOT MODIFY THIS FILE! Add the code in your calling function)
// glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); // GLint last_program;
// glUseProgram(0); // glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
// ImGui_ImplOpenGL2_RenderDrawData(...); // glUseProgram(0);
// glUseProgram(last_program) // ImGui_ImplOpenGL2_RenderDrawData(...);
// glUseProgram(last_program)
// There are potentially many more states you could need to clear/setup that we can't access from default headers.
// e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP).
// Setup viewport, orthographic projection matrix // Setup viewport, orthographic projection matrix
// Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
@ -139,6 +146,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model);
GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode); GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode);
glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
@ -207,6 +215,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]);
glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
glShadeModel(last_shade_model);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode);
} }

@ -15,7 +15,8 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface. // 2020-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2020-10-23: OpenGL: Save and restore current GL_PRIMITIVE_RESTART state. // 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) // 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
// 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. // 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
// 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
@ -260,6 +261,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST);
glEnable(GL_SCISSOR_TEST); glEnable(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
if (g_GlVersion >= 310) if (g_GlVersion >= 310)
@ -270,8 +272,8 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
#endif #endif
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
bool clip_origin_lower_left = true;
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) #if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
bool clip_origin_lower_left = true;
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin); GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
if (current_clip_origin == GL_UPPER_LEFT) if (current_clip_origin == GL_UPPER_LEFT)
clip_origin_lower_left = false; clip_origin_lower_left = false;
@ -284,7 +286,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
float T = draw_data->DisplayPos.y; float T = draw_data->DisplayPos.y;
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
#endif
const float ortho_projection[4][4] = const float ortho_projection[4][4] =
{ {
{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, { 2.0f/(R-L), 0.0f, 0.0f, 0.0f },
@ -354,6 +358,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
GLboolean last_enable_blend = glIsEnabled(GL_BLEND); GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
@ -442,6 +447,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }

@ -56,7 +56,7 @@ List of Platforms Backends:
imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends) imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends)
imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org
imgui_impl_win32.cpp ; Win32 native API (Windows) imgui_impl_win32.cpp ; Win32 native API (Windows)
imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2020!) imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!)
List of Renderer Backends: List of Renderer Backends:

@ -159,6 +159,7 @@ Other Changes:
- InputText: Fixed updating cursor/selection position when a callback altered the buffer in a way - InputText: Fixed updating cursor/selection position when a callback altered the buffer in a way
where the byte count is unchanged but the decoded character count changes. (#3587) [@gqw] where the byte count is unchanged but the decoded character count changes. (#3587) [@gqw]
- InputText: Fixed swiching from single to multi-line while preserving same ID. - InputText: Fixed swiching from single to multi-line while preserving same ID.
- Fixed using IsItemEdited() after Combo() not matching the return value from Combo(). (#2034)
- Nav: Fixed IsItemFocused() from returning false when Nav highlight is hidden because mouse has moved. - Nav: Fixed IsItemFocused() from returning false when Nav highlight is hidden because mouse has moved.
It's essentially been always the case but it doesn't make much sense. Instead we will aim at exposing It's essentially been always the case but it doesn't make much sense. Instead we will aim at exposing
feedback and control of keyboard/gamepad navigation highlight and mouse hover disable flag. (#787, #2048) feedback and control of keyboard/gamepad navigation highlight and mouse hover disable flag. (#787, #2048)
@ -180,10 +181,16 @@ Other Changes:
- Misc: Made EndFrame() assertion for key modifiers being unchanged during the frame (added in 1.76) more - Misc: Made EndFrame() assertion for key modifiers being unchanged during the frame (added in 1.76) more
lenient, allowing full mid-frame releases. This is to accommodate the use of mid-frame modal native lenient, allowing full mid-frame releases. This is to accommodate the use of mid-frame modal native
windows calls, which leads backends such as GLFW to send key clearing events on focus loss. (#3575) windows calls, which leads backends such as GLFW to send key clearing events on focus loss. (#3575)
- Style: Changed default style.WindowRounding value to 0.0f (matches default for multi-viewports).
- Style: Reduced the size of the resizing grip, made alpha less prominent.
- Style: Classic: Increase the default alpha value of WindowBg to be closer to other styles.
- Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width. - Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width.
- Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...)
when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn]
- Backends: OpenGL2: Backup and restore GL_SHADE_MODEL and disable GL_NORMAL_ARRAY state to increase
compatibility with legacy code. (#3671)
- Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon]
- Backends: OpenGL2, OpenGL3: Backup and restore GL_STENCIL_TEST enable state. (#3668)
- Backends: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation. (@3579) [@bdero] - Backends: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation. (@3579) [@bdero]
- Backends: Win32: Fix setting of io.DisplaySize to invalid/uninitialized data after hwnd has been closed. - Backends: Win32: Fix setting of io.DisplaySize to invalid/uninitialized data after hwnd has been closed.
- Backends: OSX: Fix keypad-enter key not working on MacOS. (#3554) [@rokups, @lfnoise] - Backends: OSX: Fix keypad-enter key not working on MacOS. (#3554) [@rokups, @lfnoise]

@ -198,9 +198,9 @@ This is quite long and tedious, because: DirectX12.
**Building** **Building**
Unfortunately in 2020 it is still tedious to create and maintain portable build files using external Unfortunately nowadays it is still tedious to create and maintain portable build files using external
libraries (the kind we're using here to create a window and render 3D triangles) without relying on libraries (the kind we're using here to create a window and render 3D triangles) without relying on
third party software. For most examples here we choose to provide: third party software and build systems. For most examples here we choose to provide:
- Makefiles for Linux/OSX - Makefiles for Linux/OSX
- Batch files for Visual Studio 2008+ - Batch files for Visual Studio 2008+
- A .sln project file for Visual Studio 2012+ - A .sln project file for Visual Studio 2012+

@ -23,7 +23,7 @@ or view this file with any Markdown viewer.
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) | | [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) | | [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
| **Q&A: Usage** | | **Q&A: Usage** |
| **[Why is my widget not reacting when I click on it?<br>How can I have multiple widgets with the same label?<br>Why are multiple widgets reacting when I interact with one?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** | | **[Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** |
| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)| | [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)|
| [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) | | [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) |
| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) | | [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) |

@ -120,7 +120,7 @@ Officially maintained backends/bindings (in repository):
- Frameworks: Emscripten, Allegro5, Marmalade. - Frameworks: Emscripten, Allegro5, Marmalade.
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page: [Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... - Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
- Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, nCine, Nim Game Lib, Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SFML, Sokol, Unity, Unreal Engine 4, vtk, Win32 GDI, WxWidgets. - Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, nCine, Nim Game Lib, Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SFML, Sokol, Unity, Unreal Engine 4, vtk, Win32 GDI, WxWidgets.
- Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages.

@ -148,7 +148,7 @@ int main(int, char**)
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
// If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
// you may need to backup/reset/restore current shader using the commented lines below. // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
//GLint last_program; //GLint last_program;
//glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); //glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
//glUseProgram(0); //glUseProgram(0);

@ -2,8 +2,8 @@
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs // Read online: https://github.com/ocornut/imgui/tree/master/docs
// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! // !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!!
// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! // !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!!
// !!! Nowadays, prefer using GLFW or SDL instead! // !!! Nowadays, prefer using GLFW or SDL instead!
#include "imgui.h" #include "imgui.h"

@ -968,7 +968,7 @@ ImGuiStyle::ImGuiStyle()
{ {
Alpha = 1.0f; // Global alpha applies to everything in ImGui Alpha = 1.0f; // Global alpha applies to everything in ImGui
WindowPadding = ImVec2(8,8); // Padding within a window WindowPadding = ImVec2(8,8); // Padding within a window
WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended.
WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested.
WindowMinSize = ImVec2(32,32); // Minimum window size WindowMinSize = ImVec2(32,32); // Minimum window size
WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text
@ -2323,7 +2323,7 @@ bool ImGuiListClipper::Step()
{ {
// While we are in frozen row state, keep displaying items one by one, unclipped // While we are in frozen row state, keep displaying items one by one, unclipped
// FIXME: Could be stored as a table-agnostic state. // FIXME: Could be stored as a table-agnostic state.
if (table != NULL && !table->IsUnfrozen) if (table != NULL && !table->IsUnfrozenRows)
{ {
DisplayStart = ItemsFrozen; DisplayStart = ItemsFrozen;
DisplayEnd = ItemsFrozen + 1; DisplayEnd = ItemsFrozen + 1;
@ -3069,6 +3069,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
// Clear declaration of inputs claimed by the widget // Clear declaration of inputs claimed by the widget
// (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet)
g.ActiveIdUsingMouseWheel = false;
g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingNavDirMask = 0x00;
g.ActiveIdUsingNavInputMask = 0x00; g.ActiveIdUsingNavInputMask = 0x00;
g.ActiveIdUsingKeyInputMask = 0x00; g.ActiveIdUsingKeyInputMask = 0x00;
@ -3084,6 +3085,7 @@ void ImGui::SetHoveredID(ImGuiID id)
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.HoveredId = id; g.HoveredId = id;
g.HoveredIdAllowOverlap = false; g.HoveredIdAllowOverlap = false;
g.HoveredIdUsingMouseWheel = false;
if (id != 0 && g.HoveredIdPreviousFrame != id) if (id != 0 && g.HoveredIdPreviousFrame != id)
g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f;
} }
@ -3764,6 +3766,9 @@ void ImGui::UpdateMouseWheel()
if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f) if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f)
return; return;
if ((g.ActiveId != 0 && g.ActiveIdUsingMouseWheel) || (g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrameUsingMouseWheel))
return;
ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow; ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
if (!window || window->Collapsed) if (!window || window->Collapsed)
return; return;
@ -4003,8 +4008,10 @@ void ImGui::NewFrame()
if (g.HoveredId && g.ActiveId != g.HoveredId) if (g.HoveredId && g.ActiveId != g.HoveredId)
g.HoveredIdNotActiveTimer += g.IO.DeltaTime; g.HoveredIdNotActiveTimer += g.IO.DeltaTime;
g.HoveredIdPreviousFrame = g.HoveredId; g.HoveredIdPreviousFrame = g.HoveredId;
g.HoveredIdPreviousFrameUsingMouseWheel = g.HoveredIdUsingMouseWheel;
g.HoveredId = 0; g.HoveredId = 0;
g.HoveredIdAllowOverlap = false; g.HoveredIdAllowOverlap = false;
g.HoveredIdUsingMouseWheel = false;
g.HoveredIdDisabled = false; g.HoveredIdDisabled = false;
// Update ActiveId data (clear reference to active widget if the widget isn't alive anymore) // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore)
@ -5081,12 +5088,23 @@ bool ImGui::IsItemEdited()
void ImGui::SetItemAllowOverlap() void ImGui::SetItemAllowOverlap()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (g.HoveredId == g.CurrentWindow->DC.LastItemId) ImGuiID id = g.CurrentWindow->DC.LastItemId;
if (g.HoveredId == id)
g.HoveredIdAllowOverlap = true; g.HoveredIdAllowOverlap = true;
if (g.ActiveId == g.CurrentWindow->DC.LastItemId) if (g.ActiveId == id)
g.ActiveIdAllowOverlap = true; g.ActiveIdAllowOverlap = true;
} }
void ImGui::SetItemUsingMouseWheel()
{
ImGuiContext& g = *GImGui;
ImGuiID id = g.CurrentWindow->DC.LastItemId;
if (g.HoveredId == id)
g.HoveredIdUsingMouseWheel = true;
if (g.ActiveId == id)
g.ActiveIdUsingMouseWheel = true;
}
ImVec2 ImGui::GetItemRectMin() ImVec2 ImGui::GetItemRectMin()
{ {
ImGuiWindow* window = GetCurrentWindowRead(); ImGuiWindow* window = GetCurrentWindowRead();
@ -6402,7 +6420,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
int border_held = -1; int border_held = -1;
ImU32 resize_grip_col[4] = {}; ImU32 resize_grip_col[4] = {};
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it.
const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f));
if (handle_borders_and_resize_grips && !window->Collapsed) if (handle_borders_and_resize_grips && !window->Collapsed)
if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect)) if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect))
use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true; use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true;

@ -60,7 +60,7 @@ Index of this file:
// Version // Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.80 WIP" #define IMGUI_VERSION "1.80 WIP"
#define IMGUI_VERSION_NUM 17907 #define IMGUI_VERSION_NUM 17909
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE #define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch #define IMGUI_HAS_VIEWPORT // Viewport WIP branch
@ -676,7 +676,7 @@ namespace ImGui
// - 1. Call BeginTable() // - 1. Call BeginTable()
// - 2. Optionally call TableSetupColumn() to submit column name/flags/defaults // - 2. Optionally call TableSetupColumn() to submit column name/flags/defaults
// - 3. Optionally call TableSetupScrollFreeze() to request scroll freezing of columns/rows // - 3. Optionally call TableSetupScrollFreeze() to request scroll freezing of columns/rows
// - 4. Optionally call TableHeadersRow() to submit a header row (names will be pulled from data submitted to TableSetupColumns) // - 4. Optionally call TableHeadersRow() to submit a header row. Names will be pulled from data provided TableSetupColumn() calls)
// - 5. Populate contents // - 5. Populate contents
// - In most situations you can use TableNextRow() + TableSetColumnIndex(N) to start appending into a column. // - In most situations you can use TableNextRow() + TableSetColumnIndex(N) to start appending into a column.
// - If you are using tables as a sort of grid, where every columns is holding the same type of contents, // - If you are using tables as a sort of grid, where every columns is holding the same type of contents,
@ -1079,30 +1079,34 @@ enum ImGuiTabItemFlags_
}; };
// Flags for ImGui::BeginTable() // Flags for ImGui::BeginTable()
// - Important! Sizing policies have particularly complex and subtle side effects, more so than you would expect. // - Important! Sizing policies have complex and subtle side effects, more so than you would expect.
// Read comments/demos carefully + experiment with live demos to get acquainted with them. // Read comments/demos carefully + experiment with live demos to get acquainted with them.
// - The default sizing policy for columns depends on whether the ScrollX flag is set on the table: // - The DEFAULT policy depends on whether the _ScrollX flag is set on the table, and whether _AlwaysAutoResize flag is set on window.
// When ScrollX is off: // - ImGuiTableFlags_SizingPolicyStretch is the default if ScrollX if off.
// - Table defaults to ImGuiTableFlags_ColumnsWidthStretch -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch. // - ImGuiTableFlags_SizingPolicyFixed is the default if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize.
// - Columns sizing policy allowed: Stretch (default) or Fixed/Auto. // - When ScrollX is off:
// - Fixed Columns will generally obtain their requested width (unless the Table cannot fit them all). // - Table defaults to ImGuiTableFlags_SizingPolicyStretch -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch.
// - Columns sizing policy allowed: Stretch (default), Fixed/Auto.
// - Fixed Columns will generally obtain their requested width (unless the table cannot fit them all).
// - Stretch Columns will share the remaining width. // - Stretch Columns will share the remaining width.
// When ScrollX is on: // - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors.
// - Table defaults to ImGuiTableFlags_ColumnsWidthFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed. // The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns.
// - Columns sizing policy allowed: Fixed/Auto mostly! // (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing).
// - When ScrollX is on:
// - Table defaults to ImGuiTableFlags_SizingPolicyFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto.
// - Columns sizing policy allowed: Fixed/Auto mostly.
// - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed. // - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed.
// - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). // - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable().
// - Mixing up columns with different sizing policy is possible BUT can be tricky and has some side-effects and restrictions. // If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again.
// (their visible order and the scrolling state have subtle but necessary effects on how they can be manually resized). // - Read on documentation at the top of imgui_tables.cpp for details.
// The typical use of mixing sizing policies is to have ScrollX disabled, first Fixed columns and then one or two TRAILING Stretch columns.
enum ImGuiTableFlags_ enum ImGuiTableFlags_
{ {
// Features // Features
ImGuiTableFlags_None = 0, ImGuiTableFlags_None = 0,
ImGuiTableFlags_Resizable = 1 << 0, // Allow resizing columns. ImGuiTableFlags_Resizable = 1 << 0, // Enable resizing columns.
ImGuiTableFlags_Reorderable = 1 << 1, // Allow reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
ImGuiTableFlags_Hideable = 1 << 2, // Allow hiding/disabling columns in context menu. ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu.
ImGuiTableFlags_Sortable = 1 << 3, // Allow sorting on one column (sort_specs_count will always be == 1). Call TableGetSortSpecs() to obtain sort specs. ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate.
ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file. ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file.
ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow(). ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow().
// Decorations // Decorations
@ -1116,11 +1120,12 @@ enum ImGuiTableFlags_
ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders. ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders.
ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders. ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders.
ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders. ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders.
ImGuiTableFlags_NoBordersInBody = 1 << 11, // Disable vertical borders in columns Body (borders will always appears in Headers). ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appears in Headers). -> May move to style
ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). -> May move to style
// Sizing // Sizing Policy
ImGuiTableFlags_ColumnsWidthStretch = 1 << 13, // Default if ScrollX is off. Columns will default to use _WidthStretch. Read description above for more details. ImGuiTableFlags_SizingPolicyFixed = 1 << 13, // [Default if ScrollX is on] Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width.
ImGuiTableFlags_ColumnsWidthFixed = 1 << 14, // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAutoResize policy (if Resizable is off). Read description above for more details. ImGuiTableFlags_SizingPolicyStretch = 1 << 14, // [Default if ScrollX is off] Columns default to _WidthStretch with same weights.
// Sizing Extra Options
ImGuiTableFlags_SameWidths = 1 << 15, // Make all columns the same widths which is useful with Fixed columns policy (but granted by default with Stretch policy + no resize). Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible and disable ImGuiTableFlags_Resizable. ImGuiTableFlags_SameWidths = 1 << 15, // Make all columns the same widths which is useful with Fixed columns policy (but granted by default with Stretch policy + no resize). Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible and disable ImGuiTableFlags_Resizable.
ImGuiTableFlags_NoHostExtendY = 1 << 16, // Disable extending table past the limit set by outer_size.y. Only meaningful when neither ScrollX nor ScrollY are set (data below the limit will be clipped and not visible) ImGuiTableFlags_NoHostExtendY = 1 << 16, // Disable extending table past the limit set by outer_size.y. Only meaningful when neither ScrollX nor ScrollY are set (data below the limit will be clipped and not visible)
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable. ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable.
@ -1137,6 +1142,11 @@ enum ImGuiTableFlags_
// Sorting // Sorting
ImGuiTableFlags_SortMulti = 1 << 25, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). ImGuiTableFlags_SortMulti = 1 << 25, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
ImGuiTableFlags_SortTristate = 1 << 26 // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). ImGuiTableFlags_SortTristate = 1 << 26 // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
// Obsolete names (will be removed soon)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
, ImGuiTableFlags_ColumnsWidthFixed = ImGuiTableFlags_SizingPolicyFixed, ImGuiTableFlags_ColumnsWidthStretch = ImGuiTableFlags_SizingPolicyStretch
#endif
}; };
// Flags for ImGui::TableSetupColumn() // Flags for ImGui::TableSetupColumn()
@ -1146,9 +1156,9 @@ enum ImGuiTableColumnFlags_
ImGuiTableColumnFlags_None = 0, ImGuiTableColumnFlags_None = 0,
ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column. ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column.
ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column. ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column.
ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _ColumnsWidthStretch). ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingPolicyStretch).
ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _ColumnsWidthFixed and table is resizable). ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingPolicyFixed and table is resizable).
ImGuiTableColumnFlags_WidthAutoResize = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _ColumnsWidthFixed and table is not resizable). ImGuiTableColumnFlags_WidthAuto = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _SizingPolicyFixed and table is not resizable). Generally compatible with using right-most fitting widgets (e.g. SetNextItemWidth(-FLT_MIN))
ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing. ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.
ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.
ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column. ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.
@ -1169,7 +1179,7 @@ enum ImGuiTableColumnFlags_
ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse
// [Internal] Combinations and masks // [Internal] Combinations and masks
ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize, ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto,
ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable, ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable,
ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered, ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered,
ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30 // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge) ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30 // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge)
@ -2427,6 +2437,7 @@ struct ImDrawList
ImVector<ImVec2> _Path; // [Internal] current path building ImVector<ImVec2> _Path; // [Internal] current path building
ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back(). ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back().
ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!)
float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content
// If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui)
ImDrawList(const ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; } ImDrawList(const ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; }

@ -2032,18 +2032,18 @@ static void ShowDemoWindowWidgets()
ImGui::TreePop(); ImGui::TreePop();
} }
if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)")) if (ImGui::TreeNode("Querying Status (Edited/Active/Focused/Hovered etc.)"))
{ {
// Select an item type // Select an item type
const char* item_names[] = const char* item_names[] =
{ {
"Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat", "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat",
"InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "ListBox" "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox"
}; };
static int item_type = 1; static int item_type = 1;
ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names));
ImGui::SameLine(); ImGui::SameLine();
HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions."); HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
// Submit selected item item so we can query their status in the code following it. // Submit selected item item so we can query their status in the code following it.
bool ret = false; bool ret = false;
@ -2062,7 +2062,8 @@ static void ShowDemoWindowWidgets()
if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy)
if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node
if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy.
if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", &current, items, IM_ARRAYSIZE(items)); }
if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", &current, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); }
// Display the values of IsItemHovered() and other common item state functions. // Display the values of IsItemHovered() and other common item state functions.
// Note that the ImGuiHoveredFlags_XXX flags can be combined. // Note that the ImGuiHoveredFlags_XXX flags can be combined.
@ -3419,8 +3420,8 @@ static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
*p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch); *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch);
if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed)) if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed))
*p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed); *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed);
if (ImGui::CheckboxFlags("_WidthAutoResize", p_flags, ImGuiTableColumnFlags_WidthAutoResize)) if (ImGui::CheckboxFlags("_WidthAuto", p_flags, ImGuiTableColumnFlags_WidthAuto))
*p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthAutoResize); *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthAuto);
ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize); ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize);
ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder); ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder);
ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide); ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide);
@ -3647,17 +3648,19 @@ static void ShowDemoWindowTables()
ImGui::SetNextItemOpen(open_action != 0); ImGui::SetNextItemOpen(open_action != 0);
if (ImGui::TreeNode("Resizable, fixed")) if (ImGui::TreeNode("Resizable, fixed"))
{ {
// Here we use ImGuiTableFlags_ColumnsWidthFixed (even though _ScrollX is not set) // Here we use ImGuiTableFlags_SizingPolicyFixed (even though _ScrollX is not set)
// So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small) // So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small)
// If there is not enough available width to fit all columns, they will however be resized down. // If there is not enough available width to fit all columns, they will however be resized down.
// FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings
HelpMarker( HelpMarker(
"Using _Resizable + _ColumnsWidthFixed flags.\n" "Using _Resizable + _SizingPolicyFixed flags.\n"
"Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n" "Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n"
"Double-click a column border to auto-fit the column to its contents."); "Double-click a column border to auto-fit the column to its contents.");
static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody; static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody;
static bool use_all_width = true; static bool use_all_width = true;
ImGui::Checkbox("Use all width", &use_all_width); if (ImGui::RadioButton("fit", use_all_width == false)) { use_all_width = false; }
ImGui::SameLine();
if (ImGui::RadioButton("right-most edge", use_all_width == true)) { use_all_width = true; }
if (ImGui::BeginTable("##table1", 3, flags, ImVec2(use_all_width ? -FLT_MIN : 0.0f, 0.0f))) if (ImGui::BeginTable("##table1", 3, flags, ImVec2(use_all_width ? -FLT_MIN : 0.0f, 0.0f)))
{ {
@ -3680,7 +3683,7 @@ static void ShowDemoWindowTables()
if (ImGui::TreeNode("Resizable, mixed")) if (ImGui::TreeNode("Resizable, mixed"))
{ {
HelpMarker("Using columns flag to alter resizing policy on a per-column basis."); HelpMarker("Using columns flag to alter resizing policy on a per-column basis.");
static ImGuiTableFlags flags = ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; static ImGuiTableFlags flags = ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
if (ImGui::BeginTable("##table1", 3, flags)) if (ImGui::BeginTable("##table1", 3, flags))
{ {
@ -3757,7 +3760,7 @@ static void ShowDemoWindowTables()
} }
// Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column) // Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column)
if (ImGui::BeginTable("##table2", 3, flags | ImGuiTableFlags_ColumnsWidthFixed, ImVec2(0.0f, 0.0f))) if (ImGui::BeginTable("##table2", 3, flags | ImGuiTableFlags_SizingPolicyFixed, ImVec2(0.0f, 0.0f)))
{ {
ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("One");
ImGui::TableSetupColumn("Two"); ImGui::TableSetupColumn("Two");
@ -3897,7 +3900,7 @@ static void ShowDemoWindowTables()
if (ImGui::BeginTable("##table1", 4, flags)) if (ImGui::BeginTable("##table1", 4, flags))
{ {
// We could also set ImGuiTableFlags_ColumnsWidthFixed on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. // We could also set ImGuiTableFlags_SizingPolicyFixed on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed.
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f);
ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f);
@ -3965,7 +3968,7 @@ static void ShowDemoWindowTables()
if (ImGui::TreeNode("Horizontal scrolling")) if (ImGui::TreeNode("Horizontal scrolling"))
{ {
HelpMarker( HelpMarker(
"When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_ColumnsWidthFixed," "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingPolicyFixed,"
"as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n" "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n"
"Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX," "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX,"
"because the container window won't automatically extend vertically to fix contents (this may be improved in future versions)."); "because the container window won't automatically extend vertically to fix contents (this may be improved in future versions).");
@ -3974,6 +3977,7 @@ static void ShowDemoWindowTables()
static int freeze_rows = 1; static int freeze_rows = 1;
PushStyleCompact(); PushStyleCompact();
ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); ImGui::SetNextItemWidth(ImGui::GetFrameHeight());
@ -4055,7 +4059,7 @@ static void ShowDemoWindowTables()
// We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in
// a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down) // a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down)
const ImGuiTableFlags flags const ImGuiTableFlags flags
= ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY = ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
| ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV
| ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable; | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable;
ImVec2 size = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 9); ImVec2 size = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 9);
@ -4086,11 +4090,11 @@ static void ShowDemoWindowTables()
if (open_action != -1) if (open_action != -1)
ImGui::SetNextItemOpen(open_action != 0); ImGui::SetNextItemOpen(open_action != 0);
if (ImGui::TreeNode("Recursive")) if (ImGui::TreeNode("Nested"))
{ {
HelpMarker("This demonstrate embedding a table into another table cell."); HelpMarker("This demonstrate embedding a table into another table cell.");
if (ImGui::BeginTable("recurse1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) if (ImGui::BeginTable("nested1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
{ {
ImGui::TableSetupColumn("A0"); ImGui::TableSetupColumn("A0");
ImGui::TableSetupColumn("A1"); ImGui::TableSetupColumn("A1");
@ -4100,7 +4104,7 @@ static void ShowDemoWindowTables()
ImGui::Text("A0 Cell 0"); ImGui::Text("A0 Cell 0");
{ {
float rows_height = TEXT_BASE_HEIGHT * 2; float rows_height = TEXT_BASE_HEIGHT * 2;
if (ImGui::BeginTable("recurse2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) if (ImGui::BeginTable("nested2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable))
{ {
ImGui::TableSetupColumn("B0"); ImGui::TableSetupColumn("B0");
ImGui::TableSetupColumn("B1"); ImGui::TableSetupColumn("B1");
@ -4139,26 +4143,26 @@ static void ShowDemoWindowTables()
static int column_count = 3; static int column_count = 3;
PushStyleCompact(); PushStyleCompact();
ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 22); ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
ImGui::Combo("Contents", &contents_type, "Short Text\0Long Text\0Button\0Fill Button\0InputText\0"); ImGui::Combo("Contents", &contents_type, "Short Text\0Long Text\0Button\0Fill Button\0InputText\0");
if (contents_type == CT_FillButton) if (contents_type == CT_FillButton)
{ {
ImGui::SameLine(); ImGui::SameLine();
HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width."); HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width.");
} }
ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 22);
ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp); ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
ImGui::PopItemWidth();
ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH); ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH);
ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH); ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH);
ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV); ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV);
ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV); ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags, ImGuiTableFlags_ColumnsWidthStretch)) if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretch", &flags, ImGuiTableFlags_SizingPolicyStretch))
flags &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other flags &= ~ImGuiTableFlags_SizingPolicyFixed; // Can't specify both sizing polices so we clear the other
ImGui::SameLine(); HelpMarker("Default if _ScrollX if disabled. Makes columns use _WidthStretch policy by default."); ImGui::SameLine(); HelpMarker("Default if _ScrollX if disabled. Makes columns use _WidthStretch policy by default.");
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags, ImGuiTableFlags_ColumnsWidthFixed)) if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixed", &flags, ImGuiTableFlags_SizingPolicyFixed))
flags &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other flags &= ~ImGuiTableFlags_SizingPolicyStretch; // Can't specify both sizing polices so we clear the other
ImGui::SameLine(); HelpMarker("Default if _ScrollX if enabled. Makes columns use _WidthFixed by default, or _WidthFixedResize if _Resizable is not set."); ImGui::SameLine(); HelpMarker("Default if _ScrollX if enabled. Makes columns use _WidthFixed by default, or _WidthFixedResize if _Resizable is not set.");
ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths); ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth."); ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.");
@ -4236,20 +4240,21 @@ static void ShowDemoWindowTables()
"Showcase using Stretch columns + ScrollX together: " "Showcase using Stretch columns + ScrollX together: "
"this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n" "this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
"Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense."); "Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense.");
static ImGuiTableFlags flags3 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg; static ImGuiTableFlags flags3 = ImGuiTableFlags_SizingPolicyStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
static float inner_width = 1000.0f; static float inner_width = 1000.0f;
PushStyleCompact(); PushStyleCompact();
ImGui::PushID("flags3"); ImGui::PushID("flags3");
ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags3, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags3, ImGuiTableFlags_ScrollX);
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags3, ImGuiTableFlags_ColumnsWidthStretch)) if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretch", &flags3, ImGuiTableFlags_SizingPolicyStretch))
flags3 &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other flags3 &= ~ImGuiTableFlags_SizingPolicyFixed; // Can't specify both sizing polices so we clear the other
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags3, ImGuiTableFlags_ColumnsWidthFixed)) if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixed", &flags3, ImGuiTableFlags_SizingPolicyFixed))
flags3 &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other flags3 &= ~ImGuiTableFlags_SizingPolicyStretch; // Can't specify both sizing polices so we clear the other
ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 10.0f);
ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f"); ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
ImGui::PopItemWidth();
ImGui::PopID(); ImGui::PopID();
PopStyleCompact(); PopStyleCompact();
if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width)) if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_SizingPolicyStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width))
{ {
for (int cell = 0; cell < 20 * 7; cell++) for (int cell = 0; cell < 20 * 7; cell++)
{ {
@ -4289,7 +4294,7 @@ static void ShowDemoWindowTables()
// The default value of outer_size.x is -FLT_MIN which right-align tables. // The default value of outer_size.x is -FLT_MIN which right-align tables.
// Using outer_size.x == 0.0f on a table with no scrolling and no stretch column we can make them tighter. // Using outer_size.x == 0.0f on a table with no scrolling and no stretch column we can make them tighter.
ImGui::Text("Using auto/all width, using NoHostExtendY:"); ImGui::Text("Using auto/all width, using NoHostExtendY:");
static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_ColumnsWidthFixed; static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingPolicyFixed;
static bool use_all_width = false; static bool use_all_width = false;
ImGui::Checkbox("Use all width", &use_all_width); ImGui::Checkbox("Use all width", &use_all_width);
ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
@ -4561,7 +4566,7 @@ static void ShowDemoWindowTables()
// [2.2] Right-click on the ".." to open a custom popup // [2.2] Right-click on the ".." to open a custom popup
// [2.3] Right-click in columns to open another custom popup // [2.3] Right-click in columns to open another custom popup
HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body)."); HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body).");
ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders; ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders;
if (ImGui::BeginTable("##table2", COLUMNS_COUNT, flags2)) if (ImGui::BeginTable("##table2", COLUMNS_COUNT, flags2))
{ {
ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("One");
@ -4635,7 +4640,7 @@ static void ShowDemoWindowTables()
char buf[32]; char buf[32];
sprintf(buf, "Synced Table %d", n); sprintf(buf, "Synced Table %d", n);
bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen); bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen);
if (open && ImGui::BeginTable("Table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_NoSavedSettings)) if (open && ImGui::BeginTable("Table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_NoSavedSettings))
{ {
ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("One");
ImGui::TableSetupColumn("Two"); ImGui::TableSetupColumn("Two");
@ -4751,7 +4756,7 @@ static void ShowDemoWindowTables()
| ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti
| ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody
| ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY
| ImGuiTableFlags_ColumnsWidthFixed; | ImGuiTableFlags_SizingPolicyFixed;
enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow }; enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow };
static int contents_type = CT_SelectableSpanRow; static int contents_type = CT_SelectableSpanRow;
@ -4800,11 +4805,11 @@ static void ShowDemoWindowTables()
if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen)) if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen))
{ {
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags, ImGuiTableFlags_ColumnsWidthStretch)) if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretch", &flags, ImGuiTableFlags_SizingPolicyStretch))
flags &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other flags &= ~ImGuiTableFlags_SizingPolicyFixed; // Can't specify both sizing polices so we clear the other
ImGui::SameLine(); HelpMarker("[Default if ScrollX is off]\nFit all columns within available width (or specified inner_width). Fixed and Stretch columns allowed."); ImGui::SameLine(); HelpMarker("[Default if ScrollX is off]\nFit all columns within available width (or specified inner_width). Fixed and Stretch columns allowed.");
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags, ImGuiTableFlags_ColumnsWidthFixed)) if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixed", &flags, ImGuiTableFlags_SizingPolicyFixed))
flags &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other flags &= ~ImGuiTableFlags_SizingPolicyStretch; // Can't specify both sizing polices so we clear the other
ImGui::SameLine(); HelpMarker("[Default if ScrollX is on]\nEnlarge as needed: enable scrollbar if ScrollX is enabled, otherwise extend parent window's contents rectangle. Only Fixed columns allowed. Stretched columns will calculate their width assuming no scrolling."); ImGui::SameLine(); HelpMarker("[Default if ScrollX is on]\nEnlarge as needed: enable scrollbar if ScrollX is enabled, otherwise extend parent window's contents rectangle. Only Fixed columns allowed. Stretched columns will calculate their width assuming no scrolling.");
ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible); ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible);
@ -4851,6 +4856,7 @@ static void ShowDemoWindowTables()
{ {
ImGui::Checkbox("show_headers", &show_headers); ImGui::Checkbox("show_headers", &show_headers);
ImGui::Checkbox("show_wrapped_text", &show_wrapped_text); ImGui::Checkbox("show_wrapped_text", &show_wrapped_text);
ImGui::DragFloat2("##OuterSize", &outer_size_value.x); ImGui::DragFloat2("##OuterSize", &outer_size_value.x);
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::Checkbox("outer_size", &outer_size_enabled); ImGui::Checkbox("outer_size", &outer_size_enabled);
@ -4862,12 +4868,14 @@ static void ShowDemoWindowTables()
"- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set)."); "- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set).");
// From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling. // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling.
// To facilitate experimentation we expose two values and will select the right one depending on active flags. // To facilitate toying with this demo we will actually pass 0.0f to the BeginTable() when ScrollX is disabled.
ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX); ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX);
ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX); ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX);
ImGui::SameLine(); HelpMarker("Specify height of the Selectable item."); ImGui::SameLine(); HelpMarker("Specify height of the Selectable item.");
ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999); ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999);
ImGui::Combo("contents_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names)); ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names));
//filter.Draw("filter"); //filter.Draw("filter");
ImGui::TreePop(); ImGui::TreePop();
} }
@ -4909,8 +4917,8 @@ static void ShowDemoWindowTables()
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, -1.0f, MyItemColumnID_ID); ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, -1.0f, MyItemColumnID_ID);
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name);
ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action); ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action);
ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending, 1.0f, MyItemColumnID_Quantity); ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending, -1.0f, MyItemColumnID_Quantity);
ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch, 1.0f, MyItemColumnID_Description); ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Description);
ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort); ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort);
ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows); ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows);
@ -6119,7 +6127,7 @@ struct ExampleAppConsole
// Portable helpers // Portable helpers
static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; } static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; } static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; }
static char* Strdup(const char* s) { size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); } static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; } static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
void ClearLog() void ClearLog()

@ -210,7 +210,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_Separator] = colors[ImGuiCol_Border]; colors[ImGuiCol_Separator] = colors[ImGuiCol_Border];
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
@ -244,7 +244,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f);
colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f); colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f); colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);
@ -272,7 +272,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f); colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f); colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f);
@ -335,7 +335,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f); colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f);
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f);
colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f);
colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f); colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f);
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f);
@ -411,6 +411,7 @@ void ImDrawList::_ResetForNewFrame()
_Path.resize(0); _Path.resize(0);
_Splitter.Clear(); _Splitter.Clear();
CmdBuffer.push_back(ImDrawCmd()); CmdBuffer.push_back(ImDrawCmd());
_FringeScale = 1.0f;
} }
void ImDrawList::_ClearFreeMemory() void ImDrawList::_ClearFreeMemory()
@ -686,12 +687,12 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const ImVec2 opaque_uv = _Data->TexUvWhitePixel; const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
const bool thick_line = (thickness > 1.0f); const bool thick_line = (thickness > _FringeScale);
if (Flags & ImDrawListFlags_AntiAliasedLines) if (Flags & ImDrawListFlags_AntiAliasedLines)
{ {
// Anti-aliased stroke // Anti-aliased stroke
const float AA_SIZE = 1.0f; const float AA_SIZE = _FringeScale;
const ImU32 col_trans = col & ~IM_COL32_A_MASK; const ImU32 col_trans = col & ~IM_COL32_A_MASK;
// Thicknesses <1.0 should behave like thickness 1.0 // Thicknesses <1.0 should behave like thickness 1.0
@ -702,7 +703,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
// Do we want to draw this line using a texture? // Do we want to draw this line using a texture?
// - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved. // - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved.
// - If AA_SIZE is not 1.0f we cannot use the texture path. // - If AA_SIZE is not 1.0f we cannot use the texture path.
const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f); const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f);
// We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off // We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off
IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)); IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines));
@ -944,7 +945,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
if (Flags & ImDrawListFlags_AntiAliasedFill) if (Flags & ImDrawListFlags_AntiAliasedFill)
{ {
// Anti-aliased Fill // Anti-aliased Fill
const float AA_SIZE = 1.0f; const float AA_SIZE = _FringeScale;
const ImU32 col_trans = col & ~IM_COL32_A_MASK; const ImU32 col_trans = col & ~IM_COL32_A_MASK;
const int idx_count = (points_count - 2)*3 + points_count * 6; const int idx_count = (points_count - 2)*3 + points_count * 6;
const int vtx_count = (points_count * 2); const int vtx_count = (points_count * 2);
@ -2176,10 +2177,11 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++)
if (cfg.DstFont == atlas->Fonts[output_i]) if (cfg.DstFont == atlas->Fonts[output_i])
src_tmp.DstIndex = output_i; src_tmp.DstIndex = output_i;
IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array?
if (src_tmp.DstIndex == -1) if (src_tmp.DstIndex == -1)
{
IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array?
return false; return false;
}
// Initialize helper structure for font loading and verify that the TTF/OTF data is correct // Initialize helper structure for font loading and verify that the TTF/OTF data is correct
const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo);
IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found."); IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found.");

@ -1444,9 +1444,11 @@ struct ImGuiContext
float WheelingWindowTimer; float WheelingWindowTimer;
// Item/widgets state and tracking information // Item/widgets state and tracking information
ImGuiID HoveredId; // Hovered widget ImGuiID HoveredId; // Hovered widget, filled during the frame
ImGuiID HoveredIdPreviousFrame; ImGuiID HoveredIdPreviousFrame;
bool HoveredIdAllowOverlap; bool HoveredIdAllowOverlap;
bool HoveredIdUsingMouseWheel; // Hovered widget will use mouse wheel. Blocks scrolling the underlying window.
bool HoveredIdPreviousFrameUsingMouseWheel;
bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0. bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0.
float HoveredIdTimer; // Measure contiguous hovering time float HoveredIdTimer; // Measure contiguous hovering time
float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active
@ -1459,6 +1461,7 @@ struct ImGuiContext
bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state.
bool ActiveIdHasBeenEditedThisFrame; bool ActiveIdHasBeenEditedThisFrame;
bool ActiveIdUsingMouseWheel; // Active widget will want to read mouse wheel. Blocks scrolling the underlying window.
ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it)
ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs. ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs.
ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array. ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array.
@ -1681,6 +1684,7 @@ struct ImGuiContext
HoveredId = HoveredIdPreviousFrame = 0; HoveredId = HoveredIdPreviousFrame = 0;
HoveredIdAllowOverlap = false; HoveredIdAllowOverlap = false;
HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false;
HoveredIdDisabled = false; HoveredIdDisabled = false;
HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f; HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f;
ActiveId = 0; ActiveId = 0;
@ -1692,6 +1696,7 @@ struct ImGuiContext
ActiveIdHasBeenPressedBefore = false; ActiveIdHasBeenPressedBefore = false;
ActiveIdHasBeenEditedBefore = false; ActiveIdHasBeenEditedBefore = false;
ActiveIdHasBeenEditedThisFrame = false; ActiveIdHasBeenEditedThisFrame = false;
ActiveIdUsingMouseWheel = false;
ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingNavDirMask = 0x00;
ActiveIdUsingNavInputMask = 0x00; ActiveIdUsingNavInputMask = 0x00;
ActiveIdUsingKeyInputMask = 0x00; ActiveIdUsingKeyInputMask = 0x00;
@ -2212,6 +2217,7 @@ struct ImGuiTable
float BorderX1; float BorderX1;
float BorderX2; float BorderX2;
float HostIndentX; float HostIndentX;
float MinColumnWidth;
float OuterPaddingX; float OuterPaddingX;
float CellPaddingX; // Padding from each borders float CellPaddingX; // Padding from each borders
float CellPaddingY; float CellPaddingY;
@ -2220,7 +2226,7 @@ struct ImGuiTable
float LastOuterHeight; // Outer height from last frame float LastOuterHeight; // Outer height from last frame
float LastFirstRowHeight; // Height of first row from last frame float LastFirstRowHeight; // Height of first row from last frame
float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details.
float ColumnsTotalWidth; // Sum of current column width float ColumnsGivenWidth; // Sum of current column width
float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window
float ResizedColumnNextWidth; float ResizedColumnNextWidth;
float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table. float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table.
@ -2284,7 +2290,7 @@ struct ImGuiTable
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1) bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
bool IsResetAllRequest; bool IsResetAllRequest;
bool IsResetDisplayOrderRequest; bool IsResetDisplayOrderRequest;
bool IsUnfrozen; // Set when we got past the frozen row. bool IsUnfrozenRows; // Set when we got past the frozen row.
bool IsOuterRectAutoFitX; // Set when outer_size.x == 0.0f in BeginTable(), scrolling is disabled, and there are stretch columns. bool IsOuterRectAutoFitX; // Set when outer_size.x == 0.0f in BeginTable(), scrolling is disabled, and there are stretch columns.
bool MemoryCompacted; bool MemoryCompacted;
bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis
@ -2482,6 +2488,7 @@ namespace ImGui
// Inputs // Inputs
// FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions.
IMGUI_API void SetItemUsingMouseWheel();
inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; }
inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; }
inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; }
@ -2581,6 +2588,7 @@ namespace ImGui
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table); IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column); IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column); IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column);
IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column);
IMGUI_API void TableBeginRow(ImGuiTable* table); IMGUI_API void TableBeginRow(ImGuiTable* table);
IMGUI_API void TableEndRow(ImGuiTable* table); IMGUI_API void TableEndRow(ImGuiTable* table);
IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n); IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n);
@ -2588,7 +2596,6 @@ namespace ImGui
IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n); IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n); IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0); IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0);
IMGUI_API float TableGetMinColumnWidth();
IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n); IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
@ -2663,6 +2670,8 @@ namespace ImGui
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
IMGUI_API ImGuiID GetWindowResizeID(ImGuiWindow* window, int n); // 0..3: corners, 4..7: borders IMGUI_API ImGuiID GetWindowResizeID(ImGuiWindow* window, int n); // 0..3: corners, 4..7: borders
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags); IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags);
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value);
// Widgets low-level behaviors // Widgets low-level behaviors
IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0);

@ -98,12 +98,34 @@ Index of this file:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// TABLES CULLING // COLUMNS SIZING POLICIES
//-----------------------------------------------------------------------------
// About overriding column width/weight with TableSetupColumn():
// We use a default parameter of 'init_width_or_weight == -1'.
// - With ImGuiTableColumnFlags_WidthAuto, init_width (ignored) --> width is automatic
// - With ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic
// - With ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom
// - With ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f
// - With ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom
// Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f)
// and you can fit a 100.0f wide item in it without clipping and with full padding.
//-----------------------------------------------------------------------------
// About default width policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag)
// - When Table policy ImGuiTableFlags_SizingPolicyStretch --> default Column policy is ImGuiTableColumnFlags_WidthStretch
// - When Table policy ImGuiTableFlags_SizingPolicyFixed and (Table is Resizable or init_width > 0) --> default Column policy is ImGuiTableColumnFlags_WidthFixed
// - When Table policy ImGuiTableFlags_SizingPolicyFixed and (Table is not Resizable and init_width <= 0) --> default Column policy is ImGuiTableColumnFlags_WidthAuto
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// TABLES CLIPPING/CULLING
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About clipping/culling of Rows in Tables: // About clipping/culling of Rows in Tables:
// - For large numbers of rows, it is recommended you use ImGuiListClipper to only submit visible rows. // - For large numbers of rows, it is recommended you use ImGuiListClipper to only submit visible rows.
// ImGuiListClipper is reliant on the fact that rows are of equal height. // ImGuiListClipper is reliant on the fact that rows are of equal height.
// See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper. // See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper.
// - Note that columns with the ImGuiTableColumnFlags_WidthAuto policy generally don't play well with using the clipper,
// and by default a table with _ScrollX but without _Resizable will have columns default to _WidthAuto.
// So, if you want to use the clipper, make sure to either enable _Resizable, either setup columns explicitly with _WidthFixed.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// About clipping/culling of Columns in Tables: // About clipping/culling of Columns in Tables:
// - Case A: column is not hidden by user, and at least partially in sight (most common case). // - Case A: column is not hidden by user, and at least partially in sight (most common case).
@ -192,8 +214,8 @@ static const float TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER = 0.06f; // Delay/tim
inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window) inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window)
{ {
// Adjust flags: set default sizing policy // Adjust flags: set default sizing policy
if ((flags & (ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ColumnsWidthFixed)) == 0) if ((flags & (ImGuiTableFlags_SizingPolicyStretch | ImGuiTableFlags_SizingPolicyFixed)) == 0)
flags |= (flags & ImGuiTableFlags_ScrollX) ? ImGuiTableFlags_ColumnsWidthFixed : ImGuiTableFlags_ColumnsWidthStretch; flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_SizingPolicyFixed : ImGuiTableFlags_SizingPolicyStretch;
// Adjust flags: disable Resizable when using SameWidths (done above enforcing BordersInnerV) // Adjust flags: disable Resizable when using SameWidths (done above enforcing BordersInnerV)
if (flags & ImGuiTableFlags_SameWidths) if (flags & ImGuiTableFlags_SameWidths)
@ -370,7 +392,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any
table->FreezeColumnsRequest = table->FreezeColumnsCount = 0; table->FreezeColumnsRequest = table->FreezeColumnsCount = 0;
table->IsUnfrozen = true; table->IsUnfrozenRows = true;
table->DeclColumnsCount = 0; table->DeclColumnsCount = 0;
// Using opaque colors facilitate overlapping elements of the grid // Using opaque colors facilitate overlapping elements of the grid
@ -564,14 +586,14 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I
// Sizing Policy // Sizing Policy
if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0)
{ {
// FIXME-TABLE: Inconsistent to promote columns to WidthAutoResize // FIXME-TABLE: Inconsistent to promote columns to WidthAuto
if (table->Flags & ImGuiTableFlags_ColumnsWidthFixed) if (table->Flags & ImGuiTableFlags_SizingPolicyFixed)
flags |= ((table->Flags & ImGuiTableFlags_Resizable) && !(flags & ImGuiTableColumnFlags_NoResize)) ? ImGuiTableColumnFlags_WidthFixed : ImGuiTableColumnFlags_WidthAutoResize; flags |= ((table->Flags & ImGuiTableFlags_Resizable) && !(flags & ImGuiTableColumnFlags_NoResize)) ? ImGuiTableColumnFlags_WidthFixed : ImGuiTableColumnFlags_WidthAuto;
else else
flags |= ImGuiTableColumnFlags_WidthStretch; flags |= ImGuiTableColumnFlags_WidthStretch;
} }
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used. IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used.
if (flags & ImGuiTableColumnFlags_WidthAutoResize) if (flags & ImGuiTableColumnFlags_WidthAuto)
flags |= ImGuiTableColumnFlags_NoResize; flags |= ImGuiTableColumnFlags_NoResize;
// Sorting // Sorting
@ -609,22 +631,23 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I
// Layout columns for the frame. This is in essence the followup to BeginTable(). // Layout columns for the frame. This is in essence the followup to BeginTable().
// Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first. // Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first.
// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for WidthAutoResize // FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns.
// columns, increase feedback side-effect with widgets relying on WorkRect.Max.x. Maybe provide a default distribution // Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns?
// for WidthAutoResize columns?
void ImGui::TableUpdateLayout(ImGuiTable* table) void ImGui::TableUpdateLayout(ImGuiTable* table)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
IM_ASSERT(table->IsLayoutLocked == false); IM_ASSERT(table->IsLayoutLocked == false);
// [Part 1] Apply/lock Enabled and Order states.
// Process columns in their visible orders as we are building the Prev/Next indices.
int last_visible_column_idx = -1;
bool want_column_auto_fit = false;
table->IsDefaultDisplayOrder = true; table->IsDefaultDisplayOrder = true;
table->ColumnsEnabledCount = 0; table->ColumnsEnabledCount = 0;
table->EnabledMaskByIndex = 0x00; table->EnabledMaskByIndex = 0x00;
table->EnabledMaskByDisplayOrder = 0x00; table->EnabledMaskByDisplayOrder = 0x00;
table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE
// [Part 1] Apply/lock Enabled and Order states. Calculate auto/ideal width for columns.
// Process columns in their visible orders as we are building the Prev/Next indices.
int last_visible_column_idx = -1;
bool want_auto_fit = false;
for (int order_n = 0; order_n < table->ColumnsCount; order_n++) for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{ {
const int column_n = table->DisplayOrderToIndex[order_n]; const int column_n = table->DisplayOrderToIndex[order_n];
@ -657,36 +680,40 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->IsSortSpecsDirty = true; table->IsSortSpecsDirty = true;
bool start_auto_fit = false; bool start_auto_fit = false;
if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize)) if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto))
start_auto_fit = column->WidthRequest < 0.0f; start_auto_fit = column->WidthRequest < 0.0f;
else else
start_auto_fit = column->StretchWeight < 0.0f; start_auto_fit = column->StretchWeight < 0.0f;
if (start_auto_fit) if (start_auto_fit)
column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames
if (column->AutoFitQueue != 0x00)
want_column_auto_fit = true;
ImU64 index_mask = (ImU64)1 << column_n; ImU64 index_mask = (ImU64)1 << column_n;
ImU64 display_order_mask = (ImU64)1 << column->DisplayOrder; ImU64 display_order_mask = (ImU64)1 << column->DisplayOrder;
if (column->IsEnabled) if (!column->IsEnabled)
{
// Mark as enabled and link to previous/next enabled column
column->PrevEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx;
column->NextEnabledColumn = -1;
if (last_visible_column_idx != -1)
table->Columns[last_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n;
column->IndexWithinEnabledSet = table->ColumnsEnabledCount;
table->ColumnsEnabledCount++;
table->EnabledMaskByIndex |= index_mask;
table->EnabledMaskByDisplayOrder |= display_order_mask;
last_visible_column_idx = column_n;
}
else
{ {
column->IndexWithinEnabledSet = -1; column->IndexWithinEnabledSet = -1;
continue;
} }
// Mark as enabled and link to previous/next enabled column
column->PrevEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx;
column->NextEnabledColumn = -1;
if (last_visible_column_idx != -1)
table->Columns[last_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n;
column->IndexWithinEnabledSet = table->ColumnsEnabledCount;
table->ColumnsEnabledCount++;
table->EnabledMaskByIndex |= index_mask;
table->EnabledMaskByDisplayOrder |= display_order_mask;
last_visible_column_idx = column_n;
IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder); IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder);
// Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping)
// Combine width from regular rows + width from headers unless requested not to.
if (!column->IsPreserveWidthAuto)
column->WidthAuto = TableGetColumnWidthAuto(table, column);
if (column->AutoFitQueue != 0x00)
want_auto_fit = true;
} }
if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate))
table->IsSortSpecsDirty = true; table->IsSortSpecsDirty = true;
@ -696,13 +723,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible // [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible
// to avoid the column fitting to wait until the first visible frame of the child container (may or not be a good thing). // to avoid the column fitting to wait until the first visible frame of the child container (may or not be a good thing).
// FIXME-TABLE: for always auto-resizing columns may not want to do that all the time. // FIXME-TABLE: for always auto-resizing columns may not want to do that all the time.
if (want_column_auto_fit && table->OuterWindow != table->InnerWindow) if (want_auto_fit && table->OuterWindow != table->InnerWindow)
table->InnerWindow->SkipItems = false; table->InnerWindow->SkipItems = false;
if (want_column_auto_fit) if (want_auto_fit)
table->IsSettingsDirty = true; table->IsSettingsDirty = true;
// [Part 3] Fix column flags. Calculate ideal width for columns. Count how many fixed/stretch columns we have and sum of weights. // [Part 3] Fix column flags. Count how many fixed/stretch columns we have and sum of weights.
const float min_column_width = TableGetMinColumnWidth();
int count_fixed = 0; // Number of columns that have fixed sizing policy (not stretched sizing policy) (this is NOT the opposite of count_resizable!) int count_fixed = 0; // Number of columns that have fixed sizing policy (not stretched sizing policy) (this is NOT the opposite of count_resizable!)
int count_resizable = 0; // Number of columns the user can resize (this is NOT the opposite of count_fixed!) int count_resizable = 0; // Number of columns the user can resize (this is NOT the opposite of count_fixed!)
float sum_weights_stretched = 0.0f; // Sum of all weights for weighted columns. float sum_weights_stretched = 0.0f; // Sum of all weights for weighted columns.
@ -719,31 +745,16 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if ((column->Flags & ImGuiTableColumnFlags_NoResize) == 0) if ((column->Flags & ImGuiTableColumnFlags_NoResize) == 0)
count_resizable++; count_resizable++;
// Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping) if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto))
// Combine width from regular rows + width from headers unless requested not to.
if (!column->IsPreserveWidthAuto)
{ {
const float content_width_body = ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX; // Non-resizable columns keep their requested width
const float content_width_headers = column->ContentMaxXHeadersIdeal - column->WorkMinX;
float width_auto = content_width_body;
if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth))
width_auto = ImMax(width_auto, content_width_headers);
width_auto = ImMax(width_auto, min_column_width);
// Non-resizable columns also submit their requested width
if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f) if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f)
if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize)) if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize))
width_auto = ImMax(width_auto, column->InitStretchWeightOrWidth); column->WidthRequest = column->WidthAuto = ImMax(column->WidthAuto, column->InitStretchWeightOrWidth); // Use user value regardless of IsPreserveWidthAuto
column->WidthAuto = width_auto;
}
column->IsPreserveWidthAuto = false;
if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize))
{
// Process auto-fit for non-stretched columns // Process auto-fit for non-stretched columns
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAutoResize) && column->IsVisibleX)) if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAuto) && column->IsVisibleX))
column->WidthRequest = column->WidthAuto; column->WidthRequest = column->WidthAuto;
// FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
@ -751,8 +762,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// large height (= first frame scrollbar display very off + clipper would skip lots of items). // large height (= first frame scrollbar display very off + clipper would skip lots of items).
// This is merely making the side-effect less extreme, but doesn't properly fixes it. // This is merely making the side-effect less extreme, but doesn't properly fixes it.
// FIXME: Move this to ->WidthGiven to avoid temporary lossyless? // FIXME: Move this to ->WidthGiven to avoid temporary lossyless?
if (column->AutoFitQueue > 0x01 && table->IsInitializing) // FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller.
column->WidthRequest = ImMax(column->WidthRequest, min_column_width * 4.0f); // FIXME-TABLE: Another constant/scale? if (column->AutoFitQueue > 0x01 && table->IsInitializing && !column->IsPreserveWidthAuto)
column->WidthRequest = ImMax(column->WidthRequest, table->MinColumnWidth * 4.0f); // FIXME-TABLE: Another constant/scale?
count_fixed += 1; count_fixed += 1;
sum_width_fixed_requests += column->WidthRequest; sum_width_fixed_requests += column->WidthRequest;
} }
@ -770,6 +782,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (table->RightMostStretchedColumn == -1 || table->Columns[table->RightMostStretchedColumn].DisplayOrder < column->DisplayOrder) if (table->RightMostStretchedColumn == -1 || table->Columns[table->RightMostStretchedColumn].DisplayOrder < column->DisplayOrder)
table->RightMostStretchedColumn = (ImGuiTableColumnIdx)column_n; table->RightMostStretchedColumn = (ImGuiTableColumnIdx)column_n;
} }
column->IsPreserveWidthAuto = false;
max_width_auto = ImMax(max_width_auto, column->WidthAuto); max_width_auto = ImMax(max_width_auto, column->WidthAuto);
sum_width_fixed_requests += table->CellPaddingX * 2.0f; sum_width_fixed_requests += table->CellPaddingX * 2.0f;
} }
@ -786,7 +799,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n))) if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
continue; continue;
ImGuiTableColumn* column = &table->Columns[column_n]; ImGuiTableColumn* column = &table->Columns[column_n];
if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize)) if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto))
{ {
sum_width_fixed_requests += max_width_auto - column->WidthRequest; // Update old sum sum_width_fixed_requests += max_width_auto - column->WidthRequest; // Update old sum
column->WidthRequest = max_width_auto; column->WidthRequest = max_width_auto;
@ -807,8 +820,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
const float width_avail = ((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth(); const float width_avail = ((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth();
const float width_avail_for_stretched_columns = mixed_same_widths ? 0.0f : width_avail - width_spacings - sum_width_fixed_requests; const float width_avail_for_stretched_columns = mixed_same_widths ? 0.0f : width_avail - width_spacings - sum_width_fixed_requests;
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns; float width_remaining_for_stretched_columns = width_avail_for_stretched_columns;
table->ColumnsTotalWidth = width_spacings; table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
table->ColumnsAutoFitWidth = width_spacings;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
{ {
if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n))) if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
@ -819,7 +831,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) && !mixed_same_widths) if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) && !mixed_same_widths)
{ {
float weight_ratio = column->StretchWeight / sum_weights_stretched; float weight_ratio = column->StretchWeight / sum_weights_stretched;
column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, min_column_width) + 0.01f); column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, table->MinColumnWidth) + 0.01f);
width_remaining_for_stretched_columns -= column->WidthRequest; width_remaining_for_stretched_columns -= column->WidthRequest;
} }
@ -829,9 +841,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->Flags |= ImGuiTableColumnFlags_NoDirectResize_; column->Flags |= ImGuiTableColumnFlags_NoDirectResize_;
// Assign final width, record width in case we will need to shrink // Assign final width, record width in case we will need to shrink
column->WidthGiven = ImFloor(ImMax(column->WidthRequest, min_column_width)); column->WidthGiven = ImFloor(ImMax(column->WidthRequest, table->MinColumnWidth));
table->ColumnsTotalWidth += column->WidthGiven + table->CellPaddingX * 2.0f; table->ColumnsGivenWidth += column->WidthGiven;
table->ColumnsAutoFitWidth += column->WidthAuto + table->CellPaddingX * 2.0f;
} }
// [Part 6] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column). // [Part 6] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
@ -857,6 +868,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// [Part 7] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column // [Part 7] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column
// Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping. // Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping.
int visible_n = 0; int visible_n = 0;
bool offset_x_frozen = (table->FreezeColumnsCount > 0);
float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1; float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1;
ImRect host_clip_rect = table->InnerClipRect; ImRect host_clip_rect = table->InnerClipRect;
//host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2; //host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2;
@ -869,8 +881,11 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column->NavLayerCurrent = (ImS8)((table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); column->NavLayerCurrent = (ImS8)((table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main);
if (table->FreezeColumnsCount > 0 && table->FreezeColumnsCount == visible_n) if (offset_x_frozen && table->FreezeColumnsCount == visible_n)
{
offset_x += work_rect.Min.x - table->OuterRect.Min.x; offset_x += work_rect.Min.x - table->OuterRect.Min.x;
offset_x_frozen = false;
}
// Clear status flags // Clear status flags
column->Flags &= ~ImGuiTableColumnFlags_StatusMask_; column->Flags &= ~ImGuiTableColumnFlags_StatusMask_;
@ -900,7 +915,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Lock width based on start position and minimum/maximum width for this position // Lock width based on start position and minimum/maximum width for this position
float max_width = TableGetMaxColumnWidth(table, column_n); float max_width = TableGetMaxColumnWidth(table, column_n);
column->WidthGiven = ImMin(column->WidthGiven, max_width); column->WidthGiven = ImMin(column->WidthGiven, max_width);
column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, min_column_width)); column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth));
column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
// Lock other positions // Lock other positions
@ -978,7 +993,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// [Part 8] Detect/store when we are hovering the unused space after the right-most column (so e.g. context menus can react on it) // [Part 8] Detect/store when we are hovering the unused space after the right-most column (so e.g. context menus can react on it)
// Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either
// because of using _WidthAutoResize/_WidthStretch). This will hide the resizing option from the context menu. // because of using _WidthAuto/_WidthStretch). This will hide the resizing option from the context menu.
const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x); const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x);
if (is_hovering_table && table->HoveredColumnBody == -1) if (is_hovering_table && table->HoveredColumnBody == -1)
{ {
@ -1073,6 +1088,10 @@ void ImGui::TableUpdateBorders(ImGuiTable* table)
if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false) if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false)
continue; continue;
if (table->FreezeColumnsCount > 0)
if (column->MaxX < table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsCount - 1]].MaxX)
continue;
ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent); ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent);
ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit); ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit);
//GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100)); //GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100));
@ -1156,16 +1175,6 @@ void ImGui::EndTable()
if ((flags & ImGuiTableFlags_Borders) != 0) if ((flags & ImGuiTableFlags_Borders) != 0)
TableDrawBorders(table); TableDrawBorders(table);
// Store content width reference for each column (before attempting to merge draw calls)
const float backup_outer_cursor_pos_x = outer_window->DC.CursorPos.x;
const float backup_outer_max_pos_x = outer_window->DC.CursorMaxPos.x;
const float backup_inner_max_pos_x = inner_window->DC.CursorMaxPos.x;
float max_pos_x = backup_inner_max_pos_x;
if (table->RightMostEnabledColumn != -1)
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].MaxX);
if (table->ResizedColumn != -1)
max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
#if 0 #if 0
// Strip out dummy channel draw calls // Strip out dummy channel draw calls
// We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out) // We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out)
@ -1185,14 +1194,22 @@ void ImGui::EndTable()
TableMergeDrawChannels(table); TableMergeDrawChannels(table);
table->DrawSplitter.Merge(inner_window->DrawList); table->DrawSplitter.Merge(inner_window->DrawList);
if (!(table->Flags & ImGuiTableFlags_ScrollX) && inner_window != outer_window) // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable()
const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
if (table->EnabledMaskByIndex & ((ImU64)1 << column_n))
table->ColumnsAutoFitWidth += TableGetColumnWidthAuto(table, &table->Columns[column_n]);
// Update scroll
if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window)
{ {
inner_window->Scroll.x = 0.0f; inner_window->Scroll.x = 0.0f;
} }
else if (table->LastResizedColumn != -1 && table->ResizedColumn == -1 && inner_window->ScrollbarX && table->InstanceInteracted == table->InstanceCurrent) else if (table->LastResizedColumn != -1 && table->ResizedColumn == -1 && inner_window->ScrollbarX && table->InstanceInteracted == table->InstanceCurrent)
{ {
// When releasing a column being resized, scroll to keep the resulting column in sight // When releasing a column being resized, scroll to keep the resulting column in sight
const float neighbor_width_to_keep_visible = TableGetMinColumnWidth() + table->CellPaddingX * 2.0f; const float neighbor_width_to_keep_visible = table->MinColumnWidth + table->CellPaddingX * 2.0f;
ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn]; ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn];
if (column->MaxX < table->InnerClipRect.Min.x) if (column->MaxX < table->InnerClipRect.Min.x)
SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x - neighbor_width_to_keep_visible, 1.0f); SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x - neighbor_width_to_keep_visible, 1.0f);
@ -1209,10 +1226,20 @@ void ImGui::EndTable()
table->ResizedColumnNextWidth = new_width; table->ResizedColumnNextWidth = new_width;
} }
// Layout in outer window // Pop from id stack
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!"); IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!"); IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
PopID(); PopID();
// Layout in outer window
const float backup_outer_cursor_pos_x = outer_window->DC.CursorPos.x;
const float backup_outer_max_pos_x = outer_window->DC.CursorMaxPos.x;
const float backup_inner_max_pos_x = inner_window->DC.CursorMaxPos.x;
float max_pos_x = backup_inner_max_pos_x;
if (table->RightMostEnabledColumn != -1)
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].MaxX);
if (table->ResizedColumn != -1)
max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
inner_window->WorkRect = table->HostBackupWorkRect; inner_window->WorkRect = table->HostBackupWorkRect;
inner_window->ParentWorkRect = table->HostBackupParentWorkRect; inner_window->ParentWorkRect = table->HostBackupParentWorkRect;
inner_window->SkipItems = table->HostSkipItems; inner_window->SkipItems = table->HostSkipItems;
@ -1236,7 +1263,7 @@ void ImGui::EndTable()
if (table->Flags & ImGuiTableFlags_ScrollX) if (table->Flags & ImGuiTableFlags_ScrollX)
{ {
inner_window->DC.CursorMaxPos.x = max_pos_x; // Set contents width for scrolling inner_window->DC.CursorMaxPos.x = max_pos_x; // Set contents width for scrolling
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, backup_outer_cursor_pos_x + table->ColumnsTotalWidth + inner_window->ScrollbarSizes.x); // For auto-fit outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, backup_outer_cursor_pos_x + table->ColumnsGivenWidth + inner_window->ScrollbarSizes.x); // For scrolling
} }
else else
{ {
@ -1256,12 +1283,7 @@ void ImGui::EndTable()
outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1;
} }
// We use a default parameter of 'init_width_or_weight == -1', // See "COLUMN SIZING POLICIES" comments at the top of this file
// - with ImGuiTableColumnFlags_WidthFixed, width <= 0 --> init width == auto
// - with ImGuiTableColumnFlags_WidthFixed, width > 0 --> init width == manual
// - with ImGuiTableColumnFlags_WidthStretch, weight < 0 --> init weight == 1.0f
// - with ImGuiTableColumnFlags_WidthStretch, weight >= 0 --> init weight == custom
// Widths are specified _without_ CellPadding. So if you specify a width of 100.0f the column will be 100.0f+Padding*2.0f and you can fit a 100.0-wide item in it.
void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id)
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1279,9 +1301,9 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
table->DeclColumnsCount++; table->DeclColumnsCount++;
// When passing a width automatically enforce WidthFixed policy // When passing a width automatically enforce WidthFixed policy
// (whereas TableSetupColumnFlags would default to WidthAutoResize) // (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable)
if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0)
if ((table->Flags & ImGuiTableFlags_ColumnsWidthFixed) && (init_width_or_weight > 0.0f)) if ((table->Flags & ImGuiTableFlags_SizingPolicyFixed) && (init_width_or_weight > 0.0f))
flags |= ImGuiTableColumnFlags_WidthFixed; flags |= ImGuiTableColumnFlags_WidthFixed;
TableSetupColumnFlags(table, column, flags); TableSetupColumnFlags(table, column, flags);
@ -1298,7 +1320,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f) if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f)
column->WidthRequest = init_width_or_weight; column->WidthRequest = init_width_or_weight;
if (flags & ImGuiTableColumnFlags_WidthStretch) if (flags & ImGuiTableColumnFlags_WidthStretch)
column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : 1.0f; column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f;
// Disable auto-fit if an explicit width/weight has been specified // Disable auto-fit if an explicit width/weight has been specified
if (init_width_or_weight > 0.0f) if (init_width_or_weight > 0.0f)
@ -1339,7 +1361,7 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0;
table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0; table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0;
table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0;
table->IsUnfrozen = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
} }
int ImGui::TableGetColumnCount() int ImGui::TableGetColumnCount()
@ -1639,8 +1661,8 @@ void ImGui::TableEndRow(ImGuiTable* table)
} }
if (unfreeze_rows_actual) if (unfreeze_rows_actual)
{ {
IM_ASSERT(table->IsUnfrozen == false); IM_ASSERT(table->IsUnfrozenRows == false);
table->IsUnfrozen = true; table->IsUnfrozenRows = true;
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
@ -1798,7 +1820,7 @@ void ImGui::TableEndCell(ImGuiTable* table)
if (table->RowFlags & ImGuiTableRowFlags_Headers) if (table->RowFlags & ImGuiTableRowFlags_Headers)
p_max_pos_x = &column->ContentMaxXHeadersUsed; // Useful in case user submit contents in header row that is not a TableHeader() call p_max_pos_x = &column->ContentMaxXHeadersUsed; // Useful in case user submit contents in header row that is not a TableHeader() call
else else
p_max_pos_x = table->IsUnfrozen ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen;
*p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x); *p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x);
table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY); table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);
column->ItemWidth = window->DC.ItemWidth; column->ItemWidth = window->DC.ItemWidth;
@ -1811,28 +1833,20 @@ void ImGui::TableEndCell(ImGuiTable* table)
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// [SECTION] Tables: Columns width management // [SECTION] Tables: Columns width management
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// - TableGetMinColumnWidth() [Internal]
// - TableGetMaxColumnWidth() [Internal] // - TableGetMaxColumnWidth() [Internal]
// - TableGetColumnWidthAuto() [Internal]
// - TableSetColumnWidth() // - TableSetColumnWidth()
// - TableSetColumnWidthAutoSingle() [Internal] // - TableSetColumnWidthAutoSingle() [Internal]
// - TableSetColumnWidthAutoAll() [Internal] // - TableSetColumnWidthAutoAll() [Internal]
// - TableUpdateColumnsWeightFromWidth() [Internal] // - TableUpdateColumnsWeightFromWidth() [Internal]
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Minimum column content width (without padding)
float ImGui::TableGetMinColumnWidth()
{
ImGuiContext& g = *GImGui;
//return g.Style.ColumnsMinSpacing; // FIXME-TABLE
return g.Style.FramePadding.x * 1.0f;
}
// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis. // Maximum column content width given current layout. Use column->MinX so this value on a per-column basis.
float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
{ {
const ImGuiTableColumn* column = &table->Columns[column_n]; const ImGuiTableColumn* column = &table->Columns[column_n];
float max_width = FLT_MAX; float max_width = FLT_MAX;
const float min_column_distance = TableGetMinColumnWidth() + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2; const float min_column_distance = table->MinColumnWidth + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2;
if (table->Flags & ImGuiTableFlags_ScrollX) if (table->Flags & ImGuiTableFlags_ScrollX)
{ {
// Frozen columns can't reach beyond visible width else scrolling will naturally break. // Frozen columns can't reach beyond visible width else scrolling will naturally break.
@ -1858,6 +1872,23 @@ float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
return max_width; return max_width;
} }
// Note this is meant to be stored in column->WidthAuto, please generally use the WidthAuto field
float ImGui::TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column)
{
const float content_width_body = ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX;
const float content_width_headers = column->ContentMaxXHeadersIdeal - column->WorkMinX;
float width_auto = content_width_body;
if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth))
width_auto = ImMax(width_auto, content_width_headers);
// Non-resizable fixed columns preserve their requested width
if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f)
if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize))
width_auto = ImMax(width_auto, column->InitStretchWeightOrWidth);
return ImMax(width_auto, table->MinColumnWidth);
}
// 'width' = inner column width, without padding // 'width' = inner column width, without padding
void ImGui::TableSetColumnWidth(int column_n, float width) void ImGui::TableSetColumnWidth(int column_n, float width)
{ {
@ -1870,8 +1901,9 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
// Apply constraints early // Apply constraints early
// Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded) // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded)
const float min_width = TableGetMinColumnWidth(); IM_ASSERT(table->MinColumnWidth > 0.0f);
const float max_width = TableGetMaxColumnWidth(table, column_n); const float min_width = table->MinColumnWidth;
const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n));
column_0_width = ImClamp(column_0_width, min_width, max_width); column_0_width = ImClamp(column_0_width, min_width, max_width);
if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width)
return; return;
@ -1931,6 +1963,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
// (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b) // (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b)
float column_1_width = ImMax(column_1->WidthRequest - (column_0_width - column_0->WidthRequest), min_width); float column_1_width = ImMax(column_1->WidthRequest - (column_0_width - column_0->WidthRequest), min_width);
column_0_width = column_0->WidthRequest + column_1->WidthRequest - column_1_width; column_0_width = column_0->WidthRequest + column_1->WidthRequest - column_1_width;
IM_ASSERT(column_0_width > 0.0f && column_1_width > 0.0f);
column_0->WidthRequest = column_0_width; column_0->WidthRequest = column_0_width;
column_1->WidthRequest = column_1_width; column_1->WidthRequest = column_1_width;
if ((column_0->Flags | column_1->Flags) & ImGuiTableColumnFlags_WidthStretch) if ((column_0->Flags | column_1->Flags) & ImGuiTableColumnFlags_WidthStretch)
@ -3293,7 +3326,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
return; return;
bool clear_settings = SmallButton("Clear settings"); bool clear_settings = SmallButton("Clear settings");
BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f)", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight()); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f)", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight());
BulletText("ColumnsWidth: %.1f, AutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsTotalWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : "");
BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX); BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX);
BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder); BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder);
BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn); BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn);
@ -3307,21 +3340,21 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
ImGuiTableColumn* column = &table->Columns[n]; ImGuiTableColumn* column = &table->Columns[n];
const char* name = TableGetColumnName(table, n); const char* name = TableGetColumnName(table, n);
ImFormatString(buf, IM_ARRAYSIZE(buf), ImFormatString(buf, IM_ARRAYSIZE(buf),
"Column %d order %d name '%s': offset %+.2f to %+.2f\n" "Column %d order %d '%s': offset %+.2f to %+.2f%s\n"
"Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n" "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n"
"WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n" "WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n"
"MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n" "MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n"
"ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n" "ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n"
"Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s..", "Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s..",
n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, (n < table->FreezeColumnsRequest) ? " (Frozen)" : "",
column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen, column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen,
column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, (column->StretchWeight / sum_weights) * 100.0f, column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, column->StretchWeight > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f,
column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x, column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x,
column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX, column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX,
column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags, column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags,
(column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "", (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "",
(column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "", (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "",
(column->Flags & ImGuiTableColumnFlags_WidthAutoResize) ? "WidthAutoResize " : "", (column->Flags & ImGuiTableColumnFlags_WidthAuto) ? "WidthAuto " : "",
(column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : ""); (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : "");
Bullet(); Bullet();
Selectable(buf); Selectable(buf);

@ -1070,7 +1070,10 @@ bool ImGui::Checkbox(const char* label, bool* v)
const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f));
ItemSize(total_bb, style.FramePadding.y); ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id)) if (!ItemAdd(total_bb, id))
{
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
return false; return false;
}
bool hovered, held; bool hovered, held;
bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); bool pressed = ButtonBehavior(total_bb, id, &hovered, &held);
@ -1146,6 +1149,16 @@ bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int f
return CheckboxFlagsT(label, flags, flags_value); return CheckboxFlagsT(label, flags, flags_value);
} }
bool ImGui::CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value)
{
return CheckboxFlagsT(label, flags, flags_value);
}
bool ImGui::CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value)
{
return CheckboxFlagsT(label, flags, flags_value);
}
bool ImGui::RadioButton(const char* label, bool active) bool ImGui::RadioButton(const char* label, bool active)
{ {
ImGuiWindow* window = GetCurrentWindow(); ImGuiWindow* window = GetCurrentWindow();
@ -1707,6 +1720,9 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi
} }
EndCombo(); EndCombo();
if (value_changed)
MarkItemEdited(g.CurrentWindow->DC.LastItemId);
return value_changed; return value_changed;
} }
@ -6159,7 +6175,9 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item
// FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature. // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
void ImGui::ListBoxFooter() void ImGui::ListBoxFooter()
{ {
ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow; ImGuiWindow * window = GetCurrentWindow();
IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched ListBoxHeader/ListBoxFooter calls. Did you test the return value of ListBoxHeader()?");
ImGuiWindow* parent_window = window->ParentWindow;
const ImRect bb = parent_window->DC.LastItemRect; const ImRect bb = parent_window->DC.LastItemRect;
const ImGuiStyle& style = GetStyle(); const ImGuiStyle& style = GetStyle();

Loading…
Cancel
Save