mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 01:15:12 +03:00
A humble start to a Percent type for #274. There are so many places to
use it; just start a few in ezgui. Also a good time to object to the API so far.
This commit is contained in:
parent
2c5bbd3e7e
commit
14c66c5528
@ -125,3 +125,4 @@ modify the mode for some people (change 50% of all driving trips between 7 and
|
||||
- https://activitysim.github.io
|
||||
- https://github.com/BayAreaMetro/travel-model-one
|
||||
- https://github.com/RSGInc/DaySim
|
||||
- https://github.com/arup-group/pam
|
||||
|
@ -69,7 +69,6 @@ data/system/maps/huge_seattle.bin,0d39e0b2ebdac0cb51b83271e6f60d75,https://www.d
|
||||
data/system/maps/krakow_center.bin,bbd3465c1942a64edbf379ba04dd6b43,https://www.dropbox.com/s/y14pywaoc1ziw1c/krakow_center.bin.zip?dl=0
|
||||
data/system/maps/lakeslice.bin,7489d94e804c43d05e63534a4e9923f0,https://www.dropbox.com/s/22ncb1qo0no2qzq/lakeslice.bin.zip?dl=0
|
||||
data/system/maps/montlake.bin,be359bd5fa0f3f90d854940fc36c4d34,https://www.dropbox.com/s/02b7ty6deae327m/montlake.bin.zip?dl=0
|
||||
data/system/maps/shinjuku.bin,181d694a813ecf5744314138f0f8459c,https://www.dropbox.com/s/j9hkfw0eprfvaut/shinjuku.bin.zip?dl=0
|
||||
data/system/maps/south_seattle.bin,87815aaddcc294c0cd30f0b7db97d0d4,https://www.dropbox.com/s/fqg4roo7jqib8fb/south_seattle.bin.zip?dl=0
|
||||
data/system/maps/udistrict.bin,ae9163526dcd1b4f15d4cee2b3a2f91f,https://www.dropbox.com/s/hb6yxpvkums7mtt/udistrict.bin.zip?dl=0
|
||||
data/system/maps/west_seattle.bin,d91214290adac1f8d8db63f6d680f2d1,https://www.dropbox.com/s/qk0kxreqjpoghwh/west_seattle.bin.zip?dl=0
|
||||
|
@ -10,7 +10,7 @@ use ezgui::{
|
||||
HorizontalAlignment, Key, Line, LinePlot, Outcome, PlotOptions, Series, Text, TextExt,
|
||||
UpdateType, VerticalAlignment, Widget, GUI,
|
||||
};
|
||||
use geom::{Angle, Duration, Polygon, Pt2D, Time};
|
||||
use geom::{Angle, Duration, Percent, Polygon, Pt2D, Time};
|
||||
use rand::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use std::collections::HashSet;
|
||||
@ -100,7 +100,7 @@ impl App {
|
||||
]))
|
||||
// Don't let the panel exceed this percentage of the window. Scrollbars appear
|
||||
// automatically if needed.
|
||||
.max_size_percent(30, 40)
|
||||
.max_size(Percent::int(30), Percent::int(40))
|
||||
// We take up 30% width, and we want to leave 10% window width as buffer.
|
||||
.aligned(HorizontalAlignment::Percent(0.6), VerticalAlignment::Center)
|
||||
.build(ctx);
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
RewriteColor, ScreenDims, ScreenPt, ScreenRectangle, Slider, Spinner, TextBox,
|
||||
VerticalAlignment, WidgetImpl, WidgetOutput,
|
||||
};
|
||||
use geom::{Distance, Polygon};
|
||||
use geom::{Distance, Percent, Polygon};
|
||||
use std::collections::HashSet;
|
||||
use stretch::geometry::{Rect, Size};
|
||||
use stretch::node::{Node, Stretch};
|
||||
@ -71,11 +71,9 @@ impl Widget {
|
||||
// This one is really weird. percent_width should be LESS than the max_size_percent given to
|
||||
// the overall Composite, otherwise weird things happen.
|
||||
// Only makes sense for rows/columns.
|
||||
pub fn flex_wrap(mut self, ctx: &EventCtx, percent_width: usize) -> Widget {
|
||||
pub fn flex_wrap(mut self, ctx: &EventCtx, width: Percent) -> Widget {
|
||||
self.layout.style.size = Size {
|
||||
width: Dimension::Points(
|
||||
(ctx.canvas.window_width * (percent_width as f64) / 100.0) as f32,
|
||||
),
|
||||
width: Dimension::Points((ctx.canvas.window_width * width.inner()) as f32),
|
||||
height: Dimension::Undefined,
|
||||
};
|
||||
self.layout.style.flex_wrap = FlexWrap::Wrap;
|
||||
@ -87,9 +85,9 @@ impl Widget {
|
||||
self.layout.style.size.width = Dimension::Points(width as f32);
|
||||
self
|
||||
}
|
||||
pub fn force_width_pct(mut self, ctx: &EventCtx, percent_width: usize) -> Widget {
|
||||
pub fn force_width_pct(mut self, ctx: &EventCtx, width: Percent) -> Widget {
|
||||
self.layout.style.size.width =
|
||||
Dimension::Points((ctx.canvas.window_width * (percent_width as f64) / 100.0) as f32);
|
||||
Dimension::Points((ctx.canvas.window_width * width.inner()) as f32);
|
||||
self
|
||||
}
|
||||
|
||||
@ -594,7 +592,7 @@ impl Widget {
|
||||
}
|
||||
|
||||
enum Dims {
|
||||
MaxPercent(f64, f64),
|
||||
MaxPercent(Percent, Percent),
|
||||
ExactPercent(f64, f64),
|
||||
}
|
||||
|
||||
@ -624,7 +622,7 @@ impl Composite {
|
||||
top_level,
|
||||
horiz: HorizontalAlignment::Center,
|
||||
vert: VerticalAlignment::Center,
|
||||
dims: Dims::MaxPercent(1.0, 1.0),
|
||||
dims: Dims::MaxPercent(Percent::int(100), Percent::int(100)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -969,8 +967,12 @@ impl CompositeBuilder {
|
||||
c.contents_dims = ScreenDims::new(c.top_level.rect.width(), c.top_level.rect.height());
|
||||
c.container_dims = match c.dims {
|
||||
Dims::MaxPercent(w, h) => ScreenDims::new(
|
||||
c.contents_dims.width.min(w * ctx.canvas.window_width),
|
||||
c.contents_dims.height.min(h * ctx.canvas.window_height),
|
||||
c.contents_dims
|
||||
.width
|
||||
.min(w.inner() * ctx.canvas.window_width),
|
||||
c.contents_dims
|
||||
.height
|
||||
.min(h.inner() * ctx.canvas.window_height),
|
||||
),
|
||||
Dims::ExactPercent(w, h) => {
|
||||
ScreenDims::new(w * ctx.canvas.window_width, h * ctx.canvas.window_height)
|
||||
@ -1029,11 +1031,11 @@ impl CompositeBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn max_size_percent(mut self, pct_width: usize, pct_height: usize) -> CompositeBuilder {
|
||||
if pct_width == 100 && pct_height == 100 {
|
||||
pub fn max_size(mut self, width: Percent, height: Percent) -> CompositeBuilder {
|
||||
if width == Percent::int(100) && height == Percent::int(100) {
|
||||
panic!("By default, Composites are capped at 100% of the screen. This is redundant.");
|
||||
}
|
||||
self.dims = Dims::MaxPercent((pct_width as f64) / 100.0, (pct_height as f64) / 100.0);
|
||||
self.dims = Dims::MaxPercent(width, height);
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,9 @@ use crate::{
|
||||
ScreenRectangle, Text, TextExt, Widget, WidgetImpl, WidgetOutput,
|
||||
};
|
||||
use abstutil::prettyprint_usize;
|
||||
use geom::{Angle, Bounds, Circle, Distance, Duration, FindClosest, PolyLine, Polygon, Pt2D, Time};
|
||||
use geom::{
|
||||
Angle, Bounds, Circle, Distance, Duration, FindClosest, Percent, PolyLine, Polygon, Pt2D, Time,
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
|
||||
// The X is always time
|
||||
@ -343,7 +345,7 @@ pub fn make_legend<T: Yvalue<T>>(
|
||||
]));
|
||||
}
|
||||
}
|
||||
Widget::custom_row(row).flex_wrap(ctx, 24)
|
||||
Widget::custom_row(row).flex_wrap(ctx, Percent::int(24))
|
||||
}
|
||||
|
||||
// TODO If this proves useful, lift to geom
|
||||
|
@ -6,7 +6,7 @@ use abstutil::{prettyprint_usize, Timer};
|
||||
use ezgui::{
|
||||
hotkey, Btn, Color, Composite, EventCtx, GfxCtx, Key, Line, Outcome, Text, TextExt, Widget,
|
||||
};
|
||||
use geom::{Duration, Time};
|
||||
use geom::{Duration, Percent, Time};
|
||||
use map_model::Map;
|
||||
use sim::{AlertHandler, OrigPersonID, Scenario, Sim, SimFlags, SimOptions};
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
@ -161,7 +161,7 @@ impl ChallengesPicker {
|
||||
}
|
||||
master_col.push(
|
||||
Widget::custom_row(flex_row)
|
||||
.flex_wrap(ctx, 80)
|
||||
.flex_wrap(ctx, Percent::int(80))
|
||||
.bg(app.cs.panel_bg)
|
||||
.padding(16)
|
||||
.outline(2.0, Color::BLACK),
|
||||
|
@ -14,7 +14,7 @@ use ezgui::{
|
||||
hotkey, Btn, Choice, Composite, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome,
|
||||
TextExt, VerticalAlignment, Widget,
|
||||
};
|
||||
use geom::LonLat;
|
||||
use geom::{LonLat, Percent};
|
||||
|
||||
pub struct DevToolsMode {
|
||||
composite: Composite,
|
||||
@ -45,7 +45,7 @@ impl DevToolsMode {
|
||||
Btn::text_fg("view KML").build_def(ctx, hotkey(Key::K)),
|
||||
Btn::text_fg("story maps").build_def(ctx, hotkey(Key::S)),
|
||||
])
|
||||
.flex_wrap(ctx, 60),
|
||||
.flex_wrap(ctx, Percent::int(60)),
|
||||
]))
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx),
|
||||
|
@ -5,7 +5,7 @@ use ezgui::{
|
||||
Btn, Color, EventCtx, GeomBatch, Line, LinePlot, PlotOptions, RewriteColor, Series, Text,
|
||||
TextExt, Widget,
|
||||
};
|
||||
use geom::{ArrowCap, Distance, Duration, PolyLine, Polygon, Pt2D, Time};
|
||||
use geom::{ArrowCap, Distance, Duration, Percent, PolyLine, Polygon, Pt2D, Time};
|
||||
use map_model::{Map, Path, PathStep};
|
||||
use maplit::btreemap;
|
||||
use sim::{AgentID, PersonID, TripEndpoint, TripID, TripPhase, TripPhaseType};
|
||||
@ -52,7 +52,7 @@ pub fn ongoing(
|
||||
.get_trip_phases(id, &app.primary.map);
|
||||
let trip = app.primary.sim.trip_info(id);
|
||||
|
||||
let col_width = 7;
|
||||
let col_width = Percent::int(7);
|
||||
let props = app.primary.sim.agent_properties(agent);
|
||||
let activity = agent.to_type().ongoing_verb();
|
||||
let time_so_far = app.primary.sim.time() - trip.departure;
|
||||
@ -282,7 +282,7 @@ pub fn finished(
|
||||
}
|
||||
|
||||
{
|
||||
let col_width = 15;
|
||||
let col_width = Percent::int(15);
|
||||
|
||||
let total_trip_time =
|
||||
phases.last().as_ref().and_then(|p| p.end_time).unwrap() - trip.departure;
|
||||
|
@ -11,7 +11,7 @@ use ezgui::{
|
||||
hotkey, hotkeys, Btn, Color, Composite, EventCtx, GfxCtx, Key, Line, Outcome, RewriteColor,
|
||||
Text, UpdateType, Widget,
|
||||
};
|
||||
use geom::{Duration, Line, Pt2D, Speed};
|
||||
use geom::{Duration, Line, Percent, Pt2D, Speed};
|
||||
use instant::Instant;
|
||||
use map_model::PermanentMapEdits;
|
||||
use rand::Rng;
|
||||
@ -380,7 +380,7 @@ impl Proposals {
|
||||
txt.add(Line("Contact dabreegster@gmail.com to add your idea here!"));
|
||||
txt.draw(ctx).centered_horiz().margin_below(20)
|
||||
},
|
||||
Widget::custom_row(buttons).flex_wrap(ctx, 80),
|
||||
Widget::custom_row(buttons).flex_wrap(ctx, Percent::int(80)),
|
||||
];
|
||||
col.extend(current_tab);
|
||||
|
||||
|
@ -6,6 +6,7 @@ mod duration;
|
||||
mod find_closest;
|
||||
mod gps;
|
||||
mod line;
|
||||
mod percent;
|
||||
mod polygon;
|
||||
mod polyline;
|
||||
mod pt;
|
||||
@ -22,6 +23,7 @@ pub use crate::duration::Duration;
|
||||
pub use crate::find_closest::FindClosest;
|
||||
pub use crate::gps::LonLat;
|
||||
pub use crate::line::{InfiniteLine, Line};
|
||||
pub use crate::percent::Percent;
|
||||
pub use crate::polygon::{Polygon, Triangle};
|
||||
pub use crate::polyline::{ArrowCap, PolyLine};
|
||||
pub use crate::pt::{HashablePt2D, Pt2D};
|
||||
|
24
geom/src/percent.rs
Normal file
24
geom/src/percent.rs
Normal file
@ -0,0 +1,24 @@
|
||||
use std::fmt;
|
||||
|
||||
// Most of the time, [0, 1]. But some callers may go outside this range.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub struct Percent(f64);
|
||||
|
||||
impl Percent {
|
||||
pub fn inner(self) -> f64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn int(x: usize) -> Percent {
|
||||
if x > 100 {
|
||||
panic!("Percent::int({}) too big", x);
|
||||
}
|
||||
Percent((x as f64) / 100.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Percent {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "{:.2}%", self.0 * 100.0)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user