widgetry/tools/
choose_something.rs1use crate::{
2 Choice, DrawBaselayer, EventCtx, GfxCtx, Line, Menu, Outcome, Panel, State, Transition, Widget,
3};
4
5pub struct ChooseSomething<A, T> {
7 panel: Panel,
8 cb: Option<Box<dyn FnOnce(T, &mut EventCtx, &mut A) -> Transition<A>>>,
10}
11
12impl<A: 'static, T: 'static> ChooseSomething<A, T> {
13 pub fn new_state<I: Into<String>>(
14 ctx: &mut EventCtx,
15 query: I,
16 choices: Vec<Choice<T>>,
17 cb: Box<dyn FnOnce(T, &mut EventCtx, &mut A) -> Transition<A>>,
18 ) -> Box<dyn State<A>> {
19 Box::new(ChooseSomething {
20 panel: Panel::new_builder(Widget::col(vec![
21 Widget::row(vec![
22 Line(query).small_heading().into_widget(ctx),
23 ctx.style().btn_close_widget(ctx),
24 ]),
25 Menu::widget(ctx, choices).named("menu"),
26 ]))
27 .build(ctx),
28 cb: Some(cb),
29 })
30 }
31}
32
33impl<A: 'static, T: 'static> State<A> for ChooseSomething<A, T> {
34 fn event(&mut self, ctx: &mut EventCtx, app: &mut A) -> Transition<A> {
35 match self.panel.event(ctx) {
36 Outcome::Clicked(x) => match x.as_ref() {
37 "close" => Transition::Pop,
38 _ => {
39 let data = self.panel.take_menu_choice::<T>("menu");
40 (self.cb.take().unwrap())(data, ctx, app)
43 }
44 },
45 _ => {
46 if ctx.normal_left_click() && ctx.canvas.get_cursor_in_screen_space().is_none() {
47 return Transition::Pop;
48 }
49 Transition::Keep
50 }
51 }
52 }
53
54 fn draw_baselayer(&self) -> DrawBaselayer {
55 DrawBaselayer::PreviousState
56 }
57
58 fn draw(&self, g: &mut GfxCtx, _: &A) {
59 super::grey_out_map(g);
60 self.panel.draw(g);
61 }
62}