🔘 imgui_toggle
A small Dear ImGui widget that implements a modern toggle style switch. Requires C++11.
Overview
Based on the discussion in ocornut/imgui#1537, and on the implementation of ImGui::Checkbox()
,
this small widget collection implements a customizable "Toggle" style button for Dear ImGui. A toggle represents a boolean on/off much like a checkbox, but is better suited
to some particular paradigms depending on the UI designer's goals. It can often more clearly indicate an enabled/disabled state.
imgui_toggle
also supports an optional small animation, similar to that seen in mobile OS and web applications, which can further aid in user feedback.
Internally, imgui_toggle
functions very similarly to ImGui::Checkbox()
, with the exception that it activates on mouse down rather than the release. It supports drawing
a label in the same way, and toggling the value by clicking that associated label. The label can be hidden as on other controls.
Preview
An example of imgui_toggle
, produced by the example code, as an animated gif.
Usage
Add the *.cpp
and *.h
files to your project, and include imgui_toggle.h
in the source file you wish to use toggles.
See imgui_toggle.h
for the API, or below for a brief example. As well, EXAMPLE.md has a more thorough usage example.
const ImVec4 green(0.16f, 0.66f, 0.45f, 1.0f);
const ImVec4 green_hover(0.0f, 1.0f, 0.57f, 1.0f);
const ImVec4 gray_dim(0.45f, 0.45f, 0.45f, 1.0f);
const ImVec4 gray(0.65f, 0.65f, 0.65f, 1.0f);
// use some lovely gray backgrounds for "off" toggles
// the default will use your theme's frame background colors.
ImGui::PushStyleColor(ImGuiCol_FrameBg, gray_dim);
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, gray);
static bool values[] = { true, true, true, true, true, true, true, true };
size_t value_index = 0;
const ImVec4 green(0.16f, 0.66f, 0.45f, 1.0f);
const ImVec4 green_hover(0.0f, 1.0f, 0.57f, 1.0f);
const ImVec4 salmon(1.0f, 0.43f, 0.35f, 1.0f);
const ImVec4 green_shadow(0.0f, 1.0f, 0.0f, 0.4f);
// a default and default animated toggle
ImGui::Toggle("Default Toggle", &values[value_index++]);
ImGui::Toggle("Animated Toggle", &values[value_index++], ImGuiToggleFlags_Animated);
// this toggle draws a simple border around it's frame and knob
ImGui::Toggle("Bordered Knob", &values[value_index++], ImGuiToggleFlags_Bordered, 1.0f);
// this toggle draws a simple shadow around it's frame and knob
ImGui::PushStyleColor(ImGuiCol_BorderShadow, green_shadow);
ImGui::Toggle("Shadowed Knob", &values[value_index++], ImGuiToggleFlags_Shadowed, 1.0f);
// this toggle draws the shadow & and the border around it's frame and knob.
ImGui::Toggle("Bordered + Shadowed Knob", &values[value_index++], ImGuiToggleFlags_Bordered | ImGuiToggleFlags_Shadowed, 1.0f);
ImGui::PopStyleColor(1);
// this toggle uses stack-pushed style colors to change the way it displays
ImGui::PushStyleColor(ImGuiCol_Button, green);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, green_hover);
ImGui::Toggle("Green Toggle", &values[value_index++]);
ImGui::PopStyleColor(2);
ImGui::Toggle("Toggle with A11y Labels", &values[value_index++], ImGuiToggleFlags_A11y);
// this toggle shows no label
ImGui::Toggle("##Toggle With Hidden Label", &values[value_index++]);
// pop the FrameBg/FrameBgHover color styles
ImGui::PopStyleColor(2);
Styling
While imgui_toggle
maintains a simple API for quick and easy toggles, a more complex one exists to allow the user to better customize the widget.
By using the overload that takes a const ImGuiToggleConfig&
, a structure can be provided that provides a multitude of configuration parameters.
Notably this also allows providing a pointer to a ImGuiTogglePalette
structure, which allows changing all the colors used to draw the widget. However, this method of configuration is not strictly necessary, as imgui_toggle
will follow your theme colors as defined below if no palette or color replacement is specified.
Theme Colors
Since imgui_toggle
isn't part of Dear ImGui proper, it doesn't have any direct references in ImGuiCol_
for styling. imgui_toggle
in addition to the method described above, you can use ImGui::PushStyleColor()
and ImGui::PopStyleColor()
to adjust the following theme colors around your call to ImGui::Toggle()
:
ImGuiCol_Text
: Will be used as the color of the knob portion of the toggle, and the color of the accessibility glyph if enabled and "on".ImGuiCol_Button
: Will be used as the frame color of the toggle when it is in the "on" position, and the widget is not hovered.ImGuiCol_ButtonHovered
: Will be used as the frame color of the toggle when it is in the "on" position, and the widget is hovered over.ImGuiCol_FrameBg
: Will be used as the frame color of the toggle when it is in the "off" position, and the widget is not hovered. Also used for the color of the accessibility glyph if enabled and "off".ImGuiCol_FrameBgHovered
: Will be used as the frame color of the toggle when it is in the "off" position, and the widget is hovered over.ImGuiCol_Border
: Will be used as the color drawn as the border on the frame and knob if the related flags are passed.
Unfortunately, the dark gray and light gray used while the toggle is in the "off" position are currently defined by the widget code itself and not by any theme color.
Future Considerations
As brought up by ocornut, if imgui_toggle
were to be part of mainline Dear ImGui in the future,
there are some questions that should likely be answered. Most notably for me are the following:
- Should the toggle get it's own enums in the style system?
- If so, should which colors should it define, and which would it be okay sharing?
- If I were choosing, I feel the button and hovered styles as the "on" coloring are acceptable, and perhaps adding three more shared styles
ImGuiCol_Knob
,ImGuiCol_FrameBgOff
, andImGuiCol_FrameBgOffHover
for use as the foreground knob color, and the "off" background states. (AnActive
may be needed too if switching to operate on input release instead of press.)
- Is the rendering quality good enough?
- Is the dependence on the
LastActiveIdTimer
acceptable for animation, and the user must accept that clicking quickly would skip previous animations? - Should the toggle behave exactly like
ImGui::Checkbox()
, toggling on release rather than press?
📝 License
imgui_toggle
is licensed under the Zero-Clause BSD License (SPDX-License-Identifier: 0BSD). If you're interested in imgui_toggle
under other terms, please contact the author.
Copyright © 2022 Chris Marc Dailey
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Acknowledgements
imgui_toggle
drew inspiration from ocornut's original share,
his animated variant, nerdtronik's shift to theme colors,
and ashifolfi's squircle concept. Inspiration for border drawing came from moebiussurfing.
As well, inspiration was derived from Dear ImGui's current Checkbox
implementation,
for the behavior, label drawing, and hopefully preparing to handle mixed values/indeterminate states (albeit unsupported as of yet).