Standardizing app header and handling in the LTN tool. The select boundary UI was also missing button handlers...

This commit is contained in:
Dustin Carlino 2022-02-04 10:33:09 +00:00
parent b06129da58
commit 69d2fdd39b
5 changed files with 65 additions and 86 deletions

View File

@ -2,7 +2,7 @@ use std::collections::HashSet;
use abstutil::{Counter, Timer}; use abstutil::{Counter, Timer};
use geom::Distance; 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 synthpop::Scenario;
use widgetry::mapspace::{ToggleZoomed, World, WorldOutcome}; use widgetry::mapspace::{ToggleZoomed, World, WorldOutcome};
use widgetry::{ use widgetry::{
@ -41,18 +41,8 @@ impl BrowseNeighborhoods {
let draw_all_filters = app.session.modal_filters.draw(ctx, &app.map, None); let draw_all_filters = app.session.modal_filters.draw(ctx, &app.map, None);
let panel = Panel::new_builder(Widget::col(vec![ let panel = Panel::new_builder(Widget::col(vec![
map_gui::tools::app_header(ctx, app, "Low traffic neighborhoods"), crate::app_header(ctx, app),
Widget::row(vec![ "Click a neighborhood to edit filters".text_widget(ctx),
"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(),
]),
Widget::col(vec![ Widget::col(vec![
Toggle::checkbox( Toggle::checkbox(
ctx, ctx,
@ -125,26 +115,6 @@ impl State<App> for BrowseNeighborhoods {
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition { fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
match self.panel.event(ctx) { match self.panel.event(ctx) {
Outcome::Clicked(x) => match x.as_ref() { 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" => { "New" => {
app.session.partitioning = Partitioning::empty(); app.session.partitioning = Partitioning::empty();
app.session.modal_filters = ModalFilters::default(); app.session.modal_filters = ModalFilters::default();
@ -188,7 +158,9 @@ impl State<App> for BrowseNeighborhoods {
}); });
return Transition::Replace(BrowseNeighborhoods::new_state(ctx, app)); return Transition::Replace(BrowseNeighborhoods::new_state(ctx, app));
} }
_ => unreachable!(), x => {
return crate::handle_app_header_click(ctx, app, x).unwrap();
}
}, },
Outcome::Changed(_) => { Outcome::Changed(_) => {
app.session.highlight_boundary_roads = app.session.highlight_boundary_roads =

View File

@ -1,7 +1,7 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use map_gui::load::FileLoader; 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 synthpop::{Scenario, TripMode};
use widgetry::{ use widgetry::{
Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Panel, SimpleState, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Panel, SimpleState,
@ -46,7 +46,7 @@ impl ShowResults {
} }
let panel = Panel::new_builder(Widget::col(vec![ 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), "Impact prediction".text_widget(ctx),
ctx.style().btn_outline.text("Browse neighborhoods").hotkey(Key::Escape).build_def(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), 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<App> for ShowResults {
panel: &mut Panel, panel: &mut Panel,
) -> Transition { ) -> Transition {
match x { 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" => { "Browse neighborhoods" => {
// Don't just Pop; if we updated the results, the UI won't warn the user about a slow // Don't just Pop; if we updated the results, the UI won't warn the user about a slow
// loading // loading
@ -125,6 +105,10 @@ impl SimpleState<App> for ShowResults {
)) ))
} }
x => { x => {
if let Some(t) = crate::handle_app_header_click(ctx, app, x) {
return t;
}
// Avoid a double borrow // Avoid a double borrow
let mut impact = std::mem::replace(&mut app.session.impact, Impact::empty(ctx)); let mut impact = std::mem::replace(&mut app.session.impact, Impact::empty(ctx));
let widget = impact let widget = impact

View File

@ -2,7 +2,7 @@
use structopt::StructOpt; use structopt::StructOpt;
use widgetry::{GfxCtx, Settings}; use widgetry::{lctrl, EventCtx, GfxCtx, Key, Line, Settings, Widget};
pub use browse::BrowseNeighborhoods; pub use browse::BrowseNeighborhoods;
pub use filters::{DiagonalFilter, ModalFilters, Toggle3Zoomed}; pub use filters::{DiagonalFilter, ModalFilters, Toggle3Zoomed};
@ -169,3 +169,47 @@ fn draw_with_layering<F: Fn(&mut GfxCtx)>(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<Transition> {
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,
}
}

View File

@ -1,5 +1,5 @@
use geom::Distance; use geom::Distance;
use map_gui::tools::{open_browser, CityPicker, Navigator}; use map_gui::tools::open_browser;
use map_model::{IntersectionID, PathConstraints, RoadID}; use map_model::{IntersectionID, PathConstraints, RoadID};
use widgetry::mapspace::{ObjectID, World, WorldOutcome}; use widgetry::mapspace::{ObjectID, World, WorldOutcome};
use widgetry::{ use widgetry::{
@ -25,7 +25,7 @@ impl Tab {
per_tab_contents: Widget, per_tab_contents: Widget,
) -> PanelBuilder { ) -> PanelBuilder {
Panel::new_builder(Widget::col(vec![ Panel::new_builder(Widget::col(vec![
map_gui::tools::app_header(ctx, app, "Low traffic neighborhoods"), crate::app_header(ctx, app),
Widget::row(vec![ Widget::row(vec![
ctx.style() ctx.style()
.btn_outline .btn_outline
@ -76,17 +76,6 @@ impl Tab {
id: NeighborhoodID, id: NeighborhoodID,
) -> Option<Transition> { ) -> Option<Transition> {
Some(match action { 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" => { "Browse neighborhoods" => {
// Recalculate the state to redraw any changed filters // Recalculate the state to redraw any changed filters
Transition::Replace(BrowseNeighborhoods::new_state(ctx, app)) Transition::Replace(BrowseNeighborhoods::new_state(ctx, app))
@ -104,11 +93,8 @@ impl Tab {
// dropdowns) // dropdowns)
self.switch_to_state(ctx, app, id) self.switch_to_state(ctx, app, id)
} }
"search" => { x => {
return Some(Transition::Push(Navigator::new_state(ctx, app))); return crate::handle_app_header_click(ctx, app, x);
}
_ => {
return None;
} }
}) })
} }
@ -145,15 +131,6 @@ impl Tab {
.build_def(ctx), .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) Widget::row(row)
} }
} }

View File

@ -199,7 +199,9 @@ impl State<App> for SelectBoundary {
ctx, app, self.id, ctx, app, self.id,
)); ));
} }
_ => unreachable!(), x => {
return crate::handle_app_header_click(ctx, app, x).unwrap();
}
} }
} }
@ -236,7 +238,7 @@ impl State<App> for SelectBoundary {
fn make_panel(ctx: &mut EventCtx, app: &App) -> Panel { fn make_panel(ctx: &mut EventCtx, app: &App) -> Panel {
Panel::new_builder(Widget::col(vec![ 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" "Draw a custom boundary for a neighborhood"
.text_widget(ctx) .text_widget(ctx)
.centered_vert(), .centered_vert(),