1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
use super::{CloneCell, Color, Event, Placeable, Point, Rect, Renderer, Widget, WidgetCore}; use super::callback::Click; use super::cell::CheckSet; use std::cell::Cell; use std::sync::Arc; pub struct Button { pub core: WidgetCore, pub text: CloneCell<String>, pub bg_pressed: Color, pub text_offset: Point, click_callback: Option<Arc<Fn(&Button, Point)>>, pressed: Cell<bool>, } impl Button { pub fn new() -> Self { Button { core: WidgetCore::new() .bg(Color::rgb(220, 222, 227)), text: CloneCell::new(String::new()), bg_pressed: Color::rgb(203, 205, 210), text_offset: Point::default(), click_callback: None, pressed: Cell::new(false), } } pub fn text<S: Into<String>>(self, text: S) -> Self { self.text.set(text.into()); self } pub fn text_offset(mut self, x: i32, y: i32) -> Self { self.text_offset = Point::new(x, y); self } } impl Click for Button { fn emit_click(&self, point: Point) { if let Some(ref click_callback) = self.click_callback { click_callback(self, point); } } fn on_click<T: Fn(&Self, Point) + 'static>(mut self, func: T) -> Self { self.click_callback = Some(Arc::new(func)); self } } impl Placeable for Button {} impl Widget for Button { fn rect(&self) -> &Cell<Rect> { &self.core.rect } fn draw(&self, renderer: &mut Renderer, _focused: bool) { let rect = self.core.rect.get(); if self.pressed.get() { renderer.rect(rect, self.bg_pressed); } else { renderer.rect(rect, self.core.bg); } let text = self.text.borrow(); let mut point = self.text_offset; for c in text.chars() { if c == '\n' { point.x = 0; point.y += 16; } else { if point.x + 8 <= rect.width as i32 && point.y + 16 <= rect.height as i32 { renderer.char(point + rect.point(), c, self.core.fg); } point.x += 8; } } } fn event(&self, event: Event, focused: bool, redraw: &mut bool) -> bool { match event { Event::Mouse { point, left_button, .. } => { let mut click = false; let rect = self.core.rect.get(); if rect.contains(point) { if left_button { if self.pressed.check_set(true) { *redraw = true; } } else { if self.pressed.check_set(false) { click = true; *redraw = true; } } } else { if !left_button { if self.pressed.check_set(false) { *redraw = true; } } } if click { let click_point: Point = point - rect.point(); self.emit_click(click_point); } } _ => (), } focused } }