1use map_gui::tools::ColorDiscrete;
2use map_model::{PathConstraints, PathStep};
3use widgetry::mapspace::ToggleZoomed;
4use widgetry::{EventCtx, GfxCtx, Outcome, Panel, Toggle, Widget};
5
6use crate::app::App;
7use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
8
9pub struct TransitNetwork {
10 panel: Panel,
11 draw: ToggleZoomed,
12}
13
14impl Layer for TransitNetwork {
15 fn name(&self) -> Option<&'static str> {
16 Some("transit network")
17 }
18 fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
19 match self.panel.event(ctx) {
20 Outcome::Clicked(x) => match x.as_ref() {
21 "close" => {
22 return Some(LayerOutcome::Close);
23 }
24 _ => unreachable!(),
25 },
26 Outcome::Changed(_) => {
27 *self = TransitNetwork::new(
28 ctx,
29 app,
30 self.panel.is_checked("show all routes"),
31 self.panel.is_checked("show buses"),
32 self.panel.is_checked("show trains"),
33 );
34 }
35 _ => {}
36 }
37 None
38 }
39 fn draw(&self, g: &mut GfxCtx, _: &App) {
40 self.panel.draw(g);
41 self.draw.draw(g);
42 }
43 fn draw_minimap(&self, g: &mut GfxCtx) {
44 g.redraw(&self.draw.unzoomed);
45 }
46}
47
48impl TransitNetwork {
49 pub fn new(
50 ctx: &mut EventCtx,
51 app: &App,
52 show_all_routes: bool,
53 show_buses: bool,
54 show_trains: bool,
55 ) -> TransitNetwork {
56 let map = &app.primary.map;
57 let mut categories = vec![
59 ("bus lanes / rails", app.cs.bus_layer),
60 ("transit stops", app.cs.bus_layer),
61 ];
62 if show_all_routes {
63 categories.push(("routes", app.cs.bus_layer));
64 }
65 let mut colorer = ColorDiscrete::new(app, categories);
66 for l in map.all_lanes() {
67 if l.is_bus() && show_buses {
68 colorer.add_l(l.id, "bus lanes / rails");
69 }
70 if l.is_light_rail() && show_trains {
71 colorer.add_l(l.id, "bus lanes / rails");
72 }
73 }
74 for ts in map.all_transit_stops().values() {
75 if !ts.is_train_stop && show_buses {
76 colorer.add_ts(ts.id, "transit stops");
77 }
78 if ts.is_train_stop && show_trains {
79 colorer.add_ts(ts.id, "transit stops");
80 }
81 }
82 if show_all_routes {
83 for tr in map.all_transit_routes() {
84 if !show_buses && tr.route_type == PathConstraints::Bus {
85 continue;
86 }
87 if !show_trains && tr.route_type == PathConstraints::Train {
88 continue;
89 }
90 for path in tr.all_paths(map).unwrap() {
91 for step in path.get_steps() {
92 if let PathStep::Lane(l) = step {
93 colorer.add_l(*l, "routes");
94 }
95 }
96 }
97 }
98 }
99 let (draw, legend) = colorer.build(ctx);
100
101 let panel = Panel::new_builder(Widget::col(vec![
102 header(ctx, "Transit network"),
103 Toggle::switch(ctx, "show all routes", None, show_all_routes),
104 Toggle::switch(ctx, "show buses", None, show_buses),
105 Toggle::switch(ctx, "show trains", None, show_trains),
106 legend,
107 ]))
108 .aligned_pair(PANEL_PLACEMENT)
109 .build(ctx);
110
111 TransitNetwork { panel, draw }
112 }
113}