mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
more layout refactor
This commit is contained in:
parent
54b4bd318e
commit
ef51a8b9b8
@ -61,26 +61,22 @@ impl CityPicker {
|
||||
batch = batch.scale(zoom);
|
||||
}
|
||||
|
||||
let mut other_cities = vec![Line("Other cities").draw(ctx).margin_below(10)];
|
||||
let mut other_cities = vec![Line("Other cities").draw(ctx)];
|
||||
let mut this_city = vec![];
|
||||
for name in abstutil::list_all_objects(abstutil::path_all_maps()) {
|
||||
if let Some((_, color, _)) = regions.iter().find(|(n, _, _)| &name == n) {
|
||||
let btn = Btn::txt(&name, Text::from(Line(nice_map_name(&name)).fg(*color)))
|
||||
.tooltip(Text::new());
|
||||
this_city.push(
|
||||
if &name == app.primary.map.get_name() {
|
||||
btn.inactive(ctx)
|
||||
} else {
|
||||
btn.build_def(ctx, None)
|
||||
}
|
||||
.margin_below(5),
|
||||
);
|
||||
this_city.push(if &name == app.primary.map.get_name() {
|
||||
btn.inactive(ctx)
|
||||
} else {
|
||||
btn.build_def(ctx, None)
|
||||
});
|
||||
} else {
|
||||
other_cities.push(
|
||||
Btn::txt(&name, Text::from(Line(nice_map_name(&name))))
|
||||
.tooltip(Text::new())
|
||||
.build_def(ctx, None)
|
||||
.margin_below(5),
|
||||
.build_def(ctx, None),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -90,22 +86,22 @@ impl CityPicker {
|
||||
selected: None,
|
||||
on_load,
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Select a region").small_heading().draw(ctx),
|
||||
Btn::plaintext("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
]),
|
||||
Widget::row(vec![
|
||||
Widget::col(other_cities).centered_vert(),
|
||||
Widget::row2(vec![
|
||||
Widget::col2(other_cities).centered_vert(),
|
||||
Widget::draw_batch(ctx, batch).named("picker"),
|
||||
Widget::col(this_city).centered_vert(),
|
||||
Widget::col2(this_city).centered_vert(),
|
||||
]),
|
||||
])
|
||||
.bg(app.cs.panel_bg)
|
||||
.outline(2.0, Color::WHITE)
|
||||
.padding(10),
|
||||
.padding(16),
|
||||
)
|
||||
.build(ctx),
|
||||
})
|
||||
|
@ -71,12 +71,9 @@ impl BlockMap {
|
||||
|
||||
draw_all_blocks: ctx.upload(all_blocks),
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Commute map by block")
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.margin_right(10),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Commute map by block").small_heading().draw(ctx),
|
||||
Btn::text_fg("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
@ -84,7 +81,7 @@ impl BlockMap {
|
||||
Checkbox::text(ctx, "from / to this block", hotkey(Key::Space), true),
|
||||
Checkbox::text(ctx, "arrows / heatmap", hotkey(Key::H), true),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
|
@ -48,7 +48,7 @@ impl PopularDestinations {
|
||||
}
|
||||
// TODO Er, the heatmap actually looks terrible.
|
||||
let legend = make_heatmap(ctx, &mut batch, map.get_bounds(), pts, o);
|
||||
Widget::col(o.to_controls(ctx, legend))
|
||||
Widget::col2(o.to_controls(ctx, legend))
|
||||
} else {
|
||||
let max = per_bldg.max();
|
||||
let gradient = colorous::REDS;
|
||||
@ -92,12 +92,9 @@ impl PopularDestinations {
|
||||
per_bldg,
|
||||
draw: ctx.upload(batch),
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Most popular destinations")
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.margin_right(10),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Most popular destinations").small_heading().draw(ctx),
|
||||
Btn::text_fg("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
@ -106,7 +103,7 @@ impl PopularDestinations {
|
||||
controls,
|
||||
breakdown.draw(ctx),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
|
||||
|
@ -79,12 +79,9 @@ impl ViewKML {
|
||||
Box::new(ViewKML {
|
||||
draw: ctx.upload(batch),
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("KML viewer")
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.margin_right(10),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("KML viewer").small_heading().draw(ctx),
|
||||
Btn::text_fg("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
@ -95,13 +92,13 @@ impl ViewKML {
|
||||
prettyprint_usize(objects.len())
|
||||
)
|
||||
.draw_text(ctx),
|
||||
Widget::row(vec![
|
||||
"Query:".draw_text(ctx).margin_right(10),
|
||||
Widget::row2(vec![
|
||||
"Query:".draw_text(ctx),
|
||||
Widget::dropdown(ctx, "query", "None".to_string(), choices),
|
||||
]),
|
||||
"Query matches 0 objects".draw_text(ctx).named("matches"),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
|
@ -123,19 +123,15 @@ impl ParkingMapper {
|
||||
draw_layer: ctx.upload(batch),
|
||||
show,
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Parking mapper")
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.margin_right(10),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Parking mapper").small_heading().draw(ctx),
|
||||
Btn::text_fg("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
])
|
||||
.margin_below(5),
|
||||
Widget::row(vec![
|
||||
"Change map:".draw_text(ctx).margin_right(10),
|
||||
]),
|
||||
Widget::row2(vec![
|
||||
"Change map:".draw_text(ctx),
|
||||
Btn::text_fg(format!("{} ↓", nice_map_name(app.primary.map.get_name())))
|
||||
.build(ctx, "change map", None),
|
||||
]),
|
||||
@ -145,9 +141,8 @@ impl ParkingMapper {
|
||||
prettyprint_usize(done.len() + todo.len()),
|
||||
data.len()
|
||||
)
|
||||
.draw_text(ctx)
|
||||
.margin_below(5),
|
||||
Widget::row(vec![
|
||||
.draw_text(ctx),
|
||||
Widget::row2(vec![
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"Show",
|
||||
@ -165,8 +160,7 @@ impl ParkingMapper {
|
||||
)
|
||||
.tooltip("Roads often have the wrong number of lanes tagged"),
|
||||
],
|
||||
)
|
||||
.margin_right(15),
|
||||
),
|
||||
ColorLegend::row(
|
||||
ctx,
|
||||
color,
|
||||
@ -179,15 +173,12 @@ impl ParkingMapper {
|
||||
}
|
||||
},
|
||||
),
|
||||
])
|
||||
.margin_below(5),
|
||||
]),
|
||||
Checkbox::text(ctx, "max 3 days parking (default in Seattle)", None, false),
|
||||
Btn::text_fg("Generate OsmChange file")
|
||||
.build_def(ctx, None)
|
||||
.margin_below(30),
|
||||
Btn::text_fg("Generate OsmChange file").build_def(ctx, None),
|
||||
"Select a road".draw_text(ctx).named("info"),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
|
||||
|
@ -25,24 +25,19 @@ impl DevToolsMode {
|
||||
pub fn new(ctx: &mut EventCtx, app: &App) -> Box<dyn State> {
|
||||
Box::new(DevToolsMode {
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Internal dev tools")
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.margin_right(10),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Internal dev tools").small_heading().draw(ctx),
|
||||
Btn::text_fg("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
])
|
||||
.margin_below(5),
|
||||
Widget::row(vec![
|
||||
"Change map:".draw_text(ctx).margin_right(10),
|
||||
]),
|
||||
Widget::row2(vec![
|
||||
"Change map:".draw_text(ctx),
|
||||
Btn::text_fg(format!("{} ↓", nice_map_name(app.primary.map.get_name())))
|
||||
.build(ctx, "change map", None),
|
||||
])
|
||||
.margin_below(5),
|
||||
Widget::row(vec![
|
||||
]),
|
||||
Widget::custom_row(vec![
|
||||
Btn::text_fg("edit a polygon").build_def(ctx, hotkey(Key::E)),
|
||||
Btn::text_fg("draw a polygon").build_def(ctx, hotkey(Key::P)),
|
||||
Btn::text_fg("load scenario").build_def(ctx, hotkey(Key::W)),
|
||||
@ -51,7 +46,7 @@ impl DevToolsMode {
|
||||
])
|
||||
.flex_wrap(ctx, 60),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
|
@ -34,8 +34,8 @@ impl PolygonEditor {
|
||||
points.pop();
|
||||
Box::new(PolygonEditor {
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Polygon editor").small_heading().draw(ctx),
|
||||
Btn::text_fg("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
|
@ -48,8 +48,8 @@ impl ScenarioManager {
|
||||
let (unzoomed, zoomed, legend) = colorer.build(ctx);
|
||||
ScenarioManager {
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line(format!("Scenario {}", scenario.scenario_name))
|
||||
.small_heading()
|
||||
.draw(ctx),
|
||||
|
@ -325,20 +325,14 @@ fn make_panel(
|
||||
dirty: bool,
|
||||
) -> Composite {
|
||||
Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Story map editor")
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.margin_right(5),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Story map editor").small_heading().draw(ctx),
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(Color::WHITE, Polygon::rectangle(2.0, 30.0))]),
|
||||
)
|
||||
.margin_right(5),
|
||||
Btn::text_fg(format!("{} ↓", story.name))
|
||||
.build(ctx, "load", lctrl(Key::L))
|
||||
.margin_right(5),
|
||||
),
|
||||
Btn::text_fg(format!("{} ↓", story.name)).build(ctx, "load", lctrl(Key::L)),
|
||||
if dirty {
|
||||
Btn::svg_def("../data/system/assets/tools/save.svg").build(
|
||||
ctx,
|
||||
@ -351,13 +345,12 @@ fn make_panel(
|
||||
"../data/system/assets/tools/save.svg",
|
||||
RewriteColor::ChangeAlpha(0.5),
|
||||
)
|
||||
}
|
||||
.margin_right(5),
|
||||
},
|
||||
Btn::plaintext("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
.align_right(),
|
||||
]),
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
if let Mode::PlacingMarker = mode {
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
@ -550,8 +543,8 @@ impl Marker {
|
||||
|
||||
fn make_editor(&self, ctx: &mut EventCtx, app: &App) -> Composite {
|
||||
Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Editing marker").small_heading().draw(ctx),
|
||||
Btn::plaintext("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
|
@ -27,15 +27,18 @@ impl TitleScreen {
|
||||
let mut rng = app.primary.current_flags.sim_flags.make_rng();
|
||||
TitleScreen {
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::draw_svg(ctx, "../data/system/assets/pregame/logo.svg").margin(5),
|
||||
Widget::col2(vec![
|
||||
Widget::draw_svg(ctx, "../data/system/assets/pregame/logo.svg"),
|
||||
// TODO that nicer font
|
||||
// TODO Any key
|
||||
Btn::text_bg2("PLAY")
|
||||
.build(ctx, "start game", hotkeys(vec![Key::Space, Key::Enter]))
|
||||
.margin(5),
|
||||
Btn::text_bg2("PLAY").build(
|
||||
ctx,
|
||||
"start game",
|
||||
hotkeys(vec![Key::Space, Key::Enter]),
|
||||
),
|
||||
])
|
||||
.bg(app.cs.grass)
|
||||
.padding(16)
|
||||
.outline(3.0, Color::BLACK)
|
||||
.centered(),
|
||||
)
|
||||
@ -83,7 +86,7 @@ impl MainMenu {
|
||||
txt.add(Line("Created by Dustin Carlino and Yuwen Li"));
|
||||
txt.draw(ctx).centered_horiz()
|
||||
},
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
Btn::svg(
|
||||
"../data/system/assets/pregame/tutorial.svg",
|
||||
RewriteColor::Change(Color::WHITE, app.cs.hovering),
|
||||
@ -116,7 +119,7 @@ impl MainMenu {
|
||||
.build(ctx, "Challenges", hotkey(Key::C)),
|
||||
])
|
||||
.centered(),
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
Btn::text_bg2("Community Proposals")
|
||||
.tooltip({
|
||||
let mut txt = Text::tooltip(ctx, hotkey(Key::P), "Community Proposals");
|
||||
@ -138,9 +141,9 @@ impl MainMenu {
|
||||
Btn::text_bg2("Internal Dev Tools").build_def(ctx, hotkey(Key::D)),
|
||||
])
|
||||
.centered(),
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Btn::text_bg2("About").build_def(ctx, None).margin_right(20),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Btn::text_bg2("About").build_def(ctx, None),
|
||||
Btn::text_bg2("Feedback").build_def(ctx, None),
|
||||
]),
|
||||
built_info::time().draw(ctx),
|
||||
@ -149,7 +152,7 @@ impl MainMenu {
|
||||
];
|
||||
|
||||
Box::new(MainMenu {
|
||||
composite: Composite::new(Widget::col(col).evenly_spaced())
|
||||
composite: Composite::new(Widget::col2(col).evenly_spaced())
|
||||
.exact_size_percent(90, 85)
|
||||
.build(ctx),
|
||||
})
|
||||
@ -276,7 +279,7 @@ impl About {
|
||||
];
|
||||
|
||||
Box::new(About {
|
||||
composite: Composite::new(Widget::col(col))
|
||||
composite: Composite::new(Widget::custom_col(col))
|
||||
.exact_size_percent(90, 85)
|
||||
.build(ctx),
|
||||
})
|
||||
@ -375,18 +378,18 @@ impl Proposals {
|
||||
txt.add(Line("Contact dabreegster@gmail.com to add your idea here!"));
|
||||
txt.draw(ctx).centered_horiz().margin_below(20)
|
||||
},
|
||||
Widget::row(buttons).flex_wrap(ctx, 80),
|
||||
Widget::custom_row(buttons).flex_wrap(ctx, 80),
|
||||
];
|
||||
col.extend(current_tab);
|
||||
|
||||
Box::new(Proposals {
|
||||
proposals,
|
||||
composite: Composite::new(Widget::col(vec![
|
||||
composite: Composite::new(Widget::custom_col(vec![
|
||||
Btn::svg_def("../data/system/assets/pregame/back.svg")
|
||||
.build(ctx, "back", hotkey(Key::Escape))
|
||||
.align_left()
|
||||
.margin_below(20),
|
||||
Widget::col(col).bg(app.cs.panel_bg).padding(16),
|
||||
Widget::col2(col).bg(app.cs.panel_bg).padding(16),
|
||||
]))
|
||||
.exact_size_percent(90, 85)
|
||||
.build(ctx),
|
||||
|
@ -37,7 +37,7 @@ impl DashTab {
|
||||
row.push(Btn::text_bg2(name).build_def(ctx, None));
|
||||
}
|
||||
}
|
||||
Widget::row(vec![
|
||||
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),
|
||||
|
@ -269,7 +269,7 @@ fn make(ctx: &mut EventCtx, app: &App, opts: &Options) -> Composite {
|
||||
|
||||
let mut col = vec![DashTab::ParkingOverhead.picker(ctx, app)];
|
||||
col.push(
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
Text::from_multiline(vec![
|
||||
Line(
|
||||
"Trips taken by car also include time to walk between the building and \
|
||||
@ -296,46 +296,37 @@ fn make(ctx: &mut EventCtx, app: &App, opts: &Options) -> Composite {
|
||||
))
|
||||
.named("preview"),
|
||||
])
|
||||
.evenly_spaced()
|
||||
.margin_below(10),
|
||||
.evenly_spaced(),
|
||||
);
|
||||
col.push(
|
||||
Widget::row(vec![
|
||||
Checkbox::text(ctx, "starting off-map", None, opts.off_map_starts).margin_right(10),
|
||||
Checkbox::text(ctx, "ending off-map", None, opts.off_map_ends),
|
||||
])
|
||||
.margin_below(5),
|
||||
);
|
||||
col.push(
|
||||
Widget::row(vec![
|
||||
if opts.skip > 0 {
|
||||
Btn::text_fg("<").build(ctx, "previous trips", None)
|
||||
col.push(Widget::row2(vec![
|
||||
Checkbox::text(ctx, "starting off-map", None, opts.off_map_starts),
|
||||
Checkbox::text(ctx, "ending off-map", None, opts.off_map_ends),
|
||||
]));
|
||||
col.push(Widget::row2(vec![
|
||||
if opts.skip > 0 {
|
||||
Btn::text_fg("<").build(ctx, "previous trips", None)
|
||||
} else {
|
||||
Btn::text_fg("<").inactive(ctx)
|
||||
},
|
||||
format!(
|
||||
"{}-{} of {}",
|
||||
if total_rows > 0 {
|
||||
prettyprint_usize(opts.skip + 1)
|
||||
} else {
|
||||
Btn::text_fg("<").inactive(ctx)
|
||||
}
|
||||
.margin_right(10),
|
||||
format!(
|
||||
"{}-{} of {}",
|
||||
if total_rows > 0 {
|
||||
prettyprint_usize(opts.skip + 1)
|
||||
} else {
|
||||
"0".to_string()
|
||||
},
|
||||
prettyprint_usize((opts.skip + 1 + ROWS).min(total_rows)),
|
||||
prettyprint_usize(total_rows)
|
||||
)
|
||||
.draw_text(ctx)
|
||||
.margin_right(10),
|
||||
if opts.skip + 1 + ROWS < total_rows {
|
||||
Btn::text_fg(">").build(ctx, "next trips", None)
|
||||
} else {
|
||||
Btn::text_fg(">").inactive(ctx)
|
||||
"0".to_string()
|
||||
},
|
||||
])
|
||||
.margin_below(5),
|
||||
);
|
||||
prettyprint_usize((opts.skip + 1 + ROWS).min(total_rows)),
|
||||
prettyprint_usize(total_rows)
|
||||
)
|
||||
.draw_text(ctx),
|
||||
if opts.skip + 1 + ROWS < total_rows {
|
||||
Btn::text_fg(">").build(ctx, "next trips", None)
|
||||
} else {
|
||||
Btn::text_fg(">").inactive(ctx)
|
||||
},
|
||||
]));
|
||||
|
||||
col.extend(make_table(
|
||||
col.push(make_table(
|
||||
ctx,
|
||||
app,
|
||||
headers,
|
||||
@ -343,7 +334,7 @@ fn make(ctx: &mut EventCtx, app: &App, opts: &Options) -> Composite {
|
||||
0.88 * ctx.canvas.window_width,
|
||||
));
|
||||
|
||||
Composite::new(Widget::col(col).bg(app.cs.panel_bg).padding(10))
|
||||
Composite::new(Widget::col2(col).bg(app.cs.panel_bg).padding(16))
|
||||
.exact_size_percent(90, 90)
|
||||
.build(ctx)
|
||||
}
|
||||
|
@ -29,27 +29,24 @@ impl TripSummaries {
|
||||
Choice::new("at least 10% change", Some(0.1)),
|
||||
Choice::new("at least 50% change", Some(0.5)),
|
||||
],
|
||||
)
|
||||
.margin_right(10),
|
||||
),
|
||||
checkbox_per_mode(ctx, app, &filter.modes),
|
||||
];
|
||||
|
||||
Box::new(TripSummaries {
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
DashTab::TripSummaries.picker(ctx, app),
|
||||
Widget::row(filters).centered_horiz().margin_below(10),
|
||||
summary(ctx, app, &filter).margin_below(10),
|
||||
Widget::row(vec![
|
||||
contingency_table(ctx, app, &filter)
|
||||
.centered_vert()
|
||||
.margin_right(20),
|
||||
Widget::row2(filters).centered_horiz(),
|
||||
summary(ctx, app, &filter),
|
||||
Widget::row2(vec![
|
||||
contingency_table(ctx, app, &filter).centered_vert(),
|
||||
scatter_plot(ctx, app, &filter),
|
||||
])
|
||||
.evenly_spaced(),
|
||||
])
|
||||
.bg(app.cs.panel_bg)
|
||||
.padding(10),
|
||||
.padding(16),
|
||||
)
|
||||
.exact_size_percent(90, 90)
|
||||
.build(ctx),
|
||||
@ -127,8 +124,8 @@ fn summary(ctx: &mut EventCtx, app: &App, filter: &Filter) -> Widget {
|
||||
}
|
||||
}
|
||||
|
||||
Widget::col(vec![Widget::row(vec![
|
||||
Widget::col(vec![Text::from_multiline(vec![
|
||||
Widget::col2(vec![Widget::row2(vec![
|
||||
Widget::col2(vec![Text::from_multiline(vec![
|
||||
Line(format!("{} trips faster", prettyprint_usize(num_faster))),
|
||||
Line(format!("{} total time saved", sum_faster)),
|
||||
Line(format!(
|
||||
@ -146,10 +143,9 @@ fn summary(ctx: &mut EventCtx, app: &App, filter: &Filter) -> Widget {
|
||||
Line(format!("{} trips unchanged", prettyprint_usize(num_same)))
|
||||
.draw(ctx)
|
||||
.centered_vert()
|
||||
.margin_horiz(5)
|
||||
.outline(2.0, Color::YELLOW)
|
||||
.padding(10),
|
||||
Widget::col(vec![Text::from_multiline(vec![
|
||||
Widget::col2(vec![Text::from_multiline(vec![
|
||||
Line(format!("{} trips slower", prettyprint_usize(num_slower))),
|
||||
Line(format!("{} total time lost", sum_slower)),
|
||||
Line(format!(
|
||||
@ -317,7 +313,8 @@ fn contingency_table(ctx: &mut EventCtx, app: &App, filter: &Filter) -> Widget {
|
||||
}
|
||||
batch.extend(Color::BLACK, outlines);
|
||||
|
||||
Widget::row(vec![DrawWithTooltips::new(ctx, batch, tooltips)])
|
||||
DrawWithTooltips::new(ctx, batch, tooltips)
|
||||
.container()
|
||||
.outline(2.0, Color::WHITE)
|
||||
.padding(10)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use geom::{Distance, Duration, Polygon, Pt2D, Time};
|
||||
use sim::{TripEndpoint, TripID, TripMode};
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
|
||||
const ROWS: usize = 10;
|
||||
const ROWS: usize = 8;
|
||||
|
||||
pub struct TripTable {
|
||||
composite: Composite,
|
||||
@ -326,14 +326,11 @@ fn make(ctx: &mut EventCtx, app: &App, opts: &Options) -> Composite {
|
||||
headers.push(btn(SortBy::PercentWaiting, "Percent waiting"));
|
||||
|
||||
let mut col = vec![DashTab::TripTable.picker(ctx, app)];
|
||||
col.push(checkbox_per_mode(ctx, app, &opts.modes).margin_below(5));
|
||||
col.push(
|
||||
Widget::row(vec![
|
||||
Checkbox::text(ctx, "starting off-map", None, opts.off_map_starts).margin_right(10),
|
||||
Checkbox::text(ctx, "ending off-map", None, opts.off_map_ends),
|
||||
])
|
||||
.margin_below(5),
|
||||
);
|
||||
col.push(checkbox_per_mode(ctx, app, &opts.modes));
|
||||
col.push(Widget::row2(vec![
|
||||
Checkbox::text(ctx, "starting off-map", None, opts.off_map_starts),
|
||||
Checkbox::text(ctx, "ending off-map", None, opts.off_map_ends),
|
||||
]));
|
||||
let (_, unfinished, _) = app.primary.sim.num_trips();
|
||||
col.push(
|
||||
Text::from_multiline(vec![
|
||||
@ -346,40 +343,34 @@ fn make(ctx: &mut EventCtx, app: &App, opts: &Options) -> Composite {
|
||||
prettyprint_usize(unfinished)
|
||||
)),
|
||||
])
|
||||
.draw(ctx)
|
||||
.margin_below(10),
|
||||
.draw(ctx),
|
||||
);
|
||||
|
||||
col.push(
|
||||
Widget::row(vec![
|
||||
if opts.skip > 0 {
|
||||
Btn::text_fg("<").build(ctx, "previous trips", None)
|
||||
col.push(Widget::row2(vec![
|
||||
if opts.skip > 0 {
|
||||
Btn::text_fg("<").build(ctx, "previous trips", None)
|
||||
} else {
|
||||
Btn::text_fg("<").inactive(ctx)
|
||||
},
|
||||
format!(
|
||||
"{}-{} of {}",
|
||||
if total_rows > 0 {
|
||||
prettyprint_usize(opts.skip + 1)
|
||||
} else {
|
||||
Btn::text_fg("<").inactive(ctx)
|
||||
}
|
||||
.margin_right(10),
|
||||
format!(
|
||||
"{}-{} of {}",
|
||||
if total_rows > 0 {
|
||||
prettyprint_usize(opts.skip + 1)
|
||||
} else {
|
||||
"0".to_string()
|
||||
},
|
||||
prettyprint_usize((opts.skip + 1 + ROWS).min(total_rows)),
|
||||
prettyprint_usize(total_rows)
|
||||
)
|
||||
.draw_text(ctx)
|
||||
.margin_right(10),
|
||||
if opts.skip + 1 + ROWS < total_rows {
|
||||
Btn::text_fg(">").build(ctx, "next trips", None)
|
||||
} else {
|
||||
Btn::text_fg(">").inactive(ctx)
|
||||
"0".to_string()
|
||||
},
|
||||
])
|
||||
.margin_below(5),
|
||||
);
|
||||
prettyprint_usize((opts.skip + 1 + ROWS).min(total_rows)),
|
||||
prettyprint_usize(total_rows)
|
||||
)
|
||||
.draw_text(ctx),
|
||||
if opts.skip + 1 + ROWS < total_rows {
|
||||
Btn::text_fg(">").build(ctx, "next trips", None)
|
||||
} else {
|
||||
Btn::text_fg(">").inactive(ctx)
|
||||
},
|
||||
]));
|
||||
|
||||
col.extend(make_table(
|
||||
col.push(make_table(
|
||||
ctx,
|
||||
app,
|
||||
headers,
|
||||
@ -392,11 +383,10 @@ fn make(ctx: &mut EventCtx, app: &App, opts: &Options) -> Composite {
|
||||
0.15 * ctx.canvas.window_width,
|
||||
))
|
||||
.named("preview")
|
||||
.centered_horiz()
|
||||
.margin_above(10),
|
||||
.centered_horiz(),
|
||||
);
|
||||
|
||||
Composite::new(Widget::col(col).bg(app.cs.panel_bg).padding(10))
|
||||
Composite::new(Widget::col2(col).bg(app.cs.panel_bg).padding(16))
|
||||
.exact_size_percent(90, 90)
|
||||
.build(ctx)
|
||||
}
|
||||
@ -408,7 +398,7 @@ pub fn make_table(
|
||||
headers: Vec<Widget>,
|
||||
rows: Vec<(String, Vec<GeomBatch>)>,
|
||||
total_width: f64,
|
||||
) -> Vec<Widget> {
|
||||
) -> Widget {
|
||||
let total_width = total_width / ctx.get_scale_factor();
|
||||
let mut width_per_col: Vec<f64> = headers
|
||||
.iter()
|
||||
@ -423,7 +413,7 @@ pub fn make_table(
|
||||
/ (width_per_col.len() - 1) as f64)
|
||||
.max(0.0);
|
||||
|
||||
let mut col = vec![Widget::row(
|
||||
let mut col = vec![Widget::custom_row(
|
||||
headers
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
@ -461,7 +451,7 @@ pub fn make_table(
|
||||
);
|
||||
}
|
||||
|
||||
col
|
||||
Widget::custom_col(col)
|
||||
}
|
||||
|
||||
pub fn preview_trip(g: &mut GfxCtx, app: &App, composite: &Composite) {
|
||||
|
@ -47,9 +47,9 @@ impl OptimizeCommute {
|
||||
let trips = app.primary.sim.get_person(person).trips.clone();
|
||||
Box::new(OptimizeCommute {
|
||||
top_center: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
challenge_header(ctx, "Optimize the VIP's commute"),
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
format!("Speed up the VIP's trips by {}", goal)
|
||||
.draw_text(ctx)
|
||||
.centered_vert(),
|
||||
@ -252,7 +252,7 @@ fn make_meter(
|
||||
txt.append(Line(")"));
|
||||
|
||||
Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
// Separator
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
@ -261,15 +261,14 @@ fn make_meter(
|
||||
Polygon::rectangle(0.2 * ctx.canvas.window_width / ctx.get_scale_factor(), 2.0),
|
||||
)]),
|
||||
)
|
||||
.margin(15)
|
||||
.centered_horiz(),
|
||||
Widget::row(vec![
|
||||
Btn::svg_def("../data/system/assets/tools/location.svg")
|
||||
.build(ctx, "locate VIP", None)
|
||||
.margin_right(10),
|
||||
format!("{}/{} trips done", done, trips)
|
||||
.draw_text(ctx)
|
||||
.margin_right(20),
|
||||
Widget::row2(vec![
|
||||
Btn::svg_def("../data/system/assets/tools/location.svg").build(
|
||||
ctx,
|
||||
"locate VIP",
|
||||
None,
|
||||
),
|
||||
format!("{}/{} trips done", done, trips).draw_text(ctx),
|
||||
txt.draw(ctx),
|
||||
]),
|
||||
])
|
||||
@ -364,7 +363,7 @@ fn cutscene_task(mode: &GameplayMode) -> Box<dyn Fn(&mut EventCtx) -> Widget> {
|
||||
};
|
||||
|
||||
Box::new(move |ctx| {
|
||||
Widget::col(vec![
|
||||
Widget::custom_col(vec![
|
||||
Text::from_multiline(vec![
|
||||
Line(format!("Speed up the VIP's trips by a total of {}", goal)).fg(Color::BLACK),
|
||||
Line("Ignore the damage done to everyone else.").fg(Color::BLACK),
|
||||
@ -372,45 +371,39 @@ fn cutscene_task(mode: &GameplayMode) -> Box<dyn Fn(&mut EventCtx) -> Widget> {
|
||||
.draw(ctx)
|
||||
.margin_below(30),
|
||||
Widget::row(vec![
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
Line("Time").fg(Color::BLACK).draw(ctx),
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
"../data/system/assets/tools/time.svg",
|
||||
RewriteColor::ChangeAll(Color::BLACK),
|
||||
)
|
||||
.margin_below(5)
|
||||
.margin_above(5),
|
||||
),
|
||||
Text::from_multiline(vec![
|
||||
Line("Until the VIP's").fg(Color::BLACK),
|
||||
Line("last trip is done").fg(Color::BLACK),
|
||||
])
|
||||
.draw(ctx),
|
||||
]),
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
Line("Goal").fg(Color::BLACK).draw(ctx),
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
"../data/system/assets/tools/location.svg",
|
||||
RewriteColor::ChangeAll(Color::BLACK),
|
||||
)
|
||||
.margin_below(5)
|
||||
.margin_above(5),
|
||||
),
|
||||
Text::from_multiline(vec![
|
||||
Line("Speed up the VIP's trips").fg(Color::BLACK),
|
||||
Line(format!("by at least {}", goal)).fg(Color::BLACK),
|
||||
])
|
||||
.draw(ctx),
|
||||
]),
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
Line("Score").fg(Color::BLACK).draw(ctx),
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
"../data/system/assets/tools/star.svg",
|
||||
RewriteColor::ChangeAll(Color::BLACK),
|
||||
)
|
||||
.margin_below(5)
|
||||
.margin_above(5),
|
||||
),
|
||||
Text::from_multiline(vec![
|
||||
Line("How much time").fg(Color::BLACK),
|
||||
Line("the VIP saves").fg(Color::BLACK),
|
||||
|
@ -30,15 +30,14 @@ impl FixTrafficSignals {
|
||||
pub fn new(ctx: &mut EventCtx, app: &App) -> Box<dyn GameplayState> {
|
||||
Box::new(FixTrafficSignals {
|
||||
top_center: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
challenge_header(ctx, "Traffic signal survivor"),
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
Line(format!(
|
||||
"Keep delay at all intersections under {}",
|
||||
THRESHOLD
|
||||
))
|
||||
.draw(ctx)
|
||||
.margin_right(16),
|
||||
.draw(ctx),
|
||||
Btn::svg(
|
||||
"../data/system/assets/tools/hint.svg",
|
||||
RewriteColor::Change(Color::WHITE, app.cs.hovering),
|
||||
@ -137,9 +136,9 @@ impl GameplayState for FixTrafficSignals {
|
||||
if dt >= THRESHOLD {
|
||||
self.done = true;
|
||||
self.top_center = Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
challenge_header(ctx, "Traffic signal survivor"),
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
Line(format!(
|
||||
"Delay exceeded {} at {}",
|
||||
THRESHOLD,
|
||||
@ -147,8 +146,7 @@ impl GameplayState for FixTrafficSignals {
|
||||
))
|
||||
.fg(Color::RED)
|
||||
.draw(ctx)
|
||||
.centered_vert()
|
||||
.margin_right(10),
|
||||
.centered_vert(),
|
||||
Btn::text_fg("try again").build_def(ctx, None),
|
||||
]),
|
||||
])
|
||||
@ -292,7 +290,7 @@ fn make_meter(
|
||||
worst: Option<(IntersectionID, Duration)>,
|
||||
) -> Composite {
|
||||
Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
// Separator
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
@ -301,10 +299,9 @@ fn make_meter(
|
||||
Polygon::rectangle(0.2 * ctx.canvas.window_width / ctx.get_scale_factor(), 2.0),
|
||||
)]),
|
||||
)
|
||||
.margin(15)
|
||||
.centered_horiz(),
|
||||
if let Some((_, delay)) = worst {
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
Text::from_all(vec![
|
||||
Line("Worst delay: "),
|
||||
Line(delay.to_string()).fg(if delay < Duration::minutes(5) {
|
||||
@ -321,12 +318,11 @@ fn make_meter(
|
||||
.align_right(),
|
||||
])
|
||||
} else {
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
if app.primary.dirty_from_edits {
|
||||
Btn::plaintext("(!)")
|
||||
.pad(0)
|
||||
.build(ctx, "explain score", None)
|
||||
.margin_right(10)
|
||||
} else {
|
||||
Widget::nothing()
|
||||
},
|
||||
@ -342,7 +338,7 @@ fn make_meter(
|
||||
},
|
||||
])
|
||||
.bg(app.cs.panel_bg)
|
||||
.padding(20),
|
||||
.padding(35),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
|
||||
.build(ctx)
|
||||
@ -379,7 +375,7 @@ fn final_score(
|
||||
|
||||
// TODO Can we automatically transform text and SVG colors?
|
||||
fn cutscene_pt1_task(ctx: &mut EventCtx) -> Widget {
|
||||
Widget::col(vec![
|
||||
Widget::custom_col(vec![
|
||||
Text::from_multiline(vec![
|
||||
Line(format!(
|
||||
"Don't let anyone be delayed by one traffic signal more than {}!",
|
||||
@ -391,42 +387,36 @@ fn cutscene_pt1_task(ctx: &mut EventCtx) -> Widget {
|
||||
])
|
||||
.draw(ctx)
|
||||
.margin_below(30),
|
||||
Widget::row(vec![
|
||||
Widget::col(vec![
|
||||
Widget::custom_row(vec![
|
||||
Widget::col2(vec![
|
||||
Line("Time").fg(Color::BLACK).draw(ctx),
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
"../data/system/assets/tools/time.svg",
|
||||
RewriteColor::ChangeAll(Color::BLACK),
|
||||
)
|
||||
.margin_below(5)
|
||||
.margin_above(5),
|
||||
),
|
||||
Line("24 hours").fg(Color::BLACK).draw(ctx),
|
||||
]),
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
Line("Goal").fg(Color::BLACK).draw(ctx),
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
"../data/system/assets/tools/location.svg",
|
||||
RewriteColor::ChangeAll(Color::BLACK),
|
||||
)
|
||||
.margin_below(5)
|
||||
.margin_above(5),
|
||||
),
|
||||
Text::from_multiline(vec![
|
||||
Line("Keep delay at all intersections").fg(Color::BLACK),
|
||||
Line(format!("under {}", THRESHOLD)).fg(Color::BLACK),
|
||||
])
|
||||
.draw(ctx),
|
||||
]),
|
||||
Widget::col(vec![
|
||||
Widget::col2(vec![
|
||||
Line("Score").fg(Color::BLACK).draw(ctx),
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
"../data/system/assets/tools/star.svg",
|
||||
RewriteColor::ChangeAll(Color::BLACK),
|
||||
)
|
||||
.margin_below(5)
|
||||
.margin_above(5),
|
||||
),
|
||||
Line("How long you survive").fg(Color::BLACK).draw(ctx),
|
||||
]),
|
||||
])
|
||||
|
@ -82,24 +82,25 @@ impl GameplayState for Freeform {
|
||||
|
||||
fn make_top_center(ctx: &mut EventCtx, app: &App) -> Composite {
|
||||
let rows = vec![
|
||||
Widget::row(vec![
|
||||
Line("Sandbox").small_heading().draw(ctx).margin(5),
|
||||
Widget::row2(vec![
|
||||
Line("Sandbox").small_heading().draw(ctx),
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(Color::WHITE, Polygon::rectangle(2.0, 50.0))]),
|
||||
)
|
||||
.margin(5),
|
||||
"Map:".draw_text(ctx).margin(5),
|
||||
Btn::text_fg(format!("{} ↓", nice_map_name(app.primary.map.get_name())))
|
||||
.build(ctx, "change map", lctrl(Key::L))
|
||||
.margin(5),
|
||||
"Traffic:".draw_text(ctx).margin(5),
|
||||
Btn::text_fg("none ↓")
|
||||
.build(ctx, "change traffic", hotkey(Key::S))
|
||||
.margin(5),
|
||||
Btn::svg_def("../data/system/assets/tools/edit_map.svg")
|
||||
.build(ctx, "edit map", lctrl(Key::E))
|
||||
.margin(5),
|
||||
),
|
||||
"Map:".draw_text(ctx),
|
||||
Btn::text_fg(format!("{} ↓", nice_map_name(app.primary.map.get_name()))).build(
|
||||
ctx,
|
||||
"change map",
|
||||
lctrl(Key::L),
|
||||
),
|
||||
"Traffic:".draw_text(ctx),
|
||||
Btn::text_fg("none ↓").build(ctx, "change traffic", hotkey(Key::S)),
|
||||
Btn::svg_def("../data/system/assets/tools/edit_map.svg").build(
|
||||
ctx,
|
||||
"edit map",
|
||||
lctrl(Key::E),
|
||||
),
|
||||
])
|
||||
.centered(),
|
||||
Btn::text_fg("Start a new trip")
|
||||
@ -113,7 +114,7 @@ fn make_top_center(ctx: &mut EventCtx, app: &App) -> Composite {
|
||||
.draw(ctx),
|
||||
];
|
||||
|
||||
Composite::new(Widget::col(rows).bg(app.cs.panel_bg).padding(10))
|
||||
Composite::new(Widget::col2(rows).bg(app.cs.panel_bg).padding(16))
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx)
|
||||
}
|
||||
@ -190,8 +191,8 @@ impl AgentSpawner {
|
||||
goal: None,
|
||||
confirmed: false,
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("New trip").small_heading().draw(ctx),
|
||||
Btn::plaintext("X")
|
||||
.build(ctx, "close", hotkey(Key::Escape))
|
||||
@ -199,10 +200,9 @@ impl AgentSpawner {
|
||||
]),
|
||||
"Click a building or border to specify start"
|
||||
.draw_text(ctx)
|
||||
.named("instructions")
|
||||
.margin_below(10),
|
||||
Widget::row(vec![
|
||||
"Type of trip:".draw_text(ctx).margin_right(10),
|
||||
.named("instructions"),
|
||||
Widget::row2(vec![
|
||||
"Type of trip:".draw_text(ctx),
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"mode",
|
||||
@ -212,17 +212,15 @@ impl AgentSpawner {
|
||||
.map(|m| Choice::new(m.ongoing_verb(), m))
|
||||
.collect(),
|
||||
),
|
||||
])
|
||||
.margin_below(10),
|
||||
Widget::row(vec![
|
||||
"Number of trips:".draw_text(ctx).margin_right(10),
|
||||
]),
|
||||
Widget::row2(vec![
|
||||
"Number of trips:".draw_text(ctx),
|
||||
Spinner::new(ctx, (1, 1000), 1).named("number"),
|
||||
])
|
||||
.margin_below(10),
|
||||
]),
|
||||
Btn::text_fg("Confirm").inactive(ctx).named("Confirm"),
|
||||
])
|
||||
.bg(app.cs.panel_bg)
|
||||
.padding(10),
|
||||
.padding(16),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
|
||||
.build(ctx),
|
||||
|
@ -276,21 +276,15 @@ impl ContextualActions for GameplayMode {
|
||||
}
|
||||
|
||||
fn challenge_header(ctx: &mut EventCtx, title: &str) -> Widget {
|
||||
Widget::row(vec![
|
||||
Line(title)
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.centered_vert()
|
||||
.margin_right(10),
|
||||
Widget::row2(vec![
|
||||
Line(title).small_heading().draw(ctx).centered_vert(),
|
||||
Btn::svg_def("../data/system/assets/tools/info.svg")
|
||||
.build(ctx, "instructions", None)
|
||||
.centered_vert()
|
||||
.margin_right(10),
|
||||
.centered_vert(),
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(Color::WHITE, Polygon::rectangle(2.0, 50.0))]),
|
||||
)
|
||||
.margin_right(10),
|
||||
),
|
||||
Btn::svg_def("../data/system/assets/tools/edit_map.svg")
|
||||
.build(ctx, "edit map", lctrl(Key::E))
|
||||
.centered_vert(),
|
||||
@ -314,24 +308,18 @@ impl FinalScore {
|
||||
) -> Box<dyn State> {
|
||||
Box::new(FinalScore {
|
||||
composite: Composite::new(
|
||||
Widget::row(vec![
|
||||
Widget::custom_row(vec![
|
||||
Widget::draw_svg(ctx, "../data/system/assets/characters/boss.svg")
|
||||
.container()
|
||||
.outline(10.0, Color::BLACK)
|
||||
.padding(10),
|
||||
Widget::col(vec![
|
||||
msg.draw_text(ctx).margin_below(5),
|
||||
Widget::col2(vec![
|
||||
msg.draw_text(ctx),
|
||||
// TODO Adjust wording
|
||||
Btn::text_bg2("Keep simulating")
|
||||
.build_def(ctx, None)
|
||||
.margin_below(5),
|
||||
Btn::text_bg2("Try again")
|
||||
.build_def(ctx, None)
|
||||
.margin_below(5),
|
||||
Btn::text_bg2("Keep simulating").build_def(ctx, None),
|
||||
Btn::text_bg2("Try again").build_def(ctx, None),
|
||||
if next_mode.is_some() {
|
||||
Btn::text_bg2("Next challenge")
|
||||
.build_def(ctx, None)
|
||||
.margin_below(5)
|
||||
Btn::text_bg2("Next challenge").build_def(ctx, None)
|
||||
} else {
|
||||
Widget::nothing()
|
||||
},
|
||||
|
@ -101,31 +101,38 @@ fn make_top_center(
|
||||
modifiers: &Vec<ScenarioModifier>,
|
||||
) -> Composite {
|
||||
let rows = vec![
|
||||
Widget::row(vec![
|
||||
Line("Sandbox").small_heading().draw(ctx).margin(5),
|
||||
Widget::row2(vec![
|
||||
Line("Sandbox").small_heading().draw(ctx),
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(Color::WHITE, Polygon::rectangle(2.0, 50.0))]),
|
||||
)
|
||||
.margin(5),
|
||||
"Map:".draw_text(ctx).margin(5),
|
||||
Btn::text_fg(format!("{} ↓", nice_map_name(app.primary.map.get_name())))
|
||||
.build(ctx, "change map", lctrl(Key::L))
|
||||
.margin(5),
|
||||
"Traffic:".draw_text(ctx).margin(5),
|
||||
Btn::text_fg(format!("{} ↓", scenario_name))
|
||||
.build(ctx, "change traffic", hotkey(Key::S))
|
||||
.margin(5),
|
||||
Btn::svg_def("../data/system/assets/tools/edit_map.svg")
|
||||
.build(ctx, "edit map", lctrl(Key::E))
|
||||
.margin(5),
|
||||
),
|
||||
"Map:".draw_text(ctx),
|
||||
Btn::text_fg(format!("{} ↓", nice_map_name(app.primary.map.get_name()))).build(
|
||||
ctx,
|
||||
"change map",
|
||||
lctrl(Key::L),
|
||||
),
|
||||
"Traffic:".draw_text(ctx),
|
||||
Btn::text_fg(format!("{} ↓", scenario_name)).build(
|
||||
ctx,
|
||||
"change traffic",
|
||||
hotkey(Key::S),
|
||||
),
|
||||
Btn::svg_def("../data/system/assets/tools/edit_map.svg").build(
|
||||
ctx,
|
||||
"edit map",
|
||||
lctrl(Key::E),
|
||||
),
|
||||
])
|
||||
.centered(),
|
||||
if scenario_name == "weekday" {
|
||||
Widget::row(vec![
|
||||
Btn::svg_def("../data/system/assets/tools/pencil.svg")
|
||||
.build(ctx, "edit traffic patterns", None)
|
||||
.margin_right(15),
|
||||
Widget::row2(vec![
|
||||
Btn::svg_def("../data/system/assets/tools/pencil.svg").build(
|
||||
ctx,
|
||||
"edit traffic patterns",
|
||||
None,
|
||||
),
|
||||
format!("{} modifications to traffic patterns", modifiers.len()).draw_text(ctx),
|
||||
])
|
||||
.centered_horiz()
|
||||
@ -134,7 +141,7 @@ fn make_top_center(
|
||||
},
|
||||
];
|
||||
|
||||
Composite::new(Widget::col(rows).bg(app.cs.panel_bg).padding(10))
|
||||
Composite::new(Widget::col2(rows).bg(app.cs.panel_bg).padding(16))
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx)
|
||||
}
|
||||
@ -153,10 +160,7 @@ impl EditScenarioModifiers {
|
||||
modifiers: Vec<ScenarioModifier>,
|
||||
) -> Box<dyn State> {
|
||||
let mut rows = vec![
|
||||
Line("Modify traffic patterns")
|
||||
.small_heading()
|
||||
.draw(ctx)
|
||||
.margin_below(10),
|
||||
Line("Modify traffic patterns").small_heading().draw(ctx),
|
||||
Text::from_multiline(vec![
|
||||
Line(
|
||||
"Data for all of the people in this simulation comes from PSRC's 2014 \
|
||||
@ -167,29 +171,23 @@ impl EditScenarioModifiers {
|
||||
Line("You can modify those patterns here. The modifications apply in order."),
|
||||
])
|
||||
.wrap_to_pct(ctx, 50)
|
||||
.draw(ctx)
|
||||
.margin_below(10),
|
||||
.draw(ctx),
|
||||
];
|
||||
for (idx, m) in modifiers.iter().enumerate() {
|
||||
rows.push(
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
m.describe().draw_text(ctx),
|
||||
Btn::svg_def("../data/system/assets/tools/delete.svg")
|
||||
.build(ctx, format!("delete modifier {}", idx + 1), None)
|
||||
.align_right(),
|
||||
])
|
||||
.padding(10)
|
||||
.outline(2.0, Color::WHITE)
|
||||
.margin_below(10),
|
||||
.outline(2.0, Color::WHITE),
|
||||
);
|
||||
}
|
||||
rows.push(Btn::text_bg2("New modification").build_def(ctx, None));
|
||||
rows.push(
|
||||
Btn::text_bg2("New modification")
|
||||
.build_def(ctx, None)
|
||||
.margin_below(10),
|
||||
);
|
||||
rows.push(
|
||||
Widget::row(vec![
|
||||
Widget::row2(vec![
|
||||
Btn::text_bg2("Apply").build_def(ctx, hotkey(Key::Enter)),
|
||||
Btn::text_bg2("Discard changes").build_def(ctx, hotkey(Key::Escape)),
|
||||
])
|
||||
@ -199,7 +197,7 @@ impl EditScenarioModifiers {
|
||||
Box::new(EditScenarioModifiers {
|
||||
scenario_name,
|
||||
modifiers,
|
||||
composite: Composite::new(Widget::col(rows).padding(16).bg(app.cs.panel_bg))
|
||||
composite: Composite::new(Widget::col2(rows).padding(16).bg(app.cs.panel_bg))
|
||||
.exact_size_percent(80, 80)
|
||||
.build(ctx),
|
||||
})
|
||||
|
@ -719,38 +719,35 @@ impl TutorialState {
|
||||
}
|
||||
|
||||
fn make_top_center(&self, ctx: &mut EventCtx, cs: &ColorScheme, edit_map: bool) -> Composite {
|
||||
let mut col = vec![Widget::row(vec![
|
||||
Line("Tutorial").small_heading().draw(ctx).margin(5),
|
||||
let mut col = vec![Widget::row2(vec![
|
||||
Line("Tutorial").small_heading().draw(ctx),
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(Color::WHITE, Polygon::rectangle(2.0, 50.0))]),
|
||||
)
|
||||
.margin(5),
|
||||
),
|
||||
if self.current.stage == 0 {
|
||||
Btn::text_fg("<").inactive(ctx)
|
||||
} else {
|
||||
Btn::text_fg("<").build(ctx, "previous tutorial", None)
|
||||
}
|
||||
.margin(5),
|
||||
},
|
||||
{
|
||||
let mut txt = Text::from(Line(format!("Task {}", self.current.stage + 1)));
|
||||
// TODO Smaller font and use alpha for the "/9" part
|
||||
txt.append(Line(format!("/{}", self.stages.len())).fg(Color::grey(0.7)));
|
||||
txt.draw(ctx).margin(5)
|
||||
txt.draw(ctx)
|
||||
},
|
||||
if self.current.stage == self.stages.len() - 1 {
|
||||
Btn::text_fg(">").inactive(ctx)
|
||||
} else {
|
||||
Btn::text_fg(">").build(ctx, "next tutorial", None)
|
||||
}
|
||||
.margin(5),
|
||||
Btn::text_fg("Quit").build_def(ctx, None).margin(5),
|
||||
},
|
||||
Btn::text_fg("Quit").build_def(ctx, None),
|
||||
])
|
||||
.centered()];
|
||||
{
|
||||
let task = self.interaction();
|
||||
if task != Task::Nil {
|
||||
col.push(Widget::row(vec![
|
||||
col.push(Widget::row2(vec![
|
||||
Text::from(
|
||||
Line(format!(
|
||||
"Task {}: {}",
|
||||
@ -759,8 +756,7 @@ impl TutorialState {
|
||||
))
|
||||
.small_heading(),
|
||||
)
|
||||
.draw(ctx)
|
||||
.margin_right(15),
|
||||
.draw(ctx),
|
||||
// TODO also text saying "instructions"... can we layout two things easily to
|
||||
// make a button?
|
||||
Btn::svg_def("../data/system/assets/tools/info.svg")
|
||||
@ -768,18 +764,20 @@ impl TutorialState {
|
||||
.centered_vert()
|
||||
.align_right(),
|
||||
]));
|
||||
col.push(task.top_txt(self).draw(ctx).margin(5));
|
||||
col.push(task.top_txt(self).draw(ctx));
|
||||
}
|
||||
}
|
||||
if edit_map {
|
||||
col.push(
|
||||
Btn::svg_def("../data/system/assets/tools/edit_map.svg")
|
||||
.build(ctx, "edit map", lctrl(Key::E))
|
||||
.margin(5),
|
||||
Btn::svg_def("../data/system/assets/tools/edit_map.svg").build(
|
||||
ctx,
|
||||
"edit map",
|
||||
lctrl(Key::E),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Composite::new(Widget::col(col).bg(cs.panel_bg).padding(16))
|
||||
Composite::new(Widget::col2(col).bg(cs.panel_bg).padding(16))
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx)
|
||||
}
|
||||
@ -817,7 +815,7 @@ impl TutorialState {
|
||||
}
|
||||
txt.wrap_to_pct(ctx, 30).draw(ctx)
|
||||
}];
|
||||
let mut controls = vec![Widget::row(vec![
|
||||
let mut controls = vec![Widget::row2(vec![
|
||||
if self.current.part > 0 {
|
||||
Btn::svg(
|
||||
"../data/system/assets/tools/prev.svg",
|
||||
@ -834,12 +832,10 @@ impl TutorialState {
|
||||
"../data/system/assets/tools/prev.svg",
|
||||
RewriteColor::ChangeAll(Color::WHITE.alpha(0.5)),
|
||||
)
|
||||
}
|
||||
.margin_right(15),
|
||||
},
|
||||
format!("{}/{}", self.current.part + 1, self.stage().messages.len())
|
||||
.draw_text(ctx)
|
||||
.centered_vert()
|
||||
.margin_right(15),
|
||||
.centered_vert(),
|
||||
if self.current.part == self.stage().messages.len() - 1 {
|
||||
Widget::draw_svg_transform(
|
||||
ctx,
|
||||
@ -862,15 +858,14 @@ impl TutorialState {
|
||||
if self.current.part == self.stage().messages.len() - 1 {
|
||||
controls.push(
|
||||
Btn::text_bg2("Try it")
|
||||
.build_def(ctx, hotkeys(vec![Key::RightArrow, Key::Space, Key::Enter]))
|
||||
.margin_above(10),
|
||||
.build_def(ctx, hotkeys(vec![Key::RightArrow, Key::Space, Key::Enter])),
|
||||
);
|
||||
}
|
||||
col.push(Widget::col(controls).align_bottom());
|
||||
col.push(Widget::col2(controls).align_bottom());
|
||||
|
||||
Some(
|
||||
Composite::new(
|
||||
Widget::col(col)
|
||||
Widget::col2(col)
|
||||
.bg(app.cs.panel_bg)
|
||||
.outline(5.0, Color::WHITE)
|
||||
.padding(16),
|
||||
|
@ -242,7 +242,7 @@ impl TurnExplorer {
|
||||
fn make_panel(ctx: &mut EventCtx, app: &App, l: LaneID, idx: usize) -> Composite {
|
||||
let num_turns = app.primary.map.get_turns_from_lane(l).len();
|
||||
|
||||
let mut col = vec![Widget::row(vec![
|
||||
let mut col = vec![Widget::row2(vec![
|
||||
Text::from(
|
||||
Line(format!(
|
||||
"Turns from {}",
|
||||
@ -250,29 +250,24 @@ impl TurnExplorer {
|
||||
))
|
||||
.small_heading(),
|
||||
)
|
||||
.draw(ctx)
|
||||
.margin(5),
|
||||
.draw(ctx),
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(Color::WHITE, Polygon::rectangle(2.0, 50.0))]),
|
||||
)
|
||||
.margin(5),
|
||||
),
|
||||
if idx == 0 {
|
||||
Btn::text_fg("<").inactive(ctx)
|
||||
} else {
|
||||
Btn::text_fg("<").build(ctx, "previous turn", hotkey(Key::LeftArrow))
|
||||
}
|
||||
.margin(5),
|
||||
},
|
||||
Text::from(Line(format!("{}/{}", idx, num_turns)).secondary())
|
||||
.draw(ctx)
|
||||
.margin(5)
|
||||
.centered_vert(),
|
||||
if idx == num_turns {
|
||||
Btn::text_fg(">").inactive(ctx)
|
||||
} else {
|
||||
Btn::text_fg(">").build(ctx, "next turn", hotkey(Key::RightArrow))
|
||||
}
|
||||
.margin(5),
|
||||
},
|
||||
Btn::text_fg("X").build(ctx, "close", hotkey(Key::Escape)),
|
||||
])];
|
||||
if idx == 0 {
|
||||
@ -319,7 +314,7 @@ impl TurnExplorer {
|
||||
col.push(ColorLegend::row(ctx, CONFLICTING_TURN, "conflicting turn"));
|
||||
}
|
||||
|
||||
Composite::new(Widget::col(col).bg(app.cs.panel_bg))
|
||||
Composite::new(Widget::col2(col).bg(app.cs.panel_bg).padding(16))
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx)
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ impl UberTurnPicker {
|
||||
Box::new(UberTurnPicker {
|
||||
members,
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Select multiple intersections")
|
||||
.small_heading()
|
||||
.draw(ctx),
|
||||
@ -42,7 +42,7 @@ impl UberTurnPicker {
|
||||
Btn::text_fg("View uber-turns").build_def(ctx, hotkey(Key::Enter)),
|
||||
Btn::text_fg("Edit").build_def(ctx, hotkey(Key::E)),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
@ -165,14 +165,13 @@ impl UberTurnViewer {
|
||||
Box::new(UberTurnViewer {
|
||||
draw: ctx.upload(batch),
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Widget::row(vec![
|
||||
Line("Uber-turn viewer").small_heading().draw(ctx).margin(5),
|
||||
Widget::col2(vec![
|
||||
Widget::row2(vec![
|
||||
Line("Uber-turn viewer").small_heading().draw(ctx),
|
||||
Widget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(Color::WHITE, Polygon::rectangle(2.0, 50.0))]),
|
||||
)
|
||||
.margin(5),
|
||||
),
|
||||
if idx == 0 {
|
||||
Btn::text_fg("<").inactive(ctx)
|
||||
} else {
|
||||
@ -181,23 +180,20 @@ impl UberTurnViewer {
|
||||
"previous uber-turn",
|
||||
hotkey(Key::LeftArrow),
|
||||
)
|
||||
}
|
||||
.margin(5),
|
||||
},
|
||||
Text::from(Line(format!("{}/{}", idx, ic.uber_turns.len())).secondary())
|
||||
.draw(ctx)
|
||||
.margin(5)
|
||||
.centered_vert(),
|
||||
if ic.uber_turns.is_empty() || idx == ic.uber_turns.len() - 1 {
|
||||
Btn::text_fg(">").inactive(ctx)
|
||||
} else {
|
||||
Btn::text_fg(">").build(ctx, "next uber-turn", hotkey(Key::RightArrow))
|
||||
}
|
||||
.margin(5),
|
||||
},
|
||||
Btn::text_fg("X").build(ctx, "close", hotkey(Key::Escape)),
|
||||
]),
|
||||
Checkbox::text(ctx, "legal / illegal movements", None, legal_turns),
|
||||
])
|
||||
.padding(10)
|
||||
.padding(16)
|
||||
.bg(app.cs.panel_bg),
|
||||
)
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
|
Loading…
Reference in New Issue
Block a user