wrap text in signal diagram to limit width

This commit is contained in:
Dustin Carlino 2020-01-13 14:57:46 -08:00
parent 1ab3c5200a
commit af76ad9d60
7 changed files with 43 additions and 40 deletions

View File

@ -378,7 +378,7 @@ impl GeomBatch {
for (_, poly) in &self.list {
bounds.union(poly.get_bounds());
}
ScreenDims::new(bounds.max_x - bounds.min_x, bounds.max_y - bounds.min_y)
ScreenDims::new(bounds.width(), bounds.height())
}
// Slightly weird use case, but hotswap colors.
@ -495,8 +495,8 @@ impl<'a> Prerender<'a> {
center.y() + origin_pt.y() * cos + origin_pt.x() * sin,
);
let tx = (rot_pt.x() - b.min_x) / (b.max_x - b.min_x);
let ty = (rot_pt.y() - b.min_y) / (b.max_y - b.min_y);
let tx = (rot_pt.x() - b.min_x) / b.width();
let ty = (rot_pt.y() - b.min_y) / b.height();
[tx as f32, ty as f32, id.0, 100.0 + id.1]
}
Color::CustomUVTexture(id) => {
@ -603,6 +603,6 @@ impl DrawBoth {
// TODO Hack
pub(crate) fn override_bounds(&mut self, b: Bounds) {
self.dims = ScreenDims::new(b.max_x - b.min_x, b.max_y - b.min_y);
self.dims = ScreenDims::new(b.width(), b.height());
}
}

View File

@ -1,5 +1,5 @@
use crate::assets::Assets;
use crate::{Color, EventCtx, GfxCtx, ScreenDims, ScreenPt, ScreenRectangle};
use crate::{Color, GfxCtx, ScreenDims, ScreenPt, ScreenRectangle};
use geom::{Polygon, Pt2D};
use glium_glyph::glyph_brush::rusttype::Scale;
use glium_glyph::glyph_brush::{FontId, GlyphCruncher};
@ -153,9 +153,8 @@ impl Text {
}
}
// TODO Ideally we'd wrap last-minute when drawing, but eh, start somewhere.
pub fn add_wrapped_line(&mut self, ctx: &EventCtx, line: String) {
let wrap_to = ctx.canvas.window_width / MAX_CHAR_WIDTH;
pub fn add_wrapped(&mut self, line: String, width: f64) {
let wrap_to = width / MAX_CHAR_WIDTH;
for l in textwrap::wrap(&line, wrap_to as usize).into_iter() {
self.add(Line(l));
}

View File

@ -31,7 +31,7 @@ impl Minimap {
// Initially pick a zoom to fit the entire map's width in the minimap. Arbitrary and
// probably pretty weird.
let bounds = ui.primary.map.get_bounds();
let base_zoom = 0.15 * ctx.canvas.window_width / (bounds.max_x - bounds.min_x);
let base_zoom = 0.15 * ctx.canvas.window_width / bounds.width();
Minimap {
dragging: false,
composite: make_minimap_panel(ctx, &ui.agent_cs, 0),

View File

@ -1,7 +1,7 @@
use crate::common::CommonState;
use crate::edit::apply_map_edits;
use crate::game::{msg, State, Transition, WizardState};
use crate::helpers::list_names;
use crate::helpers::plain_list_names;
use crate::managed::{Composite, Outcome};
use crate::render::{draw_signal_phase, DrawOptions, DrawTurnGroup, BIG_ARROW_THICKNESS};
use crate::sandbox::{spawn_agents_around, SpeedControls, TimePanel};
@ -348,17 +348,13 @@ fn make_diagram(
// but this is close enough.
let bounds = ui.primary.map.get_i(i).polygon.get_bounds();
// Pick a zoom so that we fit some percentage of the screen
let zoom = 0.2 * ctx.canvas.window_width / (bounds.max_x - bounds.min_x);
let bbox = Polygon::rectangle(
zoom * (bounds.max_x - bounds.min_x),
zoom * (bounds.max_y - bounds.min_y),
);
let zoom = 0.2 * ctx.canvas.window_width / bounds.width();
let bbox = Polygon::rectangle(zoom * bounds.width(), zoom * bounds.height());
let signal = ui.primary.map.get_traffic_signal(i);
let mut col = vec![
ManagedWidget::draw_text(ctx, {
let mut txt = Text::new();
txt.add(Line(i.to_string()).roboto());
let road_names = ui
.primary
.map
@ -367,15 +363,10 @@ fn make_diagram(
.iter()
.map(|r| ui.primary.map.get_r(*r).get_name())
.collect::<BTreeSet<_>>();
// TODO Some kind of reusable TextStyle thing
txt.add(Line("").roboto().size(21).fg(Color::WHITE.alpha(0.54)));
list_names(
&mut txt,
|l| l.roboto().fg(Color::WHITE.alpha(0.54)),
road_names,
);
// TODO Style inside here. Also 0.4 is manually tuned and pretty wacky, because it
// assumes default font.
txt.add_wrapped(plain_list_names(road_names), 0.4 * ctx.canvas.window_width);
txt.add(Line(format!("{} phases", signal.phases.len())));
txt.add(Line(""));
txt.add(Line(format!("Signal offset: {}", signal.offset)));
txt.add(Line(format!("One cycle lasts {}", signal.cycle_length())));
txt

View File

@ -7,6 +7,7 @@ use map_model::{AreaID, BuildingID, BusStopID, IntersectionID, LaneID, RoadID, T
use serde_derive::{Deserialize, Serialize};
use sim::{AgentID, CarID, PedestrianID};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt::Write;
// Aside from Road, everything here can actually be selected.
#[derive(Clone, Hash, PartialEq, Eq, Debug, PartialOrd, Ord)]
@ -200,3 +201,24 @@ pub fn list_names<F: Fn(TextSpan) -> TextSpan>(txt: &mut Text, styler: F, names:
txt.append(styler(Line(n)));
}
}
// TODO Ideally use list_names, but this is hard to make work with word wrap
pub fn plain_list_names(names: BTreeSet<String>) -> String {
let mut s = String::new();
let len = names.len();
for (idx, n) in names.into_iter().enumerate() {
if idx != 0 {
if idx == len - 1 {
if len == 2 {
write!(s, " and ").unwrap();
} else {
write!(s, ", and ").unwrap();
}
} else {
write!(s, ", ").unwrap();
}
}
write!(s, "{}", n).unwrap();
}
s
}

View File

@ -1,4 +1,4 @@
use crate::helpers::list_names;
use crate::helpers::plain_list_names;
use crate::options::TrafficSignalStyle;
use crate::render::{DrawCtx, DrawTurnGroup, BIG_ARROW_THICKNESS};
use crate::ui::UI;
@ -211,16 +211,12 @@ fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &mut EventCtx)
// but this is close enough.
let bounds = ui.primary.map.get_i(i).polygon.get_bounds();
// Pick a zoom so that we fit some percentage of the screen
let zoom = 0.2 * ctx.canvas.window_width / (bounds.max_x - bounds.min_x);
let bbox = Polygon::rectangle(
zoom * (bounds.max_x - bounds.min_x),
zoom * (bounds.max_y - bounds.min_y),
);
let zoom = 0.2 * ctx.canvas.window_width / bounds.width();
let bbox = Polygon::rectangle(zoom * bounds.width(), zoom * bounds.height());
let signal = ui.primary.map.get_traffic_signal(i);
let mut col = vec![ManagedWidget::draw_text(ctx, {
let mut txt = Text::new();
txt.add(Line(i.to_string()).roboto());
let road_names = ui
.primary
.map
@ -229,15 +225,10 @@ fn make_diagram(i: IntersectionID, selected: usize, ui: &UI, ctx: &mut EventCtx)
.iter()
.map(|r| ui.primary.map.get_r(*r).get_name())
.collect::<BTreeSet<_>>();
// TODO Some kind of reusable TextStyle thing
txt.add(Line("").roboto().size(21).fg(Color::WHITE.alpha(0.54)));
list_names(
&mut txt,
|l| l.roboto().fg(Color::WHITE.alpha(0.54)),
road_names,
);
// TODO Style inside here. Also 0.4 is manually tuned and pretty wacky, because it
// assumes default font.
txt.add_wrapped(plain_list_names(road_names), 0.4 * ctx.canvas.window_width);
txt.add(Line(format!("{} phases", signal.phases.len())));
txt.add(Line(""));
txt.add(Line(format!("Signal offset: {}", signal.offset)));
txt.add(Line(format!("One cycle lasts {}", signal.cycle_length())));
txt

View File

@ -285,7 +285,7 @@ fn pick_finished_trips(
fn parking_overhead(ctx: &EventCtx, ui: &UI) -> ManagedWidget {
let mut txt = Text::new();
for line in ui.primary.sim.get_analytics().analyze_parking_phases() {
txt.add_wrapped_line(ctx, line);
txt.add_wrapped(line, 0.9 * ctx.canvas.window_width);
}
ManagedWidget::draw_text(ctx, txt)
}