A tiny start to the great UI button refactor: make the "X" button

consistent. #331
This commit is contained in:
Dustin Carlino 2020-10-28 12:04:36 -07:00
parent 3b838c1225
commit 0167b4be31
41 changed files with 87 additions and 196 deletions

View File

@ -1,8 +1,8 @@
use geom::{Distance, Polygon, Pt2D}; use geom::{Distance, Polygon, Pt2D};
use map_model::City; use map_model::City;
use widgetry::{ use widgetry::{
Btn, Color, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Key, Line, Outcome, Panel, ScreenPt, Btn, Color, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Line, Outcome, Panel, ScreenPt, State,
State, Text, Widget, Text, Widget,
}; };
use crate::app::App; use crate::app::App;
@ -88,9 +88,7 @@ impl CityPicker {
Widget::col(vec![ Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Select a region").small_heading().draw(ctx), Line("Select a region").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
Widget::col(other_cities).centered_vert(), Widget::col(other_cities).centered_vert(),

View File

@ -1,8 +1,8 @@
use geom::{Distance, Polygon}; use geom::{Distance, Polygon};
use map_model::{connectivity, BuildingID}; use map_model::{connectivity, BuildingID};
use widgetry::{ use widgetry::{
Btn, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Btn, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Outcome, Panel,
Panel, State, VerticalAlignment, Widget, State, VerticalAlignment, Widget,
}; };
use crate::app::App; use crate::app::App;
@ -22,9 +22,7 @@ impl IsochroneViewer {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Isochrone").small_heading().draw(ctx), Line("Isochrone").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
// TODO legend, mode picker // TODO legend, mode picker
])) ]))

View File

