1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
use map_gui::tools::PromptInput;
use map_model::{Direction, LaneSpec, LaneType, Road};
use widgetry::{EventCtx, State};
use crate::app::{App, Transition};
use crate::edit::apply_map_edits;
pub fn prompt_for_lanes(ctx: &mut EventCtx, road: &Road) -> Box<dyn State<App>> {
let r = road.id;
PromptInput::new(
ctx,
"Define lanes_ltr",
lanes_to_string(road),
Box::new(move |string, ctx, app| {
app.primary.current_selection = None;
let mut edits = app.primary.map.get_edits().clone();
edits.commands.push(app.primary.map.edit_road_cmd(r, |new| {
new.lanes_ltr = string_to_lanes(string.clone());
}));
apply_map_edits(ctx, app, edits);
Transition::Multi(vec![Transition::Pop, Transition::Pop])
}),
)
}
fn lanes_to_string(road: &Road) -> String {
let mut dir_change = false;
let mut string = String::new();
for (_, dir, lt) in road.lanes_ltr() {
if !dir_change && dir == Direction::Fwd {
string.push('/');
dir_change = true;
}
string.push(
lane_type_codes()
.into_iter()
.find(|(x, _)| *x == lt)
.unwrap()
.1,
);
}
string
}
fn string_to_lanes(string: String) -> Vec<LaneSpec> {
let mut lanes = Vec::new();
let mut dir = Direction::Back;
for x in string.chars() {
if x == '/' {
dir = Direction::Fwd;
continue;
}
let lt = lane_type_codes()
.into_iter()
.find(|(_, code)| *code == x)
.unwrap()
.0;
lanes.push(LaneSpec {
lt,
dir,
width: map_model::NORMAL_LANE_THICKNESS,
});
}
lanes
}
fn lane_type_codes() -> Vec<(LaneType, char)> {
vec![
(LaneType::Driving, 'd'),
(LaneType::Parking, 'p'),
(LaneType::Sidewalk, 's'),
(LaneType::Shoulder, 'S'),
(LaneType::Biking, 'b'),
(LaneType::Bus, 't'),
(LaneType::SharedLeftTurn, 'l'),
(LaneType::Construction, 'c'),
(LaneType::LightRail, 'r'),
]
}