Collapse a few more of the Transitions

This commit is contained in:
Dustin Carlino 2020-09-07 10:49:20 -07:00
parent 0b9b7e1a65
commit 5c6e781016
9 changed files with 178 additions and 140 deletions

View File

@ -41,18 +41,21 @@ impl State for Warping {
Transition::Keep Transition::Keep
} else { } else {
if let Some(id) = self.id.clone() { if let Some(id) = self.id.clone() {
Transition::PopWithData(Box::new(move |state, ctx, app| { Transition::Multi(vec![
// Other states pretty much don't use info panels. Transition::Pop,
if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() { Transition::ModifyState(Box::new(move |state, ctx, app| {
let mut actions = s.contextual_actions(); // Other states pretty much don't use info panels.
s.controls.common.as_mut().unwrap().launch_info_panel( if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() {
ctx, let mut actions = s.contextual_actions();
app, s.controls.common.as_mut().unwrap().launch_info_panel(
Tab::from_id(app, id), ctx,
&mut actions, app,
); Tab::from_id(app, id),
} &mut actions,
})) );
}
})),
])
} else { } else {
Transition::Pop Transition::Pop
} }
@ -178,18 +181,21 @@ fn warp_to_id(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Transitio
'R' => { 'R' => {
let r = BusRouteID(idx); let r = BusRouteID(idx);
app.primary.map.maybe_get_br(r)?; app.primary.map.maybe_get_br(r)?;
return Some(Transition::PopWithData(Box::new(move |state, ctx, app| { return Some(Transition::Multi(vec![
// Other states pretty much don't use info panels. Transition::Pop,
if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() { Transition::ModifyState(Box::new(move |state, ctx, app| {
let mut actions = s.contextual_actions(); // Other states pretty much don't use info panels.
s.controls.common.as_mut().unwrap().launch_info_panel( if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() {
ctx, let mut actions = s.contextual_actions();
app, s.controls.common.as_mut().unwrap().launch_info_panel(
Tab::BusRoute(r), ctx,
&mut actions, app,
); Tab::BusRoute(r),
} &mut actions,
}))); );
}
})),
]));
} }
'l' => ID::Lane(LaneID(idx)), 'l' => ID::Lane(LaneID(idx)),
'i' => ID::Intersection(IntersectionID(idx)), 'i' => ID::Intersection(IntersectionID(idx)),
@ -199,18 +205,21 @@ fn warp_to_id(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Transitio
'P' => { 'P' => {
let id = PersonID(idx); let id = PersonID(idx);
app.primary.sim.lookup_person(id)?; app.primary.sim.lookup_person(id)?;
return Some(Transition::PopWithData(Box::new(move |state, ctx, app| { return Some(Transition::Multi(vec![
// Other states pretty much don't use info panels. Transition::Pop,
if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() { Transition::ModifyState(Box::new(move |state, ctx, app| {
let mut actions = s.contextual_actions(); // Other states pretty much don't use info panels.
s.controls.common.as_mut().unwrap().launch_info_panel( if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() {
ctx, let mut actions = s.contextual_actions();
app, s.controls.common.as_mut().unwrap().launch_info_panel(
Tab::PersonTrips(id, BTreeMap::new()), ctx,
&mut actions, app,
); Tab::PersonTrips(id, BTreeMap::new()),
} &mut actions,
}))); );
}
})),
]));
} }
'c' => { 'c' => {
// This one gets more complicated. :) // This one gets more complicated. :)
@ -220,18 +229,21 @@ fn warp_to_id(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Transitio
't' => { 't' => {
let trip = TripID(idx); let trip = TripID(idx);
let person = app.primary.sim.trip_to_person(trip); let person = app.primary.sim.trip_to_person(trip);
return Some(Transition::PopWithData(Box::new(move |state, ctx, app| { return Some(Transition::Multi(vec![
// Other states pretty much don't use info panels. Transition::Pop,
if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() { Transition::ModifyState(Box::new(move |state, ctx, app| {
let mut actions = s.contextual_actions(); // Other states pretty much don't use info panels.
s.controls.common.as_mut().unwrap().launch_info_panel( if let Some(ref mut s) = state.downcast_mut::<SandboxMode>() {
ctx, let mut actions = s.contextual_actions();
app, s.controls.common.as_mut().unwrap().launch_info_panel(
Tab::PersonTrips(person, OpenTrip::single(trip)), ctx,
&mut actions, app,
); Tab::PersonTrips(person, OpenTrip::single(trip)),
} &mut actions,
}))); );
}
})),
]));
} }
_ => { _ => {
return None; return None;

View File

@ -410,11 +410,14 @@ fn search_osm(filter: String, ctx: &mut EventCtx, app: &mut App) -> Transition {
draw: batch.upload(ctx), draw: batch.upload(ctx),
}; };
Transition::PopWithData(Box::new(|state, ctx, _| { Transition::Multi(vec![
let mut mode = state.downcast_mut::<DebugMode>().unwrap(); Transition::Pop,
mode.search_results = Some(results); Transition::ModifyState(Box::new(|state, ctx, _| {
mode.reset_info(ctx); let mut mode = state.downcast_mut::<DebugMode>().unwrap();
})) mode.search_results = Some(results);
mode.reset_info(ctx);
})),
])
} }
struct SearchResults { struct SearchResults {
@ -496,7 +499,7 @@ impl ContextualActions for Actions {
close_info: &mut bool, close_info: &mut bool,
) -> Transition { ) -> Transition {
match (id, action.as_ref()) { match (id, action.as_ref()) {
(id, "hide this") => Transition::KeepWithData(Box::new(|state, ctx, app| { (id, "hide this") => Transition::ModifyState(Box::new(|state, ctx, app| {
let mode = state.downcast_mut::<DebugMode>().unwrap(); let mode = state.downcast_mut::<DebugMode>().unwrap();
println!("Hiding {:?}", id); println!("Hiding {:?}", id);
app.primary.current_selection = None; app.primary.current_selection = None;

View File

@ -184,13 +184,17 @@ impl State for StoryMapEditor {
ctx, ctx,
"Name this story map", "Name this story map",
Box::new(|name, _, _| { Box::new(|name, _, _| {
Transition::PopWithData(Box::new(move |state, ctx, app| { Transition::Multi(vec![
let editor = state.downcast_mut::<StoryMapEditor>().unwrap(); Transition::Pop,
editor.story.name = name; Transition::ModifyState(Box::new(move |state, ctx, app| {
editor.story.save(app); let editor =
editor.dirty = false; state.downcast_mut::<StoryMapEditor>().unwrap();
editor.redo_panel(ctx); editor.story.name = name;
})) editor.story.save(app);
editor.dirty = false;
editor.redo_panel(ctx);
})),
])
}), }),
)); ));
} else { } else {
@ -225,12 +229,15 @@ impl State for StoryMapEditor {
self.panel.rect_of("load"), self.panel.rect_of("load"),
choices, choices,
Box::new(|story, _, _| { Box::new(|story, _, _| {
Transition::PopWithData(Box::new(move |state, ctx, _| { Transition::Multi(vec![
let editor = state.downcast_mut::<StoryMapEditor>().unwrap(); Transition::Pop,
editor.story = story; Transition::ModifyState(Box::new(move |state, ctx, _| {
editor.dirty = false; let editor = state.downcast_mut::<StoryMapEditor>().unwrap();
editor.redo_panel(ctx); editor.story = story;
})) editor.dirty = false;
editor.redo_panel(ctx);
})),
])
}), }),
)); ));
} }

View File

@ -74,12 +74,15 @@ impl State for ChangeDuration {
PhaseType::Adaptive(dt) PhaseType::Adaptive(dt)
}; };
let idx = self.idx; let idx = self.idx;
return Transition::PopWithData(Box::new(move |state, ctx, app| { return Transition::Multi(vec![
let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap(); Transition::Pop,
editor.add_new_edit(ctx, app, idx, |ts| { Transition::ModifyState(Box::new(move |state, ctx, app| {
ts.stages[idx].phase_type = new_type.clone(); let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
}); editor.add_new_edit(ctx, app, idx, |ts| {
})); ts.stages[idx].phase_type = new_type.clone();
});
})),
]);
} }
_ => unreachable!(), _ => unreachable!(),
}, },
@ -145,23 +148,29 @@ pub fn edit_entire_signal(
&mut Timer::throwaway(), &mut Timer::throwaway(),
)), )),
Box::new(move |new_signal, _, _| { Box::new(move |new_signal, _, _| {
Transition::PopWithData(Box::new(move |state, ctx, app| { Transition::Multi(vec![
Transition::Pop,
Transition::ModifyState(Box::new(move |state, ctx, app| {
let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
editor.add_new_edit(ctx, app, 0, |ts| {
*ts = new_signal.clone();
});
})),
])
}),
)),
x if x == all_walk => Transition::Multi(vec![
Transition::Pop,
Transition::ModifyState(Box::new(move |state, ctx, app| {
let mut new_signal = app.primary.map.get_traffic_signal(i).clone();
if new_signal.convert_to_ped_scramble() {
let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap(); let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
editor.add_new_edit(ctx, app, 0, |ts| { editor.add_new_edit(ctx, app, 0, |ts| {
*ts = new_signal.clone(); *ts = new_signal.clone();
}); });
})) }
}), })),
)), ]),
x if x == all_walk => Transition::PopWithData(Box::new(move |state, ctx, app| {
let mut new_signal = app.primary.map.get_traffic_signal(i).clone();
if new_signal.convert_to_ped_scramble() {
let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
editor.add_new_edit(ctx, app, 0, |ts| {
*ts = new_signal.clone();
});
}
})),
x if x == stop_sign => { x if x == stop_sign => {
original.apply(app); original.apply(app);
@ -195,19 +204,22 @@ pub fn edit_entire_signal(
Transition::Multi(vec![Transition::Pop, Transition::Pop]) Transition::Multi(vec![Transition::Pop, Transition::Pop])
} }
} }
x if x == reset => Transition::PopWithData(Box::new(move |state, ctx, app| { x if x == reset => Transition::Multi(vec![
let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap(); Transition::Pop,
let new_signal = ControlTrafficSignal::get_possible_policies( Transition::ModifyState(Box::new(move |state, ctx, app| {
&app.primary.map, let editor = state.downcast_mut::<TrafficSignalEditor>().unwrap();
i, let new_signal = ControlTrafficSignal::get_possible_policies(
&mut Timer::throwaway(), &app.primary.map,
) i,
.remove(0) &mut Timer::throwaway(),
.1; )
editor.add_new_edit(ctx, app, 0, |ts| { .remove(0)
*ts = new_signal.clone(); .1;
}); editor.add_new_edit(ctx, app, 0, |ts| {
})), *ts = new_signal.clone();
});
})),
]),
_ => unreachable!(), _ => unreachable!(),
}), }),
) )

