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;

/// Specify the lane types for a road using a text box. This is a temporary UI to start
/// experimenting with widening roads. It'll be replaced by a real UI once the design is ready.
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| {
            // We're selecting a lane before this, but the ID is probably about to be invalidated.
            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 {
    // TODO Assuming driving on the right.
    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'), // transit
        (LaneType::SharedLeftTurn, 'l'),
        (LaneType::Construction, 'c'),
        (LaneType::LightRail, 'r'),
    ]
}