old school music tracker
1use std::{cell::Cell, rc::Rc};
2
3use crate::{app::EventQueue, coordinates::CharRect, draw_buffer::DrawBuffer};
4
5use super::{NextWidget, Widget, WidgetResponse, button::Button};
6
7// dont need to store a callback as it gets pushed into the inner button callback
8pub struct ToggleButton<T: Copy + PartialEq, R> {
9 button: Button<()>,
10
11 variant: T,
12 cb: fn(T) -> R,
13 state: Rc<Cell<T>>,
14}
15
16impl<T: Copy + PartialEq, R> Widget for ToggleButton<T, R> {
17 type Response = R;
18 fn draw(&self, draw_buffer: &mut DrawBuffer, selected: bool) {
19 self.button
20 .draw_overwrite_pressed(draw_buffer, selected, self.variant == self.state.get())
21 }
22
23 fn process_input(
24 &mut self,
25 modifiers: &winit::event::Modifiers,
26 key_event: &winit::event::KeyEvent,
27 event: &mut EventQueue<'_>,
28 ) -> WidgetResponse<R> {
29 let WidgetResponse { standard, extra } =
30 self.button.process_input(modifiers, key_event, event);
31 let extra = extra.map(|_| {
32 self.state.set(self.variant);
33 (self.cb)(self.variant)
34 });
35 WidgetResponse { standard, extra }
36 }
37}
38
39impl<T: Copy + PartialEq + 'static, R> ToggleButton<T, R> {
40 pub fn new(
41 text: &'static str,
42 rect: CharRect,
43 next_widget: NextWidget,
44 variant: T,
45 state: Rc<Cell<T>>,
46 cb: fn(T) -> R,
47 ) -> Self {
48 let button = Button::new(text, rect, next_widget, || ());
49 Self {
50 button,
51 variant,
52 cb,
53 state,
54 }
55 }
56}