custom_choice/
custom_choice.rs

1#![allow(dead_code)]
2
3use fltk::{enums::*, prelude::*, *};
4use std::cell::RefCell;
5use std::ops::{Deref, DerefMut};
6use std::rc::Rc;
7
8pub struct PopupButton {
9    but: button::Button,
10}
11
12impl PopupButton {
13    pub fn new(label: &str) -> Self {
14        let mut but = button::Button::default().with_label(label);
15        but.set_frame(FrameType::FlatBox);
16        but.set_color(Color::White);
17        but.handle(|b, ev| match ev {
18            Event::Enter => {
19                b.set_color(Color::Blue);
20                b.top_window().unwrap().redraw();
21                true
22            }
23            Event::Leave => {
24                b.set_color(Color::White);
25                b.top_window().unwrap().redraw();
26                true
27            }
28            _ => false,
29        });
30        Self { but }
31    }
32}
33
34impl Deref for PopupButton {
35    type Target = button::Button;
36
37    fn deref(&self) -> &Self::Target {
38        &self.but
39    }
40}
41
42impl DerefMut for PopupButton {
43    fn deref_mut(&mut self) -> &mut Self::Target {
44        &mut self.but
45    }
46}
47
48pub struct MyPopup {
49    win: window::Window,
50    val: Rc<RefCell<String>>,
51    idx: RefCell<i32>,
52}
53
54impl MyPopup {
55    pub fn new(choices: &[&str]) -> Self {
56        let val = Rc::from(RefCell::from(String::from("")));
57        let idx = RefCell::from(0);
58        let mut win = window::Window::default().with_size(120, choices.len() as i32 * 25);
59        win.set_color(Color::White);
60        win.set_frame(FrameType::BorderBox);
61        let mut pack = group::Pack::new(1, 1, win.w() - 2, win.h() - 2, None);
62        win.set_border(false);
63        win.end();
64        for (i, choice) in choices.iter().enumerate() {
65            let mut but = PopupButton::new(choice);
66            but.clear_visible_focus();
67            but.set_callback({
68                let mut win = win.clone();
69                let val = val.clone();
70                let idx = idx.clone();
71                move |b| {
72                    *val.borrow_mut() = b.label().unwrap();
73                    *idx.borrow_mut() = i as i32;
74                    win.hide();
75                }
76            });
77            pack.add(&*but);
78        }
79        pack.auto_layout();
80        Self { win, val, idx }
81    }
82    pub fn popup(&mut self, x: i32, y: i32) -> (String, i32) {
83        self.win.show();
84        self.win.handle(|w, ev| match ev {
85            Event::Unfocus => {
86                w.hide();
87                true
88            }
89            _ => false,
90        });
91        self.win.force_position(true);
92        self.win.resize(x, y, self.win.w(), self.win.h());
93        while self.win.shown() {
94            app::wait();
95        }
96        (self.val.borrow().to_string(), *self.idx.borrow())
97    }
98}
99
100struct MyChoice {
101    grp: group::Group,
102    frame: frame::Frame,
103    btn: button::Button,
104    choices: Rc<RefCell<Vec<&'static str>>>,
105}
106
107impl MyChoice {
108    pub fn new<S: Into<Option<&'static str>>>(x: i32, y: i32, w: i32, h: i32, label: S) -> Self {
109        let grp = group::Group::new(x, y, w, h, label).with_align(Align::Left);
110        let mut frame = frame::Frame::new(x, y, w - w / 4, h, None);
111        frame.set_frame(FrameType::DownBox);
112        frame.set_color(Color::Background2);
113        let mut btn = button::Button::new(x + w - w / 4, y, w / 4, h, "@2>");
114        btn.clear_visible_focus();
115        grp.end();
116        let choices = Rc::from(RefCell::from(vec![]));
117        btn.set_callback({
118            let c = choices.clone();
119            let mut f = frame.clone();
120            let btn_win = btn.window().unwrap();
121            move |b| {
122                let mut menu = MyPopup::new(&c.borrow());
123                let s = menu.popup(b.x() + btn_win.x() - f.w(), b.y() + btn_win.y() + b.h());
124                f.set_label(&s.0);
125            }
126        });
127        Self {
128            grp,
129            frame,
130            btn,
131            choices,
132        }
133    }
134
135    pub fn add_choices(&mut self, choices: &[&'static str]) {
136        *self.choices.borrow_mut() = choices.to_vec();
137    }
138
139    pub fn button(&mut self) -> &mut button::Button {
140        &mut self.btn
141    }
142
143    pub fn frame(&mut self) -> &mut frame::Frame {
144        &mut self.frame
145    }
146
147    pub fn group(&mut self) -> &mut group::Group {
148        &mut self.grp
149    }
150
151    pub fn set_current_choice(&mut self, idx: i32) {
152        self.frame.set_label(self.choices.borrow()[idx as usize])
153    }
154
155    pub fn choice(&self) -> String {
156        self.frame.label().unwrap()
157    }
158
159    pub fn value(&self) -> i32 {
160        let choice = self.choice();
161        if let Some(val) = self.choices.borrow().iter().position(|x| x == &choice) {
162            val as _
163        } else {
164            -1
165        }
166    }
167}
168
169fn main() {
170    let app = app::App::default();
171    let mut win = window::Window::default().with_size(400, 300);
172    let mut choice = MyChoice::new(160, 200, 100, 30, None);
173    choice.add_choices(&["choice1", "choice2", "choice3"]);
174    choice.set_current_choice(1);
175    choice.button().set_frame(FrameType::BorderBox);
176    choice.frame().set_frame(FrameType::BorderBox);
177    win.end();
178    win.show();
179    app.run().unwrap();
180}