diff --git a/apps/ltn/src/browse.rs b/apps/ltn/src/browse.rs index 01d9165e44..ec2f5425a7 100644 --- a/apps/ltn/src/browse.rs +++ b/apps/ltn/src/browse.rs @@ -39,67 +39,72 @@ impl BrowseNeighborhoods { ) }); - let left_panel = crate::common::left_panel_builder(Widget::col(vec![ - app.session.alt_proposals.to_widget(ctx, app), - "Click a neighborhood to edit filters".text_widget(ctx), - Widget::row(vec![ - ctx.style() - .btn_outline - .text("Plan a route") - .hotkey(Key::R) - .build_def(ctx), - ctx.style() - .btn_outline - .text("Export to GeoJSON") - .build_def(ctx), - ]) - .section(ctx), - Line("Advanced").small_heading().into_widget(ctx), + let top_panel = crate::common::app_top_panel(ctx, app); + let left_panel = crate::common::left_panel_builder( + ctx, + &top_panel, Widget::col(vec![ + app.session.alt_proposals.to_widget(ctx, app), + "Click a neighborhood to edit filters".text_widget(ctx), Widget::row(vec![ - "Draw neighborhoods:".text_widget(ctx).centered_vert(), + ctx.style() + .btn_outline + .text("Plan a route") + .hotkey(Key::R) + .build_def(ctx), + ctx.style() + .btn_outline + .text("Export to GeoJSON") + .build_def(ctx), + ]) + .section(ctx), + Line("Advanced").small_heading().into_widget(ctx), + Widget::col(vec![ + Widget::row(vec![ + "Draw neighborhoods:".text_widget(ctx).centered_vert(), + Widget::dropdown( + ctx, + "style", + app.session.draw_neighborhood_style, + vec![ + Choice::new("simple", Style::SimpleColoring), + Choice::new("cells", Style::Cells), + Choice::new("quietness", Style::Quietness), + Choice::new("all rat-runs", Style::RatRuns), + ], + ), + ]), + Toggle::checkbox( + ctx, + "highlight boundary roads", + Key::H, + app.session.highlight_boundary_roads, + ), + ]) + .section(ctx), + Widget::col(vec![ + "Predict proposal impact".text_widget(ctx), + impact_widget(ctx, app), + ]) + .section(ctx), + Widget::col(vec![Widget::row(vec![ Widget::dropdown( ctx, - "style", - app.session.draw_neighborhood_style, - vec![ - Choice::new("simple", Style::SimpleColoring), - Choice::new("cells", Style::Cells), - Choice::new("quietness", Style::Quietness), - Choice::new("all rat-runs", Style::RatRuns), - ], + "heuristic", + app.session.heuristic, + Heuristic::choices(), ), - ]), - Toggle::checkbox( - ctx, - "highlight boundary roads", - Key::H, - app.session.highlight_boundary_roads, - ), - ]) - .section(ctx), - Widget::col(vec![ - "Predict proposal impact".text_widget(ctx), - impact_widget(ctx, app), - ]) - .section(ctx), - Widget::col(vec![Widget::row(vec![ - Widget::dropdown( - ctx, - "heuristic", - app.session.heuristic, - Heuristic::choices(), - ), - ctx.style() - .btn_outline - .text("Automatically place filters") - .build_def(ctx), - ])]) - .section(ctx), - ])) + ctx.style() + .btn_outline + .text("Automatically place filters") + .build_def(ctx), + ])]) + .section(ctx), + ]), + ) .build(ctx); Box::new(BrowseNeighborhoods { - top_panel: crate::common::app_top_panel(ctx, app), + top_panel, left_panel, world, draw_over_roads, diff --git a/apps/ltn/src/common/mod.rs b/apps/ltn/src/common/mod.rs index 9a22e7ab9e..4dea7604a0 100644 --- a/apps/ltn/src/common/mod.rs +++ b/apps/ltn/src/common/mod.rs @@ -12,13 +12,13 @@ pub fn app_top_panel(ctx: &mut EventCtx, app: &App) -> Panel { .small_heading() .into_widget(ctx) .centered_vert(), - map_gui::tools::change_map_btn(ctx, app), + map_gui::tools::change_map_btn(ctx, app).centered_vert(), ctx.style() .btn_plain .icon("system/assets/tools/search.svg") .hotkey(lctrl(Key::F)) .build_widget(ctx, "search") - .align_right(), + .centered_vert(), ])) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top) .dims_width(PanelDims::ExactPercent(1.0)) @@ -51,12 +51,14 @@ pub fn handle_top_panel(ctx: &mut EventCtx, app: &App, panel: &mut Panel) -> Opt } } -pub fn left_panel_builder(contents: Widget) -> PanelBuilder { +pub fn left_panel_builder(ctx: &EventCtx, top_panel: &Panel, contents: Widget) -> PanelBuilder { + let top_height = top_panel.panel_dims().height; Panel::new_builder(contents) - // TODO Vertical alignment below top panel is brittle .aligned( HorizontalAlignment::Percent(0.0), - VerticalAlignment::Percent(0.1), + VerticalAlignment::Below(top_height), ) - .dims_height(PanelDims::ExactPercent(0.9)) + .dims_height(PanelDims::ExactPixels( + ctx.canvas.window_height - top_height, + )) } diff --git a/apps/ltn/src/connectivity.rs b/apps/ltn/src/connectivity.rs index 8bc905ba00..c96bc4b694 100644 --- a/apps/ltn/src/connectivity.rs +++ b/apps/ltn/src/connectivity.rs @@ -51,6 +51,7 @@ impl Viewer { .panel_builder( ctx, app, + &self.top_panel, Widget::col(vec![ ctx.style() .btn_outline diff --git a/apps/ltn/src/impact/ui.rs b/apps/ltn/src/impact/ui.rs index 773c3c0266..e463a217b2 100644 --- a/apps/ltn/src/impact/ui.rs +++ b/apps/ltn/src/impact/ui.rs @@ -46,7 +46,7 @@ impl ShowResults { }); } - let left_panel = crate::common::left_panel_builder(Widget::col(vec![ + let contents = Widget::col(vec![ Widget::row(vec![ Line("Impact prediction").small_heading().into_widget(ctx), ctx.style() @@ -60,8 +60,9 @@ impl ShowResults { app.session.impact.filters.to_panel(ctx, app), app.session.impact.compare_counts.get_panel_widget(ctx).named("compare counts"), ctx.style().btn_outline.text("Save before/after counts to files").build_def(ctx), - ])) - .build(ctx); + ]); + let top_panel = crate::common::app_top_panel(ctx, app); + let left_panel = crate::common::left_panel_builder(ctx, &top_panel, contents).build(ctx); let mut batch = GeomBatch::new(); for (_, (block, color)) in app.session.partitioning.all_neighborhoods() { @@ -69,7 +70,7 @@ impl ShowResults { } let draw_all_neighborhoods = batch.upload(ctx); Box::new(Self { - top_panel: crate::common::app_top_panel(ctx, app), + top_panel, left_panel, draw_all_neighborhoods, }) diff --git a/apps/ltn/src/per_neighborhood.rs b/apps/ltn/src/per_neighborhood.rs index f4414e5125..87da325cd5 100644 --- a/apps/ltn/src/per_neighborhood.rs +++ b/apps/ltn/src/per_neighborhood.rs @@ -3,7 +3,8 @@ use map_model::{IntersectionID, PathConstraints, RoadID}; use widgetry::mapspace::{ObjectID, World, WorldOutcome}; use widgetry::tools::open_browser; use widgetry::{ - lctrl, Color, EventCtx, Image, Key, Line, PanelBuilder, TextExt, Widget, DEFAULT_CORNER_RADIUS, + lctrl, Color, EventCtx, Image, Key, Line, Panel, PanelBuilder, TextExt, Widget, + DEFAULT_CORNER_RADIUS, }; use crate::{ @@ -21,9 +22,10 @@ impl Tab { self, ctx: &mut EventCtx, app: &App, + top_panel: &Panel, per_tab_contents: Widget, ) -> PanelBuilder { - crate::common::left_panel_builder(Widget::col(vec![ + let contents = Widget::col(vec![ app.session.alt_proposals.to_widget(ctx, app), Widget::row(vec![ Line("Editing neighborhood") @@ -61,7 +63,8 @@ impl Tab { .section(ctx), self.make_buttons(ctx), per_tab_contents.section(ctx), - ])) + ]); + crate::common::left_panel_builder(ctx, top_panel, contents) } pub fn handle_action( diff --git a/apps/ltn/src/rat_run_viewer.rs b/apps/ltn/src/rat_run_viewer.rs index 664dbdabe7..4669efb85a 100644 --- a/apps/ltn/src/rat_run_viewer.rs +++ b/apps/ltn/src/rat_run_viewer.rs @@ -79,6 +79,7 @@ impl BrowseRatRuns { .panel_builder( ctx, app, + &self.top_panel, percentage_bar( ctx, Text::from(Line(format!( @@ -101,6 +102,7 @@ impl BrowseRatRuns { .panel_builder( ctx, app, + &self.top_panel, Widget::col(vec![ percentage_bar( ctx, diff --git a/apps/ltn/src/route_planner.rs b/apps/ltn/src/route_planner.rs index b368bc6ceb..2328fe529b 100644 --- a/apps/ltn/src/route_planner.rs +++ b/apps/ltn/src/route_planner.rs @@ -64,7 +64,7 @@ impl RoutePlanner { self.files.autosave(app); let results_widget = self.recalculate_paths(ctx, app); - let mut panel = crate::common::left_panel_builder(Widget::col(vec![ + let contents = Widget::col(vec![ app.session.alt_proposals.to_widget(ctx, app), Widget::row(vec![ Line("Plan a route").small_heading().into_widget(ctx), @@ -98,10 +98,11 @@ impl RoutePlanner { ]) .into_widget(ctx), results_widget, - ])) - // Hovering on waypoint cards - .ignore_initial_events() - .build(ctx); + ]); + let mut panel = crate::common::left_panel_builder(ctx, &self.top_panel, contents) + // Hovering on waypoint cards + .ignore_initial_events() + .build(ctx); panel.restore(ctx, &self.left_panel); self.left_panel = panel; diff --git a/apps/ltn/src/select_boundary.rs b/apps/ltn/src/select_boundary.rs index 37d50a15d1..b95828b115 100644 --- a/apps/ltn/src/select_boundary.rs +++ b/apps/ltn/src/select_boundary.rs @@ -36,9 +36,11 @@ pub struct SelectBoundary { impl SelectBoundary { pub fn new_state(ctx: &mut EventCtx, app: &App, id: NeighborhoodID) -> Box> { + let top_panel = crate::common::app_top_panel(ctx, app); + let left_panel = make_panel(ctx, &top_panel); let mut state = SelectBoundary { - top_panel: crate::common::app_top_panel(ctx, app), - left_panel: make_panel(ctx), + top_panel, + left_panel, id, world: World::bounded(app.map.get_bounds()), draw_boundary_roads: draw_boundary_roads(ctx, app), @@ -145,7 +147,7 @@ impl SelectBoundary { } self.draw_boundary_roads = draw_boundary_roads(ctx, app); - self.left_panel = make_panel(ctx); + self.left_panel = make_panel(ctx, &self.top_panel); } Err(err) => { self.last_failed_change = Some((id, self.currently_have_block(app, id))); @@ -249,7 +251,7 @@ impl State for SelectBoundary { if let Some(polygon) = lasso.event(ctx) { self.lasso = None; self.add_blocks_freehand(ctx, app, polygon); - self.left_panel = make_panel(ctx); + self.left_panel = make_panel(ctx, &self.top_panel); } return Transition::Keep; } @@ -275,7 +277,7 @@ impl State for SelectBoundary { } "Select freehand" => { self.lasso = Some(Lasso::new()); - self.left_panel = make_panel_for_lasso(ctx); + self.left_panel = make_panel_for_lasso(ctx, &self.top_panel); } _ => unreachable!(), } @@ -319,60 +321,68 @@ impl State for SelectBoundary { } } -fn make_panel(ctx: &mut EventCtx) -> Panel { - crate::common::left_panel_builder(Widget::col(vec![ - Line("Adjusting neighborhood boundary") - .small_heading() +fn make_panel(ctx: &mut EventCtx, top_panel: &Panel) -> Panel { + crate::common::left_panel_builder( + ctx, + top_panel, + Widget::col(vec![ + Line("Adjusting neighborhood boundary") + .small_heading() + .into_widget(ctx), + Text::from_all(vec![ + Line("Click").fg(ctx.style().text_hotkey_color), + Line(" to add/remove a block"), + ]) + .into_widget(ctx), + Text::from_all(vec![ + Line("Hold "), + Line(Key::LeftControl.describe()).fg(ctx.style().text_hotkey_color), + Line(" and paint over blocks to add"), + ]) + .into_widget(ctx), + Text::from_all(vec![ + Line("Hold "), + Line(Key::LeftShift.describe()).fg(ctx.style().text_hotkey_color), + Line(" and paint over blocks to remove"), + ]) .into_widget(ctx), - Text::from_all(vec![ - Line("Click").fg(ctx.style().text_hotkey_color), - Line(" to add/remove a block"), - ]) - .into_widget(ctx), - Text::from_all(vec![ - Line("Hold "), - Line(Key::LeftControl.describe()).fg(ctx.style().text_hotkey_color), - Line(" and paint over blocks to add"), - ]) - .into_widget(ctx), - Text::from_all(vec![ - Line("Hold "), - Line(Key::LeftShift.describe()).fg(ctx.style().text_hotkey_color), - Line(" and paint over blocks to remove"), - ]) - .into_widget(ctx), - ctx.style() - .btn_outline - .icon_text("system/assets/tools/select.svg", "Select freehand") - .hotkey(Key::F) - .build_def(ctx), - Widget::row(vec![ ctx.style() - .btn_solid_primary - .text("Confirm") - .hotkey(Key::Enter) - .build_def(ctx), - ctx.style() - .btn_solid_destructive - .text("Cancel") - .hotkey(Key::Escape) + .btn_outline + .icon_text("system/assets/tools/select.svg", "Select freehand") + .hotkey(Key::F) .build_def(ctx), + Widget::row(vec![ + ctx.style() + .btn_solid_primary + .text("Confirm") + .hotkey(Key::Enter) + .build_def(ctx), + ctx.style() + .btn_solid_destructive + .text("Cancel") + .hotkey(Key::Escape) + .build_def(ctx), + ]), + Text::new().into_widget(ctx).named("warning"), ]), - Text::new().into_widget(ctx).named("warning"), - ])) + ) .build(ctx) } -fn make_panel_for_lasso(ctx: &mut EventCtx) -> Panel { - crate::common::left_panel_builder(Widget::col(vec![ - "Draw a custom boundary for a neighborhood" - .text_widget(ctx) - .centered_vert(), - Text::from_all(vec![ - Line("Click and drag").fg(ctx.style().text_hotkey_color), - Line(" to select the blocks to add to this neighborhood"), - ]) - .into_widget(ctx), - ])) +fn make_panel_for_lasso(ctx: &mut EventCtx, top_panel: &Panel) -> Panel { + crate::common::left_panel_builder( + ctx, + top_panel, + Widget::col(vec![ + "Draw a custom boundary for a neighborhood" + .text_widget(ctx) + .centered_vert(), + Text::from_all(vec![ + Line("Click and drag").fg(ctx.style().text_hotkey_color), + Line(" to select the blocks to add to this neighborhood"), + ]) + .into_widget(ctx), + ]), + ) .build(ctx) } diff --git a/map_gui/src/colors.rs b/map_gui/src/colors.rs index 908df32011..dea782f506 100644 --- a/map_gui/src/colors.rs +++ b/map_gui/src/colors.rs @@ -361,6 +361,10 @@ impl ColorScheme { let mut cs = ColorScheme::day_mode(); cs.scheme = ColorSchemeChoice::LTN; cs.private_road = None; + + cs.gui_style.panel_bg = Color::WHITE; + cs.panel_bg = cs.gui_style.panel_bg; + cs } }