New dashboard picker. #331

This commit is contained in:
Dustin Carlino 2020-09-24 10:40:18 -07:00
parent 597ef473f2
commit 119e887425
5 changed files with 96 additions and 59 deletions

View File

@ -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);
}

View File

@ -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]

View File

@ -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!(),
}))
}
}

View File

@ -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(),

View File

@ -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)