View File

@ -96,8 +96,7 @@ impl Game {
} }
true true
} }
Transition::PopWithData(cb) => { Transition::ModifyState(cb) => {
self.states.pop().unwrap().on_destroy(ctx, &mut self.app);
cb(self.states.last_mut().unwrap(), ctx, &mut self.app); cb(self.states.last_mut().unwrap(), ctx, &mut self.app);
true true
} }
@ -108,10 +107,6 @@ impl Game {
self.states.extend(new_states); self.states.extend(new_states);
true true
} }
Transition::KeepWithData(cb) => {
cb(self.states.last_mut().unwrap(), ctx, &mut self.app);
true
}
Transition::Push(state) => { Transition::Push(state) => {
self.states.push(state); self.states.push(state);
true true
@ -276,9 +271,9 @@ pub enum Transition {
KeepWithMouseover, KeepWithMouseover,
Pop, Pop,
// If a state needs to pass data back to the parent, use this. Sadly, runtime type casting. // If a state needs to pass data back to the parent, use this. Sadly, runtime type casting.
// TODO Collapse some of these cases too ModifyState(Box<dyn FnOnce(&mut Box<dyn State>, &mut EventCtx, &mut App)>),
PopWithData(Box<dyn FnOnce(&mut Box<dyn State>, &mut EventCtx, &mut App)>), // TODO This is like Replace + ModifyState, then returning a few Push's from the callback. Not
KeepWithData(Box<dyn FnOnce(&mut Box<dyn State>, &mut EventCtx, &mut App)>), // sure how to express it in terms of the others without complicating ModifyState everywhere.
ReplaceWithData( ReplaceWithData(
Box<dyn FnOnce(Box<dyn State>, &mut EventCtx, &mut App) -> Vec<Box<dyn State>>>, Box<dyn FnOnce(Box<dyn State>, &mut EventCtx, &mut App) -> Vec<Box<dyn State>>>,
), ),

View File

@ -177,16 +177,19 @@ impl State for TransitRoutes {
} }
}; };
Transition::PopWithData(Box::new(move |state, ctx, app| { Transition::Multi(vec![
let sandbox = state.downcast_mut::<SandboxMode>().unwrap(); Transition::Pop,
let mut actions = sandbox.contextual_actions(); Transition::ModifyState(Box::new(move |state, ctx, app| {
sandbox.controls.common.as_mut().unwrap().launch_info_panel( let sandbox = state.downcast_mut::<SandboxMode>().unwrap();
ctx, let mut actions = sandbox.contextual_actions();
app, sandbox.controls.common.as_mut().unwrap().launch_info_panel(
Tab::BusRoute(route), ctx,
&mut actions, app,
) Tab::BusRoute(route),
})) &mut actions,
)
})),
])
} }
fn draw_baselayer(&self) -> DrawBaselayer { fn draw_baselayer(&self) -> DrawBaselayer {

View File

@ -109,16 +109,19 @@ impl State for ParkingOverhead {
if let Ok(idx) = x.parse::<usize>() { if let Ok(idx) = x.parse::<usize>() {
let trip = TripID(idx); let trip = TripID(idx);
let person = app.primary.sim.trip_to_person(trip); let person = app.primary.sim.trip_to_person(trip);
return Transition::PopWithData(Box::new(move |state, ctx, app| { return Transition::Multi(vec![
let sandbox = state.downcast_mut::<SandboxMode>().unwrap(); Transition::Pop,
let mut actions = sandbox.contextual_actions(); Transition::ModifyState(Box::new(move |state, ctx, app| {
sandbox.controls.common.as_mut().unwrap().launch_info_panel( let sandbox = state.downcast_mut::<SandboxMode>().unwrap();
ctx, let mut actions = sandbox.contextual_actions();
app, sandbox.controls.common.as_mut().unwrap().launch_info_panel(
Tab::PersonTrips(person, OpenTrip::single(trip)), ctx,
&mut actions, app,
); Tab::PersonTrips(person, OpenTrip::single(trip)),
})); &mut actions,
);
})),
]);
} }
return DashTab::ParkingOverhead.transition(ctx, app, x); return DashTab::ParkingOverhead.transition(ctx, app, x);
} }

View File

@ -121,16 +121,19 @@ impl State for TripTable {
if let Ok(idx) = x.parse::<usize>() { if let Ok(idx) = x.parse::<usize>() {
let trip = TripID(idx); let trip = TripID(idx);
let person = app.primary.sim.trip_to_person(trip); let person = app.primary.sim.trip_to_person(trip);
return Transition::PopWithData(Box::new(move |state, ctx, app| { return Transition::Multi(vec![
let sandbox = state.downcast_mut::<SandboxMode>().unwrap(); Transition::Pop,
let mut actions = sandbox.contextual_actions(); Transition::ModifyState(Box::new(move |state, ctx, app| {
sandbox.controls.common.as_mut().unwrap().launch_info_panel( let sandbox = state.downcast_mut::<SandboxMode>().unwrap();
ctx, let mut actions = sandbox.contextual_actions();
app, sandbox.controls.common.as_mut().unwrap().launch_info_panel(
Tab::PersonTrips(person, OpenTrip::single(trip)), ctx,
&mut actions, app,
); Tab::PersonTrips(person, OpenTrip::single(trip)),
})); &mut actions,
);
})),
]);
} }
return DashTab::TripTable.transition(ctx, app, x); return DashTab::TripTable.transition(ctx, app, x);
} }

