custom_popup/
custom_popup.rs

1use fltk::{enums::*, prelude::*, *};
2use std::cell::RefCell;
3use std::ops::{Deref, DerefMut};
4use std::rc::Rc;
5
6pub struct PopupButton {
7    but: button::Button,
8}
9
10impl PopupButton {
11    pub fn new(label: &str) -> Self {
12        let mut but = button::Button::default().with_label(label);
13        but.set_frame(FrameType::FlatBox);
14        but.handle(|b, ev| match ev {
15            Event::Enter => {
16                b.set_color(Color::Blue);
17                b.top_window().unwrap().redraw();
18                true
19            }
20            Event::Leave => {
21                b.set_color(Color::Background);
22                b.top_window().unwrap().redraw();
23                true
24            }
25            _ => false,
26        });
27        Self { but }
28    }
29}
30
31impl Deref for PopupButton {
32    type Target = button::Button;
33
34    fn deref(&self) -> &Self::Target {
35        &self.but
36    }
37}
38
39impl DerefMut for PopupButton {
40    fn deref_mut(&mut self) -> &mut Self::Target {
41        &mut self.but
42    }
43}
44
45pub struct MyPopup {
46    win: window::Window,
47    val: Rc<RefCell<String>>,
48}
49
50impl MyPopup {
51    pub fn new(choices: &[&str]) -> Self {
52        let val = Rc::from(RefCell::from(String::from("")));
53        let mut win = window::Window::default().with_size(120, choices.len() as i32 * 25);
54        let mut pack = group::Pack::default().size_of_parent();
55        pack.set_frame(FrameType::ThinUpFrame);
56        pack.set_color(Color::Black);
57        win.set_border(false);
58        win.make_modal(true);
59        win.end();
60        for choice in choices {
61            let mut but = PopupButton::new(choice);
62            but.clear_visible_focus();
63            but.set_callback({
64                let mut win = win.clone();
65                let val = val.clone();
66                move |b| {
67                    *val.borrow_mut() = b.label().unwrap();
68                    win.hide();
69                }
70            });
71            pack.add(&*but);
72        }
73        pack.auto_layout();
74        Self { win, val }
75    }
76    pub fn popup(&mut self, x: i32, y: i32) -> String {
77        self.win.show();
78        self.win.resize(x, y, self.win.w(), self.win.h());
79        self.win.redraw();
80        while self.win.shown() {
81            app::wait();
82        }
83        self.val.borrow().to_string()
84    }
85}
86
87fn main() {
88    let app = app::App::default();
89    let mut win = window::Window::default().with_size(400, 300);
90    let mut frame = frame::Frame::default()
91        .with_size(200, 100)
92        .with_label("Right click me!")
93        .center_of_parent();
94    frame.set_frame(FrameType::BorderFrame);
95    frame.set_color(Color::Red);
96    win.end();
97    win.show();
98    let mut menu = MyPopup::new(&["1st item", "2nd item", &format!("{:?}", frame.frame())]);
99    frame.handle(move |_, ev| match ev {
100        Event::Push => {
101            if app::event_mouse_button() == app::MouseButton::Right {
102                println!("{}", menu.popup(app::event_x_root(), app::event_y_root()));
103                true
104            } else {
105                false
106            }
107        }
108        _ => false,
109    });
110    app.run().unwrap();
111}