@ -22,9 +22,7 @@ impl Navigator {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Enter a street name").small_heading().draw(ctx), Line("Enter a street name").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Autocomplete::new( Autocomplete::new(
ctx, ctx,
@ -114,9 +112,7 @@ impl CrossStreet {
))); )));
txt.draw(ctx) txt.draw(ctx)
}, },
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Autocomplete::new( Autocomplete::new(
ctx, ctx,
@ -206,9 +202,7 @@ impl SearchBuildings {
Line("Enter a business name or address") Line("Enter a business name or address")
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Autocomplete::new( Autocomplete::new(
ctx, ctx,

View File

@ -78,9 +78,7 @@ impl DebugWarp {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Warp to an object by ID").small_heading().draw(ctx), Line("Warp to an object by ID").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
"Example: r42 is Road #42".draw_text(ctx), "Example: r42 is Road #42".draw_text(ctx),
// T // T

View File

@ -2,7 +2,7 @@ use std::collections::HashSet;
use map_model::{connectivity, LaneID, Map, PathConstraints}; use map_model::{connectivity, LaneID, Map, PathConstraints};
use widgetry::{ use widgetry::{
Btn, Choice, Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, Btn, Choice, Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Line, Outcome, Panel,
State, TextExt, VerticalAlignment, Widget, State, TextExt, VerticalAlignment, Widget,
}; };
@ -50,12 +50,7 @@ impl Floodfiller {
let (unzoomed, zoomed, legend) = colorer.build(ctx); let (unzoomed, zoomed, legend) = colorer.build(ctx);
Box::new(Floodfiller { Box::new(Floodfiller {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![Line(title).small_heading().draw(ctx), Btn::close(ctx)]),
Line(title).small_heading().draw(ctx),
Btn::text_fg("X")
.build(ctx, "close", Key::Escape)
.align_right(),
]),
format!("{} unreachable lanes", num_unreachable).draw_text(ctx), format!("{} unreachable lanes", num_unreachable).draw_text(ctx),
legend, legend,
Widget::row(vec![ Widget::row(vec![

View File

@ -45,9 +45,7 @@ impl DebugMode {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Debug Mode").small_heading().draw(ctx), Line("Debug Mode").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::new().draw(ctx).named("current info"), Text::new().draw(ctx).named("current info"),
Checkbox::switch(ctx, "show buildings", Key::Num1, true), Checkbox::switch(ctx, "show buildings", Key::Num1, true),

View File

@ -3,8 +3,8 @@
use abstutil::Counter; use abstutil::Counter;
use map_model::{IntersectionID, PathStep, RoadID, Traversable}; use map_model::{IntersectionID, PathStep, RoadID, Traversable};
use widgetry::{ use widgetry::{
Btn, Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, Btn, Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Line, Outcome, Panel, State, Text,
Text, VerticalAlignment, Widget, VerticalAlignment, Widget,
}; };
use crate::app::App; use crate::app::App;
@ -68,9 +68,7 @@ impl PathCounter {
Line(format!("Paths across {}", i)) Line(format!("Paths across {}", i))
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
ColorLegend::gradient( ColorLegend::gradient(
ctx, ctx,

View File

@ -36,9 +36,7 @@ impl PolygonDebugger {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Geometry debugger").small_heading().draw(ctx), Line("Geometry debugger").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
// TODO inactive // TODO inactive

View File

@ -2,7 +2,7 @@ use abstutil::Counter;
use map_model::BuildingID; use map_model::BuildingID;
use sim::{Scenario, TripEndpoint}; use sim::{Scenario, TripEndpoint};
use widgetry::{ use widgetry::{
Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line,
Outcome, Panel, State, Text, VerticalAlignment, Widget, Outcome, Panel, State, Text, VerticalAlignment, Widget,
}; };
@ -94,9 +94,7 @@ impl PopularDestinations {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Most popular destinations").small_heading().draw(ctx), Line("Most popular destinations").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Checkbox::switch(ctx, "Show heatmap", None, opts.is_some()), Checkbox::switch(ctx, "Show heatmap", None, opts.is_some()),
controls, controls,

View File

@ -119,9 +119,7 @@ impl ViewKML {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("KML viewer").small_heading().draw(ctx), Line("KML viewer").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
format!( format!(
"{}: {} objects", "{}: {} objects",

View File

@ -124,9 +124,7 @@ impl ParkingMapper {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Parking mapper").small_heading().draw(ctx), Line("Parking mapper").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
"Change map:".draw_text(ctx), "Change map:".draw_text(ctx),
@ -428,9 +426,7 @@ impl ChangeWay {
Line("What kind of parking does this road have?") Line("What kind of parking does this road have?")
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Menu::new( Menu::new(
ctx, ctx,

View File

@ -28,9 +28,7 @@ impl DevToolsMode {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Internal dev tools").small_heading().draw(ctx), Line("Internal dev tools").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
"Change map:".draw_text(ctx), "Change map:".draw_text(ctx),

View File

@ -47,9 +47,7 @@ impl Viewer {
let top_panel = Panel::new(Widget::col(vec![ let top_panel = Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("OpenStreetMap viewer").small_heading().draw(ctx), Line("OpenStreetMap viewer").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
"Change map:".draw_text(ctx), "Change map:".draw_text(ctx),

View File

@ -30,9 +30,7 @@ impl PolygonEditor {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Polygon editor").small_heading().draw(ctx), Line("Polygon editor").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Btn::text_fg("export as an Osmosis polygon filter").build_def(ctx, Key::X), Btn::text_fg("export as an Osmosis polygon filter").build_def(ctx, Key::X),
])) ]))

View File

@ -52,9 +52,7 @@ impl ScenarioManager {
Line(format!("Scenario {}", scenario.scenario_name)) Line(format!("Scenario {}", scenario.scenario_name))
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Btn::text_fg("popular destinations").build_def(ctx, Key::D), Btn::text_fg("popular destinations").build_def(ctx, Key::D),
Text::from_multiline(vec![ Text::from_multiline(vec![

View File

@ -323,9 +323,7 @@ fn make_panel(ctx: &mut EventCtx, story: &StoryMap, mode: &Mode, dirty: bool) ->
RewriteColor::ChangeAlpha(0.5), RewriteColor::ChangeAlpha(0.5),
) )
}, },
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
if let Mode::PlacingMarker = mode { if let Mode::PlacingMarker = mode {
@ -507,9 +505,7 @@ impl Marker {
Panel::new(Widget::col(vec![ Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Editing marker").small_heading().draw(ctx), Line("Editing marker").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Btn::text_fg("delete").build_def(ctx, None), Btn::text_fg("delete").build_def(ctx, None),
Widget::text_entry(ctx, self.event.clone(), true).named("event"), Widget::text_entry(ctx, self.event.clone(), true).named("event"),

View File

@ -547,9 +547,7 @@ impl LoadEdits {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Load proposal").small_heading().draw(ctx), Line("Load proposal").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Btn::text_fg("Start over with blank proposal").build_def(ctx, None), Btn::text_fg("Start over with blank proposal").build_def(ctx, None),
Widget::row(vec![Widget::col(your_edits), Widget::col(proposals)]).evenly_spaced(), Widget::row(vec![Widget::col(your_edits), Widget::col(proposals)]).evenly_spaced(),
@ -838,9 +836,7 @@ impl ConfirmDiscard {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/alert.svg"), Widget::draw_svg(ctx, "system/assets/tools/alert.svg"),
Line("Alert").small_heading().draw(ctx), Line("Alert").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
"Are you sure you want to discard changes you made?".draw_text(ctx), "Are you sure you want to discard changes you made?".draw_text(ctx),
Widget::row(vec![ Widget::row(vec![

View File

@ -23,9 +23,7 @@ impl RouteEditor {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Route editor").small_heading().draw(ctx), Line("Route editor").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Line(&route.full_name).draw(ctx), Line(&route.full_name).draw(ctx),
// TODO This UI needs design, just something to start plumbing the edits // TODO This UI needs design, just something to start plumbing the edits

View File

@ -31,9 +31,7 @@ impl ChangeDuration {
Line("How long should this stage last?") Line("How long should this stage last?")
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
"Seconds:".draw_text(ctx), "Seconds:".draw_text(ctx),

View File

@ -52,9 +52,7 @@ impl ShowAbsolute {
Line(format!("Tuning offset for {} signals", members.len())) Line(format!("Tuning offset for {} signals", members.len()))
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
"Select an intersection as the base".draw_text(ctx), "Select an intersection as the base".draw_text(ctx),
])) ]))
@ -153,9 +151,7 @@ impl ShowRelative {
Line(format!("Tuning offset for {} signals", members.len())) Line(format!("Tuning offset for {} signals", members.len()))
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
"Select a second intersection to tune offset between the two".draw_text(ctx), "Select a second intersection to tune offset between the two".draw_text(ctx),
])) ]))
@ -253,9 +249,7 @@ impl TuneRelative {
Line(format!("Tuning offset between {} and {}", i1, i2)) Line(format!("Tuning offset between {} and {}", i1, i2))
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from_multiline(vec![ Text::from_multiline(vec![
Line(format!("Distance: {}", dist_btwn)), Line(format!("Distance: {}", dist_btwn)),

View File

@ -31,9 +31,7 @@ impl SignalPicker {
Line("Select multiple traffic signals") Line("Select multiple traffic signals")
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
make_btn(ctx, members.len()), make_btn(ctx, members.len()),
])) ]))

View File

@ -25,12 +25,7 @@ impl<T: 'static> ChooseSomething<T> {
) -> Box<dyn State<App>> { ) -> Box<dyn State<App>> {
Box::new(ChooseSomething { Box::new(ChooseSomething {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![Line(query).small_heading().draw(ctx), Btn::close(ctx)]),
Line(query).small_heading().draw(ctx),
Btn::plaintext("X")
.build(ctx, "close", Key::Escape)
.align_right(),
]),
Menu::new(ctx, choices).named("menu"), Menu::new(ctx, choices).named("menu"),
])) ]))
.build(ctx), .build(ctx),
@ -102,12 +97,7 @@ impl PromptInput {
) -> Box<dyn State<App>> { ) -> Box<dyn State<App>> {
Box::new(PromptInput { Box::new(PromptInput {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![Line(query).small_heading().draw(ctx), Btn::close(ctx)]),
Line(query).small_heading().draw(ctx),
Btn::plaintext("X")
.build(ctx, "close", Key::Escape)
.align_right(),
]),
Widget::text_entry(ctx, String::new(), true).named("input"), Widget::text_entry(ctx, String::new(), true).named("input"),
Btn::text_fg("confirm").build_def(ctx, Key::Enter), Btn::text_fg("confirm").build_def(ctx, Key::Enter),
])) ]))

View File

@ -494,7 +494,7 @@ impl InfoPanel {
} }
*self = new; *self = new;
(false, None) (false, None)
} else if action == "close info" { } else if action == "close" {
(true, None) (true, None)
} else if action == "jump to object" { } else if action == "jump to object" {
// TODO Messy way of doing this // TODO Messy way of doing this
@ -700,7 +700,7 @@ fn make_tabs(
fn header_btns(ctx: &EventCtx) -> Widget { fn header_btns(ctx: &EventCtx) -> Widget {
Widget::row(vec![ Widget::row(vec![
Btn::svg_def("system/assets/tools/location.svg").build(ctx, "jump to object", Key::J), Btn::svg_def("system/assets/tools/location.svg").build(ctx, "jump to object", Key::J),
Btn::plaintext("X").build(ctx, "close info", Key::Escape), Btn::close(ctx),
]) ])
.align_right() .align_right()
} }

View File

@ -505,7 +505,7 @@ pub fn parked_car(
.to_btn(ctx) .to_btn(ctx)
.build(ctx, "unfollow (pause the simulation)", Key::F) .build(ctx, "unfollow (pause the simulation)", Key::F)
}, },
Btn::plaintext("X").build(ctx, "close info", Key::Escape), Btn::close(ctx),
]) ])
.align_right(), .align_right(),
])); ]));
@ -625,7 +625,7 @@ fn header(
.to_btn(ctx) .to_btn(ctx)
.build(ctx, "unfollow (pause the simulation)", Key::F) .build(ctx, "unfollow (pause the simulation)", Key::F)
}, },
Btn::plaintext("X").build(ctx, "close info", Key::Escape), Btn::close(ctx),
]) ])
.align_right(), .align_right(),
])); ]));