View File

@ -468,7 +468,7 @@ impl ContextualActions for Actions {
} }
(_, "follow (run the simulation)") => { (_, "follow (run the simulation)") => {
*close_panel = false; *close_panel = false;
Transition::KeepWithData(Box::new(|state, ctx, app| { Transition::ModifyState(Box::new(|state, ctx, app| {
let mode = state.downcast_mut::<SandboxMode>().unwrap(); let mode = state.downcast_mut::<SandboxMode>().unwrap();
let speed = mode.controls.speed.as_mut().unwrap(); let speed = mode.controls.speed.as_mut().unwrap();
assert!(speed.is_paused()); assert!(speed.is_paused());
@ -477,7 +477,7 @@ impl ContextualActions for Actions {
} }
(_, "unfollow (pause the simulation)") => { (_, "unfollow (pause the simulation)") => {
*close_panel = false; *close_panel = false;
Transition::KeepWithData(Box::new(|state, ctx, app| { Transition::ModifyState(Box::new(|state, ctx, app| {
let mode = state.downcast_mut::<SandboxMode>().unwrap(); let mode = state.downcast_mut::<SandboxMode>().unwrap();
let speed = mode.controls.speed.as_mut().unwrap(); let speed = mode.controls.speed.as_mut().unwrap();
assert!(!speed.is_paused()); assert!(!speed.is_paused());