Lift ChooseSomething to widgetry for bus_spotting

This commit is contained in:
Dustin Carlino 2022-06-29 16:37:27 -05:00
parent 7af2c028fc
commit 6d2e5ee603
19 changed files with 108 additions and 95 deletions

View File

@ -1,6 +1,7 @@
use map_gui::tools::{draw_isochrone, ChooseSomething, ColorLegend};
use map_gui::tools::{draw_isochrone, ColorLegend};
use map_gui::ID;
use map_model::AmenityType;
use widgetry::tools::ChooseSomething;
use widgetry::{
Cached, Choice, Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Line, Panel,
SimpleState, State, TextExt, Transition, VerticalAlignment, Widget,

View File

@ -7,7 +7,7 @@ use map_gui::colors::ColorSchemeChoice;
use map_gui::load::MapLoader;
use map_gui::options::OptionsPanel;
use map_gui::render::{calculate_corners, DrawMap, DrawOptions};
use map_gui::tools::{ChooseSomething, PromptInput};
use map_gui::tools::PromptInput;
use map_gui::{AppLike, ID};
use map_model::{
osm, ControlTrafficSignal, IntersectionID, PathConstraints, Perimeter, Position, RoadID,
@ -15,7 +15,7 @@ use map_model::{
};
use sim::Sim;
use synthpop::TripEndpoint;
use widgetry::tools::PopupMsg;
use widgetry::tools::{ChooseSomething, PopupMsg};
use widgetry::{
lctrl, Cached, Choice, Color, DrawBaselayer, Drawable, EventCtx, GeomBatch, GfxCtx,
HorizontalAlignment, Key, Line, Outcome, Panel, State, Text, Toggle, UpdateType,

View File

@ -4,8 +4,9 @@
use abstutil::Timer;
use geom::{LonLat, Percent};
use map_gui::colors::ColorSchemeChoice;
use map_gui::tools::{ChooseSomething, CityPicker};
use map_gui::tools::CityPicker;
use map_gui::AppLike;
use widgetry::tools::ChooseSomething;
use widgetry::{Choice, EventCtx, Key, Line, Panel, SimpleState, State, Widget};
use crate::app::{App, Transition};

View File

@ -2,9 +2,9 @@ use serde::{Deserialize, Serialize};
use geom::{Distance, LonLat, Pt2D, Ring};
use map_gui::render::DrawOptions;
use map_gui::tools::{ChooseSomething, PromptInput};
use map_gui::tools::PromptInput;
use widgetry::mapspace::{ObjectID, World, WorldOutcome};
use widgetry::tools::Lasso;
use widgetry::tools::{ChooseSomething, Lasso};
use widgetry::{
lctrl, Choice, Color, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key,
Line, Outcome, Panel, SimpleState, State, Text, TextBox, VerticalAlignment, Widget,

View File

@ -4,11 +4,11 @@ use abstutil::{prettyprint_usize, Timer};
use geom::Speed;
use map_gui::options::OptionsPanel;
use map_gui::render::DrawMap;
use map_gui::tools::{grey_out_map, ChooseSomething, ColorLegend};
use map_gui::tools::{grey_out_map, ColorLegend};
use map_gui::ID;
use map_model::{EditCmd, IntersectionID, LaneID, MapEdits};
use widgetry::mapspace::ToggleZoomed;
use widgetry::tools::PopupMsg;
use widgetry::tools::{ChooseSomething, PopupMsg};
use widgetry::{
lctrl, Choice, Color, ControlState, EventCtx, GfxCtx, HorizontalAlignment, Image, Key, Line,
Menu, Outcome, Panel, State, Text, TextBox, TextExt, VerticalAlignment, Widget,

View File

@ -1,9 +1,9 @@
use geom::Duration;
use map_gui::tools::{ChooseSomething, FilePicker};
use map_gui::tools::FilePicker;
use map_model::{
ControlStopSign, ControlTrafficSignal, EditCmd, EditIntersection, IntersectionID, StageType,
};
use widgetry::tools::PopupMsg;
use widgetry::tools::{ChooseSomething, PopupMsg};
use widgetry::{
Choice, DrawBaselayer, EventCtx, Key, Line, Panel, SimpleState, Spinner, State, Text, TextExt,
Widget,

View File

@ -2,8 +2,8 @@ use std::collections::BTreeSet;
use abstutil::Timer;
use geom::Duration;
use map_gui::tools::ChooseSomething;
use map_model::IntersectionID;
use widgetry::tools::ChooseSomething;
use widgetry::{
Choice, EventCtx, GfxCtx, HorizontalAlignment, Key, Outcome, Panel, State, TextExt, UpdateType,
VerticalAlignment, Widget,

View File

@ -1,7 +1,7 @@
use geom::{Polygon, Pt2D};
use map_gui::tools::ChooseSomething;
use map_model::{BuildingID, IntersectionID};
use widgetry::mapspace::{ObjectID, World, WorldOutcome};
use widgetry::tools::ChooseSomething;
use widgetry::{
Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line, Outcome,
Panel, State, TextExt, VerticalAlignment, Widget,

View File

@ -4,10 +4,10 @@ use maplit::btreeset;
use abstutil::prettyprint_usize;
use geom::{Duration, Time};
use map_gui::tools::{checkbox_per_mode, grey_out_map, ChooseSomething, CityPicker};
use map_gui::tools::{checkbox_per_mode, grey_out_map, CityPicker};
use sim::SlidingWindow;
use synthpop::{ScenarioModifier, TripMode};
use widgetry::tools::{PopupMsg, URLManager};
use widgetry::tools::{ChooseSomething, PopupMsg, URLManager};
use widgetry::{
lctrl, Choice, Color, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, LinePlot, Outcome,
Panel, PlotOptions, Series, SimpleState, Slider, Spinner, State, Text, TextExt,

View File

@ -6,11 +6,11 @@ use map_gui::colors::ColorSchemeChoice;
use map_gui::load::MapLoader;
use map_gui::options::OptionsPanel;
use map_gui::render::{unzoomed_agent_radius, UnzoomedAgents};
use map_gui::tools::{ChooseSomething, Minimap, TurnExplorer};
use map_gui::tools::{Minimap, TurnExplorer};
use map_gui::{AppLike, ID};
use sim::Analytics;
use synthpop::Scenario;
use widgetry::tools::{FileLoader, FutureLoader, URLManager};
use widgetry::tools::{ChooseSomething, FileLoader, FutureLoader, URLManager};
use widgetry::{lctrl, Choice, EventCtx, GfxCtx, Key, Outcome, Panel, State, UpdateType};
pub use self::gameplay::{spawn_agents_around, GameplayMode, TutorialPointer, TutorialState};

View File

@ -5,9 +5,9 @@ use serde::{Deserialize, Serialize};
use abstio::MapName;
use abstutil::Counter;
use map_gui::tools::{ChooseSomething, PromptInput};
use map_gui::tools::PromptInput;
use map_model::PathRequest;
use widgetry::tools::PopupMsg;
use widgetry::tools::{ChooseSomething, PopupMsg};
use widgetry::{Choice, EventCtx, Key, Line, State, Widget};
use crate::partition::BlockID;

View File

@ -2,8 +2,9 @@ use std::collections::HashSet;
use abstutil::prettyprint_usize;
use geom::{ArrowCap, Circle, Distance, Duration, PolyLine, Pt2D, Time};
use map_gui::tools::{ChooseSomething, ColorLegend, Minimap, MinimapControls};
use map_gui::tools::{ColorLegend, Minimap, MinimapControls};
use map_model::BuildingID;
use widgetry::tools::ChooseSomething;
use widgetry::{
Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Image, Key, Line,
Outcome, Panel, State, Text, TextExt, UpdateType, VerticalAlignment, Widget,

View File

@ -22,7 +22,7 @@ pub use self::trip_files::{TripManagement, TripManagementState};
pub use self::turn_explorer::TurnExplorer;
pub use self::ui::{
checkbox_per_mode, cmp_count, cmp_dist, cmp_duration, color_for_mode, percentage_bar,
ChooseSomething, FilePicker, PromptInput,
FilePicker, PromptInput,
};
pub use self::waypoints::{InputWaypoints, WaypointID};
use crate::AppLike;

View File

@ -5,12 +5,13 @@ use serde::{Deserialize, Serialize};
use abstutil::Timer;
use synthpop::TripEndpoint;
use widgetry::tools::ChooseSomething;
use widgetry::{
Choice, Color, EventCtx, GfxCtx, Key, Line, Panel, SimpleState, State, Text, TextBox, TextExt,
Transition, Widget,
};
use crate::tools::{grey_out_map, ChooseSomething};
use crate::tools::grey_out_map;
use crate::AppLike;
/// Save sequences of waypoints as named trips. Basic file management -- save, load, browse. This

View File

@ -10,72 +10,13 @@ use geom::{Distance, Duration, Polygon};
use synthpop::TripMode;
use widgetry::tools::FutureLoader;
use widgetry::{
Choice, Color, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Key, Line, Menu, Outcome, Panel,
State, Text, TextBox, Toggle, Transition, Widget,
Color, DrawBaselayer, EventCtx, GeomBatch, GfxCtx, Key, Line, Outcome, Panel, State, Text,
TextBox, Toggle, Transition, Widget,
};
use crate::tools::grey_out_map;
use crate::AppLike;
/// Choose something from a menu, then feed the answer to a callback.
pub struct ChooseSomething<A: AppLike, T> {
panel: Panel,
// Wrapped in an Option so that we can consume it once
cb: Option<Box<dyn FnOnce(T, &mut EventCtx, &mut A) -> Transition<A>>>,
}
impl<A: AppLike + 'static, T: 'static> ChooseSomething<A, T> {
pub fn new_state<I: Into<String>>(
ctx: &mut EventCtx,
query: I,
choices: Vec<Choice<T>>,
cb: Box<dyn FnOnce(T, &mut EventCtx, &mut A) -> Transition<A>>,
) -> Box<dyn State<A>> {
Box::new(ChooseSomething {
panel: Panel::new_builder(Widget::col(vec![
Widget::row(vec![
Line(query).small_heading().into_widget(ctx),
ctx.style().btn_close_widget(ctx),
]),
Menu::widget(ctx, choices).named("menu"),
]))
.build(ctx),
cb: Some(cb),
})
}
}
impl<A: AppLike + 'static, T: 'static> State<A> for ChooseSomething<A, T> {
fn event(&mut self, ctx: &mut EventCtx, app: &mut A) -> Transition<A> {
match self.panel.event(ctx) {
Outcome::Clicked(x) => match x.as_ref() {
"close" => Transition::Pop,
_ => {
let data = self.panel.take_menu_choice::<T>("menu");
// If the callback doesn't replace or pop this ChooseSomething state, then
// it'll break when the user tries to interact with the menu again.
(self.cb.take().unwrap())(data, ctx, app)
}
},
_ => {
if ctx.normal_left_click() && ctx.canvas.get_cursor_in_screen_space().is_none() {
return Transition::Pop;
}
Transition::Keep
}
}
}
fn draw_baselayer(&self) -> DrawBaselayer {
DrawBaselayer::PreviousState
}
fn draw(&self, g: &mut GfxCtx, app: &A) {
grey_out_map(g, app);
self.panel.draw(g);
}
}
/// Prompt for arbitrary text input, then feed the answer to a callback.
pub struct PromptInput<A: AppLike> {
panel: Panel,

View File

@ -6,10 +6,9 @@ use futures_channel::mpsc;
use abstio::{DataPacks, Manifest, MapName};
use abstutil::prettyprint_bytes;
use widgetry::tools::{FutureLoader, PopupMsg};
use widgetry::tools::{ChooseSomething, FutureLoader, PopupMsg};
use widgetry::{EventCtx, Key, Transition};
use crate::tools::ChooseSomething;
use crate::AppLike;
// For each city, how many total bytes do the runtime files cost to download?

View File

@ -0,0 +1,62 @@
use crate::{
Choice, DrawBaselayer, EventCtx, GfxCtx, Line, Menu, Outcome, Panel, State, Transition, Widget,
};
/// Choose something from a menu, then feed the answer to a callback.
pub struct ChooseSomething<A, T> {
panel: Panel,
// Wrapped in an Option so that we can consume it once
cb: Option<Box<dyn FnOnce(T, &mut EventCtx, &mut A) -> Transition<A>>>,
}
impl<A: 'static, T: 'static> ChooseSomething<A, T> {
pub fn new_state<I: Into<String>>(
ctx: &mut EventCtx,
query: I,
choices: Vec<Choice<T>>,
cb: Box<dyn FnOnce(T, &mut EventCtx, &mut A) -> Transition<A>>,
) -> Box<dyn State<A>> {
Box::new(ChooseSomething {
panel: Panel::new_builder(Widget::col(vec![
Widget::row(vec![
Line(query).small_heading().into_widget(ctx),
ctx.style().btn_close_widget(ctx),
]),
Menu::widget(ctx, choices).named("menu"),
]))
.build(ctx),
cb: Some(cb),
})
}
}
impl<A: 'static, T: 'static> State<A> for ChooseSomething<A, T> {
fn event(&mut self, ctx: &mut EventCtx, app: &mut A) -> Transition<A> {
match self.panel.event(ctx) {
Outcome::Clicked(x) => match x.as_ref() {
"close" => Transition::Pop,
_ => {
let data = self.panel.take_menu_choice::<T>("menu");
// If the callback doesn't replace or pop this ChooseSomething state, then
// it'll break when the user tries to interact with the menu again.
(self.cb.take().unwrap())(data, ctx, app)
}
},
_ => {
if ctx.normal_left_click() && ctx.canvas.get_cursor_in_screen_space().is_none() {
return Transition::Pop;
}
Transition::Keep
}
}
}
fn draw_baselayer(&self) -> DrawBaselayer {
DrawBaselayer::PreviousState
}
fn draw(&self, g: &mut GfxCtx, _: &A) {
super::grey_out_map(g);
self.panel.draw(g);
}
}

View File

@ -1,3 +1,4 @@
mod choose_something;
mod lasso;
mod load;
mod popup;
@ -5,11 +6,15 @@ pub(crate) mod screenshot;
mod url;
pub(crate) mod warper;
pub use choose_something::ChooseSomething;
pub use lasso::{Lasso, PolyLineLasso};
pub use load::{FileLoader, FutureLoader, RawBytes};
pub use popup::PopupMsg;
pub use url::URLManager;
use crate::{Color, GfxCtx};
use geom::Polygon;
/// Store a cached key/value pair, only recalculating when the key changes.
pub struct Cached<K: PartialEq + Clone, V> {
contents: Option<(K, V)>,
@ -71,3 +76,13 @@ impl<K: PartialEq + Clone, V> Default for Cached<K, V> {
pub fn open_browser<I: AsRef<str>>(url: I) {
let _ = webbrowser::open(url.as_ref());
}
fn grey_out_map(g: &mut GfxCtx) {
// This is a copy of grey_out_map from map_gui, with no dependencies on App
g.fork_screenspace();
g.draw_polygon(
Color::BLACK.alpha(0.6),
Polygon::rectangle(g.canvas.window_width, g.canvas.window_height),
);
g.unfork();
}

View File

@ -1,8 +1,7 @@
use crate::{
hotkeys, Color, DrawBaselayer, EventCtx, GfxCtx, Key, Line, Outcome, Panel, State, Text,
Transition, Widget,
hotkeys, DrawBaselayer, EventCtx, GfxCtx, Key, Line, Outcome, Panel, State, Text, Transition,
Widget,
};
use geom::Polygon;
/// Display a message dialog.
pub struct PopupMsg {
@ -59,14 +58,7 @@ impl<A> State<A> for PopupMsg {
}
fn draw(&self, g: &mut GfxCtx, _: &A) {
// This is a copy of grey_out_map from map_gui, with no dependencies on App
g.fork_screenspace();
g.draw_polygon(
Color::BLACK.alpha(0.6),
Polygon::rectangle(g.canvas.window_width, g.canvas.window_height),
);
g.unfork();
super::grey_out_map(g);
self.panel.draw(g);
}
}