diff --git a/apps/fifteen_min/src/find_amenities.rs b/apps/fifteen_min/src/find_amenities.rs index 723f2cd5ed..e03d2e0033 100644 --- a/apps/fifteen_min/src/find_amenities.rs +++ b/apps/fifteen_min/src/find_amenities.rs @@ -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, diff --git a/apps/game/src/debug/mod.rs b/apps/game/src/debug/mod.rs index 07de2dd574..9cadd7406a 100644 --- a/apps/game/src/debug/mod.rs +++ b/apps/game/src/debug/mod.rs @@ -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, diff --git a/apps/game/src/devtools/mod.rs b/apps/game/src/devtools/mod.rs index 1698073a2f..f3ed23038f 100644 --- a/apps/game/src/devtools/mod.rs +++ b/apps/game/src/devtools/mod.rs @@ -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}; diff --git a/apps/game/src/devtools/story.rs b/apps/game/src/devtools/story.rs index 65d684b6e0..72147f090f 100644 --- a/apps/game/src/devtools/story.rs +++ b/apps/game/src/devtools/story.rs @@ -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, diff --git a/apps/game/src/edit/mod.rs b/apps/game/src/edit/mod.rs index dd0e6008ba..60644258db 100644 --- a/apps/game/src/edit/mod.rs +++ b/apps/game/src/edit/mod.rs @@ -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, diff --git a/apps/game/src/edit/traffic_signals/edits.rs b/apps/game/src/edit/traffic_signals/edits.rs index cb4e7a1e93..b4bfebc33e 100644 --- a/apps/game/src/edit/traffic_signals/edits.rs +++ b/apps/game/src/edit/traffic_signals/edits.rs @@ -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, diff --git a/apps/game/src/edit/traffic_signals/preview.rs b/apps/game/src/edit/traffic_signals/preview.rs index 602141a5f6..efdb2dedd3 100644 --- a/apps/game/src/edit/traffic_signals/preview.rs +++ b/apps/game/src/edit/traffic_signals/preview.rs @@ -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, diff --git a/apps/game/src/sandbox/gameplay/freeform/area_spawner.rs b/apps/game/src/sandbox/gameplay/freeform/area_spawner.rs index 997c84b16f..4f2e578ff2 100644 --- a/apps/game/src/sandbox/gameplay/freeform/area_spawner.rs +++ b/apps/game/src/sandbox/gameplay/freeform/area_spawner.rs @@ -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, diff --git a/apps/game/src/sandbox/gameplay/play_scenario.rs b/apps/game/src/sandbox/gameplay/play_scenario.rs index 3f392c4714..e06b8575d1 100644 --- a/apps/game/src/sandbox/gameplay/play_scenario.rs +++ b/apps/game/src/sandbox/gameplay/play_scenario.rs @@ -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, diff --git a/apps/game/src/sandbox/mod.rs b/apps/game/src/sandbox/mod.rs index 9a51550cb7..404687afa4 100644 --- a/apps/game/src/sandbox/mod.rs +++ b/apps/game/src/sandbox/mod.rs @@ -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}; diff --git a/apps/ltn/src/save/mod.rs b/apps/ltn/src/save/mod.rs index af79cd5337..136b530c81 100644 --- a/apps/ltn/src/save/mod.rs +++ b/apps/ltn/src/save/mod.rs @@ -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; diff --git a/apps/santa/src/game.rs b/apps/santa/src/game.rs index f98638d8fc..1b64a631ba 100644 --- a/apps/santa/src/game.rs +++ b/apps/santa/src/game.rs @@ -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, diff --git a/map_gui/src/tools/mod.rs b/map_gui/src/tools/mod.rs index 2a560e3512..e0b0206808 100644 --- a/map_gui/src/tools/mod.rs +++ b/map_gui/src/tools/mod.rs @@ -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; diff --git a/map_gui/src/tools/trip_files.rs b/map_gui/src/tools/trip_files.rs index f72efb0464..e4fb18cdaa 100644 --- a/map_gui/src/tools/trip_files.rs +++ b/map_gui/src/tools/trip_files.rs @@ -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 diff --git a/map_gui/src/tools/ui.rs b/map_gui/src/tools/ui.rs index eca66e7b8e..56b88abd8d 100644 --- a/map_gui/src/tools/ui.rs +++ b/map_gui/src/tools/ui.rs @@ -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 { - panel: Panel, - // Wrapped in an Option so that we can consume it once - cb: Option Transition>>, -} - -impl ChooseSomething { - pub fn new_state>( - ctx: &mut EventCtx, - query: I, - choices: Vec>, - cb: Box Transition>, - ) -> Box> { - 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 State for ChooseSomething { - fn event(&mut self, ctx: &mut EventCtx, app: &mut A) -> Transition { - match self.panel.event(ctx) { - Outcome::Clicked(x) => match x.as_ref() { - "close" => Transition::Pop, - _ => { - let data = self.panel.take_menu_choice::("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 { panel: Panel, diff --git a/map_gui/src/tools/updater.rs b/map_gui/src/tools/updater.rs index c523c7ee2d..1aed893588 100644 --- a/map_gui/src/tools/updater.rs +++ b/map_gui/src/tools/updater.rs @@ -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? diff --git a/widgetry/src/tools/choose_something.rs b/widgetry/src/tools/choose_something.rs new file mode 100644 index 0000000000..784b2e3f29 --- /dev/null +++ b/widgetry/src/tools/choose_something.rs @@ -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 { + panel: Panel, + // Wrapped in an Option so that we can consume it once + cb: Option Transition>>, +} + +impl ChooseSomething { + pub fn new_state>( + ctx: &mut EventCtx, + query: I, + choices: Vec>, + cb: Box Transition>, + ) -> Box> { + 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 State for ChooseSomething { + fn event(&mut self, ctx: &mut EventCtx, app: &mut A) -> Transition { + match self.panel.event(ctx) { + Outcome::Clicked(x) => match x.as_ref() { + "close" => Transition::Pop, + _ => { + let data = self.panel.take_menu_choice::("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); + } +} diff --git a/widgetry/src/tools/mod.rs b/widgetry/src/tools/mod.rs index 4556a8ff2f..9e0639b1da 100644 --- a/widgetry/src/tools/mod.rs +++ b/widgetry/src/tools/mod.rs @@ -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 { contents: Option<(K, V)>, @@ -71,3 +76,13 @@ impl Default for Cached { pub fn open_browser>(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(); +} diff --git a/widgetry/src/tools/popup.rs b/widgetry/src/tools/popup.rs index 86ed3d75fe..9a10136ced 100644 --- a/widgetry/src/tools/popup.rs +++ b/widgetry/src/tools/popup.rs @@ -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 State 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); } }