mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
Clean up the trip table rectangular selection UI: #574
- explicit clear/apply buttons - show start/end filters on the trip table preview
This commit is contained in:
parent
0e86b94408
commit
3c601b50c1
@ -26,7 +26,7 @@ pub(crate) fn open_trip_transition(app: &App, idx: usize) -> Transition {
|
||||
])
|
||||
}
|
||||
|
||||
pub(crate) fn preview_trip(g: &mut GfxCtx, app: &App, panel: &Panel) {
|
||||
pub(crate) fn preview_trip(g: &mut GfxCtx, app: &App, panel: &Panel, mut batch: GeomBatch) {
|
||||
let inner_rect = panel.rect_of("preview").clone();
|
||||
let map_bounds = app.primary.map.get_bounds().clone();
|
||||
let zoom = 0.15 * g.canvas.window_width / map_bounds.width().max(map_bounds.height());
|
||||
@ -49,16 +49,16 @@ pub(crate) fn preview_trip(g: &mut GfxCtx, app: &App, panel: &Panel) {
|
||||
if let Some(x) = panel.currently_hovering() {
|
||||
if let Ok(idx) = x.parse::<usize>() {
|
||||
let trip = TripID(idx);
|
||||
preview_route(g, app, trip).draw(g);
|
||||
preview_route(g, app, trip, &mut batch);
|
||||
}
|
||||
}
|
||||
batch.draw(g);
|
||||
|
||||
g.disable_clipping();
|
||||
g.unfork();
|
||||
}
|
||||
|
||||
fn preview_route(g: &mut GfxCtx, app: &App, id: TripID) -> GeomBatch {
|
||||
let mut batch = GeomBatch::new();
|
||||
fn preview_route(g: &mut GfxCtx, app: &App, id: TripID, batch: &mut GeomBatch) {
|
||||
for p in app
|
||||
.primary
|
||||
.sim
|
||||
@ -94,6 +94,4 @@ fn preview_route(g: &mut GfxCtx, app: &App, id: TripID) -> GeomBatch {
|
||||
},
|
||||
10.0,
|
||||
));
|
||||
|
||||
batch
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
use geom::Duration;
|
||||
use sim::{TripEndpoint, TripID, TripPhaseType};
|
||||
use widgetry::table::{Col, Filter, Table};
|
||||
use widgetry::{EventCtx, Filler, GfxCtx, Line, Outcome, Panel, State, Text, Toggle, Widget};
|
||||
use widgetry::{
|
||||
EventCtx, Filler, GeomBatch, GfxCtx, Line, Outcome, Panel, State, Text, Toggle, Widget,
|
||||
};
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
use crate::sandbox::dashboards::generic_trip_table::{open_trip_transition, preview_trip};
|
||||
@ -96,7 +98,7 @@ impl State<App> for ParkingOverhead {
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
preview_trip(g, app, &self.panel);
|
||||
preview_trip(g, app, &self.panel, GeomBatch::new());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use std::rc::Rc;
|
||||
|
||||
use geom::{Polygon, Pt2D};
|
||||
use widgetry::{
|
||||
Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, TextExt,
|
||||
Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, Panel, State, Text,
|
||||
VerticalAlignment, Widget,
|
||||
};
|
||||
|
||||
@ -26,8 +26,23 @@ impl RectangularSelector {
|
||||
.into_widget(ctx),
|
||||
ctx.style().btn_close_widget(ctx),
|
||||
]),
|
||||
// TODO Key style
|
||||
"Hold control, then click and drag to draw".text_widget(ctx),
|
||||
Text::from_all(vec![
|
||||
Line("Hold "),
|
||||
Line(Key::LeftControl.describe()).fg(ctx.style().text_hotkey_color),
|
||||
Line(", then click and drag to draw"),
|
||||
])
|
||||
.into_widget(ctx),
|
||||
Widget::row(vec![
|
||||
ctx.style()
|
||||
.btn_solid_primary
|
||||
.text("Apply")
|
||||
.hotkey(Key::Enter)
|
||||
.build_def(ctx),
|
||||
ctx.style()
|
||||
.btn_solid_destructive
|
||||
.text("Clear")
|
||||
.build_def(ctx),
|
||||
]),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Top)
|
||||
.build(ctx),
|
||||
@ -62,8 +77,13 @@ impl State<App> for RectangularSelector {
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
// TODO Apply button?
|
||||
// TODO Some way to clear it
|
||||
return Transition::Pop;
|
||||
}
|
||||
"Clear" => {
|
||||
self.region.replace(None);
|
||||
return Transition::Pop;
|
||||
}
|
||||
"Apply" => {
|
||||
if let Some(rect) = self
|
||||
.corners
|
||||
.and_then(|(pt1, pt2, _)| Polygon::rectangle_two_corners(pt1, pt2))
|
||||
|
@ -5,8 +5,8 @@ use geom::{Duration, Polygon, Time};
|
||||
use sim::{TripEndpoint, TripID, TripMode};
|
||||
use widgetry::table::{Col, Filter, Table};
|
||||
use widgetry::{
|
||||
EventCtx, Filler, GfxCtx, Line, Outcome, Panel, Stash, State, TabController, Text, Toggle,
|
||||
Widget,
|
||||
Color, EventCtx, Filler, GeomBatch, GfxCtx, Line, Outcome, Panel, Stash, State, TabController,
|
||||
Text, Toggle, Widget,
|
||||
};
|
||||
|
||||
use super::generic_trip_table::{open_trip_transition, preview_trip};
|
||||
@ -22,7 +22,7 @@ pub struct TripTable {
|
||||
finished_trips_table: Table<App, FinishedTrip, Filters>,
|
||||
cancelled_trips_table: Table<App, CancelledTrip, Filters>,
|
||||
unfinished_trips_table: Table<App, UnfinishedTrip, Filters>,
|
||||
dirty: bool,
|
||||
recompute_filters: bool,
|
||||
}
|
||||
|
||||
impl TripTable {
|
||||
@ -112,7 +112,7 @@ impl TripTable {
|
||||
finished_trips_table,
|
||||
cancelled_trips_table,
|
||||
unfinished_trips_table,
|
||||
dirty: false,
|
||||
recompute_filters: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -141,15 +141,15 @@ impl State<App> for TripTable {
|
||||
} else if self.table_tabs.handle_action(ctx, &x, &mut self.panel) {
|
||||
// if true, tabs handled the action
|
||||
} else if x == "filter starts" {
|
||||
// Set the dirty bit, so we re-apply the filters when the selector state is
|
||||
// done.
|
||||
self.dirty = true;
|
||||
// Set the recompute_filters bit, so we re-apply the filters when the selector
|
||||
// state is done.
|
||||
self.recompute_filters = true;
|
||||
return Transition::Push(RectangularSelector::new(
|
||||
ctx,
|
||||
self.panel.stash("starts_in"),
|
||||
));
|
||||
} else if x == "filter ends" {
|
||||
self.dirty = true;
|
||||
self.recompute_filters = true;
|
||||
return Transition::Push(RectangularSelector::new(
|
||||
ctx,
|
||||
self.panel.stash("ends_in"),
|
||||
@ -163,13 +163,13 @@ impl State<App> for TripTable {
|
||||
return t;
|
||||
}
|
||||
|
||||
self.dirty = true;
|
||||
self.recompute_filters = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if self.dirty {
|
||||
self.dirty = false;
|
||||
if self.recompute_filters {
|
||||
self.recompute_filters = false;
|
||||
match self.table_tabs.active_tab_idx() {
|
||||
0 => {
|
||||
self.finished_trips_table.panel_changed(&self.panel);
|
||||
@ -195,7 +195,14 @@ impl State<App> for TripTable {
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
preview_trip(g, app, &self.panel);
|
||||
let mut batch = GeomBatch::new();
|
||||
if let Some(p) = self.panel.clone_stashed("starts_in") {
|
||||
batch.push(Color::RED.alpha(0.5), p);
|
||||
}
|
||||
if let Some(p) = self.panel.clone_stashed("ends_in") {
|
||||
batch.push(Color::BLUE.alpha(0.5), p);
|
||||
}
|
||||
preview_trip(g, app, &self.panel, batch);
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,20 +424,12 @@ fn make_table_finished_trips(app: &App) -> Table<App, FinishedTrip, Filters> {
|
||||
return false;
|
||||
}
|
||||
if let Some(ref polygon) = state.starts_in {
|
||||
if x.start
|
||||
.pos(x.mode, true, &app.primary.map)
|
||||
.map(|pos| !polygon.contains_pt(pos.pt(&app.primary.map)))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if !polygon.contains_pt(x.start.pt(&app.primary.map)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(ref polygon) = state.ends_in {
|
||||
if x.end
|
||||
.pos(x.mode, false, &app.primary.map)
|
||||
.map(|pos| !polygon.contains_pt(pos.pt(&app.primary.map)))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if !polygon.contains_pt(x.end.pt(&app.primary.map)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -607,20 +606,12 @@ fn make_table_cancelled_trips(app: &App) -> Table<App, CancelledTrip, Filters> {
|
||||
return false;
|
||||
}
|
||||
if let Some(ref polygon) = state.starts_in {
|
||||
if x.start
|
||||
.pos(x.mode, true, &app.primary.map)
|
||||
.map(|pos| !polygon.contains_pt(pos.pt(&app.primary.map)))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if !polygon.contains_pt(x.start.pt(&app.primary.map)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if let Some(ref polygon) = state.ends_in {
|
||||
if x.end
|
||||
.pos(x.mode, false, &app.primary.map)
|
||||
.map(|pos| !polygon.contains_pt(pos.pt(&app.primary.map)))
|
||||
.unwrap_or(true)
|
||||
{
|
||||
if !polygon.contains_pt(x.end.pt(&app.primary.map)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ impl TripEndpoint {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pos(self, mode: TripMode, from: bool, map: &Map) -> Option<Position> {
|
||||
fn pos(self, mode: TripMode, from: bool, map: &Map) -> Option<Position> {
|
||||
match mode {
|
||||
TripMode::Walk | TripMode::Transit => (if from {
|
||||
self.start_sidewalk_spot(map)
|
||||
|
Loading…
Reference in New Issue
Block a user