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
use rustty::{Attr, CellAccessor, Size, HasSize};

use core::{
    Alignable, 
    HorizontalAlign, 
    VerticalAlign,
    Widget,
    Painter,
    Frame,
    Button,
    ButtonResult,
    find_accel_char_index
};

/// Standard button that returns some result based on
/// whether a key is pressed
/// 
/// # Examples
///
/// ```
/// use oxide::core::{HorizontalAlign, VerticalAlign, ButtonResult, Widget};
/// use oxide::{Dialog, StdButton};
///
/// let mut dlg = Dialog::new(60, 10);
///
/// let mut b1 = StdButton::new("Foo", 'f', ButtonResult::Ok);
/// let mut b2 = StdButton::new("Bar" ,'b', ButtonResult::Cancel);
///
/// b1.pack(&dlg, HorizontalAlign::Left, VerticalAlign::Middle, (1,1));
/// b2.pack(&dlg, HorizontalAlign::Middle, VerticalAlign::Middle, (1,1));
///
/// dlg.add_button(b1);
/// dlg.add_button(b2);
/// ```
///
pub struct StdButton {
    frame: Frame,
    accel: char,
    result: ButtonResult,
    text: String
}

impl StdButton {    
    /// Constructs a new `StdButton`, asking for the text to be displayed 
    /// by the button, the key to map to, and the result returned when the
    /// key is detected
    ///
    /// # Examples
    ///
    /// ```
    /// use oxide::core::ButtonResult;
    /// use oxide::StdButton;
    ///
    /// let mut b1 = StdButton::new("Foo", 'f', ButtonResult::Ok);
    /// ```
    ///
    pub fn new(text: &str, accel: char, result: ButtonResult) -> StdButton {
        let s = format!("< {} >", text);
        let width = s.chars().count();
        let mut button = 
            StdButton { frame: Frame::new(width, 1), 
                        accel: accel.to_lowercase().next().unwrap_or(accel),
                        result: result,
                        text: s };
        button.frame.printline(0, 0, &button.text[..]);
        match find_accel_char_index(text, button.accel) {
            Some(i) => {
                button.frame.get_mut(i+2, 0).unwrap().set_attrs(Attr::Bold);
            },
            None    => (),
        }
        button
    }
}

impl Button for StdButton {
    fn accel(&self) -> char {
        self.accel
    }

    fn result(&self) -> ButtonResult {
        self.result
    }
}

impl Widget for StdButton {
    fn draw(&mut self, parent: &mut CellAccessor) {
        self.frame.draw_into(parent);
    }

    fn pack(&mut self, parent: &HasSize, halign: HorizontalAlign, valign: VerticalAlign,
                margin: (usize,usize)) {
        self.frame.align(parent, halign, valign, margin);
    }

    fn draw_box(&mut self) {
        self.frame.draw_box();
    }

    fn resize(&mut self, new_size: Size) {
        self.frame.resize(new_size);
    }

    fn frame(&self) -> &Frame {
        &self.frame
    }

    fn frame_mut(&mut self) -> &mut Frame {
        &mut self.frame
    }
}