Remember which dashboard was open, and return to it when pressing 'more

data.' This makes it slightly less jarring to click on a specific trip
in a table or matrix, then return to the dashboard. Future work will
also remember filters/pagination of individual tables, maybe! (Since the
dashboards change over time, this might be weird.)

This also required adding a proper way to pick the dashboard from two of
the full-screen map dashboards. Otherwise, somebody would pick them and
get stuck!
This commit is contained in:
Dustin Carlino 2021-07-18 14:11:12 -07:00
parent f6a94e8a58
commit 98978fa600
5 changed files with 45 additions and 32 deletions

View File

@ -22,6 +22,7 @@ use crate::challenges::HighScore;
use crate::common::Warping;
use crate::edit::apply_map_edits;
use crate::layer::Layer;
use crate::sandbox::dashboards::DashTab;
use crate::sandbox::{GameplayMode, TutorialState};
// Convenient typedef
@ -727,6 +728,7 @@ pub struct SessionState {
pub high_scores: BTreeMap<GameplayMode, Vec<HighScore>>,
pub info_panel_tab: BTreeMap<&'static str, &'static str>,
pub last_gmns_timing_csv: Option<String>,
pub dash_tab: DashTab,
}
impl SessionState {
@ -742,6 +744,7 @@ impl SessionState {
"bus" => "status",
},
last_gmns_timing_csv: None,
dash_tab: DashTab::TripTable,
}
}
}

View File

@ -14,6 +14,7 @@ use widgetry::{
use crate::app::{App, Transition};
use crate::common::{checkbox_per_mode, CommonState};
use crate::sandbox::dashboards::DashTab;
pub struct CommuterPatterns {
bldg_to_block: HashMap<BuildingID, BlockID>,
@ -335,15 +336,22 @@ impl State<App> for CommuterPatterns {
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Transition {
ctx.canvas_movement();
if let Outcome::Clicked(x) = self.panel.event(ctx) {
match x.as_ref() {
match self.panel.event(ctx) {
Outcome::Clicked(x) => match x.as_ref() {
"close" => {
app.primary.sim = app.primary.suspended_sim.take().unwrap();
return Transition::Pop;
}
_ => unreachable!(),
},
Outcome::Changed(_) => {
if let Some(tab) = DashTab::CommuterPatterns.tab_changed(app, &self.panel) {
app.primary.sim = app.primary.suspended_sim.take().unwrap();
return Transition::Replace(tab.launch(ctx, app));
}
}
_ => {}
}
let block_selection = if let Some(Some(b)) = ctx
.canvas
@ -674,12 +682,7 @@ fn partition_sidewalk_loops(app: &App) -> Vec<Loop> {
fn make_panel(ctx: &mut EventCtx, app: &App) -> Panel {
Panel::new_builder(Widget::col(vec![
Widget::row(vec![
Line("Commute map by block")
.small_heading()
.into_widget(ctx),
ctx.style().btn_close_widget(ctx),
]),
DashTab::CommuterPatterns.picker(ctx, app),
Toggle::choice(ctx, "from / to this block", "from", "to", Key::Space, true),
Toggle::switch(ctx, "include borders", None, true),
Widget::row(vec![

View File

@ -1,8 +1,7 @@
pub use commuter::CommuterPatterns;
pub use traffic_signals::TrafficSignalDemand;
pub use trip_table::TripTable;
use widgetry::{Choice, EventCtx, Image, Line, Panel, TextExt, Widget};
use widgetry::{Choice, EventCtx, Image, Line, Panel, State, TextExt, Widget};
use crate::app::App;
use crate::app::Transition;
@ -61,19 +60,9 @@ impl DashTab {
])
}
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;
}
Some(Transition::Replace(match tab {
DashTab::TripTable => Box::new(TripTable::new(ctx, app)),
pub fn launch(self, ctx: &mut EventCtx, app: &mut App) -> Box<dyn State<App>> {
match self {
DashTab::TripTable => Box::new(trip_table::TripTable::new(ctx, app)),
DashTab::TravelTimes => {
travel_times::TravelTimes::new_state(ctx, app, travel_times::Filter::new())
}
@ -84,6 +73,25 @@ impl DashTab {
DashTab::CommuterPatterns => CommuterPatterns::new_state(ctx, app),
DashTab::TrafficSignals => TrafficSignalDemand::new_state(ctx, app),
DashTab::ModeShift => mode_shift::ModeShift::new_state(ctx, app),
}))
}
}
pub fn tab_changed(self, app: &mut App, panel: &Panel) -> Option<DashTab> {
let tab: DashTab = panel.dropdown_value("tab");
if tab == self {
return None;
}
app.session.dash_tab = tab;
Some(tab)
}
pub fn transition(
self,
ctx: &mut EventCtx,
app: &mut App,
panel: &Panel,
) -> Option<Transition> {
let tab = self.tab_changed(app, panel)?;
Some(Transition::Replace(tab.launch(ctx, app)))
}
}

View File

@ -13,6 +13,7 @@ use widgetry::{
use crate::app::{App, ShowEverything, Transition};
use crate::common::CommonState;
use crate::sandbox::dashboards::DashTab;
pub struct TrafficSignalDemand {
panel: Panel,
@ -40,12 +41,7 @@ impl TrafficSignalDemand {
draw_all,
selected: None,
panel: Panel::new_builder(Widget::col(vec![
Widget::row(vec![
Line("Traffic signal demand over time")
.small_heading()
.into_widget(ctx),
ctx.style().btn_close_widget(ctx),
]),
DashTab::TrafficSignals.picker(ctx, app),
Text::from_all(vec![
Line("Press "),
Key::LeftArrow.txt(ctx),
@ -112,6 +108,10 @@ impl State<App> for TrafficSignalDemand {
_ => unreachable!(),
},
Outcome::Changed(_) => {
if let Some(tab) = DashTab::TrafficSignals.tab_changed(app, &self.panel) {
app.primary.sim = app.primary.suspended_sim.take().unwrap();
return Transition::Replace(tab.launch(ctx, app));
}
changed = true;
}
_ => {}

View File

@ -9,7 +9,6 @@ use crate::app::App;
use crate::app::Transition;
use crate::common::Warping;
use crate::layer::PickLayer;
use crate::sandbox::dashboards::TripTable;
pub struct MinimapController;
@ -94,7 +93,7 @@ impl MinimapControls<App> for MinimapController {
"change layers" => {
return Some(Transition::Push(PickLayer::pick(ctx, app)));
}
"more data" => Some(Transition::Push(Box::new(TripTable::new(ctx, app)))),
"more data" => Some(Transition::Push(app.session.dash_tab.launch(ctx, app))),
_ => unreachable!(),
}
}