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
use super::*;

pub struct TextButton {
    core: WidgetCore,
    theme: Rc<Theme>,
    pub text: String,
    size: f32,
}

impl TextButton {
    pub fn new(
        #[allow(unused_variables)] geng: &Rc<Geng>,
        theme: &Rc<Theme>,
        text: String,
        size: f32,
    ) -> Self {
        Self {
            theme: theme.clone(),
            core: WidgetCore::new(),
            text,
            size,
        }
    }
    pub fn ui<'a>(&'a mut self, action: Box<dyn FnOnce() + 'a>) -> impl Widget + 'a {
        TextButtonUI {
            theme: &self.theme,
            core: &mut self.core,
            text: &self.text,
            size: self.size,
            action: Some(action),
        }
    }
}

pub struct TextButtonUI<'a> {
    theme: &'a Theme,
    core: &'a mut WidgetCore,
    action: Option<Box<dyn FnOnce() + 'a>>,
    text: &'a str,
    size: f32,
}

impl<'a> Deref for TextButtonUI<'a> {
    type Target = WidgetCore;
    fn deref(&self) -> &WidgetCore {
        self.core
    }
}

impl<'a> DerefMut for TextButtonUI<'a> {
    fn deref_mut(&mut self) -> &mut WidgetCore {
        self.core
    }
}

impl<'a> Widget for TextButtonUI<'a> {
    fn core(&self) -> &WidgetCore {
        &self.core
    }
    fn core_mut(&mut self) -> &mut WidgetCore {
        &mut self.core
    }
    fn calc_constraints(&mut self) {
        self.constraints = widget::Constraints {
            min_size: vec2(
                self.theme.font.measure(self.text, self.size).width() as f64,
                self.size as f64,
            ),
            flex: vec2(0.0, 0.0),
        };
    }
    fn draw(&mut self, framebuffer: &mut ugli::Framebuffer) {
        if self.text.is_empty() {
            return;
        }
        let mut size = partial_min(
            self.position.height() as f32,
            self.size * self.position.width() as f32
                / self.theme.font.measure(self.text, self.size).width(),
        );
        let color = if self.hovered() {
            self.theme.hover_color
        } else {
            self.theme.color
        };
        let offset;
        if self.captured() {
            size *= self.theme.press_ratio;
            offset = self.position.size().map(|x| x as f32) * (1.0 - self.theme.press_ratio) / 2.0;
        } else {
            offset = vec2(0.0, 0.0);
        }
        self.theme.font.draw(
            framebuffer,
            self.text,
            self.position.bottom_left().map(|x| x as f32) + offset,
            size,
            color,
        );
    }
    fn handle_event(&mut self, event: &Event) {
        if let Event::Click { .. } = event {
            if let Some(action) = self.action.take() {
                action();
            }
        }
    }
}