custom_choice/
custom_choice.rs1#![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}