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 .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}