mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
Improve the traffic signal timing UI. There's a choice between fixed and
variable timing, but currently you have to remember to toggle it; the two extra spinners get ignored otherwise. The new version is still confusing, but I think it's an improvement.
This commit is contained in:
parent
8be24bf007
commit
522b902453
@ -243,7 +243,7 @@ impl SimpleState<App> for UberTurnViewer {
|
|||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
app: &mut App,
|
app: &mut App,
|
||||||
panel: &Panel,
|
panel: &mut Panel,
|
||||||
) -> Option<Transition> {
|
) -> Option<Transition> {
|
||||||
Some(Transition::Replace(UberTurnViewer::new(
|
Some(Transition::Replace(UberTurnViewer::new(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -169,7 +169,7 @@ impl SimpleState<App> for LaneEditor {
|
|||||||
&mut self,
|
&mut self,
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
app: &mut App,
|
app: &mut App,
|
||||||
panel: &Panel,
|
panel: &mut Panel,
|
||||||
) -> Option<Transition> {
|
) -> Option<Transition> {
|
||||||
let mut edits = app.primary.map.get_edits().clone();
|
let mut edits = app.primary.map.get_edits().clone();
|
||||||
edits.commands.push(app.primary.map.edit_road_cmd(
|
edits.commands.push(app.primary.map.edit_road_cmd(
|
||||||
|
@ -4,8 +4,8 @@ use map_model::{
|
|||||||
ControlStopSign, ControlTrafficSignal, EditCmd, EditIntersection, IntersectionID, StageType,
|
ControlStopSign, ControlTrafficSignal, EditCmd, EditIntersection, IntersectionID, StageType,
|
||||||
};
|
};
|
||||||
use widgetry::{
|
use widgetry::{
|
||||||
Choice, DrawBaselayer, EventCtx, Key, Line, Panel, SimpleState, Spinner, State, TextExt,
|
Choice, DrawBaselayer, EventCtx, Key, Line, Panel, SimpleState, Spinner, State, Text, TextExt,
|
||||||
Toggle, Widget,
|
Widget,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::app::{App, Transition};
|
use crate::app::{App, Transition};
|
||||||
@ -20,6 +20,7 @@ pub struct ChangeDuration {
|
|||||||
impl ChangeDuration {
|
impl ChangeDuration {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
ctx: &mut EventCtx,
|
ctx: &mut EventCtx,
|
||||||
|
app: &App,
|
||||||
signal: &ControlTrafficSignal,
|
signal: &ControlTrafficSignal,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
) -> Box<dyn State<App>> {
|
) -> Box<dyn State<App>> {
|
||||||
@ -45,28 +46,28 @@ impl ChangeDuration {
|
|||||||
)
|
)
|
||||||
.named("duration"),
|
.named("duration"),
|
||||||
]),
|
]),
|
||||||
Widget::row(vec![
|
Line("Minimum time is set by the time required for crosswalk")
|
||||||
"Type:".text_widget(ctx),
|
.secondary()
|
||||||
Toggle::choice(
|
.into_widget(ctx),
|
||||||
ctx,
|
Widget::col(vec![
|
||||||
"stage type",
|
Text::from_all(match signal.stages[idx].stage_type {
|
||||||
"fixed",
|
StageType::Fixed(_) => vec![
|
||||||
"variable",
|
Line("Fixed timing").small_heading(),
|
||||||
None,
|
Line(" (Adjust both values below to enable variable timing)"),
|
||||||
match signal.stages[idx].stage_type {
|
],
|
||||||
StageType::Fixed(_) => true,
|
StageType::Variable(_, _, _) => vec![
|
||||||
StageType::Variable(_, _, _) => false,
|
Line("Variable timing").small_heading(),
|
||||||
},
|
Line(" (Set either values below to 0 to use fixed timing."),
|
||||||
),
|
],
|
||||||
]),
|
})
|
||||||
Widget::row(vec![Line("Additional time this stage can last?")
|
.into_widget(ctx)
|
||||||
.small_heading()
|
.named("timing type"),
|
||||||
.into_widget(ctx)]),
|
"How much additional time can this stage last?".text_widget(ctx),
|
||||||
Widget::row(vec![
|
Widget::row(vec![
|
||||||
"Seconds:".text_widget(ctx).centered_vert(),
|
"Seconds:".text_widget(ctx).centered_vert(),
|
||||||
Spinner::widget(
|
Spinner::widget(
|
||||||
ctx,
|
ctx,
|
||||||
(1, 300),
|
(0, 300),
|
||||||
match signal.stages[idx].stage_type {
|
match signal.stages[idx].stage_type {
|
||||||
StageType::Fixed(_) => 0,
|
StageType::Fixed(_) => 0,
|
||||||
StageType::Variable(_, _, additional) => {
|
StageType::Variable(_, _, additional) => {
|
||||||
@ -76,14 +77,12 @@ impl ChangeDuration {
|
|||||||
)
|
)
|
||||||
.named("additional"),
|
.named("additional"),
|
||||||
]),
|
]),
|
||||||
Widget::row(vec![Line("How long with no demand to end stage?")
|
"How long with no demand before the stage ends?".text_widget(ctx),
|
||||||
.small_heading()
|
|
||||||
.into_widget(ctx)]),
|
|
||||||
Widget::row(vec![
|
Widget::row(vec![
|
||||||
"Seconds:".text_widget(ctx).centered_vert(),
|
"Seconds:".text_widget(ctx).centered_vert(),
|
||||||
Spinner::widget(
|
Spinner::widget(
|
||||||
ctx,
|
ctx,
|
||||||
(1, 300),
|
(0, 300),
|
||||||
match signal.stages[idx].stage_type {
|
match signal.stages[idx].stage_type {
|
||||||
StageType::Fixed(_) => 0,
|
StageType::Fixed(_) => 0,
|
||||||
StageType::Variable(_, delay, _) => delay.inner_seconds() as isize,
|
StageType::Variable(_, delay, _) => delay.inner_seconds() as isize,
|
||||||
@ -91,9 +90,10 @@ impl ChangeDuration {
|
|||||||
)
|
)
|
||||||
.named("delay"),
|
.named("delay"),
|
||||||
]),
|
]),
|
||||||
Line("Minimum time is set by the time required for crosswalk")
|
])
|
||||||
.secondary()
|
.padding(10)
|
||||||
.into_widget(ctx),
|
.bg(app.cs.inner_panel_bg)
|
||||||
|
.outline(ctx.style().section_outline),
|
||||||
ctx.style()
|
ctx.style()
|
||||||
.btn_solid_primary
|
.btn_solid_primary
|
||||||
.text("Apply")
|
.text("Apply")
|
||||||
@ -111,11 +111,11 @@ impl SimpleState<App> for ChangeDuration {
|
|||||||
"close" => Transition::Pop,
|
"close" => Transition::Pop,
|
||||||
"Apply" => {
|
"Apply" => {
|
||||||
let dt = Duration::seconds(panel.spinner("duration") as f64);
|
let dt = Duration::seconds(panel.spinner("duration") as f64);
|
||||||
let new_type = if panel.is_checked("stage type") {
|
|
||||||
StageType::Fixed(dt)
|
|
||||||
} else {
|
|
||||||
let delay = Duration::seconds(panel.spinner("delay") as f64);
|
let delay = Duration::seconds(panel.spinner("delay") as f64);
|
||||||
let additional = Duration::seconds(panel.spinner("additional") as f64);
|
let additional = Duration::seconds(panel.spinner("additional") as f64);
|
||||||
|
let new_type = if delay == Duration::ZERO || additional == Duration::ZERO {
|
||||||
|
StageType::Fixed(dt)
|
||||||
|
} else {
|
||||||
StageType::Variable(dt, delay, additional)
|
StageType::Variable(dt, delay, additional)
|
||||||
};
|
};
|
||||||
let idx = self.idx;
|
let idx = self.idx;
|
||||||
@ -133,6 +133,30 @@ impl SimpleState<App> for ChangeDuration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn panel_changed(
|
||||||
|
&mut self,
|
||||||
|
ctx: &mut EventCtx,
|
||||||
|
_: &mut App,
|
||||||
|
panel: &mut Panel,
|
||||||
|
) -> Option<Transition> {
|
||||||
|
let new_label = Text::from_all(
|
||||||
|
if panel.spinner("delay") == 0 || panel.spinner("additional") == 0 {
|
||||||
|
vec![
|
||||||
|
Line("Fixed timing").small_heading(),
|
||||||
|
Line(" (Adjust both values below to enable variable timing)"),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
|
vec![
|
||||||
|
Line("Variable timing").small_heading(),
|
||||||
|
Line(" (Set either values below to 0 to use fixed timing."),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.into_widget(ctx);
|
||||||
|
panel.replace(ctx, "timing type", new_label);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn other_event(&mut self, ctx: &mut EventCtx, _: &mut App) -> Transition {
|
fn other_event(&mut self, ctx: &mut EventCtx, _: &mut App) -> Transition {
|
||||||
if ctx.normal_left_click() && ctx.canvas.get_cursor_in_screen_space().is_none() {
|
if ctx.normal_left_click() && ctx.canvas.get_cursor_in_screen_space().is_none() {
|
||||||
return Transition::Pop;
|
return Transition::Pop;
|
||||||
|
@ -223,6 +223,7 @@ impl State<App> for TrafficSignalEditor {
|
|||||||
let idx = x.parse::<usize>().unwrap() - 1;
|
let idx = x.parse::<usize>().unwrap() - 1;
|
||||||
return Transition::Push(edits::ChangeDuration::new(
|
return Transition::Push(edits::ChangeDuration::new(
|
||||||
ctx,
|
ctx,
|
||||||
|
app,
|
||||||
&canonical_signal,
|
&canonical_signal,
|
||||||
idx,
|
idx,
|
||||||
));
|
));
|
||||||
|
@ -221,7 +221,12 @@ pub trait SimpleState<A> {
|
|||||||
) -> Transition<A>;
|
) -> Transition<A>;
|
||||||
/// Called when something on the panel has changed. If a transition is returned, stop handling
|
/// Called when something on the panel has changed. If a transition is returned, stop handling
|
||||||
/// the event and immediately apply the transition.
|
/// the event and immediately apply the transition.
|
||||||
fn panel_changed(&mut self, _: &mut EventCtx, _: &mut A, _: &Panel) -> Option<Transition<A>> {
|
fn panel_changed(
|
||||||
|
&mut self,
|
||||||
|
_: &mut EventCtx,
|
||||||
|
_: &mut A,
|
||||||
|
_: &mut Panel,
|
||||||
|
) -> Option<Transition<A>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
/// Called when the mouse has moved.
|
/// Called when the mouse has moved.
|
||||||
@ -257,7 +262,7 @@ impl<A: 'static> State<A> for SimpleStateWrapper<A> {
|
|||||||
Outcome::Clicked(action) => self.inner.on_click(ctx, app, &action, &self.panel),
|
Outcome::Clicked(action) => self.inner.on_click(ctx, app, &action, &self.panel),
|
||||||
Outcome::Changed => self
|
Outcome::Changed => self
|
||||||
.inner
|
.inner
|
||||||
.panel_changed(ctx, app, &self.panel)
|
.panel_changed(ctx, app, &mut self.panel)
|
||||||
.unwrap_or_else(|| self.inner.other_event(ctx, app)),
|
.unwrap_or_else(|| self.inner.other_event(ctx, app)),
|
||||||
Outcome::Nothing => self.inner.other_event(ctx, app),
|
Outcome::Nothing => self.inner.other_event(ctx, app),
|
||||||
}
|
}
|
||||||
|
@ -71,11 +71,17 @@ impl Spinner {
|
|||||||
up.get_dims().height + down.get_dims().height + 1.0,
|
up.get_dims().height + down.get_dims().height + 1.0,
|
||||||
);
|
);
|
||||||
if current < low {
|
if current < low {
|
||||||
|
warn!(
|
||||||
|
"Spinner's initial value is out of bounds! {}, bounds ({}, {})",
|
||||||
|
current, low, high
|
||||||
|
);
|
||||||
current = low;
|
current = low;
|
||||||
warn!("Spinner current value is out of bounds!");
|
|
||||||
} else if high < current {
|
} else if high < current {
|
||||||
|
warn!(
|
||||||
|
"Spinner's initial value is out of bounds! {}, bounds ({}, {})",
|
||||||
|
current, low, high
|
||||||
|
);
|
||||||
current = high;
|
current = high;
|
||||||
warn!("Spinner current value is out of bounds!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut spinner = Spinner {
|
let mut spinner = Spinner {
|
||||||
|
Loading…
Reference in New Issue
Block a user