A small Dear ImGui widget that implements a modern toggle style switch.
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.
An example of imgui_toggle
, produced by the usage code below, as an animated gif.
Add imgui_toggle.cpp
and imgui_toggle.h
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.
static bool toggle_a = true;
static bool toggle_b = true;
static bool toggle_c = true;
static bool toggle_d = true;
static bool toggle_e = true;
static bool toggle_f = true;
static bool toggle_g = true;
static float frame_rounding = 0.2f;
static float knob_rounding = 0.2f;
// use some lovely gray backgrounds for "off" toggles
// the default will use your theme's frame background colors.
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.45f, 0.45f, 0.45f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImVec4(0.65f, 0.65f, 0.65f, 1.0f));
// a default and default animated toggle
ImGui::Toggle("Default Toggle", &toggle_a);
ImGui::Toggle("Animated Toggle", &toggle_b, ImGuiToggleFlags_Animated);
// this toggle draws a simple border around it's frame and knob
ImGui::Toggle("Bordered Knob", &toggle_c, ImGuiToggleFlags_Bordered, 1.0f);
// sliders for adjusting the rounding for the next two toggles.
ImGui::SliderFloat("frame_rounding", &frame_rounding, 0.0f, 1.0f);
ImGui::SliderFloat("knob_rounding", &knob_rounding, 0.0f, 1.0f);
// a default and animated toggle that can have their frames and knobs rounded
// a rounding of 0 is completely square, a rounding of 1 is fully rounded.
ImGui::Toggle("Square Toggle", &toggle_d, ImGuiToggleFlags_Default, frame_rounding, knob_rounding);
ImGui::Toggle("Animated Square Toggle", &toggle_e, ImGuiToggleFlags_Animated, frame_rounding, knob_rounding);
// this toggle uses stack-pushed style colors to change the way it displays
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.16f, 0.66f, 0.45f, 1.0f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.0f, 1.0f, 0.57f, 1.0f));
ImGui::Toggle("Green Toggle", &toggle_f);
ImGui::PopStyleColor(2);
// this toggle shows no label
ImGui::Toggle("##Toggle With Hidden Label", &toggle_g);
// pop the FrameBg/FrameBgHover color styles
ImGui::PopStyleColor(2);
Since imgui_toggle
isn't part of Dear ImGui proper, it doesn't have any direct references for styling. imgui_toggle
makes use of a
few shared theme colors for styling. For now, it is easiest to use ImGui::PushStyleColor()
and ImGui::PopStyleColor()
to
adjust those these colors around your call to ImGui::Toggle()
:
ImGuiCol_Text
: Will be used as the color of the knob portion of the toggle.ImGuiCol_Button
: Will be used as the background color of the toggle when it is in the "on" position, and the widget is not hovered.ImGuiCol_ButtonHovered
: Will be used as the background color of the toggle when it is in the "on" position, and the widget is hovered over.ImGuiCol_FrameBg
: Will be used as the background color of the toggle when it is in the "off" position, and the widget is not hovered.ImGuiCol_FrameBgHovered
: Will be used as the background 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 background 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.
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?
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.
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).