mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-25 22:13:27 +03:00
more button refactor:
- custom tooltips - get rid of a few old Button constructors
This commit is contained in:
parent
be9671a51f
commit
6de415033e
@ -389,6 +389,16 @@ impl GeomBatch {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_svg<I: Into<String>>(
|
||||
ctx: &EventCtx,
|
||||
path: I,
|
||||
rewrite: RewriteColor,
|
||||
) -> (GeomBatch, Bounds) {
|
||||
let (mut batch, bounds) = svg::load_svg(ctx.prerender, &path.into());
|
||||
batch.rewrite_color(rewrite);
|
||||
(batch, bounds)
|
||||
}
|
||||
|
||||
// TODO Weird API...
|
||||
pub fn add_svg(
|
||||
&mut self,
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::layout::Widget;
|
||||
use crate::svg;
|
||||
use crate::{
|
||||
text, Color, Drawable, EventCtx, GeomBatch, GfxCtx, JustDraw, Line, ManagedWidget, MultiKey,
|
||||
RewriteColor, ScreenDims, ScreenPt, Text,
|
||||
@ -27,7 +26,7 @@ pub struct Button {
|
||||
}
|
||||
|
||||
impl Button {
|
||||
pub fn new(
|
||||
fn new(
|
||||
ctx: &EventCtx,
|
||||
normal: GeomBatch,
|
||||
hovered: GeomBatch,
|
||||
@ -62,11 +61,6 @@ impl Button {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn change_tooltip(mut self, tooltip: Text) -> Button {
|
||||
self.tooltip = tooltip;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn event(&mut self, ctx: &mut EventCtx) {
|
||||
if self.clicked {
|
||||
panic!("Caller didn't consume button click");
|
||||
@ -128,38 +122,6 @@ impl Widget for Button {
|
||||
|
||||
// TODO Simplify all of these APIs!
|
||||
impl Button {
|
||||
pub fn rectangle_svg(
|
||||
filename: &str,
|
||||
tooltip: &str,
|
||||
key: Option<MultiKey>,
|
||||
hover: RewriteColor,
|
||||
ctx: &EventCtx,
|
||||
) -> Button {
|
||||
let (normal, bounds) = svg::load_svg(ctx.prerender, filename);
|
||||
|
||||
let mut hovered = normal.clone();
|
||||
hovered.rewrite_color(hover);
|
||||
|
||||
Button::new(ctx, normal, hovered, key, tooltip, bounds.get_rectangle())
|
||||
}
|
||||
|
||||
pub fn rectangle_svg_rewrite(
|
||||
filename: &str,
|
||||
tooltip: &str,
|
||||
key: Option<MultiKey>,
|
||||
normal_rewrite: RewriteColor,
|
||||
hover: RewriteColor,
|
||||
ctx: &EventCtx,
|
||||
) -> Button {
|
||||
let (mut normal, bounds) = svg::load_svg(ctx.prerender, filename);
|
||||
normal.rewrite_color(normal_rewrite);
|
||||
|
||||
let mut hovered = normal.clone();
|
||||
hovered.rewrite_color(hover);
|
||||
|
||||
Button::new(ctx, normal, hovered, key, tooltip, bounds.get_rectangle())
|
||||
}
|
||||
|
||||
pub fn text_bg(
|
||||
text: Text,
|
||||
unselected_bg_color: Color,
|
||||
@ -266,33 +228,52 @@ pub struct Btn {}
|
||||
|
||||
impl Btn {
|
||||
pub fn svg<I: Into<String>>(path: I, hover: RewriteColor) -> BtnBuilder {
|
||||
BtnBuilder::SVG(path.into(), hover)
|
||||
BtnBuilder::SVG(path.into(), hover, None)
|
||||
}
|
||||
|
||||
// Same as WrappedComposite::text_button
|
||||
pub fn text_fg<I: Into<String>>(label: I) -> BtnBuilder {
|
||||
BtnBuilder::TextFG(label.into())
|
||||
BtnBuilder::TextFG(label.into(), None)
|
||||
}
|
||||
|
||||
// The info panel style with the lighter background color
|
||||
pub fn text_bg1<I: Into<String>>(label: I) -> BtnBuilder {
|
||||
BtnBuilder::TextBG1(label.into())
|
||||
BtnBuilder::TextBG1(label.into(), None)
|
||||
}
|
||||
|
||||
// The white background. WrappedComposite::text_bg_button.
|
||||
pub fn text_bg2<I: Into<String>>(label: I) -> BtnBuilder {
|
||||
BtnBuilder::TextBG2(label.into())
|
||||
BtnBuilder::TextBG2(label.into(), None)
|
||||
}
|
||||
|
||||
pub fn custom(normal: GeomBatch, hovered: GeomBatch, hitbox: Polygon) -> BtnBuilder {
|
||||
BtnBuilder::Custom(normal, hovered, hitbox, None)
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BtnBuilder {
|
||||
SVG(String, RewriteColor),
|
||||
TextFG(String),
|
||||
TextBG1(String),
|
||||
TextBG2(String),
|
||||
SVG(String, RewriteColor, Option<Text>),
|
||||
TextFG(String, Option<Text>),
|
||||
TextBG1(String, Option<Text>),
|
||||
TextBG2(String, Option<Text>),
|
||||
Custom(GeomBatch, GeomBatch, Polygon, Option<Text>),
|
||||
}
|
||||
|
||||
impl BtnBuilder {
|
||||
pub fn tooltip(mut self, tooltip: Text) -> BtnBuilder {
|
||||
match self {
|
||||
BtnBuilder::SVG(_, _, ref mut t)
|
||||
| BtnBuilder::TextFG(_, ref mut t)
|
||||
| BtnBuilder::TextBG1(_, ref mut t)
|
||||
| BtnBuilder::TextBG2(_, ref mut t)
|
||||
| BtnBuilder::Custom(_, _, _, ref mut t) => {
|
||||
assert!(t.is_none());
|
||||
*t = Some(tooltip);
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build<I: Into<String>>(
|
||||
self,
|
||||
ctx: &EventCtx,
|
||||
@ -300,48 +281,86 @@ impl BtnBuilder {
|
||||
key: Option<MultiKey>,
|
||||
) -> ManagedWidget {
|
||||
match self {
|
||||
BtnBuilder::SVG(path, hover) => ManagedWidget::btn(Button::rectangle_svg(
|
||||
&path,
|
||||
&action_tooltip.into(),
|
||||
key,
|
||||
hover,
|
||||
BtnBuilder::SVG(path, hover, maybe_t) => {
|
||||
let (normal, bounds) = GeomBatch::from_svg(ctx, path, RewriteColor::NoOp);
|
||||
|
||||
let mut hovered = normal.clone();
|
||||
hovered.rewrite_color(hover);
|
||||
|
||||
let mut btn = Button::new(
|
||||
ctx,
|
||||
)),
|
||||
BtnBuilder::TextFG(label) => ManagedWidget::btn(Button::text_no_bg(
|
||||
normal,
|
||||
hovered,
|
||||
key,
|
||||
&action_tooltip.into(),
|
||||
bounds.get_rectangle(),
|
||||
);
|
||||
if let Some(t) = maybe_t {
|
||||
btn.tooltip = t;
|
||||
}
|
||||
ManagedWidget::btn(btn)
|
||||
}
|
||||
BtnBuilder::TextFG(label, maybe_t) => {
|
||||
let mut btn = Button::text_no_bg(
|
||||
Text::from(Line(&label)),
|
||||
Text::from(Line(label).fg(Color::ORANGE)),
|
||||
key,
|
||||
&action_tooltip.into(),
|
||||
true,
|
||||
ctx,
|
||||
))
|
||||
.outline(2.0, Color::WHITE),
|
||||
BtnBuilder::TextBG1(label) => ManagedWidget::btn(Button::text_bg(
|
||||
);
|
||||
if let Some(t) = maybe_t {
|
||||
btn.tooltip = t;
|
||||
}
|
||||
ManagedWidget::btn(btn).outline(2.0, Color::WHITE)
|
||||
}
|
||||
BtnBuilder::TextBG1(label, maybe_t) => {
|
||||
let mut btn = Button::text_bg(
|
||||
Text::from(Line(label)),
|
||||
Color::grey(0.5),
|
||||
Color::ORANGE,
|
||||
key,
|
||||
&action_tooltip.into(),
|
||||
ctx,
|
||||
)),
|
||||
BtnBuilder::TextBG2(label) => ManagedWidget::btn(Button::text_bg(
|
||||
);
|
||||
if let Some(t) = maybe_t {
|
||||
btn.tooltip = t;
|
||||
}
|
||||
ManagedWidget::btn(btn)
|
||||
}
|
||||
BtnBuilder::TextBG2(label, maybe_t) => {
|
||||
let mut btn = Button::text_bg(
|
||||
Text::from(Line(label).fg(Color::BLACK)),
|
||||
Color::WHITE,
|
||||
Color::ORANGE,
|
||||
key,
|
||||
&action_tooltip.into(),
|
||||
ctx,
|
||||
)),
|
||||
);
|
||||
if let Some(t) = maybe_t {
|
||||
btn.tooltip = t;
|
||||
}
|
||||
ManagedWidget::btn(btn)
|
||||
}
|
||||
BtnBuilder::Custom(normal, hovered, hitbox, maybe_t) => {
|
||||
let mut btn =
|
||||
Button::new(ctx, normal, hovered, key, &action_tooltip.into(), hitbox);
|
||||
if let Some(t) = maybe_t {
|
||||
btn.tooltip = t;
|
||||
}
|
||||
ManagedWidget::btn(btn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use the text as the action
|
||||
pub fn build_def(self, ctx: &EventCtx, hotkey: Option<MultiKey>) -> ManagedWidget {
|
||||
match self {
|
||||
BtnBuilder::SVG(_, _) => panic!("Can't use build_def on an SVG button"),
|
||||
BtnBuilder::TextFG(ref label)
|
||||
| BtnBuilder::TextBG1(ref label)
|
||||
| BtnBuilder::TextBG2(ref label) => {
|
||||
BtnBuilder::SVG(_, _, _) => panic!("Can't use build_def on an SVG button"),
|
||||
BtnBuilder::Custom(_, _, _, _) => panic!("Can't use build_def on a custom button"),
|
||||
BtnBuilder::TextFG(ref label, _)
|
||||
| BtnBuilder::TextBG1(ref label, _)
|
||||
| BtnBuilder::TextBG2(ref label, _) => {
|
||||
let copy = label.clone();
|
||||
self.build(ctx, copy, hotkey)
|
||||
}
|
||||
|
@ -984,34 +984,13 @@ fn trip_details(
|
||||
let mut zoomed = GeomBatch::new();
|
||||
let mut markers = HashMap::new();
|
||||
|
||||
let mut start_btn = Button::rectangle_svg(
|
||||
"../data/system/assets/timeline/start_pos.svg",
|
||||
"jump to start",
|
||||
None,
|
||||
RewriteColor::Change(Color::WHITE, colors::HOVERING),
|
||||
ctx,
|
||||
);
|
||||
let mut goal_btn = Button::rectangle_svg(
|
||||
"../data/system/assets/timeline/goal_pos.svg",
|
||||
"jump to goal",
|
||||
None,
|
||||
RewriteColor::Change(Color::WHITE, colors::HOVERING),
|
||||
ctx,
|
||||
);
|
||||
|
||||
let trip_start_time = phases[0].start_time;
|
||||
let trip_end_time = phases.last().as_ref().and_then(|p| p.end_time);
|
||||
|
||||
// Start
|
||||
{
|
||||
match trip_start {
|
||||
let start_tooltip = match trip_start {
|
||||
TripStart::Bldg(b) => {
|
||||
let bldg = map.get_b(b);
|
||||
|
||||
let mut txt = Text::from(Line("jump to start"));
|
||||
txt.add(Line(bldg.just_address(map)));
|
||||
txt.add(Line(phases[0].start_time.ampm_tostring()));
|
||||
start_btn = start_btn.change_tooltip(txt);
|
||||
markers.insert("jump to start".to_string(), ID::Building(b));
|
||||
|
||||
unzoomed.add_svg(
|
||||
@ -1028,14 +1007,15 @@ fn trip_details(
|
||||
0.5,
|
||||
Angle::ZERO,
|
||||
);
|
||||
|
||||
let mut txt = Text::from(Line("jump to start"));
|
||||
txt.add(Line(bldg.just_address(map)));
|
||||
txt.add(Line(phases[0].start_time.ampm_tostring()));
|
||||
txt
|
||||
}
|
||||
TripStart::Border(i) => {
|
||||
let i = map.get_i(i);
|
||||
|
||||
let mut txt = Text::from(Line("jump to start"));
|
||||
txt.add(Line(i.name(map)));
|
||||
txt.add(Line(phases[0].start_time.ampm_tostring()));
|
||||
start_btn = start_btn.change_tooltip(txt);
|
||||
markers.insert("jump to start".to_string(), ID::Intersection(i.id));
|
||||
|
||||
unzoomed.add_svg(
|
||||
@ -1052,22 +1032,24 @@ fn trip_details(
|
||||
0.5,
|
||||
Angle::ZERO,
|
||||
);
|
||||
|
||||
let mut txt = Text::from(Line("jump to start"));
|
||||
txt.add(Line(i.name(map)));
|
||||
txt.add(Line(phases[0].start_time.ampm_tostring()));
|
||||
txt
|
||||
}
|
||||
};
|
||||
}
|
||||
let start_btn = Btn::svg(
|
||||
"../data/system/assets/timeline/start_pos.svg",
|
||||
RewriteColor::Change(Color::WHITE, colors::HOVERING),
|
||||
)
|
||||
.tooltip(start_tooltip)
|
||||
.build(ctx, "jump to start", None);
|
||||
|
||||
// Goal
|
||||
{
|
||||
match trip_end {
|
||||
let goal_tooltip = match trip_end {
|
||||
TripEnd::Bldg(b) => {
|
||||
let bldg = map.get_b(b);
|
||||
|
||||
let mut txt = Text::from(Line("jump to goal"));
|
||||
txt.add(Line(bldg.just_address(map)));
|
||||
if let Some(t) = trip_end_time {
|
||||
txt.add(Line(t.ampm_tostring()));
|
||||
}
|
||||
goal_btn = goal_btn.change_tooltip(txt);
|
||||
markers.insert("jump to goal".to_string(), ID::Building(b));
|
||||
|
||||
unzoomed.add_svg(
|
||||
@ -1084,16 +1066,17 @@ fn trip_details(
|
||||
0.5,
|
||||
Angle::ZERO,
|
||||
);
|
||||
|
||||
let mut txt = Text::from(Line("jump to goal"));
|
||||
txt.add(Line(bldg.just_address(map)));
|
||||
if let Some(t) = trip_end_time {
|
||||
txt.add(Line(t.ampm_tostring()));
|
||||
}
|
||||
txt
|
||||
}
|
||||
TripEnd::Border(i) => {
|
||||
let i = map.get_i(i);
|
||||
|
||||
let mut txt = Text::from(Line("jump to goal"));
|
||||
txt.add(Line(i.name(map)));
|
||||
if let Some(t) = trip_end_time {
|
||||
txt.add(Line(t.ampm_tostring()));
|
||||
}
|
||||
goal_btn = goal_btn.change_tooltip(txt);
|
||||
markers.insert("jump to goal".to_string(), ID::Intersection(i.id));
|
||||
|
||||
unzoomed.add_svg(
|
||||
@ -1110,10 +1093,22 @@ fn trip_details(
|
||||
0.5,
|
||||
Angle::ZERO,
|
||||
);
|
||||
|
||||
let mut txt = Text::from(Line("jump to goal"));
|
||||
txt.add(Line(i.name(map)));
|
||||
if let Some(t) = trip_end_time {
|
||||
txt.add(Line(t.ampm_tostring()));
|
||||
}
|
||||
txt
|
||||
}
|
||||
TripEnd::ServeBusRoute(_) => unreachable!(),
|
||||
};
|
||||
}
|
||||
let goal_btn = Btn::svg(
|
||||
"../data/system/assets/timeline/goal_pos.svg",
|
||||
RewriteColor::Change(Color::WHITE, colors::HOVERING),
|
||||
)
|
||||
.tooltip(goal_tooltip)
|
||||
.build(ctx, "jump to goal", None);
|
||||
|
||||
let total_duration_so_far =
|
||||
trip_end_time.unwrap_or_else(|| app.primary.sim.time()) - phases[0].start_time;
|
||||
@ -1194,17 +1189,8 @@ fn trip_details(
|
||||
}
|
||||
|
||||
timeline.push(
|
||||
ManagedWidget::btn(
|
||||
Button::new(
|
||||
ctx,
|
||||
normal,
|
||||
hovered,
|
||||
None,
|
||||
&format!("examine trip phase {}", idx + 1),
|
||||
rect,
|
||||
)
|
||||
.change_tooltip(txt),
|
||||
)
|
||||
Btn::custom(normal, hovered, rect)
|
||||
.build(ctx, format!("examine trip phase {}", idx + 1), None)
|
||||
.centered_vert(),
|
||||
);
|
||||
|
||||
@ -1237,8 +1223,8 @@ fn trip_details(
|
||||
}
|
||||
}
|
||||
|
||||
timeline.insert(0, ManagedWidget::btn(start_btn).margin(5));
|
||||
timeline.push(ManagedWidget::btn(goal_btn).margin(5));
|
||||
timeline.insert(0, start_btn.margin(5));
|
||||
timeline.push(goal_btn.margin(5));
|
||||
|
||||
let mut table = vec![
|
||||
("Trip start".to_string(), trip_start_time.ampm_tostring()),
|
||||
|
@ -6,7 +6,7 @@ use crate::managed::WrappedComposite;
|
||||
use crate::render::{AgentColorScheme, MIN_ZOOM_FOR_DETAIL};
|
||||
use abstutil::clamp;
|
||||
use ezgui::{
|
||||
hotkey, Btn, Button, Choice, Color, Composite, EventCtx, Filler, GeomBatch, GfxCtx,
|
||||
hotkey, Btn, Choice, Color, Composite, EventCtx, Filler, GeomBatch, GfxCtx,
|
||||
HorizontalAlignment, Key, Line, ManagedWidget, Outcome, RewriteColor, ScreenDims, ScreenPt,
|
||||
Text, VerticalAlignment,
|
||||
};
|
||||
@ -294,14 +294,14 @@ fn make_minimap_panel(ctx: &mut EventCtx, acs: &AgentColorScheme, zoom_lvl: usiz
|
||||
Color::WHITE
|
||||
};
|
||||
let rect = Polygon::rectangle(20.0, 8.0);
|
||||
zoom_col.push(ManagedWidget::btn(Button::new(
|
||||
ctx,
|
||||
zoom_col.push(
|
||||
Btn::custom(
|
||||
GeomBatch::from(vec![(color, rect.clone())]),
|
||||
GeomBatch::from(vec![(colors::HOVERING, rect.clone())]),
|
||||
None,
|
||||
&format!("zoom to level {}", i + 1),
|
||||
rect,
|
||||
)));
|
||||
)
|
||||
.build(ctx, format!("zoom to level {}", i + 1), None),
|
||||
);
|
||||
}
|
||||
zoom_col.push(
|
||||
Btn::svg(
|
||||
@ -422,19 +422,23 @@ fn make_viz_panel(ctx: &mut EventCtx, acs: &AgentColorScheme) -> ManagedWidget {
|
||||
for (label, color, enabled) in &acs.rows {
|
||||
col.push(
|
||||
ManagedWidget::row(vec![
|
||||
ManagedWidget::btn(Button::rectangle_svg_rewrite(
|
||||
{
|
||||
let (normal, bounds) = GeomBatch::from_svg(
|
||||
ctx,
|
||||
"../data/system/assets/tools/visibility.svg",
|
||||
&format!("show/hide {}", label),
|
||||
None,
|
||||
if *enabled {
|
||||
RewriteColor::NoOp
|
||||
} else {
|
||||
RewriteColor::ChangeAll(Color::WHITE.alpha(0.5))
|
||||
},
|
||||
RewriteColor::ChangeAll(colors::HOVERING),
|
||||
ctx,
|
||||
))
|
||||
.margin(3),
|
||||
);
|
||||
let mut hovered = normal.clone();
|
||||
hovered.rewrite_color(RewriteColor::ChangeAll(colors::HOVERING));
|
||||
|
||||
Btn::custom(normal, hovered, bounds.get_rectangle())
|
||||
.build(ctx, format!("show/hide {}", label), None)
|
||||
.margin(3)
|
||||
},
|
||||
ManagedWidget::draw_batch(
|
||||
ctx,
|
||||
GeomBatch::from(vec![(
|
||||
|
@ -5,7 +5,7 @@ use crate::options::TrafficSignalStyle;
|
||||
use crate::render::intersection::make_crosswalk;
|
||||
use crate::render::{DrawTurnGroup, BIG_ARROW_THICKNESS};
|
||||
use ezgui::{
|
||||
hotkey, Button, Color, Composite, EventCtx, GeomBatch, HorizontalAlignment, Key, Line,
|
||||
hotkey, Btn, Color, Composite, EventCtx, GeomBatch, HorizontalAlignment, Key, Line,
|
||||
ManagedWidget, Prerender, Text, TextExt, VerticalAlignment,
|
||||
};
|
||||
use geom::{Angle, Circle, Distance, Duration, Line, PolyLine, Polygon, Pt2D};
|
||||
@ -316,14 +316,8 @@ pub fn make_signal_diagram(
|
||||
hovered.push(Color::RED, bbox.to_outline(Distance::meters(5.0)));
|
||||
|
||||
phase_rows.push(
|
||||
ManagedWidget::btn(Button::new(
|
||||
ctx,
|
||||
normal,
|
||||
hovered,
|
||||
None,
|
||||
&format!("phase {}", idx + 1),
|
||||
bbox.clone(),
|
||||
))
|
||||
Btn::custom(normal, hovered, bbox.clone())
|
||||
.build(ctx, format!("phase {}", idx + 1), None)
|
||||
.margin(5),
|
||||
);
|
||||
|
||||
|
@ -65,27 +65,27 @@ impl SpeedControls {
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(s, label)| {
|
||||
let mut tooltip = Text::from(Line(label).size(20));
|
||||
tooltip.add(Line(Key::LeftArrow.describe()).fg(Color::GREEN).size(20));
|
||||
tooltip.append(Line(" - slow down"));
|
||||
tooltip.add(Line(Key::RightArrow.describe()).fg(Color::GREEN).size(20));
|
||||
tooltip.append(Line(" - speed up"));
|
||||
let mut txt = Text::from(Line(label).size(20));
|
||||
txt.add(Line(Key::LeftArrow.describe()).fg(Color::GREEN).size(20));
|
||||
txt.append(Line(" - slow down"));
|
||||
txt.add(Line(Key::RightArrow.describe()).fg(Color::GREEN).size(20));
|
||||
txt.append(Line(" - speed up"));
|
||||
|
||||
ManagedWidget::btn(
|
||||
Button::rectangle_svg_rewrite(
|
||||
let (normal, bounds) = GeomBatch::from_svg(
|
||||
ctx,
|
||||
"../data/system/assets/speed/triangle.svg",
|
||||
label,
|
||||
None,
|
||||
if setting >= s {
|
||||
RewriteColor::NoOp
|
||||
} else {
|
||||
RewriteColor::ChangeAll(Color::WHITE.alpha(0.2))
|
||||
},
|
||||
RewriteColor::ChangeAll(colors::HOVERING),
|
||||
ctx,
|
||||
)
|
||||
.change_tooltip(tooltip),
|
||||
)
|
||||
);
|
||||
let mut hovered = normal.clone();
|
||||
hovered.rewrite_color(RewriteColor::ChangeAll(colors::HOVERING));
|
||||
|
||||
Btn::custom(normal, hovered, bounds.get_rectangle())
|
||||
.tooltip(txt)
|
||||
.build(ctx, label, None)
|
||||
.margin(5)
|
||||
})
|
||||
.collect(),
|
||||
|
Loading…
Reference in New Issue
Block a user