Gama C Library
Gama C API Documentation
switch.h
Go to the documentation of this file.
1/**
2 * @file widgets/switch.h
3 * @brief Defines the theme and functionality for a toggle switch widget.
4 *
5 * This file provides structures for customizing the appearance of an on-screen
6 * toggle switch and a function to render an interactive switch that allows
7 * users to toggle a boolean state.
8 */
9#pragma once
10
11#include "../animate.h"
12#include "../collision.h"
13#include "../draw.h"
14
15/**
16 * @brief Structure defining the visual theme for a switch widget.
17 */
18typedef struct {
19 int enabled; /**< Whether the switch is enabled for interaction (1) or disabled (0). */
20
21 double scale; /**< Default overall widget scale when normal. */
22
23 struct {
24 gmColor background; /**< Background color when the switch is off. */
25 gmColor border; /**< Border color when the switch is off. */
26 gmColor knob; /**< Knob color when the switch is off. */
27 gmColor knob_border; /**< Knob border color when the switch is off. */
28 } off; /**< Theme properties for the 'off' state of the switch. */
29
30 struct {
31 gmColor background; /**< Background color when the switch is on. */
32 gmColor border; /**< Border color when the switch is on. */
33 gmColor knob; /**< Knob color when the switch is on. */
34 gmColor knob_border; /**< Knob border color when the switch is on. */
35 } on; /**< Theme properties for the 'on' state of the switch. */
36
37 struct {
38 double scale; /**< Scale factor when focused/hovered. */
39 gmColor border; /**< Border color when focused/hovered. */
40 } focussed; /**< Theme properties when the switch is focused or hovered. */
41
42 struct {
43 double scale; /**< Scale factor when active (being clicked). */
44 gmColor border; /**< Border color when active. */
45 } active; /**< Theme properties when the switch is active (mouse button down on it). */
46
47 double border_width; /**< Width of the switch's outer border. */
49
50/**
51 * @brief Global switch theme instance with default values.
52 */
53gmwSwitchTheme gmwSwitch = {.enabled = 1,
54
55 // OFF state (muted)
56 .off =
57 {
58 .background = 0x2A1E2AE0,
59 .border = 0x5F4F5FFF,
60 .knob = 0x8A7A8AFF,
61 .knob_border = 0x5F4F5FFF,
62 },
63
64 // ON state (clear & branded)
65 .on =
66 {
67 .background = 0x4A2A4AE8,
68 .border = 0xAA77AAFF,
69 .knob = 0xEED6EEFF,
70 .knob_border = 0xAA77AAFF,
71 },
72
73 // Hover
74 .focussed =
75 {
76 .scale = 1.04,
77 .border = 0xBA87BAFF,
78 },
79
80 // Pressed
81 .active =
82 {
83 .scale = 0.97,
84 .border = 0x7F4F7FFF,
85 },
86
87 .border_width = 0.01};
88
89/**
90 * @brief Creates and renders an animated switch widget that toggles on click.
91 *
92 * This function draws a toggle switch, tracks mouse interaction to update its
93 * state, and animates the knob's position smoothly between 'off' (0) and 'on' (1).
94 *
95 * @param x The x-coordinate of the switch's center.
96 * @param y The y-coordinate of the switch's center.
97 * @param width The width of the switch.
98 * @param height The height of the switch.
99 * @param value Pointer to an integer to store the switch state (0 for off, 1 for on).
100 * This value is toggled by user clicks.
101 * @param anim Pointer to a double for the animated visual position of the knob.
102 * If NULL, `value` is used for the knob's position (non-animated).
103 * @return 1 if the switch was clicked (toggled) in the current frame, 0 otherwise.
104 */
105int gmw_switch_anim(double x, double y, double width, double height, int *value,
106 double *anim) {
107
108 int enabled = gmwSwitch.enabled;
109
110 int hovered = enabled && gm_mouse_in_rect(x, y, width, height);
111 int clicked = enabled && gm_mouse.clicked && hovered;
112
113 if (clicked) {
114 *value = !(*value);
115 }
116 double knob_pos;
117 if (anim != NULL) {
118 if (*anim > 1)
119 *anim = 1;
120 else if (*anim < 0)
121 *anim = 0;
122 gm_anim_ease_out_quad(anim, (double)(*value), 0.05);
123 knob_pos = *anim;
124 } else {
125 knob_pos = (double)(*value);
126 }
127 int on = *value != 0;
128
129 double scale = gm_mouse.down && hovered ? gmwSwitch.active.scale
130 : hovered ? gmwSwitch.focussed.scale
131 : 1.0;
132
133 gmColor bg = on ? gmwSwitch.on.background : gmwSwitch.off.background;
134 gmColor border = on ? gmwSwitch.on.border : gmwSwitch.off.border;
135 gmColor knob = on ? gmwSwitch.on.knob : gmwSwitch.off.knob;
136 gmColor knob_b = on ? gmwSwitch.on.knob_border : gmwSwitch.off.knob_border;
137
138 if (hovered)
139 border = gmwSwitch.focussed.border;
140 if (gm_mouse.down && hovered)
141 border = gmwSwitch.active.border;
142
143 double sw = width * scale;
144 double sh = height * scale;
145
146 // Outer border
147 gm_draw_rectangle(x, y, sw + gmwSwitch.border_width * 2,
148 sh + gmwSwitch.border_width * 2, border);
149
150 // Background
151 gm_draw_rectangle(x, y, sw, sh, bg);
152
153 // Knob (square)
154 double knob_size = sh * 0.8;
155 double knob_x_offset = (knob_pos * 2 - 1) *
156 (sw * 0.5 - knob_size * 0.5 - gmwSwitch.border_width);
157 // Knob border
158 gm_draw_rectangle(x + knob_x_offset, y,
159 knob_size + gmwSwitch.border_width * 2,
160 knob_size + gmwSwitch.border_width * 2, knob_b);
161
162 // Knob
163 gm_draw_rectangle(x + knob_x_offset, y, knob_size, knob_size, knob);
164
165 return clicked;
166}
167
168/**
169 * @brief Creates and renders a switch widget that toggles on click (non-animated version).
170 *
171 * This is a simplified wrapper around `gmw_switch_anim` that does not use
172 * a separate animated visual position, causing the knob to snap to the
173 * current value.
174 *
175 * @param x The x-coordinate of the switch's center.
176 * @param y The y-coordinate of the switch's center.
177 * @param width The width of the switch.
178 * @param height The height of the switch.
179 * @param value Pointer to an integer to store the switch state (0=off, 1=on).
180 * @return 1 if the switch was clicked (toggled) in the current frame, 0 otherwise.
181 */
182int gmw_switch(double x, double y, double width, double height, int *value) {
183 return gmw_switch_anim(x, y, width, height, value, NULL);
184}
Provides utility functions for animating numerical values using various easing effects.
void gm_anim_ease_out_quad(double *value, const double target, double t)
Animates a value towards a target with a quadratic ease-out effect.
Definition animate.h:56
Defines collision structures and provides functions for 2D collision detection.
int gm_mouse_in_rect(const double x, const double y, const double w, const double h)
Checks if the mouse cursor is currently within a given rectangular area.
Definition collision.h:172
uint32_t gmColor
Type definition for color values, stored as a 32-bit unsigned integer. The color components are packe...
Definition color.h:13
Functions for drawing shapes, text, and images.
int32_t gm_draw_rectangle(double x, double y, double w, double h, gmColor c)
Draws a rectangle centered at a point.
Definition draw.h:57
struct _gmMouse gm_mouse
Definition mouse.h:32
Structure defining the visual theme for a switch widget.
Definition switch.h:18
double scale
Definition switch.h:21
gmColor knob
Definition switch.h:26
gmColor knob_border
Definition switch.h:27
double border_width
Definition switch.h:47
gmColor border
Definition switch.h:25
int enabled
Definition switch.h:19
gmColor background
Definition switch.h:24
int gmw_switch(double x, double y, double width, double height, int *value)
Creates and renders a switch widget that toggles on click (non-animated version).
Definition switch.h:182
int gmw_switch_anim(double x, double y, double width, double height, int *value, double *anim)
Creates and renders an animated switch widget that toggles on click.
Definition switch.h:105
gmwSwitchTheme gmwSwitch
Global switch theme instance with default values.
Definition switch.h:53