mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-28 17:04:20 +03:00
continuing with some of the harder info tabs. got everything moved over!
This commit is contained in:
parent
fff8c8ae9d
commit
49870c0f9f
@ -1,270 +0,0 @@
|
|||||||
use crate::app::App;
|
|
||||||
use crate::colors;
|
|
||||||
use crate::helpers::ID;
|
|
||||||
use crate::info::trip::trip_details;
|
|
||||||
use crate::info::{make_browser, make_table, make_tabs, person, InfoTab, TripDetails};
|
|
||||||
use crate::render::Renderable;
|
|
||||||
use ezgui::{Color, EventCtx, GeomBatch, Line, Text, Widget};
|
|
||||||
use sim::{AgentID, CarID, PedestrianID, PersonID, VehicleType};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub enum Tab {
|
|
||||||
Person(PersonID),
|
|
||||||
// The crowd could change as we go; just freeze the list.
|
|
||||||
Crowd(Vec<PedestrianID>, usize),
|
|
||||||
}
|
|
||||||
impl std::cmp::PartialEq for Tab {
|
|
||||||
fn eq(&self, other: &Tab) -> bool {
|
|
||||||
match (self, other) {
|
|
||||||
// Only one possibility per ID
|
|
||||||
(Tab::Person(_), Tab::Person(_)) => true,
|
|
||||||
(Tab::Crowd(_, _), Tab::Crowd(_, _)) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn car_info(
|
|
||||||
ctx: &mut EventCtx,
|
|
||||||
app: &App,
|
|
||||||
id: CarID,
|
|
||||||
tab: InfoTab,
|
|
||||||
header_btns: Widget,
|
|
||||||
action_btns: Vec<Widget>,
|
|
||||||
batch: &mut GeomBatch,
|
|
||||||
hyperlinks: &mut HashMap<String, (ID, InfoTab)>,
|
|
||||||
warpers: &mut HashMap<String, ID>,
|
|
||||||
) -> (Vec<Widget>, Option<TripDetails>) {
|
|
||||||
let mut rows = vec![];
|
|
||||||
|
|
||||||
let label = match id.1 {
|
|
||||||
VehicleType::Car => "Car",
|
|
||||||
VehicleType::Bike => "Bike",
|
|
||||||
VehicleType::Bus => "Bus",
|
|
||||||
};
|
|
||||||
rows.push(Widget::row(vec![
|
|
||||||
Line(format!("{} #{}", label, id.0))
|
|
||||||
.small_heading()
|
|
||||||
.draw(ctx),
|
|
||||||
header_btns,
|
|
||||||
]));
|
|
||||||
|
|
||||||
rows.push(make_tabs(ctx, hyperlinks, ID::Car(id), tab.clone(), {
|
|
||||||
let mut tabs = vec![("Info", InfoTab::Nil)];
|
|
||||||
if let Some(p) = app
|
|
||||||
.primary
|
|
||||||
.sim
|
|
||||||
.agent_to_trip(AgentID::Car(id))
|
|
||||||
.map(|t| app.primary.sim.trip_to_person(t))
|
|
||||||
{
|
|
||||||
tabs.push(("Trips", InfoTab::Agent(Tab::Person(p))));
|
|
||||||
}
|
|
||||||
tabs
|
|
||||||
}));
|
|
||||||
|
|
||||||
let mut details: Option<TripDetails> = None;
|
|
||||||
|
|
||||||
match tab {
|
|
||||||
InfoTab::Nil => {
|
|
||||||
rows.extend(action_btns);
|
|
||||||
|
|
||||||
let (kv, extra) = app.primary.sim.car_properties(id, &app.primary.map);
|
|
||||||
rows.extend(make_table(ctx, kv));
|
|
||||||
if !extra.is_empty() {
|
|
||||||
let mut txt = Text::from(Line(""));
|
|
||||||
for line in extra {
|
|
||||||
txt.add(Line(line));
|
|
||||||
}
|
|
||||||
rows.push(txt.draw(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
let trip = if id.1 == VehicleType::Bus {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
app.primary.sim.agent_to_trip(AgentID::Car(id))
|
|
||||||
};
|
|
||||||
details = trip.map(|t| {
|
|
||||||
let (more, details) = trip_details(
|
|
||||||
ctx,
|
|
||||||
app,
|
|
||||||
t,
|
|
||||||
app.primary.sim.progress_along_path(AgentID::Car(id)),
|
|
||||||
warpers,
|
|
||||||
);
|
|
||||||
rows.push(more);
|
|
||||||
details
|
|
||||||
});
|
|
||||||
}
|
|
||||||
InfoTab::Agent(Tab::Person(p)) => {
|
|
||||||
// TODO Reorganize this
|
|
||||||
rows.extend(person::info(
|
|
||||||
ctx,
|
|
||||||
app,
|
|
||||||
p,
|
|
||||||
InfoTab::Nil,
|
|
||||||
None,
|
|
||||||
Vec::new(),
|
|
||||||
hyperlinks,
|
|
||||||
warpers,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(b) = app.primary.sim.get_owner_of_car(id) {
|
|
||||||
// TODO Mention this, with a warp tool
|
|
||||||
batch.push(
|
|
||||||
app.cs
|
|
||||||
.get_def("something associated with something else", Color::PURPLE),
|
|
||||||
app.primary.draw_map.get_b(b).get_outline(&app.primary.map),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
(rows, details)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ped_info(
|
|
||||||
ctx: &mut EventCtx,
|
|
||||||
app: &App,
|
|
||||||
id: PedestrianID,
|
|
||||||
tab: InfoTab,
|
|
||||||
header_btns: Widget,
|
|
||||||
action_btns: Vec<Widget>,
|
|
||||||
hyperlinks: &mut HashMap<String, (ID, InfoTab)>,
|
|
||||||
warpers: &mut HashMap<String, ID>,
|
|
||||||
) -> (Vec<Widget>, Option<TripDetails>) {
|
|
||||||
let mut rows = vec![];
|
|
||||||
|
|
||||||
rows.push(Widget::row(vec![
|
|
||||||
Line(format!("Pedestrian #{}", id.0))
|
|
||||||
.small_heading()
|
|
||||||
.draw(ctx),
|
|
||||||
header_btns,
|
|
||||||
]));
|
|
||||||
|
|
||||||
let trip = app
|
|
||||||
.primary
|
|
||||||
.sim
|
|
||||||
.agent_to_trip(AgentID::Pedestrian(id))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
rows.push(make_tabs(
|
|
||||||
ctx,
|
|
||||||
hyperlinks,
|
|
||||||
ID::Pedestrian(id),
|
|
||||||
tab.clone(),
|
|
||||||
vec![
|
|
||||||
("Info", InfoTab::Nil),
|
|
||||||
(
|
|
||||||
"Trips",
|
|
||||||
InfoTab::Agent(Tab::Person(app.primary.sim.trip_to_person(trip))),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut details: Option<TripDetails> = None;
|
|
||||||
|
|
||||||
match tab {
|
|
||||||
InfoTab::Nil => {
|
|
||||||
rows.extend(action_btns);
|
|
||||||
|
|
||||||
let (kv, extra) = app.primary.sim.ped_properties(id, &app.primary.map);
|
|
||||||
rows.extend(make_table(ctx, kv));
|
|
||||||
if !extra.is_empty() {
|
|
||||||
let mut txt = Text::from(Line(""));
|
|
||||||
for line in extra {
|
|
||||||
txt.add(Line(line));
|
|
||||||
}
|
|
||||||
rows.push(txt.draw(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
let (more, trip_details) = trip_details(
|
|
||||||
ctx,
|
|
||||||
app,
|
|
||||||
app.primary
|
|
||||||
.sim
|
|
||||||
.agent_to_trip(AgentID::Pedestrian(id))
|
|
||||||
.unwrap(),
|
|
||||||
app.primary.sim.progress_along_path(AgentID::Pedestrian(id)),
|
|
||||||
warpers,
|
|
||||||
);
|
|
||||||
rows.push(more);
|
|
||||||
details = Some(trip_details);
|
|
||||||
}
|
|
||||||
InfoTab::Agent(Tab::Person(p)) => {
|
|
||||||
// TODO Reorganize this
|
|
||||||
rows.extend(person::info(
|
|
||||||
ctx,
|
|
||||||
app,
|
|
||||||
p,
|
|
||||||
InfoTab::Nil,
|
|
||||||
None,
|
|
||||||
Vec::new(),
|
|
||||||
hyperlinks,
|
|
||||||
warpers,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
(rows, details)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn crowd_info(
|
|
||||||
ctx: &mut EventCtx,
|
|
||||||
app: &App,
|
|
||||||
members: Vec<PedestrianID>,
|
|
||||||
mut tab: InfoTab,
|
|
||||||
header_btns: Widget,
|
|
||||||
hyperlinks: &mut HashMap<String, (ID, InfoTab)>,
|
|
||||||
warpers: &mut HashMap<String, ID>,
|
|
||||||
) -> Vec<Widget> {
|
|
||||||
let mut rows = vec![];
|
|
||||||
|
|
||||||
rows.push(Widget::row(vec![
|
|
||||||
Line("Pedestrian crowd").small_heading().draw(ctx),
|
|
||||||
header_btns,
|
|
||||||
]));
|
|
||||||
|
|
||||||
if tab == InfoTab::Nil {
|
|
||||||
tab = InfoTab::Agent(Tab::Crowd(members, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
match tab {
|
|
||||||
InfoTab::Agent(Tab::Crowd(peds, idx)) => {
|
|
||||||
let mut inner = vec![make_browser(
|
|
||||||
ctx,
|
|
||||||
hyperlinks,
|
|
||||||
"Pedestrian",
|
|
||||||
peds.len(),
|
|
||||||
idx,
|
|
||||||
|n| {
|
|
||||||
(
|
|
||||||
ID::PedCrowd(peds.clone()),
|
|
||||||
InfoTab::Agent(Tab::Crowd(peds.clone(), n)),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)];
|
|
||||||
// If we click a tab for a pedestrian, we lose the crowd. Woops?
|
|
||||||
inner.extend(
|
|
||||||
ped_info(
|
|
||||||
ctx,
|
|
||||||
app,
|
|
||||||
peds[idx],
|
|
||||||
InfoTab::Nil,
|
|
||||||
// No header buttons
|
|
||||||
Widget::nothing(),
|
|
||||||
Vec::new(),
|
|
||||||
hyperlinks,
|
|
||||||
warpers,
|
|
||||||
)
|
|
||||||
.0,
|
|
||||||
);
|
|
||||||
rows.push(Widget::col(inner).bg(colors::INNER_PANEL_BG));
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
rows
|
|
||||||
}
|
|
@ -1,51 +1,14 @@
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::helpers::ID;
|
use crate::helpers::ID;
|
||||||
use crate::info::{make_table, make_tabs, person, InfoTab};
|
use crate::info::{header_btns, make_table, make_tabs, Details, Tab};
|
||||||
use ezgui::{EventCtx, GeomBatch, Line, Text, TextExt, Widget};
|
use ezgui::{Btn, EventCtx, Line, Text, TextExt, Widget};
|
||||||
|
use geom::Time;
|
||||||
use map_model::BuildingID;
|
use map_model::BuildingID;
|
||||||
use sim::TripEndpoint;
|
use sim::{TripEndpoint, TripMode, TripResult};
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
pub enum Tab {
|
|
||||||
// If we're live updating, the people inside could change! Re-calculate constantly.
|
|
||||||
People,
|
|
||||||
Debug,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn info(
|
|
||||||
ctx: &mut EventCtx,
|
|
||||||
app: &App,
|
|
||||||
id: BuildingID,
|
|
||||||
tab: InfoTab,
|
|
||||||
header_btns: Widget,
|
|
||||||
action_btns: Vec<Widget>,
|
|
||||||
batch: &mut GeomBatch,
|
|
||||||
hyperlinks: &mut HashMap<String, (ID, InfoTab)>,
|
|
||||||
) -> Vec<Widget> {
|
|
||||||
let mut rows = vec![];
|
|
||||||
|
|
||||||
|
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));
|
||||||
let b = app.primary.map.get_b(id);
|
let b = app.primary.map.get_b(id);
|
||||||
let ppl = app.primary.sim.bldg_to_people(id);
|
|
||||||
|
|
||||||
rows.push(Widget::row(vec![
|
|
||||||
Line(format!("Building #{}", id.0))
|
|
||||||
.small_heading()
|
|
||||||
.draw(ctx),
|
|
||||||
header_btns,
|
|
||||||
]));
|
|
||||||
|
|
||||||
rows.push(make_tabs(ctx, hyperlinks, ID::Building(id), tab.clone(), {
|
|
||||||
let mut tabs = vec![("Info", InfoTab::Nil), ("Debug", InfoTab::Bldg(Tab::Debug))];
|
|
||||||
if !ppl.is_empty() {
|
|
||||||
tabs.push(("People", InfoTab::Bldg(Tab::People)));
|
|
||||||
}
|
|
||||||
tabs
|
|
||||||
}));
|
|
||||||
|
|
||||||
match tab {
|
|
||||||
InfoTab::Nil => {
|
|
||||||
rows.extend(action_btns);
|
|
||||||
|
|
||||||
let mut kv = Vec::new();
|
let mut kv = Vec::new();
|
||||||
|
|
||||||
@ -103,8 +66,14 @@ pub fn info(
|
|||||||
if !txt.is_empty() {
|
if !txt.is_empty() {
|
||||||
rows.push(txt.draw(ctx))
|
rows.push(txt.draw(ctx))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
InfoTab::Bldg(Tab::Debug) => {
|
rows
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn debug(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID) -> Vec<Widget> {
|
||||||
|
let mut rows = header(ctx, app, details, id, Tab::BldgDebug(id));
|
||||||
|
let b = app.primary.map.get_b(id);
|
||||||
|
|
||||||
rows.extend(make_table(
|
rows.extend(make_table(
|
||||||
ctx,
|
ctx,
|
||||||
vec![(
|
vec![(
|
||||||
@ -114,21 +83,84 @@ pub fn info(
|
|||||||
));
|
));
|
||||||
rows.push("Raw OpenStreetMap data".draw_text(ctx));
|
rows.push("Raw OpenStreetMap data".draw_text(ctx));
|
||||||
rows.extend(make_table(ctx, b.osm_tags.clone().into_iter().collect()));
|
rows.extend(make_table(ctx, b.osm_tags.clone().into_iter().collect()));
|
||||||
}
|
|
||||||
InfoTab::Bldg(Tab::People) => {
|
rows
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn people(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID) -> Vec<Widget> {
|
||||||
|
let mut rows = header(ctx, app, details, id, Tab::BldgPeople(id));
|
||||||
// TODO Sort/group better
|
// TODO Sort/group better
|
||||||
// Show minimal info: ID, next departure time, type of that trip
|
// Show minimal info: ID, next departure time, type of that trip
|
||||||
for person in ppl {
|
for p in app.primary.sim.bldg_to_people(id) {
|
||||||
rows.push(person::summary(ctx, app, person, hyperlinks));
|
let person = app.primary.sim.get_person(p);
|
||||||
|
|
||||||
|
let mut next_trip: Option<(Time, TripMode)> = None;
|
||||||
|
for t in &person.trips {
|
||||||
|
match app.primary.sim.trip_to_agent(*t) {
|
||||||
|
TripResult::TripNotStarted => {
|
||||||
|
let (start_time, _, _, mode) = app.primary.sim.trip_info(*t);
|
||||||
|
next_trip = Some((start_time, mode));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
TripResult::Ok(_) | TripResult::ModeChange => {
|
||||||
|
// TODO What to do here? This is meant for building callers right now
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
TripResult::TripDone => {}
|
||||||
|
TripResult::TripDoesntExist => unreachable!(),
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let label = format!("Person #{}", p.0);
|
||||||
|
details
|
||||||
|
.hyperlinks
|
||||||
|
.insert(label.clone(), Tab::PersonStatus(p));
|
||||||
|
rows.push(Widget::col(vec![
|
||||||
|
Btn::text_bg1(label).build_def(ctx, None),
|
||||||
|
if let Some((t, mode)) = next_trip {
|
||||||
|
format!("Leaving in {} to {}", t - app.primary.sim.time(), mode).draw_text(ctx)
|
||||||
|
} else {
|
||||||
|
"Staying inside".draw_text(ctx)
|
||||||
|
},
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
rows
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header(
|
||||||
|
ctx: &EventCtx,
|
||||||
|
app: &App,
|
||||||
|
details: &mut Details,
|
||||||
|
id: BuildingID,
|
||||||
|
tab: Tab,
|
||||||
|
) -> Vec<Widget> {
|
||||||
|
let mut rows = vec![];
|
||||||
|
|
||||||
|
let b = app.primary.map.get_b(id);
|
||||||
|
|
||||||
|
rows.push(Widget::row(vec![
|
||||||
|
Line(format!("Building #{}", id.0))
|
||||||
|
.small_heading()
|
||||||
|
.draw(ctx),
|
||||||
|
header_btns(ctx),
|
||||||
|
]));
|
||||||
|
|
||||||
|
rows.push(make_tabs(
|
||||||
|
ctx,
|
||||||
|
&mut details.hyperlinks,
|
||||||
|
tab,
|
||||||
|
vec![
|
||||||
|
("Info", Tab::BldgInfo(id)),
|
||||||
|
("Debug", Tab::BldgDebug(id)),
|
||||||
|
("People", Tab::BldgPeople(id)),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
|
||||||
|
// TODO On every tab?
|
||||||
for p in app.primary.sim.get_parked_cars_by_owner(id) {
|
for p in app.primary.sim.get_parked_cars_by_owner(id) {
|
||||||
batch.push(
|
let shape = app
|
||||||
app.cs.get("something associated with something else"),
|
.primary
|
||||||
app.primary
|
|
||||||
.draw_map
|
.draw_map
|
||||||
.get_obj(
|
.get_obj(
|
||||||
ID::Car(p.vehicle.id),
|
ID::Car(p.vehicle.id),
|
||||||
@ -137,7 +169,14 @@ pub fn info(
|
|||||||
ctx.prerender,
|
ctx.prerender,
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_outline(&app.primary.map),
|
.get_outline(&app.primary.map);
|
||||||
|
details.unzoomed.push(
|
||||||
|
app.cs.get("something associated with something else"),
|
||||||
|
shape.clone(),
|
||||||
|
);
|
||||||
|
details.zoomed.push(
|
||||||
|
app.cs.get("something associated with something else"),
|
||||||
|
shape,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +1,20 @@
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
|
use crate::info::{header_btns, make_table, Details};
|
||||||
use ezgui::{EventCtx, Line, Text, Widget};
|
use ezgui::{EventCtx, Line, Text, Widget};
|
||||||
use geom::Time;
|
use geom::Time;
|
||||||
use map_model::BusStopID;
|
use map_model::BusStopID;
|
||||||
use sim::CarID;
|
use sim::CarID;
|
||||||
|
|
||||||
pub fn info(
|
// TODO Needs much more work
|
||||||
ctx: &EventCtx,
|
pub fn stop(ctx: &EventCtx, app: &App, details: &mut Details, id: BusStopID) -> Vec<Widget> {
|
||||||
app: &App,
|
|
||||||
id: BusStopID,
|
|
||||||
header_btns: Widget,
|
|
||||||
action_btns: Vec<Widget>,
|
|
||||||
) -> Vec<Widget> {
|
|
||||||
let mut rows = vec![];
|
let mut rows = vec![];
|
||||||
|
|
||||||
let sim = &app.primary.sim;
|
let sim = &app.primary.sim;
|
||||||
|
|
||||||
rows.push(Widget::row(vec![
|
rows.push(Widget::row(vec![
|
||||||
Line("Bus stop").small_heading().draw(ctx),
|
Line("Bus stop").small_heading().draw(ctx),
|
||||||
header_btns,
|
header_btns(ctx),
|
||||||
]));
|
]));
|
||||||
rows.extend(action_btns);
|
|
||||||
|
|
||||||
let mut txt = Text::new();
|
let mut txt = Text::new();
|
||||||
txt.add(Line(format!(
|
txt.add(Line(format!(
|
||||||
@ -53,3 +48,25 @@ pub fn info(
|
|||||||
|
|
||||||
rows
|
rows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Likewise
|
||||||
|
pub fn bus(ctx: &EventCtx, app: &App, details: &mut Details, id: CarID) -> Vec<Widget> {
|
||||||
|
let mut rows = vec![];
|
||||||
|
|
||||||
|
rows.push(Widget::row(vec![
|
||||||
|
Line(format!("Bus #{}", id.0)).small_heading().draw(ctx),
|
||||||
|
header_btns(ctx),
|
||||||
|
]));
|
||||||
|
|
||||||
|
let (kv, extra) = app.primary.sim.car_properties(id, &app.primary.map);
|
||||||
|
rows.extend(make_table(ctx, kv));
|
||||||
|
if !extra.is_empty() {
|
||||||
|
let mut txt = Text::from(Line(""));
|
||||||
|
for line in extra {
|
||||||
|
txt.add(Line(line));
|
||||||
|
}
|
||||||
|
rows.push(txt.draw(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
rows
|
||||||
|
}
|
@ -1,9 +1,10 @@
|
|||||||
//mod building;
|
mod building;
|
||||||
//mod bus;
|
mod bus;
|
||||||
mod debug;
|
mod debug;
|
||||||
mod intersection;
|
mod intersection;
|
||||||
mod lane;
|
mod lane;
|
||||||
//mod person;
|
mod person;
|
||||||
|
mod trip;
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
@ -200,20 +201,16 @@ impl InfoPanel {
|
|||||||
}*/
|
}*/
|
||||||
|
|
||||||
let col = match tab {
|
let col = match tab {
|
||||||
/*Tab::PersonStatus(p) => person::status(ctx, app, &mut details, p),
|
Tab::PersonStatus(p) => person::status(ctx, app, &mut details, p),
|
||||||
Tab::PersonTrips(p) => person::trips(ctx, app, &mut details, p),
|
Tab::PersonTrips(p) => person::trips(ctx, app, &mut details, p),
|
||||||
Tab::PersonBio(p) => person::bio(ctx, app, &mut details, p),
|
Tab::PersonBio(p) => person::bio(ctx, app, &mut details, p),
|
||||||
|
|
||||||
Tab::Bus(c) => bus::bus(ctx, app, &mut details, c),
|
Tab::Bus(c) => bus::bus(ctx, app, &mut details, c),
|
||||||
Tab::BusStop(bs) => bus::stop(ctx, app, &mut details, bs),
|
Tab::BusStop(bs) => bus::stop(ctx, app, &mut details, bs),
|
||||||
|
|
||||||
Tab::ParkedCar(c) => person::parked_car(ctx, app, &mut details, c),
|
Tab::ParkedCar(c) => person::parked_car(ctx, app, &mut details, c),
|
||||||
|
|
||||||
Tab::BldgInfo(b) => building::info(ctx, app, &mut details, b),
|
Tab::BldgInfo(b) => building::info(ctx, app, &mut details, b),
|
||||||
Tab::BldgDebug(b) => building::debug(ctx, app, &mut details, b),
|
Tab::BldgDebug(b) => building::debug(ctx, app, &mut details, b),
|
||||||
Tab::BldgPeople(b) => building::people(ctx, app, &mut details, b),
|
Tab::BldgPeople(b) => building::people(ctx, app, &mut details, b),
|
||||||
|
Tab::Crowd(ref members) => person::crowd(ctx, app, &mut details, members),
|
||||||
Tab::Crowd(members) => person::crowd(ctx, app, &mut details, members),*/
|
|
||||||
Tab::Area(a) => debug::area(ctx, app, &mut details, a),
|
Tab::Area(a) => debug::area(ctx, app, &mut details, a),
|
||||||
Tab::ExtraShape(es) => debug::extra_shape(ctx, app, &mut details, es),
|
Tab::ExtraShape(es) => debug::extra_shape(ctx, app, &mut details, es),
|
||||||
Tab::IntersectionInfo(i) => intersection::info(ctx, app, &mut details, i),
|
Tab::IntersectionInfo(i) => intersection::info(ctx, app, &mut details, i),
|
||||||
@ -222,7 +219,6 @@ impl InfoPanel {
|
|||||||
Tab::LaneInfo(l) => lane::info(ctx, app, &mut details, l),
|
Tab::LaneInfo(l) => lane::info(ctx, app, &mut details, l),
|
||||||
Tab::LaneDebug(l) => lane::debug(ctx, app, &mut details, l),
|
Tab::LaneDebug(l) => lane::debug(ctx, app, &mut details, l),
|
||||||
Tab::LaneTraffic(l) => lane::traffic(ctx, app, &mut details, l),
|
Tab::LaneTraffic(l) => lane::traffic(ctx, app, &mut details, l),
|
||||||
_ => panic!("TODO"),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -430,35 +426,6 @@ fn make_tabs(
|
|||||||
Widget::row(row).bg(Color::WHITE)
|
Widget::row(row).bg(Color::WHITE)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_browser<F: Fn(usize) -> Tab>(
|
|
||||||
ctx: &EventCtx,
|
|
||||||
hyperlinks: &mut HashMap<String, Tab>,
|
|
||||||
noun: &str,
|
|
||||||
total: usize,
|
|
||||||
idx: usize,
|
|
||||||
make_link: F,
|
|
||||||
) -> Widget {
|
|
||||||
// TODO Keys are weird! But left/right for speed
|
|
||||||
Widget::row(vec![
|
|
||||||
if idx != 0 {
|
|
||||||
hyperlinks.insert("previous".to_string(), make_link(idx - 1));
|
|
||||||
Btn::text_fg("<").build(ctx, "previous", hotkey(Key::UpArrow))
|
|
||||||
} else {
|
|
||||||
Btn::text_fg("<").inactive(ctx)
|
|
||||||
}
|
|
||||||
.margin(5),
|
|
||||||
format!("{} {}/{}", noun, idx + 1, total).draw_text(ctx),
|
|
||||||
if idx != total - 1 {
|
|
||||||
hyperlinks.insert("next".to_string(), make_link(idx + 1));
|
|
||||||
Btn::text_fg(">").build(ctx, "next", hotkey(Key::DownArrow))
|
|
||||||
} else {
|
|
||||||
Btn::text_fg(">").inactive(ctx)
|
|
||||||
}
|
|
||||||
.margin(5),
|
|
||||||
])
|
|
||||||
.centered()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn header_btns(ctx: &EventCtx) -> Widget {
|
fn header_btns(ctx: &EventCtx) -> Widget {
|
||||||
Widget::row(vec![
|
Widget::row(vec![
|
||||||
Btn::svg_def("../data/system/assets/tools/location.svg")
|
Btn::svg_def("../data/system/assets/tools/location.svg")
|
||||||
|
@ -1,54 +1,84 @@
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::helpers::ID;
|
|
||||||
use crate::info::trip::trip_details;
|
use crate::info::trip::trip_details;
|
||||||
use crate::info::{make_table, make_tabs, InfoTab};
|
use crate::info::{header_btns, make_table, make_tabs, Details, Tab, Text};
|
||||||
use ezgui::{Btn, EventCtx, Line, TextExt, Widget};
|
use crate::render::Renderable;
|
||||||
use geom::Time;
|
use ezgui::{Btn, Color, EventCtx, Line, TextExt, Widget};
|
||||||
use map_model::Map;
|
use map_model::Map;
|
||||||
use sim::{Person, PersonID, PersonState, TripMode, TripResult};
|
use sim::{AgentID, CarID, PedestrianID, Person, PersonID, PersonState, TripResult};
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
pub fn status(ctx: &mut EventCtx, app: &App, details: &mut Details, id: PersonID) -> Vec<Widget> {
|
||||||
pub enum Tab {
|
let mut rows = header(ctx, app, details, id, Tab::PersonStatus(id));
|
||||||
Bio,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn info(
|
let map = &app.primary.map;
|
||||||
ctx: &mut EventCtx,
|
let sim = &app.primary.sim;
|
||||||
app: &App,
|
let person = sim.get_person(id);
|
||||||
id: PersonID,
|
|
||||||
tab: InfoTab,
|
|
||||||
// If None, then the panel is embedded
|
|
||||||
header_btns: Option<Widget>,
|
|
||||||
action_btns: Vec<Widget>,
|
|
||||||
hyperlinks: &mut HashMap<String, (ID, InfoTab)>,
|
|
||||||
warpers: &mut HashMap<String, ID>,
|
|
||||||
) -> Vec<Widget> {
|
|
||||||
let mut rows = vec![];
|
|
||||||
|
|
||||||
// Header
|
match sim.get_person(id).state {
|
||||||
if let Some(btns) = header_btns {
|
PersonState::Inside(b) => {
|
||||||
rows.push(Widget::row(vec![
|
// TODO hyperlink
|
||||||
Line(format!("Person #{}", id.0)).small_heading().draw(ctx),
|
rows.push(
|
||||||
btns,
|
format!("Currently inside {}", map.get_b(b).just_address(map)).draw_text(ctx),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PersonState::OffMap => {
|
||||||
|
rows.push("Currently outside the map boundaries".draw_text(ctx));
|
||||||
|
}
|
||||||
|
PersonState::Limbo => {
|
||||||
|
rows.push(
|
||||||
|
"Currently in limbo -- they broke out of the Matrix! Woops. (A bug occurred)"
|
||||||
|
.draw_text(ctx),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
PersonState::Trip(t) => {
|
||||||
|
if let Some(a) = sim.trip_to_agent(t).ok() {
|
||||||
|
rows.push(Widget::col(vec![
|
||||||
|
Line(format!("Trip #{}", t.0)).small_heading().draw(ctx),
|
||||||
|
trip_details(ctx, app, t, sim.progress_along_path(a), details),
|
||||||
]));
|
]));
|
||||||
} else {
|
|
||||||
rows.push(Line(format!("Person #{}", id.0)).small_heading().draw(ctx));
|
let (kv, extra) = match a {
|
||||||
|
AgentID::Car(c) => sim.car_properties(c, map),
|
||||||
|
AgentID::Pedestrian(p) => sim.ped_properties(p, map),
|
||||||
|
};
|
||||||
|
rows.extend(make_table(ctx, kv));
|
||||||
|
if !extra.is_empty() {
|
||||||
|
let mut txt = Text::from(Line(""));
|
||||||
|
for line in extra {
|
||||||
|
txt.add(Line(line));
|
||||||
|
}
|
||||||
|
rows.push(txt.draw(ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
rows.push(make_tabs(
|
if let AgentID::Car(c) = a {
|
||||||
ctx,
|
if let Some(b) = app.primary.sim.get_owner_of_car(c) {
|
||||||
hyperlinks,
|
// TODO Mention this, with a warp tool
|
||||||
ID::Person(id),
|
details.unzoomed.push(
|
||||||
tab.clone(),
|
app.cs
|
||||||
vec![("Trips", InfoTab::Nil), ("Bio", InfoTab::Person(Tab::Bio))],
|
.get_def("something associated with something else", Color::PURPLE),
|
||||||
));
|
app.primary.draw_map.get_b(b).get_outline(&app.primary.map),
|
||||||
|
);
|
||||||
|
details.zoomed.push(
|
||||||
|
app.cs.get("something associated with something else"),
|
||||||
|
app.primary.draw_map.get_b(b).get_outline(&app.primary.map),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO Temporary mode change, what's going on?
|
||||||
|
rows.push(Widget::col(vec![
|
||||||
|
Line(format!("Trip #{}", t.0)).small_heading().draw(ctx),
|
||||||
|
trip_details(ctx, app, t, None, details),
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
match tab {
|
rows
|
||||||
InfoTab::Nil => {
|
}
|
||||||
// TODO None of these right now
|
|
||||||
rows.extend(action_btns);
|
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));
|
||||||
|
|
||||||
let map = &app.primary.map;
|
let map = &app.primary.map;
|
||||||
let sim = &app.primary.sim;
|
let sim = &app.primary.sim;
|
||||||
@ -56,6 +86,7 @@ pub fn info(
|
|||||||
|
|
||||||
// I'm sorry for bad variable names
|
// I'm sorry for bad variable names
|
||||||
let mut wheres_waldo = true;
|
let mut wheres_waldo = true;
|
||||||
|
// TODO Classify trips as not started, ongoing, done. Don't mention current status as much?
|
||||||
for t in &person.trips {
|
for t in &person.trips {
|
||||||
match sim.trip_to_agent(*t) {
|
match sim.trip_to_agent(*t) {
|
||||||
TripResult::TripNotStarted => {
|
TripResult::TripNotStarted => {
|
||||||
@ -77,7 +108,7 @@ pub fn info(
|
|||||||
rows.push(
|
rows.push(
|
||||||
Widget::col(vec![
|
Widget::col(vec![
|
||||||
Line(format!("Trip #{}", t.0)).small_heading().draw(ctx),
|
Line(format!("Trip #{}", t.0)).small_heading().draw(ctx),
|
||||||
trip_details(ctx, app, *t, None, warpers).0,
|
trip_details(ctx, app, *t, None, details),
|
||||||
])
|
])
|
||||||
.bg(colors::SECTION_BG)
|
.bg(colors::SECTION_BG)
|
||||||
.margin(10),
|
.margin(10),
|
||||||
@ -86,8 +117,13 @@ pub fn info(
|
|||||||
if wheres_waldo {
|
if wheres_waldo {
|
||||||
rows.push(current_status(ctx, person, map));
|
rows.push(current_status(ctx, person, map));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
InfoTab::Person(Tab::Bio) => {
|
rows
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bio(ctx: &EventCtx, app: &App, details: &mut Details, id: PersonID) -> Vec<Widget> {
|
||||||
|
let mut rows = header(ctx, app, details, id, Tab::PersonBio(id));
|
||||||
|
|
||||||
// TODO A little picture
|
// TODO A little picture
|
||||||
rows.extend(make_table(
|
rows.extend(make_table(
|
||||||
ctx,
|
ctx,
|
||||||
@ -104,9 +140,83 @@ pub fn info(
|
|||||||
// - Rides a fixie
|
// - Rides a fixie
|
||||||
// - Has 17 pinky toe piercings (surprising, considering they're the state champ at
|
// - Has 17 pinky toe piercings (surprising, considering they're the state champ at
|
||||||
// barefoot marathons)
|
// barefoot marathons)
|
||||||
|
|
||||||
|
rows
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn crowd(
|
||||||
|
ctx: &EventCtx,
|
||||||
|
app: &App,
|
||||||
|
details: &mut Details,
|
||||||
|
members: &Vec<PedestrianID>,
|
||||||
|
) -> Vec<Widget> {
|
||||||
|
let mut rows = vec![];
|
||||||
|
|
||||||
|
rows.push(Widget::row(vec![
|
||||||
|
Line("Pedestrian crowd").small_heading().draw(ctx),
|
||||||
|
header_btns(ctx),
|
||||||
|
]));
|
||||||
|
|
||||||
|
for (idx, id) in members.into_iter().enumerate() {
|
||||||
|
let person = app
|
||||||
|
.primary
|
||||||
|
.sim
|
||||||
|
.agent_to_person(AgentID::Pedestrian(*id))
|
||||||
|
.unwrap();
|
||||||
|
// TODO What other info is useful to summarize?
|
||||||
|
rows.push(Widget::row(vec![
|
||||||
|
format!("{})", idx + 1).draw_text(ctx),
|
||||||
|
Btn::text_fg(format!("Person #{}", person.0)).build_def(ctx, None),
|
||||||
|
]));
|
||||||
|
details
|
||||||
|
.hyperlinks
|
||||||
|
.insert(format!("Person #{}", person.0), Tab::PersonStatus(person));
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
|
rows
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parked_car(ctx: &EventCtx, app: &App, details: &mut Details, id: CarID) -> Vec<Widget> {
|
||||||
|
let mut rows = vec![];
|
||||||
|
|
||||||
|
rows.push(Widget::row(vec![
|
||||||
|
Line(format!("Parked car #{}", id.0))
|
||||||
|
.small_heading()
|
||||||
|
.draw(ctx),
|
||||||
|
header_btns(ctx),
|
||||||
|
]));
|
||||||
|
|
||||||
|
let (kv, extra) = app.primary.sim.car_properties(id, &app.primary.map);
|
||||||
|
rows.extend(make_table(ctx, kv));
|
||||||
|
if !extra.is_empty() {
|
||||||
|
let mut txt = Text::from(Line(""));
|
||||||
|
for line in extra {
|
||||||
|
txt.add(Line(line));
|
||||||
}
|
}
|
||||||
|
rows.push(txt.draw(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
rows
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header(ctx: &EventCtx, app: &App, details: &mut Details, id: PersonID, tab: Tab) -> Vec<Widget> {
|
||||||
|
let mut rows = vec![];
|
||||||
|
|
||||||
|
rows.push(Widget::row(vec![
|
||||||
|
Line(format!("Person #{}", id.0)).small_heading().draw(ctx),
|
||||||
|
header_btns(ctx),
|
||||||
|
]));
|
||||||
|
|
||||||
|
rows.push(make_tabs(
|
||||||
|
ctx,
|
||||||
|
&mut details.hyperlinks,
|
||||||
|
tab,
|
||||||
|
vec![
|
||||||
|
("Status", Tab::PersonStatus(id)),
|
||||||
|
("Trips", Tab::PersonTrips(id)),
|
||||||
|
("Bio", Tab::PersonBio(id)),
|
||||||
|
],
|
||||||
|
));
|
||||||
|
|
||||||
rows
|
rows
|
||||||
}
|
}
|
||||||
@ -124,40 +234,3 @@ fn current_status(ctx: &EventCtx, person: &Person, map: &Map) -> Widget {
|
|||||||
.draw_text(ctx),
|
.draw_text(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn summary(
|
|
||||||
ctx: &EventCtx,
|
|
||||||
app: &App,
|
|
||||||
id: PersonID,
|
|
||||||
hyperlinks: &mut HashMap<String, (ID, InfoTab)>,
|
|
||||||
) -> Widget {
|
|
||||||
let person = app.primary.sim.get_person(id);
|
|
||||||
|
|
||||||
let mut next_trip: Option<(Time, TripMode)> = None;
|
|
||||||
for t in &person.trips {
|
|
||||||
match app.primary.sim.trip_to_agent(*t) {
|
|
||||||
TripResult::TripNotStarted => {
|
|
||||||
let (start_time, _, _, mode) = app.primary.sim.trip_info(*t);
|
|
||||||
next_trip = Some((start_time, mode));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
TripResult::Ok(_) | TripResult::ModeChange => {
|
|
||||||
// TODO What to do here? This is meant for building callers right now
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
TripResult::TripDone => {}
|
|
||||||
TripResult::TripDoesntExist => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let label = format!("Person #{}", id.0);
|
|
||||||
hyperlinks.insert(label.clone(), (ID::Person(id), InfoTab::Nil));
|
|
||||||
Widget::col(vec![
|
|
||||||
Btn::text_bg1(label).build_def(ctx, None),
|
|
||||||
if let Some((t, mode)) = next_trip {
|
|
||||||
format!("Leaving in {} to {}", t - app.primary.sim.time(), mode).draw_text(ctx)
|
|
||||||
} else {
|
|
||||||
"Staying inside".draw_text(ctx)
|
|
||||||
},
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
@ -1,97 +1,26 @@
|
|||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::colors;
|
use crate::colors;
|
||||||
use crate::helpers::ID;
|
use crate::helpers::ID;
|
||||||
use crate::info::{make_table, make_tabs, person, InfoTab, TripDetails};
|
use crate::info::{make_table, Details};
|
||||||
use crate::render::dashed_lines;
|
use crate::render::dashed_lines;
|
||||||
use ezgui::{
|
use ezgui::{
|
||||||
hotkey, Btn, Color, EventCtx, GeomBatch, Key, Line, Plot, PlotOptions, RewriteColor, Series,
|
Btn, Color, EventCtx, GeomBatch, Line, Plot, PlotOptions, RewriteColor, Series, Text, Widget,
|
||||||
Text, Widget,
|
|
||||||
};
|
};
|
||||||
use geom::{Angle, Distance, Duration, Polygon, Pt2D, Time};
|
use geom::{Angle, Distance, Duration, Polygon, Pt2D, Time};
|
||||||
use map_model::{Map, Path, PathStep};
|
use map_model::{Map, Path, PathStep};
|
||||||
use sim::{PersonID, TripEndpoint, TripID, TripPhaseType};
|
use sim::{TripEndpoint, TripID, TripPhaseType};
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
|
||||||
pub enum Tab {
|
|
||||||
Person(PersonID),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inactive_info(
|
|
||||||
ctx: &mut EventCtx,
|
|
||||||
app: &App,
|
|
||||||
id: TripID,
|
|
||||||
tab: InfoTab,
|
|
||||||
action_btns: Vec<Widget>,
|
|
||||||
hyperlinks: &mut HashMap<String, (ID, InfoTab)>,
|
|
||||||
warpers: &mut HashMap<String, ID>,
|
|
||||||
) -> (Vec<Widget>, Option<TripDetails>) {
|
|
||||||
let mut rows = vec![];
|
|
||||||
|
|
||||||
rows.push(Widget::row(vec![
|
|
||||||
Line(format!("Trip #{}", id.0)).small_heading().draw(ctx),
|
|
||||||
Btn::text_fg("X")
|
|
||||||
.build(ctx, "close info", hotkey(Key::Escape))
|
|
||||||
.align_right(),
|
|
||||||
]));
|
|
||||||
|
|
||||||
rows.push(make_tabs(
|
|
||||||
ctx,
|
|
||||||
hyperlinks,
|
|
||||||
ID::Trip(id),
|
|
||||||
tab.clone(),
|
|
||||||
vec![
|
|
||||||
("Info", InfoTab::Nil),
|
|
||||||
(
|
|
||||||
"Trips",
|
|
||||||
InfoTab::Trip(Tab::Person(app.primary.sim.trip_to_person(id))),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
));
|
|
||||||
|
|
||||||
let mut details: Option<TripDetails> = None;
|
|
||||||
|
|
||||||
match tab {
|
|
||||||
InfoTab::Nil => {
|
|
||||||
rows.extend(action_btns);
|
|
||||||
|
|
||||||
let (more, trip_details) = trip_details(ctx, app, id, None, warpers);
|
|
||||||
rows.push(more);
|
|
||||||
details = Some(trip_details);
|
|
||||||
}
|
|
||||||
InfoTab::Trip(Tab::Person(p)) => {
|
|
||||||
// TODO Hyperlink?
|
|
||||||
rows.extend(person::info(
|
|
||||||
ctx,
|
|
||||||
app,
|
|
||||||
p,
|
|
||||||
InfoTab::Nil,
|
|
||||||
None,
|
|
||||||
Vec::new(),
|
|
||||||
hyperlinks,
|
|
||||||
warpers,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
(rows, details)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn trip_details(
|
pub fn trip_details(
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
app: &App,
|
app: &App,
|
||||||
trip: TripID,
|
trip: TripID,
|
||||||
progress_along_path: Option<f64>,
|
progress_along_path: Option<f64>,
|
||||||
warpers: &mut HashMap<String, ID>,
|
details: &mut Details,
|
||||||
) -> (Widget, TripDetails) {
|
) -> Widget {
|
||||||
let map = &app.primary.map;
|
let map = &app.primary.map;
|
||||||
let phases = app.primary.sim.get_analytics().get_trip_phases(trip, map);
|
let phases = app.primary.sim.get_analytics().get_trip_phases(trip, map);
|
||||||
let (start_time, trip_start, trip_end, trip_mode) = app.primary.sim.trip_info(trip);
|
let (start_time, trip_start, trip_end, trip_mode) = app.primary.sim.trip_info(trip);
|
||||||
|
|
||||||
let mut unzoomed = GeomBatch::new();
|
|
||||||
let mut zoomed = GeomBatch::new();
|
|
||||||
|
|
||||||
if phases.is_empty() {
|
if phases.is_empty() {
|
||||||
// The trip hasn't started
|
// The trip hasn't started
|
||||||
let kv = vec![
|
let kv = vec![
|
||||||
@ -103,27 +32,22 @@ pub fn trip_details(
|
|||||||
("From", endpoint(&trip_start, map).2),
|
("From", endpoint(&trip_start, map).2),
|
||||||
("To", endpoint(&trip_end, map).2),
|
("To", endpoint(&trip_end, map).2),
|
||||||
];
|
];
|
||||||
return (
|
return Widget::col(make_table(ctx, kv));
|
||||||
Widget::col(make_table(ctx, kv)),
|
|
||||||
TripDetails {
|
|
||||||
id: trip,
|
|
||||||
unzoomed: unzoomed.upload(ctx),
|
|
||||||
zoomed: zoomed.upload(ctx),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_btn = {
|
let start_btn = {
|
||||||
let (id, center, name) = endpoint(&trip_start, map);
|
let (id, center, name) = endpoint(&trip_start, map);
|
||||||
warpers.insert(format!("jump to start of Trip #{}", trip.0), id);
|
details
|
||||||
unzoomed.add_svg(
|
.warpers
|
||||||
|
.insert(format!("jump to start of Trip #{}", trip.0), id);
|
||||||
|
details.unzoomed.add_svg(
|
||||||
ctx.prerender,
|
ctx.prerender,
|
||||||
"../data/system/assets/timeline/start_pos.svg",
|
"../data/system/assets/timeline/start_pos.svg",
|
||||||
center,
|
center,
|
||||||
1.0,
|
1.0,
|
||||||
Angle::ZERO,
|
Angle::ZERO,
|
||||||
);
|
);
|
||||||
zoomed.add_svg(
|
details.zoomed.add_svg(
|
||||||
ctx.prerender,
|
ctx.prerender,
|
||||||
"../data/system/assets/timeline/start_pos.svg",
|
"../data/system/assets/timeline/start_pos.svg",
|
||||||
center,
|
center,
|
||||||
@ -145,15 +69,17 @@ pub fn trip_details(
|
|||||||
|
|
||||||
let goal_btn = {
|
let goal_btn = {
|
||||||
let (id, center, name) = endpoint(&trip_end, map);
|
let (id, center, name) = endpoint(&trip_end, map);
|
||||||
warpers.insert(format!("jump to goal of Trip #{}", trip.0), id);
|
details
|
||||||
unzoomed.add_svg(
|
.warpers
|
||||||
|
.insert(format!("jump to goal of Trip #{}", trip.0), id);
|
||||||
|
details.unzoomed.add_svg(
|
||||||
ctx.prerender,
|
ctx.prerender,
|
||||||
"../data/system/assets/timeline/goal_pos.svg",
|
"../data/system/assets/timeline/goal_pos.svg",
|
||||||
center,
|
center,
|
||||||
1.0,
|
1.0,
|
||||||
Angle::ZERO,
|
Angle::ZERO,
|
||||||
);
|
);
|
||||||
zoomed.add_svg(
|
details.zoomed.add_svg(
|
||||||
ctx.prerender,
|
ctx.prerender,
|
||||||
"../data/system/assets/timeline/goal_pos.svg",
|
"../data/system/assets/timeline/goal_pos.svg",
|
||||||
center,
|
center,
|
||||||
@ -281,8 +207,10 @@ pub fn trip_details(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(trace) = path.trace(map, dist, None) {
|
if let Some(trace) = path.trace(map, dist, None) {
|
||||||
unzoomed.push(color, trace.make_polygons(Distance::meters(10.0)));
|
details
|
||||||
zoomed.extend(
|
.unzoomed
|
||||||
|
.push(color, trace.make_polygons(Distance::meters(10.0)));
|
||||||
|
details.zoomed.extend(
|
||||||
color,
|
color,
|
||||||
dashed_lines(
|
dashed_lines(
|
||||||
&trace,
|
&trace,
|
||||||
@ -309,14 +237,7 @@ pub fn trip_details(
|
|||||||
col.extend(make_table(ctx, kv));
|
col.extend(make_table(ctx, kv));
|
||||||
col.extend(elevation);
|
col.extend(elevation);
|
||||||
|
|
||||||
(
|
Widget::col(col)
|
||||||
Widget::col(col),
|
|
||||||
TripDetails {
|
|
||||||
id: trip,
|
|
||||||
unzoomed: unzoomed.upload(ctx),
|
|
||||||
zoomed: zoomed.upload(ctx),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_elevation(ctx: &EventCtx, color: Color, walking: bool, path: &Path, map: &Map) -> Widget {
|
fn make_elevation(ctx: &EventCtx, color: Color, walking: bool, path: &Path, map: &Map) -> Widget {
|
||||||
|
Loading…
Reference in New Issue
Block a user