fltk 1.4.22

Rust bindings for the FLTK GUI library
Documentation
use fltk::{enums::*, prelude::*, *};
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;

pub struct PopupButton {
    but: button::Button,
}

impl PopupButton {
    pub fn new(label: &str) -> Self {
        let mut but = button::Button::default().with_label(label);
        but.set_frame(FrameType::FlatBox);
        but.handle(|b, ev| match ev {
            Event::Enter => {
                b.set_color(Color::Blue);
                b.top_window().unwrap().redraw();
                true
            }
            Event::Leave => {
                b.set_color(Color::BackGround);
                b.top_window().unwrap().redraw();
                true
            }
            _ => false,
        });
        Self { but }
    }
}

impl Deref for PopupButton {
    type Target = button::Button;

    fn deref(&self) -> &Self::Target {
        &self.but
    }
}

impl DerefMut for PopupButton {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.but
    }
}

pub struct MyPopup {
    win: window::Window,
    val: Rc<RefCell<String>>,
}

impl MyPopup {
    pub fn new(choices: &[&str]) -> Self {
        let val = Rc::from(RefCell::from(String::from("")));
        let mut win = window::Window::default().with_size(120, choices.len() as i32 * 25);
        let mut pack = group::Pack::default().size_of_parent();
        pack.set_frame(FrameType::ThinUpFrame);
        pack.set_color(Color::Black);
        win.set_border(false);
        win.make_modal(true);
        win.end();
        for choice in choices {
            let mut but = PopupButton::new(choice);
            but.clear_visible_focus();
            but.set_callback({
                let mut win = win.clone();
                let val = val.clone();
                move |b| {
                    *val.borrow_mut() = b.label();
                    win.hide();
                }
            });
            pack.add(&*but);
        }
        pack.auto_layout();
        Self { win, val }
    }
    pub fn popup(&mut self, x: i32, y: i32) -> String {
        self.win.show();
        self.win.set_pos(x, y);
        self.win.redraw();
        while self.win.shown() {
            app::wait();
        }
        self.val.borrow().to_string()
    }
}

fn main() {
    let app = app::App::default();
    let mut win = window::Window::default().with_size(400, 300);
    let mut frame = frame::Frame::default()
        .with_size(200, 100)
        .with_label("Right click me!")
        .center_of_parent();
    frame.set_frame(FrameType::BorderFrame);
    frame.set_color(Color::Red);
    win.end();
    win.show();
    let mut menu = MyPopup::new(&["1st item", "2nd item", &format!("{:?}", frame.frame())]);
    frame.handle(move |_, ev| match ev {
        Event::Push => {
            if app::event_mouse_button() == app::MouseButton::Right {
                println!("{}", menu.popup(app::event_x_root(), app::event_y_root()));
                true
            } else {
                false
            }
        }
        _ => false,
    });
    app.run().unwrap();
}