From 834f0604628eeb35c9c949f228d382aabcc6185f Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Wed, 1 Jul 2020 15:31:52 -0700 Subject: [PATCH] yet more layout refactor --- ezgui/examples/demo.rs | 73 ++++++++----------- ezgui/src/tools/wizard.rs | 19 ++--- ezgui/src/widgets/compare_times.rs | 13 ++-- ezgui/src/widgets/line_plot.rs | 25 +++---- ezgui/src/widgets/scatter_plot.rs | 13 ++-- game/src/challenges.rs | 48 +++++------- game/src/common/colors.rs | 7 +- game/src/common/minimap.rs | 59 +++++++-------- game/src/common/navigate.rs | 12 +-- game/src/common/panels.rs | 14 ++-- game/src/debug/floodfill.rs | 4 +- game/src/debug/mod.rs | 26 +++---- game/src/debug/polygons.rs | 13 ++-- game/src/edit/cluster_traffic_signals.rs | 2 +- game/src/edit/stop_signs.rs | 4 +- game/src/helpers.rs | 2 +- game/src/info/building.rs | 4 +- game/src/info/bus.rs | 17 ++--- game/src/info/debug.rs | 2 +- game/src/info/intersection.rs | 24 +++--- game/src/info/lane.rs | 12 ++- game/src/info/mod.rs | 41 ++++------- game/src/info/parking_lot.rs | 4 +- game/src/info/person.rs | 58 ++++++--------- game/src/info/trip.rs | 49 +++++++------ game/src/render/traffic_signal.rs | 35 ++++----- game/src/sandbox/dashboards/misc.rs | 8 +- game/src/sandbox/dashboards/mod.rs | 2 +- game/src/sandbox/gameplay/commute.rs | 4 +- .../sandbox/gameplay/fix_traffic_signals.rs | 2 +- game/src/sandbox/mod.rs | 15 ++-- game/src/sandbox/speed.rs | 30 +++----- map_editor/src/main.rs | 6 +- 33 files changed, 284 insertions(+), 363 deletions(-) diff --git a/ezgui/examples/demo.rs b/ezgui/examples/demo.rs index 4aaa9e23cc..7ac1b05f39 100644 --- a/ezgui/examples/demo.rs +++ b/ezgui/examples/demo.rs @@ -60,31 +60,21 @@ impl App { } let mut c = Composite::new( - Widget::col(vec![ - Widget::row(vec![{ - let mut txt = Text::from( - Line("Here's a bunch of text to force some scrolling.").small_heading(), - ); - txt.add( - Line( - "Bug: scrolling by clicking and dragging doesn't work while the \ - stopwatch is running.", - ) - .fg(Color::RED), - ); - txt.draw(ctx) - }]), - Widget::row(vec![ + Widget::col2(vec![ + Text::from_multiline(vec![ + Line("Here's a bunch of text to force some scrolling.").small_heading(), + Line( + "Bug: scrolling by clicking and dragging doesn't work while the stopwatch \ + is running.", + ) + .fg(Color::RED), + ]) + .draw(ctx), + Widget::row2(vec![ // Examples of styling widgets - Widget::col(col1) - .outline(3.0, Color::BLACK) - .padding(5) - .margin_right(5), - Widget::col(col2) - .outline(3.0, Color::BLACK) - .padding(5) - .margin_right(5), - Widget::col(col3).outline(3.0, Color::BLACK).padding(5), + Widget::col2(col1).outline(3.0, Color::BLACK).padding(5), + Widget::col2(col2).outline(3.0, Color::BLACK).padding(5), + Widget::col2(col3).outline(3.0, Color::BLACK).padding(5), ]), LinePlot::new( ctx, @@ -117,6 +107,7 @@ impl App { }, ), ]) + .padding(16) .bg(Color::grey(0.4)), ) // Don't let the panel exceed this percentage of the window. Scrollbars appear @@ -267,36 +258,30 @@ fn setup_scrollable_canvas(ctx: &mut EventCtx) -> Drawable { fn make_controls(ctx: &mut EventCtx) -> Composite { Composite::new( - Widget::col(vec![ - { - let mut txt = Text::from(Line("ezgui demo").small_heading()); - txt.add(Line( - "Click and drag to pan, use touchpad or scroll wheel to zoom", - )); - txt.draw(ctx) - }, - Widget::row(vec![ + Widget::col2(vec![ + Text::from_multiline(vec![ + Line("ezgui demo").small_heading(), + Line("Click and drag to pan, use touchpad or scroll wheel to zoom"), + ]) + .draw(ctx), + Widget::row2(vec![ // This just cycles between two arbitrary buttons Checkbox::new( false, Btn::text_bg1("Pause").build(ctx, "pause the stopwatch", hotkey(Key::Space)), Btn::text_bg1("Resume").build(ctx, "resume the stopwatch", hotkey(Key::Space)), ) - .named("paused") - .margin(5), - Btn::text_fg("Reset timer") - .build(ctx, "reset the stopwatch", None) - .margin(5), - Btn::text_fg("New faces") - .build(ctx, "generate new faces", hotkey(Key::F)) - .margin(5), - Checkbox::text(ctx, "Draw scrollable canvas", None, true).margin(5), - Checkbox::text(ctx, "Show timeseries", lctrl(Key::T), false).margin(5), + .named("paused"), + Btn::text_fg("Reset timer").build(ctx, "reset the stopwatch", None), + Btn::text_fg("New faces").build(ctx, "generate new faces", hotkey(Key::F)), + Checkbox::text(ctx, "Draw scrollable canvas", None, true), + Checkbox::text(ctx, "Show timeseries", lctrl(Key::T), false), ]) .evenly_spaced(), "Stopwatch: ...".draw_text(ctx).named("stopwatch"), ]) - .bg(Color::grey(0.4)), + .bg(Color::grey(0.4)) + .padding(16), ) .aligned(HorizontalAlignment::Center, VerticalAlignment::Top) .build(ctx) diff --git a/ezgui/src/tools/wizard.rs b/ezgui/src/tools/wizard.rs index bf294f8bdb..04e5ad0c94 100644 --- a/ezgui/src/tools/wizard.rs +++ b/ezgui/src/tools/wizard.rs @@ -78,12 +78,11 @@ impl Wizard { if self.tb_comp.is_none() { self.tb_comp = Some( Composite::new( - Widget::col(vec![ - Widget::row(vec![ + Widget::col2(vec![ + Widget::row2(vec![ Line(query).small_heading().draw(ctx), Btn::text_fg("X") .build(ctx, "quit", hotkey(Key::Escape)) - .margin(5) .align_right(), ]), Text::new().draw(ctx).named("error"), @@ -93,7 +92,7 @@ impl Wizard { ]) .bg(ctx.style().panel_bg) .outline(5.0, Color::WHITE) - .padding(5), + .padding(16), ) .build(ctx), ); @@ -264,8 +263,8 @@ impl<'a, 'b> WrappedWizard<'a, 'b> { ); self.wizard.menu_comp = Some( Composite::new( - Widget::row(vec![ - Widget::col(col).margin_right(15), + Widget::row2(vec![ + Widget::col2(col), Btn::plaintext("X").build(self.ctx, "quit", hotkey(Key::Escape)), ]) .bg(self.ctx.style().panel_bg) @@ -388,15 +387,13 @@ impl<'a, 'b> WrappedWizard<'a, 'b> { assert!(self.wizard.ack.is_none()); self.wizard.ack = Some( Composite::new( - Widget::col(vec![ + Widget::col2(vec![ txt.draw(self.ctx), - Btn::text_bg2("OK") - .build(self.ctx, "OK", hotkey(Key::Enter)) - .margin(5), + Btn::text_bg2("OK").build(self.ctx, "OK", hotkey(Key::Enter)), ]) .bg(self.ctx.style().panel_bg) .outline(10.0, Color::WHITE) - .padding(10), + .padding(16), ) .build(self.ctx), ); diff --git a/ezgui/src/widgets/compare_times.rs b/ezgui/src/widgets/compare_times.rs index 09b1eef265..51c0bd16b0 100644 --- a/ezgui/src/widgets/compare_times.rs +++ b/ezgui/src/widgets/compare_times.rs @@ -85,7 +85,7 @@ impl CompareTimes { top_left: ScreenPt::new(0.0, 0.0), })); - let y_axis = Widget::col( + let y_axis = Widget::custom_col( labels .iter() .rev() @@ -102,7 +102,7 @@ impl CompareTimes { JustDraw::wrap(ctx, label).centered_vert().margin_right(5) }; - let x_axis = Widget::row( + let x_axis = Widget::custom_row( labels .iter() .map(|x| Line(x.to_string()).small().draw(ctx)) @@ -115,12 +115,13 @@ impl CompareTimes { // It's a bit of work to make both the x and y axis line up with the plot. :) let plot_width = plot.get_width_for_forcing(); - Widget::row(vec![Widget::col(vec![ - Widget::row(vec![y_label, y_axis, plot]), - Widget::col(vec![x_axis, x_label]) + Widget::custom_col(vec![ + Widget::custom_row(vec![y_label, y_axis, plot]), + Widget::custom_col(vec![x_axis, x_label]) .force_width(plot_width) .align_right(), - ])]) + ]) + .container() } } diff --git a/ezgui/src/widgets/line_plot.rs b/ezgui/src/widgets/line_plot.rs index edcdd757f1..8bcb442504 100644 --- a/ezgui/src/widgets/line_plot.rs +++ b/ezgui/src/widgets/line_plot.rs @@ -176,7 +176,7 @@ impl> LinePlot { // The text is already scaled; don't use Widget::draw_batch and scale it again. row.push(JustDraw::wrap(ctx, batch)); } - let x_axis = Widget::row(row).padding(10); + let x_axis = Widget::custom_row(row).padding(10).evenly_spaced(); let num_y_labels = 4; let mut col = Vec::new(); @@ -185,14 +185,15 @@ impl> LinePlot { col.push(max_y.from_percent(percent_y).prettyprint().draw_text(ctx)); } col.reverse(); - let y_axis = Widget::col(col).padding(10); + let y_axis = Widget::custom_col(col).padding(10).evenly_spaced(); // Don't let the x-axis fill the parent container - Widget::row(vec![Widget::col(vec![ + Widget::custom_col(vec![ legend.margin_below(10), - Widget::row(vec![y_axis.evenly_spaced(), Widget::new(Box::new(plot))]), - x_axis.evenly_spaced(), - ])]) + Widget::custom_row(vec![y_axis, Widget::new(Box::new(plot))]), + x_axis, + ]) + .container() } } @@ -321,14 +322,13 @@ pub fn make_legend>( } seen.insert(s.label.clone()); if opts.filterable { - row.push(Widget::row(vec![ - Checkbox::colored(ctx, &s.label, s.color, !opts.disabled.contains(&s.label)) - .margin_right(8), + row.push(Widget::row2(vec![ + Checkbox::colored(ctx, &s.label, s.color, !opts.disabled.contains(&s.label)), Line(&s.label).draw(ctx), ])); } else { let radius = 15.0; - row.push(Widget::row(vec![ + row.push(Widget::row2(vec![ Widget::draw_batch( ctx, GeomBatch::from(vec![( @@ -336,13 +336,12 @@ pub fn make_legend>( Circle::new(Pt2D::new(radius, radius), Distance::meters(radius)) .to_polygon(), )]), - ) - .margin(5), + ), s.label.clone().draw_text(ctx), ])); } } - Widget::row(row).flex_wrap(ctx, 24) + Widget::custom_row(row).flex_wrap(ctx, 24) } // TODO If this proves useful, lift to geom diff --git a/ezgui/src/widgets/scatter_plot.rs b/ezgui/src/widgets/scatter_plot.rs index 54ad71e060..884d92a77e 100644 --- a/ezgui/src/widgets/scatter_plot.rs +++ b/ezgui/src/widgets/scatter_plot.rs @@ -156,7 +156,7 @@ impl ScatterPlot { // The text is already scaled; don't use Widget::draw_batch and scale it again. row.push(JustDraw::wrap(ctx, batch)); } - let x_axis = Widget::row(row).padding(10); + let x_axis = Widget::custom_row(row).padding(10).evenly_spaced(); let num_y_labels = 4; let mut col = Vec::new(); @@ -165,14 +165,15 @@ impl ScatterPlot { col.push(max_y.from_percent(percent_y).prettyprint().draw_text(ctx)); } col.reverse(); - let y_axis = Widget::col(col).padding(10); + let y_axis = Widget::custom_col(col).padding(10).evenly_spaced(); // Don't let the x-axis fill the parent container - Widget::row(vec![Widget::col(vec![ + Widget::custom_col(vec![ legend.margin_below(10), - Widget::row(vec![y_axis.evenly_spaced(), Widget::new(Box::new(plot))]), - x_axis.evenly_spaced(), - ])]) + Widget::custom_row(vec![y_axis, Widget::new(Box::new(plot))]), + x_axis, + ]) + .container() } } diff --git a/game/src/challenges.rs b/game/src/challenges.rs index e77ff7e538..18936dad02 100644 --- a/game/src/challenges.rs +++ b/game/src/challenges.rs @@ -131,16 +131,15 @@ impl Tab { master_col.push({ let mut txt = Text::from(Line("A/B STREET").display_title()); txt.add(Line("CHALLENGES").big_heading_styled()); - txt.draw(ctx).centered_horiz().margin_below(20) + txt.draw(ctx).centered_horiz() }); master_col.push( Btn::text_bg2("Introduction and tutorial") .build_def(ctx, None) .centered_horiz() .bg(app.cs.panel_bg) - .padding(10) - .outline(10.0, Color::BLACK) - .margin_below(10), + .padding(16) + .outline(2.0, Color::BLACK), ); // Slightly inconsistent: pushes twice and leaves this challenge picker open cbs.push(( @@ -156,13 +155,9 @@ impl Tab { Tab::ChallengeStage(ref n, _) => &name == n, }; if current { - flex_row.push(Btn::text_bg2(&name).inactive(ctx).margin(10)); + flex_row.push(Btn::text_bg2(&name).inactive(ctx)); } else { - flex_row.push( - Btn::text_bg2(&name) - .build_def(ctx, hotkey(Key::NUM_KEYS[idx])) - .margin(10), - ); + flex_row.push(Btn::text_bg2(&name).build_def(ctx, hotkey(Key::NUM_KEYS[idx]))); cbs.push(( name.clone(), Box::new(move |ctx, app| { @@ -174,12 +169,11 @@ impl Tab { } } master_col.push( - Widget::row(flex_row) + Widget::custom_row(flex_row) .flex_wrap(ctx, 80) .bg(app.cs.panel_bg) - .padding(10) - .margin(10) - .outline(10.0, Color::BLACK), + .padding(16) + .outline(2.0, Color::BLACK), ); let mut main_row = Vec::new(); @@ -194,9 +188,9 @@ impl Tab { .enumerate() { if current == idx { - col.push(Btn::text_fg(&stage.title).inactive(ctx).margin(10)); + col.push(Btn::text_fg(&stage.title).inactive(ctx)); } else { - col.push(Btn::text_fg(&stage.title).build_def(ctx, None).margin(10)); + col.push(Btn::text_fg(&stage.title).build_def(ctx, None)); let name = name.to_string(); cbs.push(( stage.title, @@ -209,11 +203,10 @@ impl Tab { } } main_row.push( - Widget::col(col) + Widget::col2(col) .bg(app.cs.panel_bg) - .padding(10) - .margin(10) - .outline(10.0, Color::BLACK), + .padding(16) + .outline(2.0, Color::BLACK), ); } @@ -227,9 +220,7 @@ impl Tab { let mut inner_col = vec![ txt.draw(ctx), - Btn::text_fg("Start!") - .build_def(ctx, hotkey(Key::Enter)) - .margin(10), + Btn::text_fg("Start!").build_def(ctx, hotkey(Key::Enter)), ]; if let Some(scores) = app.session.high_scores.get(&challenge.gameplay) { @@ -249,11 +240,10 @@ impl Tab { } main_row.push( - Widget::col(inner_col) + Widget::col2(inner_col) .bg(app.cs.panel_bg) - .padding(10) - .margin(10) - .outline(10.0, Color::BLACK), + .padding(16) + .outline(2.0, Color::BLACK), ); cbs.push(( "Start!".to_string(), @@ -271,10 +261,10 @@ impl Tab { )); } - master_col.push(Widget::row(main_row)); + master_col.push(Widget::row2(main_row)); let mut c = WrappedComposite::new( - Composite::new(Widget::col(master_col)) + Composite::new(Widget::col2(master_col)) .exact_size_percent(90, 85) .build(ctx), ) diff --git a/game/src/common/colors.rs b/game/src/common/colors.rs index 2a0b5d5c5c..f474f23748 100644 --- a/game/src/common/colors.rs +++ b/game/src/common/colors.rs @@ -142,16 +142,17 @@ impl ColorLegend { ); // Extra wrapping to make the labels stretch against just the scale, not everything else // TODO Long labels aren't nicely lined up with the boundaries between buckets - Widget::custom_row(vec![Widget::col(vec![ + Widget::col2(vec![ Widget::draw_batch(ctx, batch), - Widget::row( + Widget::custom_row( labels .into_iter() .map(|lbl| Line(lbl).small().draw(ctx)) .collect(), ) .evenly_spaced(), - ])]) + ]) + .container() } } diff --git a/game/src/common/minimap.rs b/game/src/common/minimap.rs index 7ba2807d82..bcff30c33f 100644 --- a/game/src/common/minimap.rs +++ b/game/src/common/minimap.rs @@ -312,9 +312,11 @@ impl Minimap { fn make_minimap_panel(ctx: &mut EventCtx, app: &App, zoom_lvl: usize) -> Composite { if ctx.canvas.cam_zoom < app.opts.min_zoom_for_detail { - return Composite::new(Widget::row(vec![ - make_tool_panel(ctx, app).align_right().margin_right(16), - make_vert_viz_panel(ctx, app).bg(app.cs.panel_bg).padding(7), + return Composite::new(Widget::row2(vec![ + make_tool_panel(ctx, app).align_right(), + make_vert_viz_panel(ctx, app) + .bg(app.cs.panel_bg) + .padding(16), ])) .aligned( HorizontalAlignment::Right, @@ -326,7 +328,7 @@ fn make_minimap_panel(ctx: &mut EventCtx, app: &App, zoom_lvl: usize) -> Composi let zoom_col = { let mut col = vec![Btn::svg_def("../data/system/assets/speed/speed_up.svg") .build(ctx, "zoom in", None) - .margin(12)]; + .margin_below(20)]; for i in (0..=3).rev() { let color = if zoom_lvl < i { Color::WHITE.alpha(0.2) @@ -341,50 +343,47 @@ fn make_minimap_panel(ctx: &mut EventCtx, app: &App, zoom_lvl: usize) -> Composi rect, ) .build(ctx, format!("zoom to level {}", i + 1), None) - .margin(12), + .margin_below(20), ); } col.push( - Btn::svg_def("../data/system/assets/speed/slow_down.svg") - .build(ctx, "zoom out", None) - .margin(12), + Btn::svg_def("../data/system/assets/speed/slow_down.svg").build(ctx, "zoom out", None), ); // The zoom column should start below the "pan up" arrow. But if we put it on the row with // <, minimap, and > then it messes up the horizontal alignment of the pan up arrow. // Also, double column to avoid the background color stretching to the bottom of the row. - Widget::col(vec![Widget::col(col).bg(app.cs.inner_panel)]).margin_above(26) + Widget::custom_col(vec![Widget::custom_col(col) + .padding(10) + .bg(app.cs.inner_panel)]) + .margin_above(26) }; let square_len = 0.15 * ctx.canvas.window_width; - let minimap_controls = Widget::col(vec![ + let minimap_controls = Widget::col2(vec![ Btn::svg_def("../data/system/assets/minimap/up.svg") .build(ctx, "pan up", None) - .margin(5) .centered_horiz(), - Widget::row(vec![ + Widget::row2(vec![ Btn::svg_def("../data/system/assets/minimap/left.svg") .build(ctx, "pan left", None) - .margin(5) .centered_vert(), Filler::new(ScreenDims::new(square_len, square_len)).named("minimap"), Btn::svg_def("../data/system/assets/minimap/right.svg") .build(ctx, "pan right", None) - .margin(5) .centered_vert(), ]), Btn::svg_def("../data/system/assets/minimap/down.svg") .build(ctx, "pan down", None) - .margin(5) .centered_horiz(), ]); - Composite::new(Widget::row(vec![ - make_tool_panel(ctx, app).margin_right(16), - Widget::col(vec![ - Widget::row(vec![minimap_controls, zoom_col]), + Composite::new(Widget::row2(vec![ + make_tool_panel(ctx, app), + Widget::col2(vec![ + Widget::row2(vec![minimap_controls, zoom_col]), make_horiz_viz_panel(ctx, app), ]) - .padding(7) + .padding(16) .bg(app.cs.panel_bg), ])) .aligned( @@ -395,8 +394,7 @@ fn make_minimap_panel(ctx: &mut EventCtx, app: &App, zoom_lvl: usize) -> Composi } fn make_tool_panel(ctx: &mut EventCtx, app: &App) -> Widget { - // TODO Apply something to everything in the column - Widget::col(vec![ + Widget::col2(vec![ (if ctx.canvas.cam_zoom >= app.opts.min_zoom_for_detail { Btn::svg_def("../data/system/assets/minimap/zoom_out_fully.svg").build( ctx, @@ -410,16 +408,13 @@ fn make_tool_panel(ctx: &mut EventCtx, app: &App) -> Widget { None, ) }) - .bg(app.cs.inner_panel) - .margin_below(16), + .bg(app.cs.inner_panel), Btn::svg_def("../data/system/assets/tools/layers.svg") .build(ctx, "change layers", hotkey(Key::L)) - .bg(app.cs.inner_panel) - .margin_below(16), + .bg(app.cs.inner_panel), Btn::svg_def("../data/system/assets/tools/search.svg") .build(ctx, "search", hotkey(Key::K)) - .bg(app.cs.inner_panel) - .margin_below(16), + .bg(app.cs.inner_panel), ]) } @@ -431,7 +426,7 @@ fn make_horiz_viz_panel(ctx: &mut EventCtx, app: &App) -> Widget { } let last = row.pop().unwrap(); row.push(last.margin_right(0)); - Widget::row(row) + Widget::custom_row(row) } fn make_vert_viz_panel(ctx: &mut EventCtx, app: &App) -> Widget { @@ -441,10 +436,8 @@ fn make_vert_viz_panel(ctx: &mut EventCtx, app: &App) -> Widget { let mut row = Vec::new(); row.push(Checkbox::colored(ctx, label, *color, *enabled).margin_right(8)); row.push(Line(label).draw(ctx)); - col.push(Widget::row(row).margin_below(7)); + col.push(Widget::custom_row(row)); } - let last = col.pop().unwrap(); - col.push(last.margin_below(0)); - Widget::col(col) + Widget::col2(col) } diff --git a/game/src/common/navigate.rs b/game/src/common/navigate.rs index 6ebcd0cc47..7a59a09ac4 100644 --- a/game/src/common/navigate.rs +++ b/game/src/common/navigate.rs @@ -18,8 +18,8 @@ impl Navigator { pub fn new(ctx: &mut EventCtx, app: &App) -> Box { Box::new(Navigator { composite: Composite::new( - Widget::col(vec![ - Widget::row(vec![ + Widget::col2(vec![ + Widget::row2(vec![ Line("Enter a street name").small_heading().draw(ctx), Btn::text_fg("X") .build(ctx, "close", hotkey(Key::Escape)) @@ -36,6 +36,7 @@ impl Navigator { ) .named("street"), ]) + .padding(16) .bg(app.cs.panel_bg), ) .build(ctx), @@ -104,8 +105,8 @@ impl CrossStreet { Box::new(CrossStreet { composite: Composite::new( - Widget::col(vec![ - Widget::row(vec![ + Widget::col2(vec![ + Widget::row2(vec![ { let mut txt = Text::from(Line("What cross street?").small_heading()); // TODO This isn't so clear... @@ -128,7 +129,8 @@ impl CrossStreet { ) .named("street"), ]) - .bg(app.cs.panel_bg), + .bg(app.cs.panel_bg) + .padding(16), ) .build(ctx), first, diff --git a/game/src/common/panels.rs b/game/src/common/panels.rs index 1238d644f4..b79b21f489 100644 --- a/game/src/common/panels.rs +++ b/game/src/common/panels.rs @@ -10,15 +10,15 @@ pub fn tool_panel(ctx: &mut EventCtx, app: &App) -> WrappedComposite { let row = vec![ // TODO Maybe this is confusing -- it doesn't jump to the title screen necessarily. // Caller has to handle this one - Btn::svg_def("../data/system/assets/tools/home.svg") - .build(ctx, "back", hotkey(Key::Escape)) - .margin(10), - Btn::svg_def("../data/system/assets/tools/settings.svg") - .build(ctx, "settings", None) - .margin(10), + Btn::svg_def("../data/system/assets/tools/home.svg").build( + ctx, + "back", + hotkey(Key::Escape), + ), + Btn::svg_def("../data/system/assets/tools/settings.svg").build(ctx, "settings", None), ]; WrappedComposite::new( - Composite::new(Widget::row(row).bg(app.cs.panel_bg)) + Composite::new(Widget::row2(row).bg(app.cs.panel_bg).padding(16)) .aligned(HorizontalAlignment::Left, VerticalAlignment::BottomAboveOSD) .build(ctx), ) diff --git a/game/src/debug/floodfill.rs b/game/src/debug/floodfill.rs index c1c6419552..67a0e0fd8f 100644 --- a/game/src/debug/floodfill.rs +++ b/game/src/debug/floodfill.rs @@ -54,8 +54,8 @@ impl Floodfiller { let (unzoomed, zoomed, legend) = colorer.build(ctx); Box::new(Floodfiller { composite: Composite::new( - Widget::col(vec![ - Widget::row(vec![ + Widget::col2(vec![ + Widget::row2(vec![ Line(title).small_heading().draw(ctx), Btn::text_fg("X") .build(ctx, "close", hotkey(Key::Escape)) diff --git a/game/src/debug/mod.rs b/game/src/debug/mod.rs index 1efdad5716..cc81b36c7b 100644 --- a/game/src/debug/mod.rs +++ b/game/src/debug/mod.rs @@ -35,23 +35,21 @@ impl DebugMode { pub fn new(ctx: &mut EventCtx, app: &App) -> DebugMode { DebugMode { composite: Composite::new( - Widget::col(vec![ - Widget::row(vec![ + Widget::col2(vec![ + Widget::row2(vec![ Line("Debug Mode").small_heading().draw(ctx), Btn::text_fg("X") .build(ctx, "close", hotkey(Key::Escape)) .align_right(), ]), Text::new().draw(ctx).named("current info"), - Checkbox::text(ctx, "show buildings", hotkey(Key::Num1), true).margin_below(5), - Checkbox::text(ctx, "show intersections", hotkey(Key::Num2), true) - .margin_below(5), - Checkbox::text(ctx, "show lanes", hotkey(Key::Num3), true).margin_below(5), - Checkbox::text(ctx, "show areas", hotkey(Key::Num4), true).margin_below(5), - Checkbox::text(ctx, "show labels", hotkey(Key::Num5), false).margin_below(5), - Checkbox::text(ctx, "show route for all agents", hotkey(Key::R), false) - .margin_below(5), - Widget::col( + Checkbox::text(ctx, "show buildings", hotkey(Key::Num1), true), + Checkbox::text(ctx, "show intersections", hotkey(Key::Num2), true), + Checkbox::text(ctx, "show lanes", hotkey(Key::Num3), true), + Checkbox::text(ctx, "show areas", hotkey(Key::Num4), true), + Checkbox::text(ctx, "show labels", hotkey(Key::Num5), false), + Checkbox::text(ctx, "show route for all agents", hotkey(Key::R), false), + Widget::col2( vec![ (lctrl(Key::H), "unhide everything"), (None, "screenshot everything"), @@ -64,13 +62,11 @@ impl DebugMode { (None, "find bad traffic signals"), ] .into_iter() - .map(|(key, action)| { - Btn::text_fg(action).build_def(ctx, key).margin_below(5) - }) + .map(|(key, action)| Btn::text_fg(action).build_def(ctx, key)) .collect(), ), ]) - .padding(10) + .padding(16) .bg(app.cs.panel_bg), ) .aligned(HorizontalAlignment::Right, VerticalAlignment::Top) diff --git a/game/src/debug/polygons.rs b/game/src/debug/polygons.rs index 1fb7951f1a..b9875e520d 100644 --- a/game/src/debug/polygons.rs +++ b/game/src/debug/polygons.rs @@ -137,17 +137,14 @@ impl State for PolygonDebugger { fn make_panel(ctx: &mut EventCtx, app: &App) -> Composite { Composite::new( - Widget::col(vec![ - Widget::row(vec![ - Line("Geometry debugger") - .small_heading() - .draw(ctx) - .margin(5), + Widget::col2(vec![ + Widget::row2(vec![ + Line("Geometry debugger").small_heading().draw(ctx), Btn::text_fg("X") .build(ctx, "close", hotkey(Key::Escape)) .align_right(), ]), - Widget::row(vec![ + Widget::row2(vec![ // TODO inactive Btn::text_fg("<").build(ctx, "previous", hotkey(Key::LeftArrow)), "noun X/Y".draw_text(ctx).named("pointer"), @@ -159,7 +156,7 @@ fn make_panel(ctx: &mut EventCtx, app: &App) -> Composite { .centered_horiz(), ]) .bg(app.cs.panel_bg) - .padding(5), + .padding(16), ) .aligned(HorizontalAlignment::Center, VerticalAlignment::Top) .build(ctx) diff --git a/game/src/edit/cluster_traffic_signals.rs b/game/src/edit/cluster_traffic_signals.rs index c54f37eb19..105a1321f5 100644 --- a/game/src/edit/cluster_traffic_signals.rs +++ b/game/src/edit/cluster_traffic_signals.rs @@ -22,7 +22,7 @@ impl ClusterTrafficSignalEditor { app.primary.current_selection = None; Box::new(ClusterTrafficSignalEditor { composite: Composite::new( - Widget::row(vec![ + Widget::row2(vec![ Btn::text_fg("Finish").build_def(ctx, hotkey(Key::Escape)) ]) .bg(app.cs.panel_bg), diff --git a/game/src/edit/stop_signs.rs b/game/src/edit/stop_signs.rs index 5c9613da77..0080eaf1d0 100644 --- a/game/src/edit/stop_signs.rs +++ b/game/src/edit/stop_signs.rs @@ -48,7 +48,7 @@ impl StopSignEditor { .collect(); let composite = Composite::new( - Widget::col(vec![ + Widget::col2(vec![ "Stop sign editor".draw_text(ctx), if ControlStopSign::new(&app.primary.map, id) != app.primary.map.get_stop_sign(id).clone() @@ -62,7 +62,7 @@ impl StopSignEditor { Btn::text_fg("Finish").build_def(ctx, hotkey(Key::Escape)), ]) .bg(app.cs.panel_bg) - .padding(10), + .padding(16), ) .aligned(HorizontalAlignment::Center, VerticalAlignment::Top) .build(ctx); diff --git a/game/src/helpers.rs b/game/src/helpers.rs index 0c99ba82d0..8fec463322 100644 --- a/game/src/helpers.rs +++ b/game/src/helpers.rs @@ -234,5 +234,5 @@ pub fn checkbox_per_mode( ); filters.push(m.ongoing_verb().draw_text(ctx).margin_right(10)); } - Widget::row(filters) + Widget::custom_row(filters) } diff --git a/game/src/info/building.rs b/game/src/info/building.rs index 1285582921..c9be68415f 100644 --- a/game/src/info/building.rs +++ b/game/src/info/building.rs @@ -119,7 +119,7 @@ pub fn people(ctx: &mut EventCtx, app: &App, details: &mut Details, id: Building details .hyperlinks .insert(p.to_string(), Tab::PersonTrips(p, BTreeMap::new())); - let widget = Widget::col(vec![ + let widget = Widget::col2(vec![ Btn::text_bg1(p.to_string()).build_def(ctx, None), if let Some((t, mode)) = next_trip { format!( @@ -161,7 +161,7 @@ fn header( ) -> Vec { let mut rows = vec![]; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line(id.to_string()).small_heading().draw(ctx), header_btns(ctx), ])); diff --git a/game/src/info/bus.rs b/game/src/info/bus.rs index 68e574f6d8..d8a53c9709 100644 --- a/game/src/info/bus.rs +++ b/game/src/info/bus.rs @@ -15,7 +15,7 @@ pub fn stop(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusStopID) let sim = &app.primary.sim; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line("Bus stop").small_heading().draw(ctx), header_btns(ctx), ])); @@ -99,7 +99,7 @@ fn bus_header( } let mut rows = vec![]; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line(format!( "{} (route {})", id, @@ -145,9 +145,9 @@ fn delays_over_time(ctx: &mut EventCtx, app: &App, id: BusRouteID) -> Widget { .unwrap_or_else(Vec::new), }); } - Widget::col(vec![ + Widget::col2(vec![ Line("Delays between stops").small_heading().draw(ctx), - LinePlot::new(ctx, series, PlotOptions::fixed()).margin(10), + LinePlot::new(ctx, series, PlotOptions::fixed()), ]) } @@ -163,7 +163,7 @@ fn passenger_delay(ctx: &mut EventCtx, app: &App, details: &mut Details, id: Bus .bus_passenger_delays(app.primary.sim.time(), id) .collect::>(); for idx in 0..route.stops.len() { - col.push(Widget::row(vec![ + col.push(Widget::row2(vec![ format!("Stop {}", idx + 1).draw_text(ctx), Btn::svg( "../data/system/assets/tools/pin.svg", @@ -214,10 +214,7 @@ fn passenger_delay(ctx: &mut EventCtx, app: &App, details: &mut Details, id: Bus } let timeline = Widget::draw_batch(ctx, batch); - master_col.push(Widget::row(vec![ - timeline.margin(5), - Widget::col(col).margin(5), - ])); + master_col.push(Widget::row2(vec![timeline, Widget::col2(col)])); - Widget::col(master_col) + Widget::col2(master_col) } diff --git a/game/src/info/debug.rs b/game/src/info/debug.rs index e82f0472da..4342fbb4c7 100644 --- a/game/src/info/debug.rs +++ b/game/src/info/debug.rs @@ -6,7 +6,7 @@ use map_model::AreaID; pub fn area(ctx: &EventCtx, app: &App, _: &mut Details, id: AreaID) -> Vec { let mut rows = vec![]; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line(id.to_string()).small_heading().draw(ctx), header_btns(ctx), ])); diff --git a/game/src/info/intersection.rs b/game/src/info/intersection.rs index fc4f5f53ee..17e7f00542 100644 --- a/game/src/info/intersection.rs +++ b/game/src/info/intersection.rs @@ -58,7 +58,7 @@ pub fn traffic( ))); rows.push(txt.draw(ctx)); - rows.push(opts.to_controls(ctx, app).margin_below(15)); + rows.push(opts.to_controls(ctx, app)); let time = if opts.show_end_of_day { app.primary.sim.get_end_of_day() @@ -98,7 +98,7 @@ pub fn delay( let i = app.primary.map.get_i(id); assert!(i.is_traffic_signal()); - rows.push(opts.to_controls(ctx, app).margin_below(10)); + rows.push(opts.to_controls(ctx, app)); rows.push(delay_plot(ctx, app, id, opts)); @@ -168,13 +168,10 @@ pub fn current_demand( ); rows.push( - Widget::col(vec![ - txt.draw(ctx).margin_below(10), - Widget::draw_batch(ctx, batch), - ]) - .padding(10) - .bg(app.cs.inner_panel) - .outline(2.0, Color::WHITE), + Widget::col2(vec![txt.draw(ctx), Widget::draw_batch(ctx, batch)]) + .padding(10) + .bg(app.cs.inner_panel) + .outline(2.0, Color::WHITE), ); rows @@ -212,11 +209,8 @@ fn delay_plot(ctx: &EventCtx, app: &App, i: IntersectionID, opts: &DataOptions) pts, }) .collect(); - Widget::col(vec![ - Line("Delay through intersection") - .small_heading() - .draw(ctx) - .margin_below(10), + Widget::col2(vec![ + Line("Delay through intersection").small_heading().draw(ctx), ScatterPlot::new( ctx, series, @@ -250,7 +244,7 @@ fn header( IntersectionType::Border => format!("Border #{}", id.0), IntersectionType::Construction => format!("{} (under construction)", id), }; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line(label).small_heading().draw(ctx), header_btns(ctx), ])); diff --git a/game/src/info/lane.rs b/game/src/info/lane.rs index 02bfa48ad3..0c83d0b67d 100644 --- a/game/src/info/lane.rs +++ b/game/src/info/lane.rs @@ -60,7 +60,7 @@ pub fn info(ctx: &EventCtx, app: &App, details: &mut Details, id: LaneID) -> Vec ), }); } - rows.push("Parking spots available".draw_text(ctx).margin_above(10)); + rows.push("Parking spots available".draw_text(ctx)); rows.push(LinePlot::new( ctx, series, @@ -130,10 +130,8 @@ pub fn debug(ctx: &EventCtx, app: &App, details: &mut Details, id: LaneID) -> Ve rows.extend(make_table(ctx, kv.into_iter())); - rows.push(Widget::row(vec![ - "Copy OriginalLane to clipboard: " - .draw_text(ctx) - .margin_right(15), + rows.push(Widget::row2(vec![ + "Copy OriginalLane to clipboard: ".draw_text(ctx), Btn::svg_def("../data/system/assets/tools/clipboard.svg").build( ctx, "copy OriginalLane", @@ -184,7 +182,7 @@ pub fn traffic( ))); rows.push(txt.draw(ctx)); - rows.push(opts.to_controls(ctx, app).margin_below(15)); + rows.push(opts.to_controls(ctx, app)); let r = map.get_l(id).parent; let time = if opts.show_end_of_day { @@ -216,7 +214,7 @@ fn header(ctx: &EventCtx, app: &App, details: &mut Details, id: LaneID, tab: Tab let r = map.get_r(l.parent); let label = if l.is_sidewalk() { "Sidewalk" } else { "Lane" }; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line(format!("{} #{}", label, id.0)) .small_heading() .draw(ctx), diff --git a/game/src/info/mod.rs b/game/src/info/mod.rs index 1e7ed8dfff..ee0d527daf 100644 --- a/game/src/info/mod.rs +++ b/game/src/info/mod.rs @@ -253,7 +253,7 @@ impl InfoPanel { if let Some(id) = maybe_id.clone() { for (key, label) in ctx_actions.actions(app, id) { cached_actions.push(key); - col.push(hotkey_btn(ctx, app, label, key).margin(5)); + col.push(hotkey_btn(ctx, app, label, key)); } } } @@ -318,7 +318,7 @@ impl InfoPanel { tab, time: app.primary.sim.time(), is_paused: ctx_actions.is_paused(), - composite: Composite::new(Widget::col(col).bg(Color::hex("#5B5B5B")).padding(16)) + composite: Composite::new(Widget::col2(col).bg(Color::hex("#5B5B5B")).padding(16)) .aligned( HorizontalAlignment::Percent(0.02), VerticalAlignment::Percent(0.2), @@ -489,25 +489,13 @@ fn make_table>( rows: impl Iterator, ) -> Vec { rows.map(|(k, v)| { - Widget::row(vec![ + Widget::row2(vec![ Line(k).secondary().draw(ctx), // TODO not quite... v.draw_text(ctx).centered_vert().align_right(), ]) }) .collect() - - // Attempt two - /*let mut keys = Text::new(); - let mut values = Text::new(); - for (k, v) in rows { - keys.add(Line(k)); - values.add(Line(v)); - } - vec![Widget::row(vec![ - keys.draw(ctx), - values.draw(ctx).centered_vert().bg(Color::GREEN), - ])]*/ } fn throughput Vec<(TripMode, Vec<(Time, usize)>)>>( @@ -537,11 +525,10 @@ fn throughput Vec<(TripMode, Vec<(Time, usize)>)>>( let mut plot_opts = PlotOptions::filterable(); plot_opts.disabled = opts.disabled_series(); - Widget::col(vec![ + Widget::col2(vec![ Line("Number of crossing agents per hour") .small_heading() - .draw(ctx) - .margin_below(10), + .draw(ctx), LinePlot::new(ctx, series, plot_opts), ]) .padding(10) @@ -558,22 +545,24 @@ fn make_tabs( let mut row = Vec::new(); for (name, link) in tabs { if current_tab == link { - row.push(Btn::text_bg2(name).inactive(ctx)); + row.push(Btn::text_bg2(name).inactive(ctx).centered_vert()); } else { hyperlinks.insert(name.to_string(), link); - row.push(Btn::text_bg2(name).build_def(ctx, None)); + row.push(Btn::text_bg2(name).build_def(ctx, None).centered_vert()); } } // TODO Centered, but actually, we need to set the padding of each button to divide the // available space evenly. Fancy fill rules... hmmm. - Widget::row(row).bg(Color::WHITE).margin_vert(16) + Widget::custom_row(row).bg(Color::WHITE).margin_vert(16) } fn header_btns(ctx: &EventCtx) -> Widget { - Widget::row(vec![ - Btn::svg_def("../data/system/assets/tools/location.svg") - .build(ctx, "jump to object", hotkey(Key::J)) - .margin(5), + Widget::row2(vec![ + Btn::svg_def("../data/system/assets/tools/location.svg").build( + ctx, + "jump to object", + hotkey(Key::J), + ), Btn::plaintext("X").build(ctx, "close info", hotkey(Key::Escape)), ]) .align_right() @@ -615,7 +604,7 @@ impl DataOptions { if app.has_prebaked().is_none() { return Widget::nothing(); } - Widget::row(vec![ + Widget::row2(vec![ Checkbox::custom_text( ctx, "Show before changes", diff --git a/game/src/info/parking_lot.rs b/game/src/info/parking_lot.rs index 408c635f59..3d5b1e79b3 100644 --- a/game/src/info/parking_lot.rs +++ b/game/src/info/parking_lot.rs @@ -39,7 +39,7 @@ pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: ParkingLot ), }); } - rows.push("Parking spots available".draw_text(ctx).margin_above(10)); + rows.push("Parking spots available".draw_text(ctx)); rows.push(LinePlot::new( ctx, series, @@ -56,7 +56,7 @@ pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: ParkingLot fn header(ctx: &EventCtx, details: &mut Details, id: ParkingLotID, tab: Tab) -> Vec { vec![ - Widget::row(vec![ + Widget::row2(vec![ Line(id.to_string()).small_heading().draw(ctx), header_btns(ctx), ]), diff --git a/game/src/info/person.rs b/game/src/info/person.rs index 44c3c43835..e5b0b9d9df 100644 --- a/game/src/info/person.rs +++ b/game/src/info/person.rs @@ -121,9 +121,9 @@ pub fn trips( // TODO Style wrong. Button should be the entire row. rows.push( - Widget::row(vec![ + Widget::custom_row(vec![ format!("Trip {} ", idx + 1).draw_text(ctx).margin_right(21), - Widget::row(vec![ + Widget::row2(vec![ Widget::draw_svg_transform( ctx, match trip_mode { @@ -133,8 +133,7 @@ pub fn trips( TripMode::Transit => "../data/system/assets/meters/bus.svg", }, RewriteColor::ChangeAll(color), - ) - .margin_right(10), + ), Line(trip_status).small().fg(color).draw(ctx), ]) .fully_rounded() @@ -224,11 +223,7 @@ pub fn bio( let batch = GeomBatch::from_svg_contents(svg_data).autocrop(); let dims = batch.get_dims(); let batch = batch.scale((200.0 / dims.width).min(200.0 / dims.height)); - rows.push( - Widget::draw_batch(ctx, batch) - .centered_horiz() - .margin_below(10), - ); + rows.push(Widget::draw_batch(ctx, batch).centered_horiz()); let nickname = petname::Petnames::default().generate(&mut rng, 2, " "); let age = rng.gen_range(5, 100); @@ -267,8 +262,7 @@ pub fn bio( Line("Pandemic model state: ").secondary(), Line(status), ]) - .draw(ctx) - .margin_below(5), + .draw(ctx), ); } @@ -372,7 +366,7 @@ pub fn crowd( ) -> Vec { let mut rows = vec![]; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line("Pedestrian crowd").small_heading().draw(ctx), header_btns(ctx), ])); @@ -384,16 +378,10 @@ pub fn crowd( .agent_to_person(AgentID::Pedestrian(*id)) .unwrap(); // TODO What other info is useful to summarize? - rows.push( - Widget::row(vec![ - format!("{})", idx + 1) - .draw_text(ctx) - .centered_vert() - .margin_right(10), - Btn::text_fg(person.to_string()).build_def(ctx, None), - ]) - .margin_below(10), - ); + rows.push(Widget::row2(vec![ + format!("{})", idx + 1).draw_text(ctx).centered_vert(), + Btn::text_fg(person.to_string()).build_def(ctx, None), + ])); details.hyperlinks.insert( person.to_string(), Tab::PersonTrips( @@ -420,23 +408,24 @@ pub fn parked_car( ) -> Vec { let mut rows = vec![]; - rows.push(Widget::row(vec![ + rows.push(Widget::row2(vec![ Line(format!("Parked car #{}", id.0)) .small_heading() .draw(ctx), - Widget::row(vec![ + Widget::row2(vec![ // Little indirect, but the handler of this action is actually the ContextualActions // for SandboxMode. if is_paused { - Btn::svg_def("../data/system/assets/tools/location.svg") - .build(ctx, "follow (run the simulation)", hotkey(Key::F)) - .margin(5) + Btn::svg_def("../data/system/assets/tools/location.svg").build( + ctx, + "follow (run the simulation)", + hotkey(Key::F), + ) } else { // TODO Blink Btn::svg_def("../data/system/assets/tools/location.svg") .normal_color(RewriteColor::ChangeAll(Color::hex("#7FFA4D"))) .build(ctx, "unfollow (pause the simulation)", hotkey(Key::F)) - .margin(5) }, Btn::plaintext("X").build(ctx, "close info", hotkey(Key::Escape)), ]) @@ -529,7 +518,7 @@ fn header( PersonState::OffMap => (None, ("off map", None)), }; - rows.push(Widget::row(vec![ + rows.push(Widget::custom_row(vec![ Line(format!("{}", id)).small_heading().draw(ctx), if let Some(icon) = maybe_icon { Widget::draw_svg_transform(ctx, icon, RewriteColor::ChangeAll(Color::hex("#A3A3A3"))) @@ -542,19 +531,20 @@ fn header( .fg(Color::hex("#A3A3A3")) .draw(ctx) .margin_horiz(10), - Widget::row(vec![ + Widget::row2(vec![ // Little indirect, but the handler of this action is actually the ContextualActions // for SandboxMode. if is_paused { - Btn::svg_def("../data/system/assets/tools/location.svg") - .build(ctx, "follow (run the simulation)", hotkey(Key::F)) - .margin(5) + Btn::svg_def("../data/system/assets/tools/location.svg").build( + ctx, + "follow (run the simulation)", + hotkey(Key::F), + ) } else { // TODO Blink Btn::svg_def("../data/system/assets/tools/location.svg") .normal_color(RewriteColor::ChangeAll(Color::hex("#7FFA4D"))) .build(ctx, "unfollow (pause the simulation)", hotkey(Key::F)) - .margin(5) }, Btn::plaintext("X").build(ctx, "close info", hotkey(Key::Escape)), ]) diff --git a/game/src/info/trip.rs b/game/src/info/trip.rs index 8cb4cd70ec..0d9816458b 100644 --- a/game/src/info/trip.rs +++ b/game/src/info/trip.rs @@ -70,8 +70,8 @@ pub fn ongoing( let mut col = Vec::new(); { - col.push(Widget::row(vec![ - Widget::row(vec![Line("Trip time").secondary().draw(ctx)]) + col.push(Widget::custom_row(vec![ + Widget::custom_row(vec![Line("Trip time").secondary().draw(ctx)]) .force_width_pct(ctx, col_width), Text::from_all(vec![ Line(props.total_time.to_string()), @@ -81,10 +81,10 @@ pub fn ongoing( ])); } { - col.push(Widget::row(vec![ - Widget::row(vec![Line("Distance").secondary().draw(ctx)]) + col.push(Widget::custom_row(vec![ + Widget::custom_row(vec![Line("Distance").secondary().draw(ctx)]) .force_width_pct(ctx, col_width), - Widget::col(vec![ + Widget::col2(vec![ Text::from_all(vec![ Line(props.dist_crossed.describe_rounded()), Line(format!("/{}", props.total_dist.describe_rounded())).secondary(), @@ -99,10 +99,13 @@ pub fn ongoing( ])); } { - col.push(Widget::row(vec![ - Widget::row(vec![Line("Waiting").secondary().draw(ctx)]) + col.push(Widget::custom_row(vec![ + Line("Waiting") + .secondary() + .draw(ctx) + .container() .force_width_pct(ctx, col_width), - Widget::col(vec![ + Widget::col2(vec![ format!("{} here", props.waiting_here).draw_text(ctx), Text::from_all(vec![ if props.total_waiting != Duration::ZERO { @@ -130,7 +133,7 @@ pub fn ongoing( Some(props.dist_crossed / props.total_dist), )); - Widget::col(col) + Widget::col2(col) } pub fn future( @@ -185,15 +188,14 @@ pub fn future( "This will advance the simulation to {}", start_time.ampm_tostring() )))) - .build(ctx, format!("wait for {}", trip), None) - .margin_above(10), + .build(ctx, format!("wait for {}", trip), None), ); details .time_warpers .insert(format!("wait for {}", trip), (trip, start_time)); } - Widget::col(col) + Widget::col2(col) } pub fn finished( @@ -270,15 +272,15 @@ pub fn finished( let col_width = 15; let total_trip_time = phases.last().as_ref().and_then(|p| p.end_time).unwrap() - start_time; - col.push(Widget::row(vec![ - Widget::row(vec![Line("Trip time").secondary().draw(ctx)]) + col.push(Widget::custom_row(vec![ + Widget::custom_row(vec![Line("Trip time").secondary().draw(ctx)]) .force_width_pct(ctx, col_width), total_trip_time.to_string().draw_text(ctx), ])); let (_, waiting) = app.primary.sim.finished_trip_time(trip).unwrap(); - col.push(Widget::row(vec![ - Widget::row(vec![Line("Total waiting time").secondary().draw(ctx)]) + col.push(Widget::custom_row(vec![ + Widget::custom_row(vec![Line("Total waiting time").secondary().draw(ctx)]) .force_width_pct(ctx, col_width), waiting.to_string().draw_text(ctx), ])); @@ -294,7 +296,7 @@ pub fn finished( None, )); - Widget::col(col) + Widget::col2(col) } pub fn aborted(ctx: &mut EventCtx, app: &App, trip: TripID) -> Widget { @@ -319,7 +321,7 @@ pub fn aborted(ctx: &mut EventCtx, app: &App, trip: TripID) -> Widget { .into_iter(), )); - Widget::col(col) + Widget::col2(col) } fn make_timeline( @@ -574,10 +576,10 @@ fn make_timeline( } let mut col = vec![ - Widget::row(vec![start_btn, Widget::row(timeline), goal_btn]) + Widget::custom_row(vec![start_btn, Widget::custom_row(timeline), goal_btn]) .evenly_spaced() .margin_above(25), - Widget::row(vec![ + Widget::row2(vec![ start_time.ampm_tostring().draw_text(ctx), if let Some(t) = end_time { t.ampm_tostring().draw_text(ctx).align_right() @@ -585,7 +587,7 @@ fn make_timeline( Widget::nothing() }, ]), - Widget::row(vec![ + Widget::row2(vec![ { details .time_warpers @@ -623,8 +625,7 @@ fn make_timeline( } else { Widget::nothing() }, - ]) - .margin_above(5), + ]), ]; if path_impossible { col.push("Map edits have disconnected the path taken before".draw_text(ctx)); @@ -633,7 +634,7 @@ fn make_timeline( if false { col.extend(elevation); } - Widget::col(col) + Widget::col2(col) } fn make_elevation(ctx: &EventCtx, color: Color, walking: bool, path: &Path, map: &Map) -> Widget { diff --git a/game/src/render/traffic_signal.rs b/game/src/render/traffic_signal.rs index f30827fa91..fbcd4a2f8e 100644 --- a/game/src/render/traffic_signal.rs +++ b/game/src/render/traffic_signal.rs @@ -331,11 +331,11 @@ pub fn make_signal_diagram( }; let mut col = if edit_mode { vec![ - txt_widget.margin_below(10), + txt_widget, Btn::text_bg2("Edit entire signal").build_def(ctx, hotkey(Key::E)), ] } else { - vec![Widget::row(vec![ + vec![Widget::row2(vec![ txt_widget, Btn::text_fg("X") .build(ctx, "close", hotkey(Key::Escape)) @@ -353,7 +353,6 @@ pub fn make_signal_diagram( Polygon::rectangle(0.2 * ctx.canvas.window_width / ctx.get_scale_factor(), 2.0), )]), ) - .margin(15) .centered_horiz(), ); @@ -381,14 +380,16 @@ pub fn make_signal_diagram( hovered.append(normal.clone()); hovered.push(Color::RED, bbox.to_outline(Distance::meters(5.0))); - Btn::custom(normal, hovered, bbox.clone()) - .build(ctx, format!("phase {}", idx + 1), None) - .margin(5) + Btn::custom(normal, hovered, bbox.clone()).build( + ctx, + format!("phase {}", idx + 1), + None, + ) }; let phase_col = if edit_mode { - Widget::col(vec![ - Widget::row(vec![ + Widget::col2(vec![ + Widget::row2(vec![ match phase.phase_type { PhaseType::Fixed(d) => Line(format!("Phase {}: {}", idx + 1, d)), PhaseType::Adaptive(d) => { @@ -396,8 +397,7 @@ pub fn make_signal_diagram( } } .small_heading() - .draw(ctx) - .margin_right(10), + .draw(ctx), Btn::svg_def("../data/system/assets/tools/edit.svg").build( ctx, format!("change duration of phase {}", idx + 1), @@ -414,17 +414,15 @@ pub fn make_signal_diagram( } else { Widget::nothing() }, - ]) - .margin_below(10), - Widget::row(vec![ + ]), + Widget::row2(vec![ phase_btn, - Widget::col(vec![ + Widget::col2(vec![ if idx == 0 { Btn::text_fg("↑").inactive(ctx) } else { Btn::text_fg("↑").build(ctx, format!("move up phase {}", idx + 1), None) - } - .margin_below(5), + }, if idx == signal.phases.len() - 1 { Btn::text_fg("↓").inactive(ctx) } else { @@ -440,7 +438,7 @@ pub fn make_signal_diagram( ]), ]) } else { - Widget::col(vec![ + Widget::col2(vec![ match phase.phase_type { PhaseType::Fixed(d) => format!("Phase {}: {}", idx + 1, d).draw_text(ctx), PhaseType::Adaptive(d) => { @@ -469,14 +467,13 @@ pub fn make_signal_diagram( Polygon::rectangle(0.2 * ctx.canvas.window_width / ctx.get_scale_factor(), 2.0), )]), ) - .margin(15) .centered_horiz(), ); col.push(Btn::text_fg("Add new phase").build_def(ctx, None)); } - Composite::new(Widget::col(col).bg(app.cs.panel_bg).padding(10)) + Composite::new(Widget::col2(col).bg(app.cs.panel_bg).padding(16)) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top) .exact_size_percent(30, 85) .build(ctx) diff --git a/game/src/sandbox/dashboards/misc.rs b/game/src/sandbox/dashboards/misc.rs index 5fb2a2e212..476a1714d1 100644 --- a/game/src/sandbox/dashboards/misc.rs +++ b/game/src/sandbox/dashboards/misc.rs @@ -34,12 +34,12 @@ impl ActiveTraffic { Box::new(ActiveTraffic { composite: Composite::new( - Widget::col(vec![ + Widget::col2(vec![ DashTab::ActiveTraffic.picker(ctx, app), LinePlot::new(ctx, active_agents, PlotOptions::fixed()), ]) .bg(app.cs.panel_bg) - .padding(10), + .padding(16), ) .exact_size_percent(90, 90) .build(ctx), @@ -86,11 +86,11 @@ impl BusRoutes { Line("Bus routes").small_heading().draw(ctx), ]; for r in routes { - col.push(Btn::text_fg(r).build_def(ctx, None).margin(5)); + col.push(Btn::text_fg(r).build_def(ctx, None)); } Box::new(BusRoutes { - composite: Composite::new(Widget::col(col).bg(app.cs.panel_bg).padding(10)) + composite: Composite::new(Widget::col2(col).bg(app.cs.panel_bg).padding(16)) .exact_size_percent(90, 90) .build(ctx), }) diff --git a/game/src/sandbox/dashboards/mod.rs b/game/src/sandbox/dashboards/mod.rs index 71eb1164b9..b04bb99961 100644 --- a/game/src/sandbox/dashboards/mod.rs +++ b/game/src/sandbox/dashboards/mod.rs @@ -40,7 +40,7 @@ impl DashTab { Widget::custom_row(vec![ // TODO Centered, but actually, we need to set the padding of each button to divide the // available space evenly. Fancy fill rules... hmmm. - Widget::row(row).bg(Color::WHITE).margin_vert(16), + Widget::custom_row(row).bg(Color::WHITE).margin_vert(16), Btn::plaintext("X") .build(ctx, "close", hotkey(Key::Escape)) .align_right(), diff --git a/game/src/sandbox/gameplay/commute.rs b/game/src/sandbox/gameplay/commute.rs index 1b257d5710..91060338ba 100644 --- a/game/src/sandbox/gameplay/commute.rs +++ b/game/src/sandbox/gameplay/commute.rs @@ -273,7 +273,7 @@ fn make_meter( ]), ]) .bg(app.cs.panel_bg) - .padding(20), + .padding(16), ) .aligned(HorizontalAlignment::Right, VerticalAlignment::Top) .build(ctx) @@ -370,7 +370,7 @@ fn cutscene_task(mode: &GameplayMode) -> Box Widget> { ]) .draw(ctx) .margin_below(30), - Widget::row(vec![ + Widget::row2(vec![ Widget::col2(vec![ Line("Time").fg(Color::BLACK).draw(ctx), Widget::draw_svg_transform( diff --git a/game/src/sandbox/gameplay/fix_traffic_signals.rs b/game/src/sandbox/gameplay/fix_traffic_signals.rs index 0f2b417303..d30b04a464 100644 --- a/game/src/sandbox/gameplay/fix_traffic_signals.rs +++ b/game/src/sandbox/gameplay/fix_traffic_signals.rs @@ -338,7 +338,7 @@ fn make_meter( }, ]) .bg(app.cs.panel_bg) - .padding(35), + .padding(16), ) .aligned(HorizontalAlignment::Right, VerticalAlignment::Top) .build(ctx) diff --git a/game/src/sandbox/mod.rs b/game/src/sandbox/mod.rs index e88a9b50c3..e5aa4946e5 100644 --- a/game/src/sandbox/mod.rs +++ b/game/src/sandbox/mod.rs @@ -284,21 +284,21 @@ impl AgentMeter { let rows = vec![ "Active trips".draw_text(ctx), - Widget::row(vec![ - Widget::row(vec![ + Widget::custom_row(vec![ + Widget::custom_row(vec![ Widget::draw_svg(ctx, "../data/system/assets/meters/pedestrian.svg") .margin_right(5), prettyprint_usize(by_mode[&TripMode::Walk]).draw_text(ctx), ]), - Widget::row(vec![ + Widget::custom_row(vec![ Widget::draw_svg(ctx, "../data/system/assets/meters/bike.svg").margin_right(5), prettyprint_usize(by_mode[&TripMode::Bike]).draw_text(ctx), ]), - Widget::row(vec![ + Widget::custom_row(vec![ Widget::draw_svg(ctx, "../data/system/assets/meters/car.svg").margin_right(5), prettyprint_usize(by_mode[&TripMode::Drive]).draw_text(ctx), ]), - Widget::row(vec![ + Widget::custom_row(vec![ Widget::draw_svg(ctx, "../data/system/assets/meters/bus.svg").margin_right(5), prettyprint_usize(by_mode[&TripMode::Transit]).draw_text(ctx), ]), @@ -312,9 +312,8 @@ impl AgentMeter { Polygon::rectangle(0.2 * ctx.canvas.window_width / ctx.get_scale_factor(), 2.0), )]), ) - .margin(15) .centered_horiz(), - Widget::row(vec![ + Widget::row2(vec![ { let mut txt = Text::new(); let pct = if unfinished == 0 { @@ -335,7 +334,7 @@ impl AgentMeter { ]), ]; - let composite = Composite::new(Widget::col(rows).bg(app.cs.panel_bg).padding(20)) + let composite = Composite::new(Widget::col2(rows).bg(app.cs.panel_bg).padding(16)) .aligned(HorizontalAlignment::Right, VerticalAlignment::Top) .build(ctx); diff --git a/game/src/sandbox/speed.rs b/game/src/sandbox/speed.rs index 9249142c4d..5560845aeb 100644 --- a/game/src/sandbox/speed.rs +++ b/game/src/sandbox/speed.rs @@ -33,7 +33,6 @@ enum SpeedSetting { } impl SpeedControls { - // TODO Could use checkbox here, but not sure it'll make things that much simpler. fn make_panel(ctx: &mut EventCtx, app: &App, paused: bool, setting: SpeedSetting) -> Composite { let mut row = Vec::new(); row.push( @@ -51,7 +50,7 @@ impl SpeedControls { ); row.push( - Widget::row( + Widget::custom_row( vec![ (SpeedSetting::Realtime, "real-time speed"), (SpeedSetting::Fast, "5x speed"), @@ -100,7 +99,7 @@ impl SpeedControls { ); row.push( - Widget::row(vec![ + Widget::custom_row(vec![ Btn::svg_def("../data/system/assets/speed/jump_to_time.svg") .pad(9) .build(ctx, "jump to specific time", hotkey(Key::B)), @@ -111,7 +110,7 @@ impl SpeedControls { .bg(app.cs.section_bg), ); - Composite::new(Widget::row(row).bg(app.cs.panel_bg).padding(16)) + Composite::new(Widget::custom_row(row).bg(app.cs.panel_bg).padding(16)) .aligned( HorizontalAlignment::Center, VerticalAlignment::BottomAboveOSD, @@ -350,14 +349,13 @@ impl JumpToTime { target, maybe_mode, composite: Composite::new( - Widget::col(vec![ - Widget::row(vec![ + Widget::col2(vec![ + Widget::row2(vec![ Line("Jump to what time?").small_heading().draw(ctx), Btn::plaintext("X") .build(ctx, "close", hotkey(Key::Escape)) .align_right(), - ]) - .margin_below(15), + ]), if app.has_prebaked().is_some() { Widget::draw_batch( ctx, @@ -380,8 +378,7 @@ impl JumpToTime { 0.25 * ctx.canvas.window_width, target.to_percent(end_of_day).min(1.0), ) - .named("time slider") - .margin_below(15), + .named("time slider"), Btn::text_bg2(format!("Jump to {}", target.ampm_tostring())) .build(ctx, "jump to time", hotkey(Key::Enter)) .centered_horiz() @@ -393,8 +390,7 @@ impl JumpToTime { Polygon::rectangle(0.25 * ctx.canvas.window_width, 2.0), )]), ) - .margin_above(20) - .margin_below(20), + .margin_above(10), Btn::text_bg2("Jump to the next delay over 5 minutes") .build_def(ctx, None) .centered_horiz(), @@ -506,7 +502,7 @@ impl TimeWarpScreen { started: Instant::now(), traffic_jams, composite: Composite::new( - Widget::col(vec![ + Widget::col2(vec![ Text::new().draw(ctx).named("text"), Btn::text_bg2("stop now") .build_def(ctx, hotkey(Key::Escape)) @@ -644,12 +640,11 @@ impl TimePanel { TimePanel { time: app.primary.sim.time(), composite: Composite::new( - Widget::col(vec![ + Widget::col2(vec![ Text::from( Line(app.primary.sim.time().ampm_tostring_spacers()).big_heading_styled(), ) .draw(ctx) - .margin(10) .centered_horiz(), { let mut batch = GeomBatch::new(); @@ -684,17 +679,16 @@ impl TimePanel { Widget::draw_batch(ctx, batch) }, - Widget::row(vec![ + Widget::custom_row(vec![ Line("00:00").small().draw(ctx), Widget::draw_svg(ctx, "../data/system/assets/speed/sunrise.svg"), Line("12:00").small().draw(ctx), Widget::draw_svg(ctx, "../data/system/assets/speed/sunset.svg"), Line("24:00").small().draw(ctx), ]) - .padding(10) .evenly_spaced(), ]) - .padding(10) + .padding(16) .bg(app.cs.panel_bg), ) .aligned(HorizontalAlignment::Left, VerticalAlignment::Top) diff --git a/map_editor/src/main.rs b/map_editor/src/main.rs index bcb441dc03..26a6c0e37c 100644 --- a/map_editor/src/main.rs +++ b/map_editor/src/main.rs @@ -72,10 +72,10 @@ impl UI { model, state: State::viewing(), composite: Composite::new( - Widget::col(vec![ + Widget::col2(vec![ Line("Map Editor").small_heading().draw(ctx), Text::new().draw(ctx).named("current info"), - Widget::col( + Widget::col2( vec![ (hotkey(Key::Escape), "quit"), (None, "save raw map"), @@ -89,7 +89,7 @@ impl UI { .collect(), ), ]) - .padding(10) + .padding(16) .bg(Color::grey(0.4)), ) .aligned(HorizontalAlignment::Right, VerticalAlignment::Top)