mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-30 18:24:04 +03:00
Recalculate LTN impact when something changes; don't make the user figure it out
This commit is contained in:
parent
ba02ead72b
commit
fc2817670a
@ -122,11 +122,7 @@ impl State<App> for BrowseNeighborhoods {
|
||||
}
|
||||
});
|
||||
}
|
||||
"Calculate" => {
|
||||
return Transition::Push(super::impact::ShowResults::new_state(ctx, app));
|
||||
}
|
||||
"Force recalculation" => {
|
||||
app.session.impact = None;
|
||||
"Calculate" | "Show impact" => {
|
||||
return Transition::Push(super::impact::ShowResults::new_state(ctx, app));
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@ -259,6 +255,33 @@ pub enum Style {
|
||||
|
||||
fn impact_widget(ctx: &EventCtx, app: &App) -> Widget {
|
||||
let map_name = app.map.get_name();
|
||||
|
||||
if let Some(ref results) = app.session.impact {
|
||||
if &results.map == map_name {
|
||||
if results.change_key == app.session.modal_filters.change_key {
|
||||
// Nothing to calculate!
|
||||
return ctx
|
||||
.style()
|
||||
.btn_solid_primary
|
||||
.text("Show impact")
|
||||
.build_def(ctx);
|
||||
}
|
||||
// We'll need to do some pathfinding
|
||||
return Widget::col(vec![
|
||||
Text::from_multiline(vec![
|
||||
Line("Predicting impact of your proposal may take a moment."),
|
||||
Line("The application may freeze up during that time."),
|
||||
])
|
||||
.into_widget(ctx),
|
||||
ctx.style()
|
||||
.btn_solid_primary
|
||||
.text("Calculate")
|
||||
.build_def(ctx),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Starting from scratch
|
||||
let scenario_name = Scenario::default_scenario_for_map(&map_name);
|
||||
if scenario_name == "home_to_work" {
|
||||
return "This city doesn't have travel demand model data available".text_widget(ctx);
|
||||
@ -274,16 +297,9 @@ fn impact_widget(ctx: &EventCtx, app: &App) -> Widget {
|
||||
Line(format!("We need to load a {} file", size)),
|
||||
])
|
||||
.into_widget(ctx),
|
||||
Widget::row(vec![
|
||||
ctx.style()
|
||||
.btn_solid_primary
|
||||
.text("Calculate")
|
||||
.build_def(ctx),
|
||||
// TODO Bad UI! Detect edits and do this. I'm being lazy.
|
||||
ctx.style()
|
||||
.btn_solid_primary
|
||||
.text("Force recalculation")
|
||||
.build_def(ctx),
|
||||
]),
|
||||
ctx.style()
|
||||
.btn_solid_primary
|
||||
.text("Calculate")
|
||||
.build_def(ctx),
|
||||
])
|
||||
}
|
||||
|
@ -17,6 +17,8 @@ pub struct ModalFilters {
|
||||
|
||||
/// Edit history is preserved recursively
|
||||
pub previous_version: Box<Option<ModalFilters>>,
|
||||
/// This changes every time an edit occurs
|
||||
pub change_key: usize,
|
||||
}
|
||||
|
||||
/// A diagonal filter exists in an intersection. It's defined by two roads (the order is
|
||||
@ -41,6 +43,7 @@ impl ModalFilters {
|
||||
pub fn before_edit(&mut self) {
|
||||
let copy = self.clone();
|
||||
self.previous_version = Box::new(Some(copy));
|
||||
self.change_key += 1;
|
||||
}
|
||||
|
||||
/// If it's possible no edits were made, undo the previous call to `before_edit` and collapse
|
||||
@ -49,6 +52,7 @@ impl ModalFilters {
|
||||
if let Some(prev) = self.previous_version.take() {
|
||||
if self.roads == prev.roads && self.intersections == prev.intersections {
|
||||
self.previous_version = prev.previous_version;
|
||||
// Leave change_key alone for simplicity
|
||||
} else {
|
||||
// There was a real difference, keep
|
||||
self.previous_version = Box::new(Some(prev));
|
||||
|
@ -10,7 +10,7 @@ use widgetry::{
|
||||
TextExt, VerticalAlignment, Widget,
|
||||
};
|
||||
|
||||
use crate::{App, NeighborhoodID, Transition};
|
||||
use crate::{App, BrowseNeighborhoods, NeighborhoodID, Transition};
|
||||
|
||||
// TODO Configurable main road penalty, like in the pathfinding tool
|
||||
// TODO Don't allow crossing filters at all -- don't just disincentivize
|
||||
@ -18,9 +18,13 @@ use crate::{App, NeighborhoodID, Transition};
|
||||
// ... can't we just produce data of a certain shape, and have a UI pretty tuned for that?
|
||||
|
||||
pub struct Results {
|
||||
map: MapName,
|
||||
pub map: MapName,
|
||||
// This changes per map
|
||||
all_driving_trips: Vec<PathRequest>,
|
||||
|
||||
// The rest need updating when this changes
|
||||
pub change_key: usize,
|
||||
|
||||
before_world: World<Obj>,
|
||||
before_road_counts: Counter<RoadID>,
|
||||
before_intersection_counts: Counter<IntersectionID>,
|
||||
@ -63,6 +67,8 @@ impl Results {
|
||||
map: app.map.get_name().clone(),
|
||||
all_driving_trips,
|
||||
|
||||
change_key: 0,
|
||||
|
||||
before_world: World::unbounded(),
|
||||
before_road_counts: Counter::new(),
|
||||
before_intersection_counts: Counter::new(),
|
||||
@ -76,6 +82,7 @@ impl Results {
|
||||
}
|
||||
|
||||
fn recalculate_impact(&mut self, ctx: &mut EventCtx, app: &App, timer: &mut Timer) {
|
||||
self.change_key = app.session.modal_filters.change_key;
|
||||
let map = &app.map;
|
||||
|
||||
// Before the filters
|
||||
@ -297,9 +304,8 @@ pub struct ShowResults {
|
||||
}
|
||||
|
||||
impl ShowResults {
|
||||
pub fn new_state(ctx: &mut EventCtx, app: &App) -> Box<dyn State<App>> {
|
||||
pub fn new_state(ctx: &mut EventCtx, app: &mut App) -> Box<dyn State<App>> {
|
||||
let map_name = app.map.get_name().clone();
|
||||
// TODO Handle changes in the filters / partitioning too
|
||||
if app
|
||||
.session
|
||||
.impact
|
||||
@ -320,6 +326,15 @@ impl ShowResults {
|
||||
);
|
||||
}
|
||||
|
||||
if app.session.impact.as_ref().unwrap().change_key != app.session.modal_filters.change_key {
|
||||
ctx.loading_screen("recalculate impact", |ctx, timer| {
|
||||
// Avoid a double borrow
|
||||
let mut results = app.session.impact.take().unwrap();
|
||||
results.recalculate_impact(ctx, app, timer);
|
||||
app.session.impact = Some(results);
|
||||
});
|
||||
}
|
||||
|
||||
let layer = Layer::Relative;
|
||||
let panel = Panel::new_builder(Widget::col(vec![
|
||||
map_gui::tools::app_header(ctx, app, "Low traffic neighborhoods"),
|
||||
@ -374,9 +389,11 @@ impl ShowResults {
|
||||
}
|
||||
|
||||
impl SimpleState<App> for ShowResults {
|
||||
fn on_click(&mut self, _: &mut EventCtx, _: &mut App, x: &str, _: &Panel) -> Transition {
|
||||
fn on_click(&mut self, ctx: &mut EventCtx, app: &mut App, x: &str, _: &Panel) -> Transition {
|
||||
if x == "close" {
|
||||
return Transition::Pop;
|
||||
// Don't just Pop; if we updated the results, the UI won't warn the user about a slow
|
||||
// loading
|
||||
return Transition::Replace(BrowseNeighborhoods::new_state(ctx, app));
|
||||
}
|
||||
unreachable!()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user