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:
Dustin Carlino 2020-08-20 11:01:59 -07:00
parent 2c5bbd3e7e
commit 14c66c5528
11 changed files with 58 additions and 28 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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