Change language of roads via settings, for #271

This commit is contained in:
Dustin Carlino 2020-08-18 17:32:49 -07:00
parent 2e93fdbf54
commit 6749edb2b6
19 changed files with 117 additions and 40 deletions

View File

@ -133,7 +133,7 @@ impl CommonState {
let r = map.get_parent(l);
osd.append_all(vec![
Line(format!("{} of ", map.get_l(l).lane_type.describe())),
Line(r.get_name()).fg(name_color),
Line(r.get_name(app.opts.language.as_ref())).fg(name_color),
]);
if app.opts.dev {
osd.append(Line(" ("));
@ -166,7 +166,7 @@ impl CommonState {
let mut road_names = BTreeSet::new();
for r in &map.get_i(i).roads {
road_names.insert(map.get_r(*r).get_name());
road_names.insert(map.get_r(*r).get_name(app.opts.language.as_ref()));
}
list_names(&mut osd, |l| l.fg(name_color), road_names);
}
@ -218,7 +218,7 @@ impl CommonState {
osd.append(Line(r.to_string()).fg(id_color));
osd.append(Line(" is "));
}
osd.append(Line(map.get_r(r).get_name()).fg(name_color));
osd.append(Line(map.get_r(r).get_name(app.opts.language.as_ref())).fg(name_color));
}
}
osd

View File

@ -30,7 +30,7 @@ impl Navigator {
.map
.all_roads()
.iter()
.map(|r| (r.get_name(), r.id))
.map(|r| (r.get_name(app.opts.language.as_ref()), r.id))
.collect(),
)
.named("street"),
@ -108,7 +108,7 @@ impl CrossStreet {
// TODO This isn't so clear...
txt.add(Line(format!(
"(Or just quit to go to {})",
map.get_r(first[0]).get_name(),
map.get_r(first[0]).get_name(app.opts.language.as_ref()),
)));
txt.draw(ctx)
},
@ -120,7 +120,7 @@ impl CrossStreet {
ctx,
cross_streets
.into_iter()
.map(|r| (map.get_r(r).get_name(), r))
.map(|r| (map.get_r(r).get_name(app.opts.language.as_ref()), r))
.collect(),
)
.named("street"),

View File

