mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 23:15:24 +03:00
Place layer panels and info panels in the same place, on the left side of the screen. Simplify layer code, now that we don't need to align relative to the minimap.
This commit is contained in:
parent
24a60b0b29
commit
1773782975
@ -11,14 +11,15 @@ use sim::{
|
||||
VehicleType,
|
||||
};
|
||||
use widgetry::{
|
||||
Color, ControlState, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key, Line,
|
||||
LinePlot, Outcome, Panel, PlotOptions, Series, TextExt, Toggle, VerticalAlignment, Widget,
|
||||
Color, ControlState, Drawable, EventCtx, GeomBatch, GfxCtx, Key, Line, LinePlot, Outcome,
|
||||
Panel, PlotOptions, Series, TextExt, Toggle, Widget,
|
||||
};
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
use crate::common::{color_for_agent_type, Warping};
|
||||
use crate::debug::path_counter::PathCounter;
|
||||
use crate::edit::{EditMode, RouteEditor};
|
||||
use crate::layer::PANEL_PLACEMENT;
|
||||
use crate::sandbox::{dashboards, GameplayMode, SandboxMode, TimeWarpScreen};
|
||||
|
||||
mod building;
|
||||
@ -440,10 +441,7 @@ impl InfoPanel {
|
||||
time: app.primary.sim.time(),
|
||||
is_paused: ctx_actions.is_paused(),
|
||||
panel: Panel::new(Widget::col(col).bg(app.cs.panel_bg).padding(16))
|
||||
.aligned(
|
||||
HorizontalAlignment::Percent(0.02),
|
||||
VerticalAlignment::Percent(0.2),
|
||||
)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
// TODO Some headings are too wide.. Intersection #xyz (Traffic signals)
|
||||
.exact_size_percent(30, 60)
|
||||
.build_custom(ctx),
|
||||
|
@ -1,12 +1,9 @@
|
||||
use geom::{ArrowCap, Distance, PolyLine};
|
||||
use map_gui::tools::{ColorLegend, ColorNetwork};
|
||||
use widgetry::{
|
||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Panel, Text,
|
||||
VerticalAlignment, Widget,
|
||||
};
|
||||
use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, Panel, Text, Widget};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
pub struct Elevation {
|
||||
unzoomed: Drawable,
|
||||
@ -18,8 +15,8 @@ impl Layer for Elevation {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("elevation")
|
||||
}
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut App, minimap: &Panel) -> Option<LayerOutcome> {
|
||||
Layer::simple_event(ctx, minimap, &mut self.panel)
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut App) -> Option<LayerOutcome> {
|
||||
Layer::simple_event(ctx, &mut self.panel)
|
||||
}
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
@ -96,7 +93,7 @@ impl Elevation {
|
||||
.into_widget(ctx),
|
||||
ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["flat", "steep"]),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
Elevation {
|
||||
|
@ -5,13 +5,10 @@ use serde::{Deserialize, Serialize};
|
||||
use abstutil::Timer;
|
||||
use map_model::osm::OsmID;
|
||||
use map_model::BuildingID;
|
||||
use widgetry::{
|
||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Panel, RewriteColor,
|
||||
VerticalAlignment,
|
||||
};
|
||||
use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Panel, RewriteColor};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
/// A set of buildings that the player has starred, persisted as player data.
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -63,8 +60,8 @@ impl Layer for ShowFavorites {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("favorites")
|
||||
}
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut App, minimap: &Panel) -> Option<LayerOutcome> {
|
||||
Layer::simple_event(ctx, minimap, &mut self.panel)
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut App) -> Option<LayerOutcome> {
|
||||
Layer::simple_event(ctx, &mut self.panel)
|
||||
}
|
||||
fn draw(&self, g: &mut GfxCtx, _: &App) {
|
||||
self.panel.draw(g);
|
||||
@ -89,7 +86,7 @@ impl ShowFavorites {
|
||||
}
|
||||
|
||||
let panel = Panel::new(header(ctx, "Your favorite buildings"))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
ShowFavorites {
|
||||
|
@ -6,13 +6,10 @@ use map_gui::tools::{ColorDiscrete, ColorLegend, ColorNetwork};
|
||||
use map_gui::ID;
|
||||
use map_model::{AmenityType, LaneType, PathConstraints};
|
||||
use sim::AgentType;
|
||||
use widgetry::{
|
||||
Color, Drawable, EventCtx, GfxCtx, HorizontalAlignment, Line, Panel, Text, TextExt,
|
||||
VerticalAlignment, Widget,
|
||||
};
|
||||
use widgetry::{Color, Drawable, EventCtx, GfxCtx, Line, Panel, Text, TextExt, Widget};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
pub struct BikeActivity {
|
||||
panel: Panel,
|
||||
@ -26,12 +23,7 @@ impl Layer for BikeActivity {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("cycling activity")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
let mut recalc_tooltip = false;
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = BikeActivity::new(ctx, app);
|
||||
@ -58,7 +50,7 @@ impl Layer for BikeActivity {
|
||||
self.tooltip = None;
|
||||
}
|
||||
|
||||
Layer::simple_event(ctx, minimap, &mut self.panel)
|
||||
Layer::simple_event(ctx, &mut self.panel)
|
||||
}
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
@ -156,7 +148,7 @@ impl BikeActivity {
|
||||
vec!["lowest count", "highest"],
|
||||
),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
let mut colorer = ColorNetwork::new(app);
|
||||
@ -187,8 +179,8 @@ impl Layer for Static {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some(self.name)
|
||||
}
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut App, minimap: &Panel) -> Option<LayerOutcome> {
|
||||
Layer::simple_event(ctx, minimap, &mut self.panel)
|
||||
fn event(&mut self, ctx: &mut EventCtx, _: &mut App) -> Option<LayerOutcome> {
|
||||
Layer::simple_event(ctx, &mut self.panel)
|
||||
}
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
@ -213,7 +205,7 @@ impl Static {
|
||||
) -> Static {
|
||||
let (unzoomed, zoomed, legend) = colorer.build(ctx);
|
||||
let panel = Panel::new(Widget::col(vec![header(ctx, &title), extra, legend]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
Static {
|
||||
@ -356,12 +348,7 @@ impl Layer for CongestionCaps {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("congestion caps")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
let mut recalc_tooltip = false;
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = CongestionCaps::new(ctx, app);
|
||||
@ -394,7 +381,7 @@ impl Layer for CongestionCaps {
|
||||
self.tooltip = None;
|
||||
}
|
||||
|
||||
Layer::simple_event(ctx, minimap, &mut self.panel)
|
||||
Layer::simple_event(ctx, &mut self.panel)
|
||||
}
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
@ -438,7 +425,7 @@ impl CongestionCaps {
|
||||
format!("{} roads have caps", prettyprint_usize(num_roads)).text_widget(ctx),
|
||||
ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["available", "full"]),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
let (unzoomed, zoomed) = colorer.build(ctx);
|
||||
|
@ -1,7 +1,8 @@
|
||||
use map_gui::tools::{grey_out_map, HeatmapOptions};
|
||||
use sim::AgentType;
|
||||
use widgetry::{
|
||||
DrawBaselayer, EventCtx, GfxCtx, Image, Key, Line, Outcome, Panel, State, TextExt, Widget,
|
||||
DrawBaselayer, EventCtx, GfxCtx, HorizontalAlignment, Image, Key, Line, Outcome, Panel, State,
|
||||
TextExt, VerticalAlignment, Widget,
|
||||
};
|
||||
|
||||
use crate::app::{App, Transition};
|
||||
@ -21,8 +22,7 @@ pub mod transit;
|
||||
|
||||
pub trait Layer {
|
||||
fn name(&self) -> Option<&'static str>;
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App, minimap: &Panel)
|
||||
-> Option<LayerOutcome>;
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome>;
|
||||
// Draw both controls and, if zoomed, the layer contents
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App);
|
||||
// Just draw contents and do it always
|
||||
@ -30,12 +30,7 @@ pub trait Layer {
|
||||
}
|
||||
|
||||
impl dyn Layer {
|
||||
fn simple_event(
|
||||
ctx: &mut EventCtx,
|
||||
minimap: &Panel,
|
||||
panel: &mut Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
panel.align_above(ctx, minimap);
|
||||
fn simple_event(ctx: &mut EventCtx, panel: &mut Panel) -> Option<LayerOutcome> {
|
||||
match panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => Some(LayerOutcome::Close),
|
||||
@ -58,14 +53,14 @@ pub struct PickLayer {
|
||||
}
|
||||
|
||||
impl PickLayer {
|
||||
pub fn update(ctx: &mut EventCtx, app: &mut App, minimap: &Panel) -> Option<Transition> {
|
||||
pub fn update(ctx: &mut EventCtx, app: &mut App) -> Option<Transition> {
|
||||
if app.primary.layer.is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// TODO Since the Layer is embedded in App, we have to do this slight trick
|
||||
let mut layer = app.primary.layer.take().unwrap();
|
||||
match layer.event(ctx, app, minimap) {
|
||||
match layer.event(ctx, app) {
|
||||
Some(LayerOutcome::Close) => {
|
||||
app.primary.layer = None;
|
||||
return None;
|
||||
@ -275,3 +270,8 @@ pub fn header(ctx: &mut EventCtx, name: &str) -> Widget {
|
||||
ctx.style().btn_close_widget(ctx),
|
||||
])
|
||||
}
|
||||
|
||||
pub const PANEL_PLACEMENT: (HorizontalAlignment, VerticalAlignment) = (
|
||||
HorizontalAlignment::Percent(0.02),
|
||||
VerticalAlignment::Percent(0.2),
|
||||
);
|
||||
|
@ -5,12 +5,12 @@ use geom::{Circle, Distance, Pt2D, Time};
|
||||
use map_gui::tools::{make_heatmap, HeatmapOptions};
|
||||
use sim::PersonState;
|
||||
use widgetry::{
|
||||
Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Outcome,
|
||||
Panel, Text, TextExt, Toggle, VerticalAlignment, Widget,
|
||||
Choice, Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, Outcome, Panel, Text, TextExt,
|
||||
Toggle, Widget,
|
||||
};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
// TODO Disable drawing unzoomed agents... or alternatively, implement this by asking Sim to
|
||||
// return this kind of data instead!
|
||||
@ -25,19 +25,13 @@ impl Layer for Pandemic {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("pandemic model")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
if app.primary.sim.time() != self.time {
|
||||
let mut new = Pandemic::new(ctx, app, self.opts.clone());
|
||||
new.panel.restore(ctx, &self.panel);
|
||||
*self = new;
|
||||
}
|
||||
|
||||
self.panel.align_above(ctx, minimap);
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -49,7 +43,6 @@ impl Layer for Pandemic {
|
||||
let new_opts = self.options();
|
||||
if self.opts != new_opts {
|
||||
*self = Pandemic::new(ctx, app, new_opts);
|
||||
self.panel.align_above(ctx, minimap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -234,6 +227,6 @@ fn make_controls(ctx: &mut EventCtx, app: &App, opts: &Options, legend: Option<W
|
||||
}
|
||||
|
||||
Panel::new(Widget::col(col))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx)
|
||||
}
|
||||
|
@ -8,13 +8,10 @@ use map_model::{
|
||||
BuildingID, Map, OffstreetParking, ParkingLotID, PathConstraints, PathRequest, RoadID,
|
||||
};
|
||||
use sim::{ParkingSpot, Scenario, VehicleType};
|
||||
use widgetry::{
|
||||
Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Outcome, Panel, Text, Toggle,
|
||||
VerticalAlignment, Widget,
|
||||
};
|
||||
use widgetry::{Drawable, EventCtx, GeomBatch, GfxCtx, Line, Outcome, Panel, Text, Toggle, Widget};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
pub struct Occupancy {
|
||||
time: Time,
|
||||
@ -32,12 +29,7 @@ impl Layer for Occupancy {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("parking occupancy")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = Occupancy::new(
|
||||
ctx,
|
||||
@ -50,7 +42,6 @@ impl Layer for Occupancy {
|
||||
);
|
||||
}
|
||||
|
||||
self.panel.align_above(ctx, minimap);
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -68,7 +59,6 @@ impl Layer for Occupancy {
|
||||
self.panel.is_checked("Private buildings"),
|
||||
self.panel.is_checked("Cars looking for parking"),
|
||||
);
|
||||
self.panel.align_above(ctx, minimap);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -127,7 +117,7 @@ impl Occupancy {
|
||||
])
|
||||
.into_widget(ctx),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
return Occupancy {
|
||||
time: app.primary.sim.time(),
|
||||
@ -245,7 +235,7 @@ impl Occupancy {
|
||||
),
|
||||
ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0%", "100%"]),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
let mut colorer = ColorNetwork::new(app);
|
||||
@ -322,17 +312,11 @@ impl Layer for Efficiency {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("parking efficiency")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = Efficiency::new(ctx, app);
|
||||
}
|
||||
|
||||
self.panel.align_above(ctx, minimap);
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -372,7 +356,7 @@ impl Efficiency {
|
||||
vec!["0", "3", "6", "10+"],
|
||||
),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
let map = &app.primary.map;
|
||||
|
@ -5,12 +5,11 @@ use geom::{Circle, Distance, Pt2D, Time};
|
||||
use map_gui::tools::{make_heatmap, HeatmapOptions};
|
||||
use sim::PersonState;
|
||||
use widgetry::{
|
||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Image, Line, Outcome, Panel,
|
||||
Toggle, VerticalAlignment, Widget,
|
||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, Image, Line, Outcome, Panel, Toggle, Widget,
|
||||
};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
// TODO Disable drawing unzoomed agents... or alternatively, implement this by asking Sim to
|
||||
// return this kind of data instead!
|
||||
@ -25,20 +24,13 @@ impl Layer for PopulationMap {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("population map")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
if app.primary.sim.time() != self.time {
|
||||
let mut new = PopulationMap::new(ctx, app, self.opts.clone());
|
||||
new.panel.align_above(ctx, minimap);
|
||||
new.panel.restore(ctx, &self.panel);
|
||||
*self = new;
|
||||
}
|
||||
|
||||
self.panel.align_above(ctx, minimap);
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -50,7 +42,6 @@ impl Layer for PopulationMap {
|
||||
let new_opts = self.options();
|
||||
if self.opts != new_opts {
|
||||
*self = PopulationMap::new(ctx, app, new_opts);
|
||||
self.panel.align_above(ctx, minimap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,6 +176,6 @@ fn make_controls(ctx: &mut EventCtx, app: &App, opts: &Options, legend: Option<W
|
||||
}
|
||||
|
||||
Panel::new(Widget::col(col))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx)
|
||||
}
|
||||
|
@ -10,12 +10,12 @@ use map_gui::ID;
|
||||
use map_model::{IntersectionID, Map, Traversable};
|
||||
use sim::{AgentType, VehicleType};
|
||||
use widgetry::{
|
||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Line, Outcome, Panel, Text,
|
||||
TextExt, Toggle, VerticalAlignment, Widget,
|
||||
Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, Outcome, Panel, Text, TextExt, Toggle,
|
||||
Widget,
|
||||
};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
pub struct Backpressure {
|
||||
time: Time,
|
||||
@ -28,17 +28,12 @@ impl Layer for Backpressure {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("backpressure")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = Backpressure::new(ctx, app);
|
||||
}
|
||||
|
||||
Layer::simple_event(ctx, minimap, &mut self.panel)
|
||||
Layer::simple_event(ctx, &mut self.panel)
|
||||
}
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
@ -84,7 +79,7 @@ impl Backpressure {
|
||||
vec!["lowest count", "highest"],
|
||||
),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
let mut colorer = ColorNetwork::new(app);
|
||||
@ -114,12 +109,7 @@ impl Layer for Throughput {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("throughput")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
let mut recalc_tooltip = false;
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = Throughput::new(ctx, app, self.agent_types.clone());
|
||||
@ -160,7 +150,6 @@ impl Layer for Throughput {
|
||||
self.tooltip = None;
|
||||
}
|
||||
|
||||
self.panel.align_above(ctx, minimap);
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -243,7 +232,7 @@ impl Throughput {
|
||||
.flex_wrap(ctx, Percent::int(20)),
|
||||
ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0", "highest"]),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
let mut colorer = ColorNetwork::new(app);
|
||||
@ -274,12 +263,7 @@ impl Layer for CompareThroughput {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("throughput")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
let mut recalc_tooltip = false;
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = CompareThroughput::new(ctx, app);
|
||||
@ -331,7 +315,6 @@ impl Layer for CompareThroughput {
|
||||
self.tooltip = None;
|
||||
}
|
||||
|
||||
self.panel.align_above(ctx, minimap);
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -421,7 +404,7 @@ impl CompareThroughput {
|
||||
Toggle::switch(ctx, "Compare before proposal", None, true),
|
||||
scale.make_legend(ctx, vec!["less traffic", "same", "more"]),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
let (unzoomed, zoomed) = colorer.build(ctx);
|
||||
|
||||
@ -446,17 +429,12 @@ impl Layer for TrafficJams {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("traffic jams")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = TrafficJams::new(ctx, app);
|
||||
}
|
||||
|
||||
Layer::simple_event(ctx, minimap, &mut self.panel)
|
||||
Layer::simple_event(ctx, &mut self.panel)
|
||||
}
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.panel.draw(g);
|
||||
@ -510,7 +488,7 @@ impl TrafficJams {
|
||||
.into_widget(ctx),
|
||||
format!("{} jams detected", cnt).text_widget(ctx),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
TrafficJams {
|
||||
@ -584,17 +562,11 @@ impl Layer for Delay {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("delay")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
if app.primary.sim.time() != self.time {
|
||||
*self = Delay::new(ctx, app);
|
||||
}
|
||||
|
||||
self.panel.align_above(ctx, minimap);
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -653,7 +625,7 @@ impl Delay {
|
||||
header(ctx, "Delay per agent (minutes)"),
|
||||
ColorLegend::gradient(ctx, &app.cs.good_to_bad_red, vec!["0", "5", "10", "15+"]),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx),
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
use map_gui::tools::ColorDiscrete;
|
||||
use map_model::{PathConstraints, PathStep};
|
||||
use widgetry::{
|
||||
Drawable, EventCtx, GfxCtx, HorizontalAlignment, Outcome, Panel, Toggle, VerticalAlignment,
|
||||
Widget,
|
||||
};
|
||||
use widgetry::{Drawable, EventCtx, GfxCtx, Outcome, Panel, Toggle, Widget};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::layer::{header, Layer, LayerOutcome};
|
||||
use crate::layer::{header, Layer, LayerOutcome, PANEL_PLACEMENT};
|
||||
|
||||
pub struct TransitNetwork {
|
||||
panel: Panel,
|
||||
@ -18,13 +15,7 @@ impl Layer for TransitNetwork {
|
||||
fn name(&self) -> Option<&'static str> {
|
||||
Some("transit network")
|
||||
}
|
||||
fn event(
|
||||
&mut self,
|
||||
ctx: &mut EventCtx,
|
||||
app: &mut App,
|
||||
minimap: &Panel,
|
||||
) -> Option<LayerOutcome> {
|
||||
self.panel.align_above(ctx, minimap);
|
||||
fn event(&mut self, ctx: &mut EventCtx, app: &mut App) -> Option<LayerOutcome> {
|
||||
match self.panel.event(ctx) {
|
||||
Outcome::Clicked(x) => match x.as_ref() {
|
||||
"close" => {
|
||||
@ -40,7 +31,6 @@ impl Layer for TransitNetwork {
|
||||
self.panel.is_checked("show buses"),
|
||||
self.panel.is_checked("show trains"),
|
||||
);
|
||||
self.panel.align_above(ctx, minimap);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -121,7 +111,7 @@ impl TransitNetwork {
|
||||
Toggle::switch(ctx, "show trains", None, show_trains),
|
||||
legend,
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Right, VerticalAlignment::Center)
|
||||
.aligned_pair(PANEL_PLACEMENT)
|
||||
.build(ctx);
|
||||
|
||||
TransitNetwork {
|
||||
|
@ -136,7 +136,7 @@ impl State<App> for SandboxMode {
|
||||
if let Some(t) = m.event(ctx, app) {
|
||||
return t;
|
||||
}
|
||||
if let Some(t) = PickLayer::update(ctx, app, m.get_panel()) {
|
||||
if let Some(t) = PickLayer::update(ctx, app) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
@ -454,21 +454,7 @@ impl Panel {
|
||||
pub fn align(&mut self, horiz: HorizontalAlignment, vert: VerticalAlignment) {
|
||||
self.horiz = horiz;
|
||||
self.vert = vert;
|
||||
}
|
||||
pub fn align_above(&mut self, ctx: &mut EventCtx, other: &Panel) {
|
||||
// Small padding
|
||||
self.vert = VerticalAlignment::Above(other.top_level.rect.y1 - 5.0);
|
||||
self.recompute_layout(ctx, false);
|
||||
|
||||
// Since we just moved things around, let all widgets respond to the mouse being somewhere
|
||||
ctx.no_op_event(true, |ctx| assert_eq!(self.event(ctx), Outcome::Nothing));
|
||||
}
|
||||
pub fn align_below(&mut self, ctx: &mut EventCtx, other: &Panel, pad: f64) {
|
||||
self.vert = VerticalAlignment::Below(other.top_level.rect.y2 + pad);
|
||||
self.recompute_layout(ctx, false);
|
||||
|
||||
// Since we just moved things around, let all widgets respond to the mouse being somewhere
|
||||
ctx.no_op_event(true, |ctx| assert_eq!(self.event(ctx), Outcome::Nothing));
|
||||
// TODO Recompute layout and fire no_op_event?
|
||||
}
|
||||
|
||||
/// All margins/padding/etc from the previous widget are retained. The ID is set on the new
|
||||
@ -485,7 +471,9 @@ impl Panel {
|
||||
new.layout.style = old.layout.style;
|
||||
*old = new;
|
||||
self.recompute_layout(ctx, true);
|
||||
// TODO Same no_op_event as align_above? Should we always do this in recompute_layout?
|
||||
// TODO Since we just moved things around, let all widgets respond to the mouse being
|
||||
// somewhere? Maybe always do this in recompute_layout?
|
||||
//ctx.no_op_event(true, |ctx| assert_eq!(self.event(ctx), Outcome::Nothing));
|
||||
}
|
||||
|
||||
/// Removes a widget from the panel. Does not recalculate layout!
|
||||
@ -578,6 +566,12 @@ impl PanelBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn aligned_pair(mut self, pair: (HorizontalAlignment, VerticalAlignment)) -> PanelBuilder {
|
||||
self.horiz = pair.0;
|
||||
self.vert = pair.1;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn max_size(mut self, width: Percent, height: Percent) -> PanelBuilder {
|
||||
if width == Percent::int(100) && height == Percent::int(100) {
|
||||
panic!("By default, Panels are capped at 100% of the screen. This is redundant.");
|
||||
|
Loading…
Reference in New Issue
Block a user