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:
Dustin Carlino 2021-03-31 16:29:34 -07:00
parent 0e86b94408
commit 3c601b50c1
5 changed files with 57 additions and 46 deletions

View File

@ -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
}

View File

@ -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());
}
}

View File

@ -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))

View File

@ -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;
}
}

View File

@ -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)