View File

@ -1,6 +1,6 @@
use geom::{ArrowCap, Distance, PolyLine}; use geom::{ArrowCap, Distance, PolyLine};
use widgetry::{ use widgetry::{
Btn, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Panel, Text, Btn, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Panel, Text,
TextExt, VerticalAlignment, Widget, TextExt, VerticalAlignment, Widget,
}; };
@ -91,9 +91,7 @@ impl Elevation {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Elevation change".draw_text(ctx), "Elevation change".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from_multiline(vec![ Text::from_multiline(vec![
Line(format!("Steepest road: {:.0}% grade", max * 100.0)), Line(format!("Steepest road: {:.0}% grade", max * 100.0)),

View File

@ -3,7 +3,7 @@ use geom::{Distance, Time};
use map_model::{LaneType, PathConstraints}; use map_model::{LaneType, PathConstraints};
use sim::AgentType; use sim::AgentType;
use widgetry::{ use widgetry::{
Btn, Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Panel, Text, TextExt, Btn, Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Line, Panel, Text, TextExt,
VerticalAlignment, Widget, VerticalAlignment, Widget,
}; };
@ -109,9 +109,7 @@ impl BikeNetwork {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Bike network".draw_text(ctx), "Bike network".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from_multiline(vec![ Text::from_multiline(vec![
Line(format!("{} lanes", num_lanes)), Line(format!("{} lanes", num_lanes)),
@ -193,9 +191,7 @@ impl Static {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
title.draw_text(ctx), title.draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
extra, extra,
legend, legend,
@ -424,9 +420,7 @@ impl CongestionCaps {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Congestion caps".draw_text(ctx), "Congestion caps".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
format!("{} roads have caps", prettyprint_usize(num_roads)).draw_text(ctx), format!("{} roads have caps", prettyprint_usize(num_roads)).draw_text(ctx),
ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["available", "full"]), ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["available", "full"]),

View File

@ -84,9 +84,7 @@ impl PickLayer {
pub fn pick(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> { pub fn pick(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
let mut col = vec![Widget::custom_row(vec![ let mut col = vec![Widget::custom_row(vec![
Line("Layers").small_heading().draw(ctx), Line("Layers").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
])]; ])];
let current = match app.primary.layer { let current = match app.primary.layer {

View File

@ -4,8 +4,8 @@ use abstutil::prettyprint_usize;
use geom::{Circle, Distance, Pt2D, Time}; use geom::{Circle, Distance, Pt2D, Time};
use sim::PersonState; use sim::PersonState;
use widgetry::{ use widgetry::{
Btn, Checkbox, Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Btn, Checkbox, Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line,
Line, Outcome, Panel, Text, TextExt, VerticalAlignment, Widget, Outcome, Panel, Text, TextExt, VerticalAlignment, Widget,
}; };
use crate::app::App; use crate::app::App;
@ -179,9 +179,7 @@ fn make_controls(ctx: &mut EventCtx, app: &App, opts: &Options, legend: Option<W
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Pandemic model".draw_text(ctx), "Pandemic model".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from_multiline(vec![ Text::from_multiline(vec![
Line(format!( Line(format!(

View File

@ -7,7 +7,7 @@ use map_model::{
}; };
use sim::{ParkingSpot, Scenario, VehicleType}; use sim::{ParkingSpot, Scenario, VehicleType};
use widgetry::{ use widgetry::{
Btn, Checkbox, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Btn, Checkbox, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Outcome,
Panel, Text, TextExt, VerticalAlignment, Widget, Panel, Text, TextExt, VerticalAlignment, Widget,
}; };
@ -114,9 +114,7 @@ impl Occupancy {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Parking occupancy".draw_text(ctx), "Parking occupancy".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from_multiline(vec![ Text::from_multiline(vec![
Line(format!( Line(format!(
@ -214,9 +212,7 @@ impl Occupancy {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Parking occupancy".draw_text(ctx), "Parking occupancy".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from_multiline(vec![ Text::from_multiline(vec![
Line(format!( Line(format!(
@ -375,9 +371,7 @@ impl Efficiency {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Parking efficiency".draw_text(ctx), "Parking efficiency".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from(Line("How far away are people parked? (minutes)").secondary()) Text::from(Line("How far away are people parked? (minutes)").secondary())
.wrap_to_pct(ctx, 15) .wrap_to_pct(ctx, 15)

View File

@ -4,7 +4,7 @@ use abstutil::prettyprint_usize;
use geom::{Circle, Distance, Pt2D, Time}; use geom::{Circle, Distance, Pt2D, Time};
use sim::PersonState; use sim::PersonState;
use widgetry::{ use widgetry::{
Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line,
Outcome, Panel, VerticalAlignment, Widget, Outcome, Panel, VerticalAlignment, Widget,
}; };
@ -149,9 +149,7 @@ fn make_controls(ctx: &mut EventCtx, app: &App, opts: &Options, legend: Option<W
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
Line(format!("Population: {}", prettyprint_usize(total_ppl))).draw(ctx), Line(format!("Population: {}", prettyprint_usize(total_ppl))).draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Widget::row(vec![ Widget::row(vec![
Widget::row(vec![ Widget::row(vec![

View File

@ -7,7 +7,7 @@ use geom::{Circle, Distance, Duration, Polygon, Pt2D, Time};
use map_model::{IntersectionID, Map, Traversable}; use map_model::{IntersectionID, Map, Traversable};
use sim::VehicleType; use sim::VehicleType;
use widgetry::{ use widgetry::{
Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Btn, Checkbox, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line,
Outcome, Panel, Text, TextExt, VerticalAlignment, Widget, Outcome, Panel, Text, TextExt, VerticalAlignment, Widget,
}; };
@ -74,9 +74,7 @@ impl Backpressure {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Backpressure".draw_text(ctx), "Backpressure".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from( Text::from(
Line("This counts all active trips passing through a road in the future") Line("This counts all active trips passing through a road in the future")
@ -203,9 +201,7 @@ impl Throughput {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Throughput".draw_text(ctx), "Throughput".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from(Line("This counts all people crossing since midnight").secondary()) Text::from(Line("This counts all people crossing since midnight").secondary())
.wrap_to_pct(ctx, 15) .wrap_to_pct(ctx, 15)
@ -338,9 +334,7 @@ impl CompareThroughput {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Relative Throughput".draw_text(ctx), "Relative Throughput".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Checkbox::switch(ctx, "Compare before proposal", None, true), Checkbox::switch(ctx, "Compare before proposal", None, true),
scale.make_legend(ctx, vec!["less traffic", "same", "more"]), scale.make_legend(ctx, vec!["less traffic", "same", "more"]),
@ -428,9 +422,7 @@ impl TrafficJams {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Traffic jams".draw_text(ctx), "Traffic jams".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from( Text::from(
Line("A jam starts when delay exceeds 5 mins, then spreads out").secondary(), Line("A jam starts when delay exceeds 5 mins, then spreads out").secondary(),
@ -582,9 +574,7 @@ impl Delay {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Delay per agent (minutes)".draw_text(ctx), "Delay per agent (minutes)".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0", "5", "10", "15+"]), ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0", "5", "10", "15+"]),
])) ]))

View File

@ -1,6 +1,6 @@
use map_model::{PathConstraints, PathStep}; use map_model::{PathConstraints, PathStep};
use widgetry::{ use widgetry::{
Btn, Checkbox, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Key, Outcome, Panel, TextExt, Btn, Checkbox, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Outcome, Panel, TextExt,
VerticalAlignment, Widget, VerticalAlignment, Widget,
}; };
@ -118,9 +118,7 @@ impl TransitNetwork {
Widget::row(vec![ Widget::row(vec![
Widget::draw_svg(ctx, "system/assets/tools/layers.svg"), Widget::draw_svg(ctx, "system/assets/tools/layers.svg"),
"Transit network".draw_text(ctx), "Transit network".draw_text(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Checkbox::switch(ctx, "show all routes", None, show_all_routes), Checkbox::switch(ctx, "show all routes", None, show_all_routes),
Checkbox::switch(ctx, "show buses", None, show_buses), Checkbox::switch(ctx, "show buses", None, show_buses),

View File

@ -98,9 +98,7 @@ impl OptionsPanel {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::custom_row(vec![ Widget::custom_row(vec![
Line("Settings").small_heading().draw(ctx), Line("Settings").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
"Camera controls".draw_text(ctx), "Camera controls".draw_text(ctx),
Widget::col(vec![ Widget::col(vec![

View File

@ -695,9 +695,7 @@ fn make_panel(ctx: &mut EventCtx, app: &App) -> Panel {
Panel::new(Widget::col(vec![ Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("Commute map by block").small_heading().draw(ctx), Line("Commute map by block").small_heading().draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Checkbox::toggle(ctx, "from / to this block", "from", "to", Key::Space, true), Checkbox::toggle(ctx, "from / to this block", "from", "to", Key::Space, true),
Checkbox::switch(ctx, "include borders", None, true), Checkbox::switch(ctx, "include borders", None, true),

View File

@ -2,7 +2,7 @@ pub use commuter::CommuterPatterns;
pub use traffic_signals::TrafficSignalDemand; pub use traffic_signals::TrafficSignalDemand;
pub use trip_table::FinishedTripTable; pub use trip_table::FinishedTripTable;
use widgetry::{Btn, Choice, EventCtx, Key, Line, Panel, TextExt, Widget}; use widgetry::{Btn, Choice, EventCtx, Line, Panel, TextExt, Widget};
use crate::app::App; use crate::app::App;
use crate::game::Transition; use crate::game::Transition;
@ -48,12 +48,10 @@ impl DashTab {
Widget::draw_svg(ctx, "system/assets/meters/trip_histogram.svg"), Widget::draw_svg(ctx, "system/assets/meters/trip_histogram.svg"),
Line("Data").big_heading_plain().draw(ctx), Line("Data").big_heading_plain().draw(ctx),
Widget::dropdown(ctx, "tab", self, choices), Widget::dropdown(ctx, "tab", self, choices),
format!("By {}", app.primary.sim.time()) format!("By {}", app.primary.sim.time().ampm_tostring())
.draw_text(ctx) .draw_text(ctx)
.centered_vert(), .centered_vert(),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]) ])
} }

View File

@ -45,9 +45,7 @@ impl TrafficSignalDemand {
Line("Traffic signal demand over time") Line("Traffic signal demand over time")
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Text::from_all(vec![ Text::from_all(vec![
Line("Press "), Line("Press "),

View File

@ -227,9 +227,7 @@ impl AgentSpawner {
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Widget::row(vec![ Widget::row(vec![
Line("New trip").small_heading().draw(ctx), Line("New trip").small_heading().draw(ctx),
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
"Click a building or border to specify start" "Click a building or border to specify start"
.draw_text(ctx) .draw_text(ctx)

View File

@ -194,7 +194,7 @@ impl TurnExplorer {
} else { } else {
Btn::text_fg(">").build(ctx, "next turn", Key::RightArrow) Btn::text_fg(">").build(ctx, "next turn", Key::RightArrow)
}, },
Btn::text_fg("X").build(ctx, "close", Key::Escape), Btn::close(ctx),
])]; ])];
if idx == 0 { if idx == 0 {
if app.primary.map.get_l(l).is_walkable() { if app.primary.map.get_l(l).is_walkable() {

View File

@ -33,9 +33,7 @@ impl JumpToTime {
target, target,
maybe_mode, maybe_mode,
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
Widget::custom_row(vec![ Widget::custom_row(vec![
Btn::text_bg2("Jump to time").inactive(ctx), Btn::text_bg2("Jump to time").inactive(ctx),
Btn::text_bg2("Jump to delay").build_def(ctx, Key::D), Btn::text_bg2("Jump to delay").build_def(ctx, Key::D),
@ -164,9 +162,7 @@ impl JumpToDelay {
Box::new(JumpToDelay { Box::new(JumpToDelay {
maybe_mode, maybe_mode,
panel: Panel::new(Widget::col(vec![ panel: Panel::new(Widget::col(vec![
Btn::plaintext("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
Widget::custom_row(vec![ Widget::custom_row(vec![
Btn::text_bg2("Jump to time").build_def(ctx, Key::T), Btn::text_bg2("Jump to time").build_def(ctx, Key::T),
Btn::text_bg2("Jump to delay").inactive(ctx), Btn::text_bg2("Jump to delay").inactive(ctx),

View File

@ -36,9 +36,7 @@ impl UberTurnPicker {
Line("Select multiple intersections") Line("Select multiple intersections")
.small_heading() .small_heading()
.draw(ctx), .draw(ctx),
Btn::text_fg("X") Btn::close(ctx),
.build(ctx, "close", Key::Escape)
.align_right(),
]), ]),
Btn::text_fg("View uber-turns").build_def(ctx, Key::Enter), Btn::text_fg("View uber-turns").build_def(ctx, Key::Enter),
Btn::text_fg("Edit").build_def(ctx, Key::E), Btn::text_fg("Edit").build_def(ctx, Key::E),
@ -195,7 +193,7 @@ impl UberTurnViewer {
} else { } else {
Btn::text_fg(">").build(ctx, "next uber-turn", Key::RightArrow) Btn::text_fg(">").build(ctx, "next uber-turn", Key::RightArrow)
}, },
Btn::text_fg("X").build(ctx, "close", Key::Escape), Btn::close(ctx),
]), ]),
format!("driving_cost for a Car: {}", sum_cost).draw_text(ctx), format!("driving_cost for a Car: {}", sum_cost).draw_text(ctx),
Widget::row(vec![ Widget::row(vec![

View File

@ -1,7 +1,7 @@
use geom::{Distance, Polygon}; use geom::{Distance, Polygon};
use crate::{ use crate::{
svg, Color, Drawable, EdgeInsets, EventCtx, GeomBatch, GfxCtx, Line, MultiKey, Outcome, svg, Color, Drawable, EdgeInsets, EventCtx, GeomBatch, GfxCtx, Key, Line, MultiKey, Outcome,
RewriteColor, ScreenDims, ScreenPt, ScreenRectangle, Text, Widget, WidgetImpl, WidgetOutput, RewriteColor, ScreenDims, ScreenPt, ScreenRectangle, Text, Widget, WidgetImpl, WidgetOutput,
}; };
@ -258,6 +258,14 @@ impl Btn {
maybe_outline: outline, maybe_outline: outline,
} }
} }
/// An "X" button to close the current state. Bound to the escape key and aligned to the right,
/// usually after a title.
pub fn close(ctx: &EventCtx) -> Widget {
Btn::plaintext("X")
.build(ctx, "close", Key::Escape)
.align_right()
}
} }
pub enum BtnBuilder { pub enum BtnBuilder {