basic accordians for trips

This commit is contained in:
Dustin Carlino 2020-03-31 14:21:03 -07:00
parent 7be5b3f34a
commit 8ed2d596ff
4 changed files with 97 additions and 29 deletions

View File

@ -6,6 +6,7 @@ use ezgui::{Btn, Color, EventCtx, Line, Text, TextExt, Widget};
use geom::{Angle, Circle, Time};
use map_model::{BuildingID, LaneID, Traversable, SIDEWALK_THICKNESS};
use sim::{DrawPedestrianInput, PedestrianID, PersonID, TripMode, TripResult};
use std::collections::BTreeSet;
pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID) -> Vec<Widget> {
let mut rows = header(ctx, app, details, id, Tab::BldgInfo(id));
@ -104,7 +105,7 @@ pub fn people(ctx: &mut EventCtx, app: &App, details: &mut Details, id: Building
let label = format!("Person #{}", p.0);
details
.hyperlinks
.insert(label.clone(), Tab::PersonTrips(p));
.insert(label.clone(), Tab::PersonTrips(p, BTreeSet::new()));
rows.push(Widget::col(vec![
Btn::text_bg1(label).build_def(ctx, None),
if let Some((t, mode)) = next_trip {

View File

@ -19,8 +19,10 @@ use ezgui::{
};
use geom::{Circle, Distance, Duration, Time};
use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID};
use sim::{AgentID, Analytics, CarID, PedestrianID, PersonID, PersonState, TripMode, VehicleType};
use std::collections::{BTreeMap, HashMap};
use sim::{
AgentID, Analytics, CarID, PedestrianID, PersonID, PersonState, TripID, TripMode, VehicleType,
};
use std::collections::{BTreeMap, BTreeSet, HashMap};
pub struct InfoPanel {
tab: Tab,
@ -40,7 +42,7 @@ pub struct InfoPanel {
#[derive(Clone, PartialEq)]
pub enum Tab {
PersonStatus(PersonID),
PersonTrips(PersonID),
PersonTrips(PersonID, BTreeSet<TripID>),
PersonBio(PersonID),
BusStatus(CarID),
@ -100,7 +102,7 @@ impl Tab {
// TODO Temporary hack until object actions go away.
fn to_id(self, app: &App) -> Option<ID> {
match self {
Tab::PersonStatus(p) | Tab::PersonTrips(p) | Tab::PersonBio(p) => {
Tab::PersonStatus(p) | Tab::PersonTrips(p, _) | Tab::PersonBio(p) => {
match app.primary.sim.get_person(p).state {
PersonState::Inside(b) => Some(ID::Building(b)),
PersonState::Trip(t) => app
@ -177,7 +179,9 @@ impl InfoPanel {
let (mut col, main_tab) = match tab {
Tab::PersonStatus(p) => (person::status(ctx, app, &mut details, p), true),
Tab::PersonTrips(p) => (person::trips(ctx, app, &mut details, p), false),
Tab::PersonTrips(p, ref open) => {
(person::trips(ctx, app, &mut details, p, open), false)
}
Tab::PersonBio(p) => (person::bio(ctx, app, &mut details, p), false),
Tab::BusStatus(c) => (bus::bus_status(ctx, app, &mut details, c), true),
Tab::BusDelays(c) => (bus::bus_delays(ctx, app, &mut details, c), true),

View File

@ -3,7 +3,10 @@ use crate::info::{building, header_btns, make_table, make_tabs, trip, Details, T
use crate::render::Renderable;
use ezgui::{Btn, Color, EventCtx, Line, TextExt, Widget};
use map_model::Map;
use sim::{AgentID, CarID, PedestrianID, Person, PersonID, PersonState, TripResult, VehicleType};
use sim::{
AgentID, CarID, PedestrianID, Person, PersonID, PersonState, TripID, TripResult, VehicleType,
};
use std::collections::BTreeSet;
pub fn status(ctx: &mut EventCtx, app: &App, details: &mut Details, id: PersonID) -> Vec<Widget> {
let mut rows = header(ctx, app, details, id, Tab::PersonStatus(id));
@ -43,15 +46,29 @@ pub fn status(ctx: &mut EventCtx, app: &App, details: &mut Details, id: PersonID
}
}
rows.push(trip::details(ctx, app, t, details));
let mut open_trips = BTreeSet::new();
open_trips.insert(t);
rows.push(trip::details(ctx, app, t, details, id, open_trips));
}
}
rows
}
pub fn trips(ctx: &mut EventCtx, app: &App, details: &mut Details, id: PersonID) -> Vec<Widget> {
let mut rows = header(ctx, app, details, id, Tab::PersonTrips(id));
pub fn trips(
ctx: &mut EventCtx,
app: &App,
details: &mut Details,
id: PersonID,
open_trips: &BTreeSet<TripID>,
) -> Vec<Widget> {
let mut rows = header(
ctx,
app,
details,
id,
Tab::PersonTrips(id, open_trips.clone()),
);
let map = &app.primary.map;
let sim = &app.primary.sim;
@ -79,7 +96,26 @@ pub fn trips(ctx: &mut EventCtx, app: &App, details: &mut Details, id: PersonID)
}
TripResult::TripDoesntExist => unreachable!(),
}
rows.push(trip::details(ctx, app, *t, details));
if open_trips.contains(t) {
rows.push(trip::details(ctx, app, *t, details, id, open_trips.clone()));
} else {
// TODO Style wrong. Button should be the entire row.
rows.push(
Widget::row(vec![
format!("Trip #{}", t.0).draw_text(ctx),
Btn::text_fg("")
.build(ctx, format!("show Trip #{}", t.0), None)
.align_right(),
])
.outline(2.0, Color::WHITE),
);
let mut new_trips = open_trips.clone();
new_trips.insert(*t);
details.hyperlinks.insert(
format!("show Trip #{}", t.0),
Tab::PersonTrips(id, new_trips),
);
}
}
if wheres_waldo {
rows.push(current_status(ctx, person, map));
@ -182,23 +218,26 @@ pub fn parked_car(ctx: &EventCtx, app: &App, details: &mut Details, id: CarID) -
fn header(ctx: &EventCtx, app: &App, details: &mut Details, id: PersonID, tab: Tab) -> Vec<Widget> {
let mut rows = vec![];
let descr = match app.primary.sim.get_person(id).state {
let (current_trip, descr) = match app.primary.sim.get_person(id).state {
PersonState::Inside(b) => {
building::draw_occupants(details, app, b, Some(id));
"inside"
(None, "inside")
}
PersonState::Trip(t) => match app.primary.sim.trip_to_agent(t).ok() {
Some(AgentID::Pedestrian(_)) => "on foot",
Some(AgentID::Car(c)) => match c.1 {
VehicleType::Car => "in a car",
VehicleType::Bike => "on a bike",
VehicleType::Bus => unreachable!(),
PersonState::Trip(t) => (
Some(t),
match app.primary.sim.trip_to_agent(t).ok() {
Some(AgentID::Pedestrian(_)) => "on foot",
Some(AgentID::Car(c)) => match c.1 {
VehicleType::Car => "in a car",
VehicleType::Bike => "on a bike",
VehicleType::Bus => unreachable!(),
},
// TODO Really should clean up the TripModeChange issue
None => "...",
},
// TODO Really should clean up the TripModeChange issue
None => "...",
},
PersonState::OffMap => "off map",
PersonState::Limbo => "in limbo",
),
PersonState::OffMap => (None, "off map"),
PersonState::Limbo => (None, "in limbo"),
};
rows.push(Widget::row(vec![
@ -208,13 +247,17 @@ fn header(ctx: &EventCtx, app: &App, details: &mut Details, id: PersonID, tab: T
header_btns(ctx),
]));
let mut open_trips = BTreeSet::new();
if let Some(t) = current_trip {
open_trips.insert(t);
}
rows.push(make_tabs(
ctx,
&mut details.hyperlinks,
tab,
vec![
("Status", Tab::PersonStatus(id)),
("Trips", Tab::PersonTrips(id)),
("Trips", Tab::PersonTrips(id, open_trips)),
("Bio", Tab::PersonBio(id)),
],
));

View File

@ -1,16 +1,24 @@
use crate::app::App;
use crate::colors;
use crate::helpers::ID;
use crate::info::{make_table, Details};
use crate::info::{make_table, Details, Tab};
use crate::render::dashed_lines;
use ezgui::{
Btn, Color, EventCtx, GeomBatch, Line, Plot, PlotOptions, RewriteColor, Series, Text, Widget,
};
use geom::{Angle, Distance, Duration, Polygon, Pt2D, Time};
use map_model::{Map, Path, PathStep};
use sim::{TripEndpoint, TripID, TripPhaseType, TripResult};
use sim::{PersonID, TripEndpoint, TripID, TripPhaseType, TripResult};
use std::collections::BTreeSet;
pub fn details(ctx: &mut EventCtx, app: &App, trip: TripID, details: &mut Details) -> Widget {
pub fn details(
ctx: &mut EventCtx,
app: &App,
trip: TripID,
details: &mut Details,
person: PersonID,
mut open_trips: BTreeSet<TripID>,
) -> Widget {
let map = &app.primary.map;
let sim = &app.primary.sim;
let phases = sim.get_analytics().get_trip_phases(trip, map);
@ -24,7 +32,19 @@ pub fn details(ctx: &mut EventCtx, app: &App, trip: TripID, details: &mut Detail
TripResult::TripDone => ("finished", None),
TripResult::TripDoesntExist => unreachable!(),
};
let mut col = vec![Line(format!("Trip #{} ({})", trip.0, trip_status)).draw(ctx)];
let mut col = vec![Widget::row(vec![
Line(format!("Trip #{} ({})", trip.0, trip_status)).draw(ctx),
Btn::text_fg("")
.build(ctx, format!("hide Trip #{}", trip.0), None)
.align_right(),
])
.outline(2.0, Color::WHITE)];
open_trips.remove(&trip);
details.hyperlinks.insert(
format!("hide Trip #{}", trip.0),
Tab::PersonTrips(person, open_trips),
);
let mut kv = vec![
("Departure", start_time.ampm_tostring()),