1use crate::styles::colors::*;
2use fltk::{enums::*, prelude::*, *};
3use std::cell::RefCell;
4use std::rc::Rc;
5
6#[derive(Clone)]
7pub struct Toggle {
8 p: group::Pack,
9 btn: button::ToggleButton,
10}
11
12impl Default for Toggle {
13 fn default() -> Self {
14 Toggle::new(0, 0, 0, 0, "")
15 }
16}
17
18impl Toggle {
19 pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> Self {
20 let p = group::Pack::new(x, y, w, h, None)
21 .with_label(label)
22 .with_align(Align::Left);
23 frame::Frame::default().with_size(w, 7);
24 let mut btn = button::ToggleButton::new(x, y, w, 14, "@+6square")
25 .with_align(Align::Left | Align::Inside);
26 btn.set_frame(FrameType::FlatBox);
27 btn.set_down_frame(FrameType::FlatBox);
28 btn.set_label_color(Color::White);
29 btn.set_color(RED);
30 btn.set_selection_color(GREEN);
31 btn.clear_visible_focus();
32 btn.handle(|b, ev| match ev {
33 Event::Push => {
34 if b.value() {
35 b.set_align(Align::Left | Align::Inside);
36 } else {
37 b.set_align(Align::Right | Align::Inside);
38 }
39 app::redraw();
40 true
41 }
42 _ => false,
43 });
44 p.end();
45 Self { btn, p }
46 }
47 pub fn set_value(&mut self, val: bool) {
48 self.btn.set_value(val);
49 if self.btn.value() {
50 self.btn.set_align(Align::Right | Align::Inside);
51 } else {
52 self.btn.set_align(Align::Left | Align::Inside);
53 }
54 app::redraw();
55 }
56 pub fn value(&self) -> bool {
57 self.btn.value()
58 }
59 pub fn set_callback<F: 'static + FnMut(&mut Self)>(&mut self, mut cb: F) {
60 let mut s = self.clone();
61 self.btn.set_callback(move |_| {
62 cb(&mut s);
63 app::redraw();
64 });
65 }
66}
67
68fltk::widget_extends!(Toggle, group::Pack, p);
69
70#[derive(Clone)]
71pub struct RoundToggle {
72 p: group::Pack,
73 btn: button::ToggleButton,
74}
75
76impl Default for RoundToggle {
77 fn default() -> Self {
78 RoundToggle::new(0, 0, 0, 0, "")
79 }
80}
81
82impl RoundToggle {
83 pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> Self {
84 let p = group::Pack::new(x, y, w, h, None)
85 .with_label(label)
86 .with_align(Align::Left);
87 let mut btn = button::ToggleButton::new(x, y, w, 30, "@+6circle")
88 .with_align(Align::Left | Align::Inside);
89 btn.set_frame(FrameType::RFlatBox);
90 btn.set_down_frame(FrameType::RFlatBox);
91 btn.set_label_color(Color::White);
92 btn.set_color(RED);
93 btn.set_selection_color(GREEN);
94 btn.clear_visible_focus();
95 btn.handle(|b, ev| match ev {
96 Event::Push => {
97 if b.value() {
98 b.set_align(Align::Left | Align::Inside);
99 } else {
100 b.set_align(Align::Right | Align::Inside);
101 }
102 app::redraw();
103 true
104 }
105 _ => false,
106 });
107 p.end();
108 Self { btn, p }
109 }
110 pub fn set_value(&mut self, val: bool) {
111 self.btn.set_value(val);
112 if self.btn.value() {
113 self.btn.set_align(Align::Right | Align::Inside);
114 } else {
115 self.btn.set_align(Align::Left | Align::Inside);
116 }
117 app::redraw();
118 }
119 pub fn value(&self) -> bool {
120 self.btn.value()
121 }
122 pub fn set_callback<F: 'static + FnMut(&mut Self)>(&mut self, mut cb: F) {
123 let mut s = self.clone();
124 self.btn.set_callback(move |_| {
125 cb(&mut s);
126 app::redraw();
127 });
128 }
129}
130
131fltk::widget_extends!(RoundToggle, group::Pack, p);
132
133#[derive(Clone)]
134pub struct HollowRoundToggle {
135 btn: button::ToggleButton,
136}
137
138impl Default for HollowRoundToggle {
139 fn default() -> Self {
140 HollowRoundToggle::new(0, 0, 0, 0, "")
141 }
142}
143
144impl HollowRoundToggle {
145 pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> Self {
146 let mut btn = button::ToggleButton::new(x, y, w, h, None)
147 .with_label(label)
148 .with_align(Align::Left);
149 btn.set_frame(FrameType::NoBox);
150 btn.set_down_frame(FrameType::NoBox);
151 btn.set_selection_color(GREEN);
152 btn.set_color(RED);
153 btn.clear_visible_focus();
154 btn.draw(|b| {
155 let col = if b.value() {
156 b.selection_color().to_rgb()
157 } else {
158 b.color().to_rgb()
159 };
160 let svg = format!(
161 "<svg viewBox='0 0 {} {}'>
162 <rect x='1%' y='1%' rx='15' width='95%' height='95%' fill='none' stroke='rgb({},{},{})'/>
163 </svg>",
164 b.w(),
165 b.h(),
166 col.0,
167 col.1,
168 col.2
169 );
170 let mut image = image::SvgImage::from_data(&svg).unwrap();
171 image.scale(b.w(), b.h(), false, true);
172 image.draw(b.x(), b.y(), b.w(), b.h());
173 let svg = format!(
174 "<svg viewBox='0 0 100 100'>
175 <circle cx='50' cy='50' r='50' fill='rgb({},{},{})'/>
176 </svg>",
177 col.0, col.1, col.2
178 );
179 let mut image = image::SvgImage::from_data(&svg).unwrap();
180 image.scale(18, 18, false, true);
181 if b.value() {
182 image.draw(b.x() + b.w() - 6 - 18, b.y() + ((b.h() - 18)/2), 18, 18);
183 } else {
184 image.draw(b.x() + 3, b.y() + ((b.h() - 18)/2), 18, 18);
185 }
186 });
187 Self { btn }
188 }
189}
190
191fltk::widget_extends!(HollowRoundToggle, button::ToggleButton, btn);
192
193pub struct RoundToggle2 {
197 toggle: button::ToggleButton,
198}
199
200impl RoundToggle2 {
201 pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> Self {
202 let p = group::Pack::new(x, y, w, h, None)
203 .with_label(label)
204 .with_align(Align::Left);
205 let mut toggle = button::ToggleButton::new(x, y, w, 30, "");
206 toggle.draw(|t| {
207 draw::set_draw_color(Color::from_u32(0xeeeeee));
208 draw::draw_pie(
209 t.x() - 10 + (t.w() - t.h() + 20) * t.value() as i32,
210 t.y(),
211 t.h(),
212 t.h(),
213 0.,
214 360.,
215 );
216 });
217 toggle.set_callback(|_t| app::redraw());
218 toggle.set_frame(FrameType::RFlatBox);
219 toggle.set_color(RED);
220 toggle.set_selection_color(GREEN);
221 toggle.clear_visible_focus();
222 p.end();
223
224 RoundToggle2 { toggle }
225 }
226
227 pub fn set_callback<F: FnMut(&mut button::ToggleButton) + 'static>(&mut self, mut cb: F) {
228 self.toggle.set_callback(move |t| {
229 if t.is_set() {
230 t.set_align(Align::Inside | Align::Right);
231 t.set_label_color(Color::from_u32(0xeeeeee));
232 } else {
233 t.set_align(Align::Inside | Align::Left);
234 t.set_label_color(Color::from_u32(0xeeeeee));
235 }
236 app::redraw();
237 cb(t);
238 });
239 }
240}
241
242impl Default for RoundToggle2 {
243 fn default() -> Self {
244 RoundToggle2::new(0, 0, 0, 0, "")
245 }
246}
247
248widget_extends!(RoundToggle2, button::ToggleButton, toggle);
249
250#[derive(Clone)]
251pub struct CheckButton {
252 btn: button::ToggleButton,
253}
254
255impl Default for CheckButton {
256 fn default() -> Self {
257 CheckButton::new(0, 0, 0, 0, "")
258 }
259}
260
261impl CheckButton {
262 pub fn new(x: i32, y: i32, w: i32, _h: i32, label: &str) -> Self {
263 let mut btn = button::ToggleButton::new(x, y, w, 14, None)
264 .with_label(label)
265 .with_align(Align::Right | Align::Inside);
266 btn.set_frame(FrameType::NoBox);
267 btn.set_down_frame(FrameType::NoBox);
268 btn.clear_visible_focus();
269 btn.draw(|b| {
270 draw::set_line_style(draw::LineStyle::Solid, 2);
271 draw::draw_box(
272 FrameType::RoundedFrame,
273 b.x(),
274 b.y() - 10 + b.h() / 2,
275 20,
276 20,
277 GREEN,
278 );
279 if b.value() {
280 draw::draw_check(b.x() + 1, b.y() - 9 + b.h() / 2, 18, 18, GREEN);
281 }
282 });
283 Self { btn }
284 }
285 pub fn set_value(&mut self, val: bool) {
286 self.btn.set_value(val);
287 app::redraw();
288 }
289 pub fn value(&self) -> bool {
290 self.btn.value()
291 }
292 pub fn set_callback<F: 'static + FnMut(&mut Self)>(&mut self, mut cb: F) {
293 let mut s = self.clone();
294 self.btn.set_callback(move |_| {
295 cb(&mut s);
296 app::redraw();
297 });
298 }
299}
300
301fltk::widget_extends!(CheckButton, button::ToggleButton, btn);
302
303#[derive(Clone)]
304pub struct RadioButton {
305 btn: button::RadioButton,
306}
307
308impl Default for RadioButton {
309 fn default() -> Self {
310 RadioButton::new(0, 0, 0, 0, "")
311 }
312}
313
314impl RadioButton {
315 pub fn new(x: i32, y: i32, w: i32, _h: i32, label: &str) -> Self {
316 let mut btn = button::RadioButton::new(x, y, w, 14, None)
317 .with_label(label)
318 .with_align(Align::Right | Align::Inside);
319 btn.set_frame(FrameType::NoBox);
320 btn.set_down_frame(FrameType::NoBox);
321 btn.clear_visible_focus();
322 btn.draw(|b| {
323 draw::set_line_style(draw::LineStyle::Solid, 2);
324 draw::set_draw_color(GREEN);
325 draw::draw_arc(b.x(), b.y() - 10 + b.h() / 2, 20, 20, 0., 360.);
326 if b.value() {
327 draw::draw_pie(b.x() + 5, b.y() - 5 + b.h() / 2, 10, 10, 0., 360.);
328 }
329 });
330 Self { btn }
331 }
332 pub fn set_value(&mut self, val: bool) {
333 self.btn.set_value(val);
334 app::redraw();
335 }
336 pub fn value(&self) -> bool {
337 self.btn.value()
338 }
339 pub fn set_callback<F: 'static + FnMut(&mut Self)>(&mut self, mut cb: F) {
340 let mut s = self.clone();
341 self.btn.set_callback(move |_| {
342 cb(&mut s);
343 app::redraw();
344 });
345 }
346}
347
348fltk::widget_extends!(RadioButton, button::RadioButton, btn);
349
350#[derive(Clone)]
351pub struct HoverButton {
352 btn: button::Button,
353 col: Rc<RefCell<Color>>,
354}
355
356impl Default for HoverButton {
357 fn default() -> Self {
358 HoverButton::new(0, 0, 0, 0, "")
359 }
360}
361
362impl HoverButton {
363 pub fn new(x: i32, y: i32, w: i32, h: i32, label: &str) -> Self {
364 let mut btn = button::Button::new(x, y, w, h, None).with_label(label);
365 btn.set_color(SEL_BLUE);
366 btn.super_draw(false);
367 btn.draw(|b| {
368 draw::set_draw_color(b.color());
369 draw::draw_rectf(b.x(), b.y(), b.w(), b.h());
370 draw::set_draw_color(b.label_color());
371 draw::draw_text2(&b.label(), b.x(), b.y(), b.w(), b.h(), Align::Center);
372 });
373 let col = Rc::new(RefCell::new(SEL_BLUE));
374 btn.handle({
375 let col = col.clone();
376 move |b, ev| match ev {
377 Event::Enter | Event::Released => {
378 b.set_color(col.borrow().lighter());
379 b.redraw();
380 true
381 }
382 Event::Leave | Event::Push => {
383 b.set_color(*col.borrow());
384 b.redraw();
385 true
386 }
387 _ => false,
388 }
389 });
390 Self { btn, col }
391 }
392 pub fn set_color(&mut self, col: Color) {
393 *self.col.borrow_mut() = col;
394 self.btn.set_color(col);
395 }
396}
397
398fltk::widget_extends!(HoverButton, button::Button, btn);