mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 02:33:54 +03:00
New dashboard picker. #331
This commit is contained in:
parent
597ef473f2
commit
119e887425
@ -3,6 +3,7 @@ use crate::game::{DrawBaselayer, State, Transition};
|
||||
use crate::helpers::color_for_trip_phase;
|
||||
use crate::info::{OpenTrip, Tab};
|
||||
use crate::sandbox::dashboards::table::Table;
|
||||
use crate::sandbox::dashboards::trip_table;
|
||||
use crate::sandbox::dashboards::DashTab;
|
||||
use crate::sandbox::SandboxMode;
|
||||
use geom::{Distance, Pt2D};
|
||||
@ -66,11 +67,23 @@ impl<T: 'static, F: 'static, P: 'static + Fn(&mut EventCtx, &App, &Table<T, F>)
|
||||
);
|
||||
})),
|
||||
]);
|
||||
} else if x == "close" {
|
||||
return Transition::Pop;
|
||||
} else if x == "finished trips" {
|
||||
return Transition::Replace(trip_table::FinishedTripTable::new(ctx, app));
|
||||
} else if x == "cancelled trips" {
|
||||
return Transition::Replace(trip_table::CancelledTripTable::new(ctx, app));
|
||||
} else if x == "unfinished trips" {
|
||||
return Transition::Replace(trip_table::UnfinishedTripTable::new(ctx, app));
|
||||
} else {
|
||||
return self.tab.transition(ctx, app, &x);
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
Outcome::Changed => {
|
||||
if let Some(t) = self.tab.transition(ctx, app, &self.panel) {
|
||||
return t;
|
||||
}
|
||||
|
||||
self.table.panel_changed(&self.panel);
|
||||
self.recalc(ctx, app);
|
||||
}
|
||||
|
@ -56,7 +56,13 @@ impl ActiveTraffic {
|
||||
impl State for ActiveTraffic {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => DashTab::TripSummaries.transition(ctx, app, &x),
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => Transition::Pop,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Outcome::Changed => DashTab::ActiveTraffic
|
||||
.transition(ctx, app, &self.panel)
|
||||
.unwrap(),
|
||||
_ => Transition::Keep,
|
||||
}
|
||||
}
|
||||
@ -194,11 +200,20 @@ impl State for TransitRoutes {
|
||||
Outcome::Clicked(x) => {
|
||||
if let Some(x) = x.strip_prefix("BusRoute #") {
|
||||
BusRouteID(x.parse::<usize>().unwrap())
|
||||
} else if x == "close" {
|
||||
return Transition::Pop;
|
||||
} else {
|
||||
return DashTab::TransitRoutes.transition(ctx, app, &x);
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
Outcome::Changed => {
|
||||
if let Some(t) = DashTab::TransitRoutes.transition(ctx, app, &self.panel) {
|
||||
return t;
|
||||
} else {
|
||||
return Transition::Keep;
|
||||
}
|
||||
}
|
||||
Outcome::Nothing => {
|
||||
if let Some(routes) = self.panel.autocomplete_done("search") {
|
||||
if !routes.is_empty() {
|
||||
routes[0]
|
||||
|
@ -12,10 +12,10 @@ use crate::game::Transition;
|
||||
pub use commuter::CommuterPatterns;
|
||||
pub use traffic_signals::TrafficSignalDemand;
|
||||
pub use trip_table::FinishedTripTable;
|
||||
use widgetry::{Btn, Color, EventCtx, Key, Widget};
|
||||
use widgetry::{Btn, Choice, EventCtx, Key, Panel, TextExt, Widget};
|
||||
|
||||
// Oh the dashboards melted, but we still had the radio
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
pub enum DashTab {
|
||||
FinishedTripTable,
|
||||
CancelledTripTable,
|
||||
@ -30,60 +30,52 @@ pub enum DashTab {
|
||||
|
||||
impl DashTab {
|
||||
pub fn picker(self, ctx: &EventCtx, app: &App) -> Widget {
|
||||
let mut row = Vec::new();
|
||||
for (name, tab) in vec![
|
||||
("trip table", DashTab::FinishedTripTable),
|
||||
("trip summaries", DashTab::TripSummaries),
|
||||
("parking overhead", DashTab::ParkingOverhead),
|
||||
("active traffic", DashTab::ActiveTraffic),
|
||||
("transit routes", DashTab::TransitRoutes),
|
||||
("commuter patterns", DashTab::CommuterPatterns),
|
||||
("traffic signal demand", DashTab::TrafficSignals),
|
||||
] {
|
||||
if tab == DashTab::TripSummaries && app.has_prebaked().is_none() {
|
||||
continue;
|
||||
}
|
||||
if self == tab {
|
||||
row.push(Btn::text_bg2(name).inactive(ctx));
|
||||
} else {
|
||||
row.push(Btn::text_bg2(name).build_def(ctx, None));
|
||||
}
|
||||
}
|
||||
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::custom_row(row).bg(Color::WHITE).margin_vert(16),
|
||||
Widget::row(vec![
|
||||
Widget::draw_svg(ctx, "system/assets/meters/trip_histogram.svg"),
|
||||
Widget::dropdown(
|
||||
ctx,
|
||||
"tab",
|
||||
self,
|
||||
vec![
|
||||
Choice::new("Trip Table", DashTab::FinishedTripTable),
|
||||
Choice::new("Trip Summaries", DashTab::TripSummaries),
|
||||
Choice::new("Parking Overhead", DashTab::ParkingOverhead),
|
||||
Choice::new("Active Traffic", DashTab::ActiveTraffic),
|
||||
Choice::new("Transit Routes", DashTab::TransitRoutes),
|
||||
Choice::new("Commuter Patterns", DashTab::CommuterPatterns),
|
||||
Choice::new("Traffic Signal Demand", DashTab::TrafficSignals),
|
||||
],
|
||||
),
|
||||
format!("By {}", app.primary.sim.time())
|
||||
.draw_text(ctx)
|
||||
.centered_vert(),
|
||||
Btn::plaintext("X")
|
||||
.build(ctx, "close", Key::Escape)
|
||||
.align_right(),
|
||||
])
|
||||
}
|
||||
|
||||
pub fn transition(self, ctx: &mut EventCtx, app: &mut App, action: &str) -> Transition {
|
||||
match action {
|
||||
"close" => Transition::Pop,
|
||||
"trip table" => Transition::Replace(FinishedTripTable::new(ctx, app)),
|
||||
"trip summaries" => Transition::Replace(summaries::TripSummaries::new(
|
||||
ctx,
|
||||
app,
|
||||
summaries::Filter::new(),
|
||||
)),
|
||||
"parking overhead" => {
|
||||
Transition::Replace(parking_overhead::ParkingOverhead::new(ctx, app))
|
||||
pub fn transition(
|
||||
self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
panel: &Panel,
|
||||
) -> Option<Transition> {
|
||||
let tab = panel.dropdown_value("tab");
|
||||
if tab == self {
|
||||
return None;
|
||||
}
|
||||
"active traffic" => Transition::Replace(misc::ActiveTraffic::new(ctx, app)),
|
||||
"transit routes" => Transition::Replace(misc::TransitRoutes::new(ctx, app)),
|
||||
"commuter patterns" => Transition::Replace(CommuterPatterns::new(ctx, app)),
|
||||
"traffic signal demand" => Transition::Replace(TrafficSignalDemand::new(ctx, app)),
|
||||
|
||||
// TODO Misleading. These doesn't show up under the DashTab, but we're hijacking this
|
||||
// for some of the sub-tabs.
|
||||
"finished trips" => Transition::Replace(FinishedTripTable::new(ctx, app)),
|
||||
"cancelled trips" => Transition::Replace(trip_table::CancelledTripTable::new(ctx, app)),
|
||||
"unfinished trips" => {
|
||||
Transition::Replace(trip_table::UnfinishedTripTable::new(ctx, app))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
Some(Transition::Replace(match tab {
|
||||
DashTab::FinishedTripTable => FinishedTripTable::new(ctx, app),
|
||||
DashTab::TripSummaries => {
|
||||
summaries::TripSummaries::new(ctx, app, summaries::Filter::new())
|
||||
}
|
||||
DashTab::ParkingOverhead => parking_overhead::ParkingOverhead::new(ctx, app),
|
||||
DashTab::ActiveTraffic => misc::ActiveTraffic::new(ctx, app),
|
||||
DashTab::TransitRoutes => misc::TransitRoutes::new(ctx, app),
|
||||
DashTab::CommuterPatterns => CommuterPatterns::new(ctx, app),
|
||||
DashTab::TrafficSignals => TrafficSignalDemand::new(ctx, app),
|
||||
DashTab::CancelledTripTable | DashTab::UnfinishedTripTable => unreachable!(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
@ -66,9 +66,16 @@ impl State for TripSummaries {
|
||||
Err(err) => PopupMsg::new(ctx, "Export failed", vec![err.to_string()]),
|
||||
});
|
||||
}
|
||||
x => DashTab::TripSummaries.transition(ctx, app, x),
|
||||
"close" => {
|
||||
return Transition::Pop;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Outcome::Changed => {
|
||||
if let Some(t) = DashTab::TripSummaries.transition(ctx, app, &self.panel) {
|
||||
return t;
|
||||
}
|
||||
|
||||
let mut filter = Filter {
|
||||
changes_pct: self.panel.dropdown_value("filter"),
|
||||
modes: BTreeSet::new(),
|
||||
|
@ -565,6 +565,7 @@ fn trip_category_selector(ctx: &mut EventCtx, app: &App, tab: DashTab) -> Widget
|
||||
aborted += 1;
|
||||
}
|
||||
}
|
||||
let total = finished + aborted + unfinished;
|
||||
|
||||
let btn = |dash, action, label| {
|
||||
if dash == tab {
|
||||
@ -583,7 +584,11 @@ fn trip_category_selector(ctx: &mut EventCtx, app: &App, tab: DashTab) -> Widget
|
||||
format!(
|
||||
"{} ({:.1}%) Finished Trips",
|
||||
prettyprint_usize(finished),
|
||||
(finished as f64) / ((finished + aborted + unfinished) as f64) * 100.0
|
||||
if total > 0 {
|
||||
(finished as f64) / (total as f64) * 100.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
),
|
||||
)
|
||||
.margin_right(28),
|
||||
@ -599,7 +604,11 @@ fn trip_category_selector(ctx: &mut EventCtx, app: &App, tab: DashTab) -> Widget
|
||||
format!(
|
||||
"{} ({:.1}%) Unfinished Trips",
|
||||
prettyprint_usize(unfinished),
|
||||
(unfinished as f64) / ((finished + aborted + unfinished) as f64) * 100.0
|
||||
if total > 0 {
|
||||
(unfinished as f64) / (total as f64) * 100.0
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
),
|
||||
),
|
||||
])
|
||||
@ -622,13 +631,14 @@ fn make_panel_finished_trips(
|
||||
.build(ctx)
|
||||
}
|
||||
|
||||
// Always use DashTab::FinishedTripTable, so the dropdown works
|
||||
fn make_panel_cancelled_trips(
|
||||
ctx: &mut EventCtx,
|
||||
app: &App,
|
||||
table: &Table<CancelledTrip, Filters>,
|
||||
) -> Panel {
|
||||
Panel::new(Widget::col(vec![
|
||||
DashTab::CancelledTripTable.picker(ctx, app),
|
||||
DashTab::FinishedTripTable.picker(ctx, app),
|
||||
trip_category_selector(ctx, app, DashTab::CancelledTripTable),
|
||||
table.render(ctx, app),
|
||||
Filler::square_width(ctx, 0.15)
|
||||
@ -645,7 +655,7 @@ fn make_panel_unfinished_trips(
|
||||
table: &Table<UnfinishedTrip, Filters>,
|
||||
) -> Panel {
|
||||
Panel::new(Widget::col(vec![
|
||||
DashTab::UnfinishedTripTable.picker(ctx, app),
|
||||
DashTab::FinishedTripTable.picker(ctx, app),
|
||||
trip_category_selector(ctx, app, DashTab::UnfinishedTripTable),
|
||||
table.render(ctx, app),
|
||||
Filler::square_width(ctx, 0.15)
|
||||
|
Loading…
Reference in New Issue
Block a user