1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
use abstutil::prettyprint_usize; use map_gui::tools::ColorDiscrete; use sim::Scenario; use widgetry::{ Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, StyledButtons, Text, VerticalAlignment, Widget, }; use crate::app::{App, Transition}; use crate::common::CommonState; use crate::devtools::destinations::PopularDestinations; pub struct ScenarioManager { panel: Panel, scenario: Scenario, unzoomed: Drawable, zoomed: Drawable, } impl ScenarioManager { pub fn new(scenario: Scenario, ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> { let mut colorer = ColorDiscrete::new( app, vec![ ("1-2", Color::BLUE), ("3-4", Color::RED), ("more", Color::BLACK), ], ); let mut total_cars_needed = 0; for (b, count) in scenario.count_parked_cars_per_bldg().consume() { total_cars_needed += count; let color = if count == 0 { continue; } else if count == 1 || count == 2 { "1-2" } else if count == 3 || count == 4 { "3-4" } else { "more" }; colorer.add_b(b, color); } let (filled_spots, free_parking_spots) = app.primary.sim.get_all_parking_spots(); assert!(filled_spots.is_empty()); let (unzoomed, zoomed, legend) = colorer.build(ctx); Box::new(ScenarioManager { panel: Panel::new(Widget::col(vec![ Widget::row(vec![ Line(format!("Scenario {}", scenario.scenario_name)) .small_heading() .draw(ctx), ctx.style().btn_close_widget(ctx), ]), ctx.style() .btn_outline_light_text("popular destinations") .hotkey(Key::D) .build_def(ctx), Text::from_multiline(vec![ Line(format!( "{} people", prettyprint_usize(scenario.people.len()) )), Line(format!( "seed {} parked cars", prettyprint_usize(total_cars_needed) )), Line(format!( "{} parking spots", prettyprint_usize(free_parking_spots.len()), )), Line(""), Line("Parked cars per building"), ]) .draw(ctx), legend, ])) .aligned(HorizontalAlignment::Right, VerticalAlignment::Top) .build(ctx), unzoomed, zoomed, scenario, }) } } impl State<App> for ScenarioManager { fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition { match self.panel.event(ctx) { Outcome::Clicked(x) => match x.as_ref() { "close" => { return Transition::Pop; } "popular destinations" => { return Transition::Push(PopularDestinations::new(ctx, app, &self.scenario)); } _ => unreachable!(), }, _ => {} } ctx.canvas_movement(); if ctx.redo_mouseover() { app.recalculate_current_selection(ctx); } Transition::Keep } fn draw(&self, g: &mut GfxCtx, app: &App) { if g.canvas.cam_zoom < app.opts.min_zoom_for_detail { g.redraw(&self.unzoomed); } else { g.redraw(&self.zoomed); } self.panel.draw(g); CommonState::draw_osd(g, app); } }