widgetry/tools/
popup.rs

1use crate::{
2    hotkeys, DrawBaselayer, EventCtx, GfxCtx, Key, Line, Outcome, Panel, State, Text, Transition,
3    Widget,
4};
5
6/// Display a message dialog.
7pub struct PopupMsg {
8    panel: Panel,
9}
10
11impl PopupMsg {
12    pub fn new_state<A>(
13        ctx: &mut EventCtx,
14        title: &str,
15        lines: Vec<impl AsRef<str>>,
16    ) -> Box<dyn State<A>> {
17        let mut txt = Text::new();
18        txt.add_line(Line(title).small_heading());
19        for l in lines {
20            txt.add_line(l);
21        }
22        Self::new_state_for_txt(ctx, txt)
23    }
24
25    pub fn new_state_for_txt<A>(ctx: &mut EventCtx, txt: Text) -> Box<dyn State<A>> {
26        Box::new(PopupMsg {
27            panel: Panel::new_builder(Widget::col(vec![
28                txt.into_widget(ctx),
29                ctx.style()
30                    .btn_solid_primary
31                    .text("OK")
32                    .hotkey(hotkeys(vec![Key::Enter, Key::Escape]))
33                    .build_def(ctx),
34            ]))
35            .build(ctx),
36        })
37    }
38}
39
40impl<A> State<A> for PopupMsg {
41    fn event(&mut self, ctx: &mut EventCtx, _: &mut A) -> Transition<A> {
42        match self.panel.event(ctx) {
43            Outcome::Clicked(x) => match x.as_ref() {
44                "OK" => Transition::Pop,
45                _ => unreachable!(),
46            },
47            _ => {
48                if ctx.normal_left_click() && ctx.canvas.get_cursor_in_screen_space().is_none() {
49                    return Transition::Pop;
50                }
51                Transition::Keep
52            }
53        }
54    }
55
56    fn draw_baselayer(&self) -> DrawBaselayer {
57        DrawBaselayer::PreviousState
58    }
59
60    fn draw(&self, g: &mut GfxCtx, _: &A) {
61        super::grey_out_map(g);
62        self.panel.draw(g);
63    }
64}