diff --git a/ltn/src/browse.rs b/ltn/src/browse.rs index 1133551331..2364fbb0e2 100644 --- a/ltn/src/browse.rs +++ b/ltn/src/browse.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; use abstutil::{Counter, Timer}; use geom::Distance; -use map_gui::tools::{CityPicker, ColorNetwork, DrawRoadLabels, Navigator, PopupMsg, URLManager}; +use map_gui::tools::{ColorNetwork, DrawRoadLabels, PopupMsg, URLManager}; use synthpop::Scenario; use widgetry::mapspace::{ToggleZoomed, World, WorldOutcome}; use widgetry::{ @@ -41,18 +41,8 @@ impl BrowseNeighborhoods { let draw_all_filters = app.session.modal_filters.draw(ctx, &app.map, None); let panel = Panel::new_builder(Widget::col(vec![ - map_gui::tools::app_header(ctx, app, "Low traffic neighborhoods"), - Widget::row(vec![ - "Click a neighborhood to edit filters" - .text_widget(ctx) - .centered_vert(), - ctx.style() - .btn_plain - .icon("system/assets/tools/search.svg") - .hotkey(Key::K) - .build_widget(ctx, "search") - .align_right(), - ]), + crate::app_header(ctx, app), + "Click a neighborhood to edit filters".text_widget(ctx), Widget::col(vec![ Toggle::checkbox( ctx, @@ -125,26 +115,6 @@ impl State for BrowseNeighborhoods { fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition { match self.panel.event(ctx) { Outcome::Clicked(x) => match x.as_ref() { - "Home" => { - return Transition::Clear(vec![map_gui::tools::TitleScreen::new_state( - ctx, - app, - map_gui::tools::Executable::LTN, - Box::new(|ctx, app, _| BrowseNeighborhoods::new_state(ctx, app)), - )]); - } - "change map" => { - return Transition::Push(CityPicker::new_state( - ctx, - app, - Box::new(|ctx, app| { - Transition::Replace(BrowseNeighborhoods::new_state(ctx, app)) - }), - )); - } - "search" => { - return Transition::Push(Navigator::new_state(ctx, app)); - } "New" => { app.session.partitioning = Partitioning::empty(); app.session.modal_filters = ModalFilters::default(); @@ -188,7 +158,9 @@ impl State for BrowseNeighborhoods { }); return Transition::Replace(BrowseNeighborhoods::new_state(ctx, app)); } - _ => unreachable!(), + x => { + return crate::handle_app_header_click(ctx, app, x).unwrap(); + } }, Outcome::Changed(_) => { app.session.highlight_boundary_roads = diff --git a/ltn/src/impact/ui.rs b/ltn/src/impact/ui.rs index e9aaa682db..5ca33e4c0c 100644 --- a/ltn/src/impact/ui.rs +++ b/ltn/src/impact/ui.rs @@ -1,7 +1,7 @@ use std::collections::BTreeSet; use map_gui::load::FileLoader; -use map_gui::tools::{checkbox_per_mode, CityPicker, Navigator, PopupMsg}; +use map_gui::tools::{checkbox_per_mode, PopupMsg}; use synthpop::{Scenario, TripMode}; use widgetry::{ Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Panel, SimpleState, @@ -46,7 +46,7 @@ impl ShowResults { } let panel = Panel::new_builder(Widget::col(vec![ - map_gui::tools::app_header(ctx, app, "Low traffic neighborhoods"), + crate::app_header(ctx, app), "Impact prediction".text_widget(ctx), ctx.style().btn_outline.text("Browse neighborhoods").hotkey(Key::Escape).build_def(ctx), Text::from(Line("This tool starts with a travel demand model, calculates the route every trip takes before and after changes, and displays volumes along roads and intersections")).wrap_to_pct(ctx, 20).into_widget(ctx), @@ -82,26 +82,6 @@ impl SimpleState for ShowResults { panel: &mut Panel, ) -> Transition { match x { - "Home" => { - return Transition::Clear(vec![map_gui::tools::TitleScreen::new_state( - ctx, - app, - map_gui::tools::Executable::LTN, - Box::new(|ctx, app, _| BrowseNeighborhoods::new_state(ctx, app)), - )]); - } - "change map" => { - return Transition::Push(CityPicker::new_state( - ctx, - app, - Box::new(|ctx, app| { - Transition::Replace(BrowseNeighborhoods::new_state(ctx, app)) - }), - )); - } - "search" => { - return Transition::Push(Navigator::new_state(ctx, app)); - } "Browse neighborhoods" => { // Don't just Pop; if we updated the results, the UI won't warn the user about a slow // loading @@ -125,6 +105,10 @@ impl SimpleState for ShowResults { )) } x => { + if let Some(t) = crate::handle_app_header_click(ctx, app, x) { + return t; + } + // Avoid a double borrow let mut impact = std::mem::replace(&mut app.session.impact, Impact::empty(ctx)); let widget = impact diff --git a/ltn/src/lib.rs b/ltn/src/lib.rs index 4ce4a66bd6..b12df2e605 100644 --- a/ltn/src/lib.rs +++ b/ltn/src/lib.rs @@ -2,7 +2,7 @@ use structopt::StructOpt; -use widgetry::{GfxCtx, Settings}; +use widgetry::{lctrl, EventCtx, GfxCtx, Key, Line, Settings, Widget}; pub use browse::BrowseNeighborhoods; pub use filters::{DiagonalFilter, ModalFilters, Toggle3Zoomed}; @@ -169,3 +169,47 @@ fn draw_with_layering(g: &mut GfxCtx, app: &App, custom: F) } } } + +// Like map_gui::tools::app_header, but squeezing in a search button +fn app_header(ctx: &EventCtx, app: &App) -> Widget { + Widget::col(vec![ + Widget::row(vec![ + map_gui::tools::home_btn(ctx), + Line("Low traffic neighborhoods") + .small_heading() + .into_widget(ctx) + .centered_vert(), + ]), + Widget::row(vec![ + map_gui::tools::change_map_btn(ctx, app), + ctx.style() + .btn_plain + .icon("system/assets/tools/search.svg") + .hotkey(lctrl(Key::F)) + .build_widget(ctx, "search") + .align_right(), + ]), + ]) +} + +fn handle_app_header_click(ctx: &mut EventCtx, app: &App, x: &str) -> Option { + match x { + "Home" => Some(Transition::Clear(vec![ + map_gui::tools::TitleScreen::new_state( + ctx, + app, + map_gui::tools::Executable::LTN, + Box::new(|ctx, app, _| BrowseNeighborhoods::new_state(ctx, app)), + ), + ])), + "change map" => Some(Transition::Push(map_gui::tools::CityPicker::new_state( + ctx, + app, + Box::new(|ctx, app| Transition::Replace(BrowseNeighborhoods::new_state(ctx, app))), + ))), + "search" => Some(Transition::Push(map_gui::tools::Navigator::new_state( + ctx, app, + ))), + _ => None, + } +} diff --git a/ltn/src/per_neighborhood.rs b/ltn/src/per_neighborhood.rs index f03b861b39..9100dd38bc 100644 --- a/ltn/src/per_neighborhood.rs +++ b/ltn/src/per_neighborhood.rs @@ -1,5 +1,5 @@ use geom::Distance; -use map_gui::tools::{open_browser, CityPicker, Navigator}; +use map_gui::tools::open_browser; use map_model::{IntersectionID, PathConstraints, RoadID}; use widgetry::mapspace::{ObjectID, World, WorldOutcome}; use widgetry::{ @@ -25,7 +25,7 @@ impl Tab { per_tab_contents: Widget, ) -> PanelBuilder { Panel::new_builder(Widget::col(vec![ - map_gui::tools::app_header(ctx, app, "Low traffic neighborhoods"), + crate::app_header(ctx, app), Widget::row(vec![ ctx.style() .btn_outline @@ -76,17 +76,6 @@ impl Tab { id: NeighborhoodID, ) -> Option { Some(match action { - "Home" => Transition::Clear(vec![map_gui::tools::TitleScreen::new_state( - ctx, - app, - map_gui::tools::Executable::LTN, - Box::new(|ctx, app, _| BrowseNeighborhoods::new_state(ctx, app)), - )]), - "change map" => Transition::Push(CityPicker::new_state( - ctx, - app, - Box::new(|ctx, app| Transition::Replace(BrowseNeighborhoods::new_state(ctx, app))), - )), "Browse neighborhoods" => { // Recalculate the state to redraw any changed filters Transition::Replace(BrowseNeighborhoods::new_state(ctx, app)) @@ -104,11 +93,8 @@ impl Tab { // dropdowns) self.switch_to_state(ctx, app, id) } - "search" => { - return Some(Transition::Push(Navigator::new_state(ctx, app))); - } - _ => { - return None; + x => { + return crate::handle_app_header_click(ctx, app, x); } }) } @@ -145,15 +131,6 @@ impl Tab { .build_def(ctx), ); } - // Not exactly sure where to put this - row.push( - ctx.style() - .btn_plain - .icon("system/assets/tools/search.svg") - .hotkey(Key::K) - .build_widget(ctx, "search") - .align_right(), - ); Widget::row(row) } } diff --git a/ltn/src/select_boundary.rs b/ltn/src/select_boundary.rs index ad5307dfac..a20474951d 100644 --- a/ltn/src/select_boundary.rs +++ b/ltn/src/select_boundary.rs @@ -199,7 +199,9 @@ impl State for SelectBoundary { ctx, app, self.id, )); } - _ => unreachable!(), + x => { + return crate::handle_app_header_click(ctx, app, x).unwrap(); + } } } @@ -236,7 +238,7 @@ impl State for SelectBoundary { fn make_panel(ctx: &mut EventCtx, app: &App) -> Panel { Panel::new_builder(Widget::col(vec![ - map_gui::tools::app_header(ctx, app, "Low traffic neighborhoods"), + crate::app_header(ctx, app), "Draw a custom boundary for a neighborhood" .text_widget(ctx) .centered_vert(),