Skip to main content

itools_tui/components/
button.rs

1//! 按钮组件
2
3use crate::{event::Event, layout::Rect, render::Frame, style::Style};
4use crossterm::event::KeyCode;
5
6/// 按钮组件
7pub struct Button {
8    /// 按钮标签
9    label: String,
10    /// 按钮样式
11    style: Style,
12    /// 按下时的样式
13    active_style: Style,
14    /// 是否被按下
15    is_pressed: bool,
16    /// 点击回调
17    on_press: Option<Box<dyn Fn()>>,
18}
19
20impl Button {
21    /// 创建新的按钮
22    pub fn new(label: &str) -> Self {
23        Self {
24            label: label.to_string(),
25            style: Style::new(),
26            active_style: Style::new().reversed(),
27            is_pressed: false,
28            on_press: None,
29        }
30    }
31
32    /// 设置按钮样式
33    pub fn style(mut self, style: Style) -> Self {
34        self.style = style;
35        self
36    }
37
38    /// 设置按下时的样式
39    pub fn active_style(mut self, style: Style) -> Self {
40        self.active_style = style;
41        self
42    }
43
44    /// 设置点击回调
45    pub fn on_press<F: Fn() + 'static>(mut self, f: F) -> Self {
46        self.on_press = Some(Box::new(f));
47        self
48    }
49
50    /// 点击按钮
51    pub fn press(&mut self) {
52        self.is_pressed = true;
53        if let Some(callback) = &self.on_press {
54            callback();
55        }
56    }
57}
58
59impl super::Component for Button {
60    fn render(&self, frame: &mut Frame, area: Rect) {
61        let style = if self.is_pressed { self.active_style.clone() } else { self.style.clone() };
62
63        frame.render_button(&self.label, area, style);
64    }
65
66    fn handle_event(&mut self, event: &Event) -> bool {
67        match event {
68            Event::Key(key_event) => {
69                if key_event.code == KeyCode::Enter {
70                    self.press();
71                    true
72                }
73                else {
74                    false
75                }
76            }
77            _ => false,
78        }
79    }
80}