old school music tracker
at main 131 lines 4.1 kB view raw
1use winit::keyboard::{Key, NamedKey}; 2 3use crate::{ 4 app::EventQueue, 5 coordinates::{CharPosition, CharRect}, 6 draw_buffer::DrawBuffer, 7}; 8 9use super::{NextWidget, StandardResponse, Widget, WidgetResponse}; 10 11pub struct Button<R> { 12 text: &'static str, 13 rect: CharRect, 14 pressed: bool, 15 next_widget: NextWidget, 16 callback: fn() -> R, 17} 18 19impl<R> Widget for Button<R> { 20 type Response = R; 21 fn draw(&self, buffer: &mut DrawBuffer, selected: bool) { 22 self.draw_overwrite_pressed(buffer, selected, false); 23 } 24 25 fn process_input( 26 &mut self, 27 modifiers: &winit::event::Modifiers, 28 key_event: &winit::event::KeyEvent, 29 _: &mut EventQueue<'_>, 30 ) -> WidgetResponse<R> { 31 if key_event.logical_key == Key::Named(NamedKey::Space) 32 || key_event.logical_key == Key::Named(NamedKey::Enter) 33 { 34 if !key_event.repeat { 35 if key_event.state.is_pressed() { 36 self.pressed = true; 37 return WidgetResponse::default(); 38 } else { 39 // only call the callback on a release event if the button was pressed in before 40 // meaning if the user pressed the key, then changed focus to another button and then releases 41 // no button should be triggered 42 let response = if self.pressed { 43 Some((self.callback)()) 44 } else { 45 None 46 }; 47 self.pressed = false; 48 return WidgetResponse { 49 standard: StandardResponse::RequestRedraw, 50 extra: response, 51 }; 52 } 53 } 54 // if focus is changed stop being pressed 55 } else { 56 return self.next_widget.process_key_event(key_event, modifiers); 57 } 58 WidgetResponse::default() 59 } 60} 61 62impl<R> Button<R> { 63 const TOPLEFT_COLOR: u8 = 3; 64 const BOTRIGHT_COLOR: u8 = 1; 65 66 pub fn new(text: &'static str, rect: CharRect, next_widget: NextWidget, cb: fn() -> R) -> Self { 67 // is 3 rows high, because bot and top are inclusive 68 assert!( 69 rect.bot() - rect.top() >= 2, 70 "buttons needs to be at least 3 rows high" 71 ); 72 Button { 73 text, 74 rect, 75 callback: cb, 76 pressed: false, 77 next_widget, 78 } 79 } 80 81 /// pressed = argument || self.pressed 82 pub fn draw_overwrite_pressed(&self, buffer: &mut DrawBuffer, selected: bool, pressed: bool) { 83 // let string_offset = { 84 // let half_string = self.text.len() / 2; 85 // if self.text.len() % 2 == 0 { 86 // half_string - 1 87 // } else { 88 // half_string 89 // } 90 // }; 91 92 // fill behind the text 93 buffer.draw_rect( 94 DrawBuffer::BACKGROUND_COLOR, 95 CharRect::new( 96 self.rect.top() + 1, 97 self.rect.bot() - 1, 98 self.rect.left() + 1, 99 self.rect.right() - 1, 100 ), 101 ); 102 103 let box_colors = match pressed || self.pressed { 104 true => (Self::BOTRIGHT_COLOR, Self::TOPLEFT_COLOR), 105 false => (Self::TOPLEFT_COLOR, Self::BOTRIGHT_COLOR), 106 }; 107 108 buffer.draw_in_box( 109 self.rect, 110 DrawBuffer::BACKGROUND_COLOR, 111 box_colors.0, 112 box_colors.1, 113 1, 114 ); 115 116 let text_color = match selected { 117 true => 11, 118 false => 0, 119 }; 120 buffer.draw_string( 121 self.text, 122 CharPosition::new( 123 // ((self.rect.right() - self.rect.left()) / 2 + self.rect.left()) - string_offset, 124 self.rect.left() + 2, 125 (self.rect.bot() - self.rect.top()) / 2 + self.rect.top(), 126 ), 127 text_color, 128 DrawBuffer::BACKGROUND_COLOR, 129 ) 130 } 131}