@ -640,7 +640,8 @@ fn find_divided_highways(app: &App) -> HashSet<RoadID> {
])
.intersection(&map.get_r(r2).center_pts)
.is_some()
&& r1.get_name() == map.get_r(r2).get_name()
&& r1.get_name(app.opts.language.as_ref())
== map.get_r(r2).get_name(app.opts.language.as_ref())
{
found.insert(r1.id);
found.insert(r2);

View File

@ -75,9 +75,12 @@ impl LaneEditor {
let parent = app.primary.map.get_parent(l);
let col = vec![
format!("Convert this lane of {} to what type?", parent.get_name())
.draw_text(ctx)
.centered_horiz(),
format!(
"Convert this lane of {} to what type?",
parent.get_name(app.opts.language.as_ref())
)
.draw_text(ctx)
.centered_horiz(),
Widget::custom_row(row).centered(),
change_speed_limit(ctx, parent.speed_limit),
Btn::text_fg("Change access restrictions").build_def(ctx, hotkey(Key::A)),

View File

@ -210,7 +210,13 @@ impl State for StopSignEditor {
let mut osd = Text::new();
osd.add_appended(vec![
Line("Stop sign for "),
Line(app.primary.map.get_r(r).get_name()).fg(app.cs.bottom_bar_name),
Line(
app.primary
.map
.get_r(r)
.get_name(app.opts.language.as_ref()),
)
.fg(app.cs.bottom_bar_name),
]);
CommonState::draw_custom_osd(g, app, osd);
} else {

View File

@ -478,13 +478,22 @@ impl State for TrafficSignalEditor {
let osd = if id.crosswalk {
Text::from(Line(format!(
"Crosswalk across {}",
app.primary.map.get_r(id.from.id).get_name()
app.primary
.map
.get_r(id.from.id)
.get_name(app.opts.language.as_ref())
)))
} else {
Text::from(Line(format!(
"Turn from {} to {}",
app.primary.map.get_r(id.from.id).get_name(),
app.primary.map.get_r(id.to.id).get_name()
app.primary
.map
.get_r(id.from.id)
.get_name(app.opts.language.as_ref()),
app.primary
.map
.get_r(id.to.id)
.get_name(app.opts.language.as_ref())
)))
};
CommonState::draw_custom_osd(g, app, osd);
@ -564,7 +573,12 @@ fn make_side_panel(
let mut road_names = BTreeSet::new();
for r in &app.primary.map.get_i(i).roads {
road_names.insert(app.primary.map.get_r(*r).get_name());
road_names.insert(
app.primary
.map
.get_r(*r)
.get_name(app.opts.language.as_ref()),
);
}
for r in road_names {
txt.add(Line(format!("- {}", r)));

View File

@ -237,7 +237,7 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
rows.push(format!("{} stops", route.stops.len()).draw_text(ctx));
{
let i = map.get_i(map.get_l(route.start).src_i);
let name = format!("Starts at {}", i.name(map));
let name = format!("Starts at {}", i.name(app.opts.language.as_ref(), map));
rows.push(Widget::row(vec![
Btn::svg(
"system/assets/timeline/goal_pos.svg",
@ -273,7 +273,7 @@ pub fn route(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BusRouteI
}
if let Some(l) = route.end_border {
let i = map.get_i(map.get_l(l).dst_i);
let name = format!("Ends at {}", i.name(map));
let name = format!("Ends at {}", i.name(app.opts.language.as_ref(), map));
rows.push(Widget::row(vec![
Btn::svg(
"system/assets/timeline/goal_pos.svg",

View File

@ -20,7 +20,12 @@ pub fn info(ctx: &EventCtx, app: &App, details: &mut Details, id: IntersectionID
let mut txt = Text::from(Line("Connecting"));
let mut road_names = BTreeSet::new();
for r in &i.roads {
road_names.insert(app.primary.map.get_r(*r).get_name());
road_names.insert(
app.primary
.map
.get_r(*r)
.get_name(app.opts.language.as_ref()),
);
}
for r in road_names {
// TODO The spacing is ignored, so use -

View File

@ -222,7 +222,7 @@ fn header(ctx: &EventCtx, app: &App, details: &mut Details, id: LaneID, tab: Tab
.draw(ctx),
header_btns(ctx),
]));
rows.push(format!("@ {}", r.get_name()).draw_text(ctx));
rows.push(format!("@ {}", r.get_name(app.opts.language.as_ref())).draw_text(ctx));
let mut tabs = vec![("Info", Tab::LaneInfo(id))];
if !l.is_parking() {

View File

@ -160,8 +160,8 @@ pub fn future(
));
} else {
// TODO Warp buttons. make_table is showing its age.
let (id1, _, name1) = endpoint(&trip.start, &app.primary.map);
let (id2, _, name2) = endpoint(&trip.end, &app.primary.map);
let (id1, _, name1) = endpoint(&trip.start, app);
let (id2, _, name2) = endpoint(&trip.end, app);
details
.warpers
.insert(format!("jump to start of {}", id), id1);
@ -323,8 +323,8 @@ pub fn aborted(ctx: &mut EventCtx, app: &App, id: TripID) -> Widget {
.draw(ctx)];
// TODO Warp buttons. make_table is showing its age.
let (_, _, name1) = endpoint(&trip.start, &app.primary.map);
let (_, _, name2) = endpoint(&trip.end, &app.primary.map);
let (_, _, name1) = endpoint(&trip.start, app);
let (_, _, name2) = endpoint(&trip.end, app);
col.extend(make_table(
ctx,
vec![
@ -344,8 +344,8 @@ pub fn cancelled(ctx: &mut EventCtx, app: &App, id: TripID) -> Widget {
let mut col = vec!["Trip cancelled due to traffic pattern modifications".draw_text(ctx)];
// TODO Warp buttons. make_table is showing its age.
let (_, _, name1) = endpoint(&trip.start, &app.primary.map);
let (_, _, name2) = endpoint(&trip.end, &app.primary.map);
let (_, _, name1) = endpoint(&trip.start, app);
let (_, _, name2) = endpoint(&trip.end, app);
col.extend(make_table(
ctx,
vec![
@ -374,7 +374,7 @@ fn make_timeline(
let end_time = phases.last().as_ref().and_then(|p| p.end_time);
let start_btn = {
let (id, center, name) = endpoint(&trip.start, map);
let (id, center, name) = endpoint(&trip.start, app);
details
.warpers
.insert(format!("jump to start of {}", trip_id), id);
@ -419,7 +419,7 @@ fn make_timeline(
};
let goal_btn = {
let (id, center, name) = endpoint(&trip.end, map);
let (id, center, name) = endpoint(&trip.end, app);
details
.warpers
.insert(format!("jump to goal of {}", trip_id), id);
@ -699,18 +699,21 @@ fn make_elevation(ctx: &EventCtx, color: Color, walking: bool, path: &Path, map:
}
// (ID, center, name)
fn endpoint(endpt: &TripEndpoint, map: &Map) -> (ID, Pt2D, String) {
fn endpoint(endpt: &TripEndpoint, app: &App) -> (ID, Pt2D, String) {
match endpt {
TripEndpoint::Bldg(b) => {
let bldg = map.get_b(*b);
let bldg = app.primary.map.get_b(*b);
(ID::Building(*b), bldg.label_center, bldg.address.clone())
}
TripEndpoint::Border(i, _) => {
let i = map.get_i(*i);
let i = app.primary.map.get_i(*i);
(
ID::Intersection(i.id),
i.polygon.center(),
format!("off map, via {}", i.name(map)),
format!(
"off map, via {}",
i.name(app.opts.language.as_ref(), &app.primary.map)
),
)
}
}

View File

@ -22,6 +22,8 @@ pub struct Options {
pub time_increment: Duration,
pub resume_after_edit: bool,
pub dont_draw_time_warp: bool,
pub language: Option<String>,
}
impl Options {
@ -39,6 +41,8 @@ impl Options {
time_increment: Duration::minutes(10),
resume_after_edit: true,
dont_draw_time_warp: false,
language: None,
}
}
}
@ -167,6 +171,17 @@ impl OptionsPanel {
None,
app.opts.large_unzoomed_agents,
),
Widget::row(vec![
"Language".draw_text(ctx),
Widget::dropdown(ctx, "language", app.opts.language.clone(), {
let mut choices = Vec::new();
choices.push(Choice::new("Map native language", None));
for lang in app.primary.map.get_languages() {
choices.push(Choice::new(lang, Some(lang.to_string())));
}
choices
}),
]),
])
.bg(app.cs.section_bg)
.padding(8),
@ -222,7 +237,7 @@ impl State for OptionsPanel {
if app.opts.traffic_signal_style != style {
app.opts.traffic_signal_style = style;
println!("Rerendering traffic signals...");
for i in app.primary.draw_map.intersections.iter_mut() {
for i in &mut app.primary.draw_map.intersections {
*i.draw_traffic_signal.borrow_mut() = None;
}
}
@ -237,6 +252,14 @@ impl State for OptionsPanel {
app.opts.large_unzoomed_agents =
self.composite.is_checked("Draw enlarged unzoomed agents");
let language = self.composite.dropdown_value("language");
if language != app.opts.language {
app.opts.language = language;
for r in &mut app.primary.draw_map.roads {
r.clear_rendering();
}
}
return Transition::Pop;
}
_ => unreachable!(),

View File

@ -26,6 +26,7 @@ impl DrawRoad {
pub fn clear_rendering(&mut self) {
*self.draw_center_line.borrow_mut() = None;
*self.label.borrow_mut() = None;
}
}
@ -73,7 +74,7 @@ impl Renderable for DrawRoad {
let mut batch = GeomBatch::new();
let r = app.primary.map.get_r(self.id);
if !r.is_light_rail() {
let name = r.get_name();
let name = r.get_name(app.opts.language.as_ref());
if r.center_pts.length() >= Distance::meters(30.0) && name != "???" {
// TODO If it's definitely straddling bus/bike lanes, change the color? Or
// even easier, just skip the center lines?

View File

@ -163,7 +163,10 @@ impl TurnExplorer {
Text::from(
Line(format!(
"Turns from {}",
app.primary.map.get_parent(l).get_name()
app.primary
.map
.get_parent(l)
.get_name(app.opts.language.as_ref())
))
.small_heading(),
)

View File

@ -105,7 +105,7 @@ fn get_address(tags: &Tags, sidewalk: LaneID, map: &Map) -> String {
match (tags.get("addr:housenumber"), tags.get("addr:street")) {
(Some(num), Some(st)) => format!("{} {}", num, st),
(None, Some(st)) => format!("??? {}", st),
_ => format!("??? {}", map.get_parent(sidewalk).get_name()),
_ => format!("??? {}", map.get_parent(sidewalk).get_name(None)),
}
}

View File

@ -197,7 +197,7 @@ impl Map {
biking_blackhole: false,
});
}
if road.get_name() == "???" {
if road.get_name(None) == "???" {
// Suppress the warning in some cases.
if !(road.osm_tags.is("noname", "yes")
|| road

View File

@ -26,7 +26,7 @@ pub fn get_possible_policies(
timer.error(format!(
"seattle_traffic_signals data for {} ({}) out of date, go update it",
i.orig_id,
i.name(map)
i.name(None, map)
));
}
}

View File

@ -633,4 +633,16 @@ impl Map {
self.bus_routes[br.0].orig_spawn_times = times.clone();
self.bus_routes[br.0].spawn_times = times;
}
pub fn get_languages(&self) -> BTreeSet<&str> {
let mut languages = BTreeSet::new();
for r in self.all_roads() {
for key in r.osm_tags.inner().keys() {
if let Some(x) = key.strip_prefix("name:") {
languages.insert(x);
}
}
}
languages
}
}

View File

@ -142,11 +142,11 @@ impl Intersection {
.map(|l| map.get_l(*l).get_directed_parent(map))
}
pub fn name(&self, map: &Map) -> String {
pub fn name(&self, lang: Option<&String>, map: &Map) -> String {
let road_names = self
.roads
.iter()
.map(|r| map.get_r(*r).get_name())
.map(|r| map.get_r(*r).get_name(lang))
.collect::<BTreeSet<_>>();
abstutil::plain_list_names(road_names)
}

View File

@ -293,7 +293,13 @@ impl Road {
.make_polygons(self.get_half_width(map) * 2.0)
}
pub fn get_name(&self) -> String {
pub fn get_name(&self, lang: Option<&String>) -> String {
if let Some(lang) = lang {
if let Some(name) = self.osm_tags.get(&format!("name:{}", lang)) {
return name.to_string();
}
}
if let Some(name) = self.osm_tags.get(osm::NAME) {
if name == "" {
return "???".to_string();