game/devtools/
polygon.rs

1use geom::LonLat;
2use map_gui::tools::EditPolygon;
3use widgetry::{
4    EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, VerticalAlignment,
5    Widget,
6};
7
8use crate::app::App;
9use crate::app::Transition;
10
11pub struct PolygonEditor {
12    panel: Panel,
13    name: String,
14    edit: EditPolygon,
15}
16
17impl PolygonEditor {
18    pub fn new_state(
19        ctx: &mut EventCtx,
20        app: &App,
21        name: String,
22        points: Vec<LonLat>,
23    ) -> Box<dyn State<App>> {
24        let points = app.primary.map.get_gps_bounds().convert(&points);
25        Box::new(Self {
26            panel: Panel::new_builder(Widget::col(vec![
27                Widget::row(vec![
28                    Line("Polygon editor").small_heading().into_widget(ctx),
29                    ctx.style().btn_close_widget(ctx),
30                ]),
31                ctx.style()
32                    .btn_outline
33                    .text("export as a GeoJSON boundary")
34                    // TODO Disable based on number of points
35                    .hotkey(Key::X)
36                    .build_def(ctx),
37            ]))
38            .aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
39            .build(ctx),
40            name,
41            edit: EditPolygon::new(ctx, points, true),
42        })
43    }
44}
45
46impl State<App> for PolygonEditor {
47    fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
48        self.edit.event(ctx);
49
50        if let Outcome::Clicked(x) = self.panel.event(ctx) {
51            match x.as_ref() {
52                "close" => {
53                    return Transition::Pop;
54                }
55                "export as a GeoJSON boundary" => {
56                    if let Ok(ring) = self.edit.get_ring() {
57                        let polygon = ring
58                            .into_polygon()
59                            .to_geojson(Some(app.primary.map.get_gps_bounds()));
60                        let gj = geom::geometries_with_properties_to_geojson(vec![(
61                            polygon,
62                            serde_json::Map::new(),
63                        )]);
64                        abstio::write_file(
65                            format!("{}.geojson", self.name),
66                            abstutil::to_json(&gj),
67                        )
68                        .unwrap();
69                    }
70                }
71                _ => unreachable!(),
72            }
73        }
74
75        Transition::Keep
76    }
77
78    fn draw(&self, g: &mut GfxCtx, _: &App) {
79        self.panel.draw(g);
80        self.edit.draw(g);
81    }
82}