mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-27 00:12:55 +03:00
draw menus centered in the screen, with highlighted lines
This commit is contained in:
parent
96994eb9bd
commit
c7f2c50e25
@ -86,10 +86,7 @@ impl ColorPicker {
|
||||
match self {
|
||||
ColorPicker::Inactive => {}
|
||||
ColorPicker::Choosing(menu) => {
|
||||
// TODO sloppy to use a mouse tooltip. ideally should be easy to figure out how
|
||||
// many lines to display and center it.
|
||||
// TODO would be nice to display the text in the current color
|
||||
canvas.draw_mouse_tooltip(g, &menu.lines_to_display());
|
||||
canvas.draw_centered_text(g, menu.get_osd());
|
||||
}
|
||||
ColorPicker::PickingColor(_, _) => {
|
||||
let (start_x, start_y) = get_screen_offset(canvas);
|
||||
|
@ -164,8 +164,8 @@ impl DrawPolygonState {
|
||||
return;
|
||||
}
|
||||
DrawPolygonState::ListingPolygons(menu) => {
|
||||
// TODO urgh, dont do this
|
||||
canvas.draw_mouse_tooltip(g, &menu.lines_to_display());
|
||||
canvas.draw_centered_text(g, menu.get_osd());
|
||||
// TODO display the current polygon
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -81,10 +81,15 @@ impl Canvas {
|
||||
}
|
||||
|
||||
pub fn draw_mouse_tooltip(&self, g: &mut GfxCtx, lines: &[String]) {
|
||||
let (width, height) = text::dims(g, lines);
|
||||
let mut osd = TextOSD::new();
|
||||
for l in lines {
|
||||
osd.add_line(l.clone());
|
||||
}
|
||||
|
||||
let (width, height) = osd.dims(g);
|
||||
let x1 = self.cursor_x - (width / 2.0);
|
||||
let y1 = self.cursor_y - (height / 2.0);
|
||||
text::draw_text_bubble(g, lines, (x1, y1), None);
|
||||
text::draw_text_bubble(g, (x1, y1), osd);
|
||||
}
|
||||
|
||||
// at the bottom-left of the screen
|
||||
@ -92,13 +97,27 @@ impl Canvas {
|
||||
if osd.is_empty() {
|
||||
return;
|
||||
}
|
||||
let (_, height) = text::dims(g, &osd.lines);
|
||||
let (_, height) = osd.dims(g);
|
||||
let y1 = f64::from(self.window_size.height) - height;
|
||||
text::draw_text_bubble(g, &osd.lines, (0.0, y1), osd.highlight_char);
|
||||
text::draw_text_bubble(g, (0.0, y1), osd);
|
||||
}
|
||||
|
||||
pub fn draw_centered_text(&self, g: &mut GfxCtx, osd: TextOSD) {
|
||||
if osd.is_empty() {
|
||||
return;
|
||||
}
|
||||
let (width, height) = osd.dims(g);
|
||||
let x1 = (f64::from(self.window_size.width) - width) / 2.0;
|
||||
let y1 = (f64::from(self.window_size.height) - height) / 2.0;
|
||||
text::draw_text_bubble(g, (x1, y1), osd);
|
||||
}
|
||||
|
||||
pub fn draw_text_at(&self, g: &mut GfxCtx, lines: &[String], pt: Pt2D) {
|
||||
text::draw_text_bubble(g, lines, self.map_to_screen(pt), None);
|
||||
let mut osd = TextOSD::new();
|
||||
for l in lines {
|
||||
osd.add_line(l.clone());
|
||||
}
|
||||
text::draw_text_bubble(g, self.map_to_screen(pt), osd);
|
||||
}
|
||||
|
||||
fn zoom_towards_mouse(&mut self, delta_zoom: f64) {
|
||||
|
@ -1,6 +1,5 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use piston::input::{Button, Event, Key, PressEvent};
|
||||
use TextOSD;
|
||||
|
||||
pub enum MenuResult {
|
||||
Canceled,
|
||||
@ -45,10 +44,17 @@ impl Menu {
|
||||
MenuResult::StillActive
|
||||
}
|
||||
|
||||
pub fn lines_to_display(&self) -> Vec<String> {
|
||||
// TODO dont copy
|
||||
let mut copy = self.choices.clone();
|
||||
copy[self.current_idx] = format!("---> {}", copy[self.current_idx]);
|
||||
copy
|
||||
// TODO different API... handle menus bigger than the screen, actually do scroll. maybe always
|
||||
// display one size for the menu, just dont fill everything out
|
||||
pub fn get_osd(&self) -> TextOSD {
|
||||
let mut osd = TextOSD::new();
|
||||
for (idx, line) in self.choices.iter().enumerate() {
|
||||
if self.current_idx == idx {
|
||||
osd.add_highlighted_line(line.clone());
|
||||
} else {
|
||||
osd.add_line(line.clone());
|
||||
}
|
||||
}
|
||||
osd
|
||||
}
|
||||
}
|
||||
|
@ -16,9 +16,11 @@ const LINE_HEIGHT: f64 = 22.0;
|
||||
|
||||
// TODO I kind of want general HTMLish markup options here -- bold, italic, underline, color, etc
|
||||
pub struct TextOSD {
|
||||
pub(crate) lines: Vec<String>,
|
||||
lines: Vec<String>,
|
||||
// (Line, character) indices
|
||||
pub(crate) highlight_char: Option<(usize, usize)>,
|
||||
// Can have one of each, sure, why not
|
||||
highlight_char: Option<(usize, usize)>,
|
||||
highlight_line: Option<usize>,
|
||||
}
|
||||
|
||||
impl TextOSD {
|
||||
@ -26,6 +28,7 @@ impl TextOSD {
|
||||
TextOSD {
|
||||
lines: Vec::new(),
|
||||
highlight_char: None,
|
||||
highlight_line: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,18 +50,26 @@ impl TextOSD {
|
||||
self.lines.push(line);
|
||||
}
|
||||
|
||||
pub fn add_highlighted_line(&mut self, line: String) {
|
||||
assert!(self.highlight_line.is_none());
|
||||
self.highlight_line = Some(self.lines.len());
|
||||
self.lines.push(line);
|
||||
}
|
||||
|
||||
pub(crate) fn is_empty(&self) -> bool {
|
||||
self.lines.is_empty()
|
||||
}
|
||||
|
||||
pub fn dims(&self, g: &mut GfxCtx) -> (f64, f64) {
|
||||
let longest_line = self.lines.iter().max_by_key(|l| l.len()).unwrap();
|
||||
let width = g.glyphs.width(FONT_SIZE, longest_line).unwrap();
|
||||
let height = (self.lines.len() as f64) * LINE_HEIGHT;
|
||||
(width, height)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_text_bubble(
|
||||
g: &mut GfxCtx,
|
||||
lines: &[String],
|
||||
(x1, y1): (f64, f64),
|
||||
highlight_char: Option<(usize, usize)>,
|
||||
) {
|
||||
let (width, height) = dims(g, lines);
|
||||
pub fn draw_text_bubble(g: &mut GfxCtx, (x1, y1): (f64, f64), osd: TextOSD) {
|
||||
let (width, height) = osd.dims(g);
|
||||
graphics::Rectangle::new(TEXT_BG_COLOR).draw(
|
||||
[x1, y1, width, height],
|
||||
&g.orig_ctx.draw_state,
|
||||
@ -68,15 +79,25 @@ pub fn draw_text_bubble(
|
||||
|
||||
let fg_text = Image::new_color(TEXT_FG_COLOR);
|
||||
let mut y = y1 + LINE_HEIGHT;
|
||||
for (line_idx, line) in lines.iter().enumerate() {
|
||||
for (line_idx, line) in osd.lines.iter().enumerate() {
|
||||
let mut x = x1;
|
||||
|
||||
if Some(line_idx) == osd.highlight_line {
|
||||
graphics::Rectangle::new(TEXT_HIGHLIGHT_COLOR).draw(
|
||||
[x, y - LINE_HEIGHT, width, LINE_HEIGHT],
|
||||
&g.orig_ctx.draw_state,
|
||||
g.orig_ctx.transform,
|
||||
g.gfx,
|
||||
);
|
||||
}
|
||||
|
||||
for (char_idx, ch) in line.chars().enumerate() {
|
||||
if let Ok(draw_ch) = g.glyphs.character(FONT_SIZE, ch) {
|
||||
let char_ctx = g
|
||||
.orig_ctx
|
||||
.transform
|
||||
.trans(x + draw_ch.left(), y - draw_ch.top());
|
||||
if Some((line_idx, char_idx)) == highlight_char {
|
||||
if Some((line_idx, char_idx)) == osd.highlight_char {
|
||||
graphics::Rectangle::new(TEXT_HIGHLIGHT_COLOR).draw(
|
||||
[0.0, 0.0, draw_ch.width(), LINE_HEIGHT],
|
||||
&g.orig_ctx.draw_state,
|
||||
@ -90,7 +111,7 @@ pub fn draw_text_bubble(
|
||||
panic!("Couldn't get glyph for {}", ch);
|
||||
}
|
||||
}
|
||||
if Some((line_idx, line.len())) == highlight_char {
|
||||
if Some((line_idx, line.len())) == osd.highlight_char {
|
||||
graphics::Rectangle::new(TEXT_HIGHLIGHT_COLOR).draw(
|
||||
[x, y - LINE_HEIGHT, END_OF_LINE_CURSOR_WIDTH, LINE_HEIGHT],
|
||||
&g.orig_ctx.draw_state,
|
||||
@ -101,10 +122,3 @@ pub fn draw_text_bubble(
|
||||
y += LINE_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dims(g: &mut GfxCtx, lines: &[String]) -> (f64, f64) {
|
||||
let longest_line = lines.iter().max_by_key(|l| l.len()).unwrap();
|
||||
let width = g.glyphs.width(FONT_SIZE, longest_line).unwrap();
|
||||
let height = (lines.len() as f64) * LINE_HEIGHT;
|
||||
(width, height)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user