mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 12:43:38 +03:00
can only type in text boxes with focus
This commit is contained in:
parent
e8bb993dfd
commit
c316d918d7
@ -40,6 +40,7 @@ pub struct Canvas {
|
||||
|
||||
// Kind of just ezgui state awkwardly stuck here...
|
||||
pub(crate) lctrl_held: bool,
|
||||
pub(crate) lshift_held: bool,
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
@ -66,6 +67,7 @@ impl Canvas {
|
||||
covered_areas: RefCell::new(Vec::new()),
|
||||
|
||||
lctrl_held: false,
|
||||
lshift_held: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
use crate::layout::Widget;
|
||||
use crate::text;
|
||||
use crate::widgets::{Checkbox, Dropdown, PopupMenu, TextBox};
|
||||
use crate::{
|
||||
Button, Choice, Color, Drawable, EventCtx, Filler, GeomBatch, GfxCtx, Histogram,
|
||||
@ -322,9 +321,14 @@ impl ManagedWidget {
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn text_entry(ctx: &EventCtx, prefilled: String) -> ManagedWidget {
|
||||
pub fn text_entry(ctx: &EventCtx, prefilled: String, exclusive_focus: bool) -> ManagedWidget {
|
||||
// TODO Hardcoded style, max chars
|
||||
ManagedWidget::new(WidgetType::TextBox(TextBox::new(ctx, 50, prefilled))).bg(text::BG_COLOR)
|
||||
ManagedWidget::new(WidgetType::TextBox(TextBox::new(
|
||||
ctx,
|
||||
50,
|
||||
prefilled,
|
||||
exclusive_focus,
|
||||
)))
|
||||
}
|
||||
|
||||
pub fn dropdown<T: 'static + PartialEq>(
|
||||
|
@ -61,6 +61,12 @@ impl<G: GUI> State<G> {
|
||||
if input.event == Event::KeyRelease(Key::LeftControl) {
|
||||
self.canvas.lctrl_held = false;
|
||||
}
|
||||
if input.event == Event::KeyPress(Key::LeftShift) {
|
||||
self.canvas.lshift_held = true;
|
||||
}
|
||||
if input.event == Event::KeyRelease(Key::LeftShift) {
|
||||
self.canvas.lshift_held = false;
|
||||
}
|
||||
|
||||
if let Some(pt) = input.get_moved_mouse() {
|
||||
self.canvas.cursor_x = pt.x;
|
||||
|
@ -67,10 +67,6 @@ impl Button {
|
||||
self
|
||||
}
|
||||
|
||||
fn get_hitbox(&self) -> Polygon {
|
||||
self.hitbox.translate(self.top_left.x, self.top_left.y)
|
||||
}
|
||||
|
||||
pub(crate) fn event(&mut self, ctx: &mut EventCtx) {
|
||||
if self.clicked {
|
||||
panic!("Caller didn't consume button click");
|
||||
@ -78,7 +74,10 @@ impl Button {
|
||||
|
||||
if ctx.redo_mouseover() {
|
||||
if let Some(pt) = ctx.canvas.get_cursor_in_screen_space() {
|
||||
self.hovering = self.get_hitbox().contains_pt(pt.to_pt());
|
||||
self.hovering = self
|
||||
.hitbox
|
||||
.translate(self.top_left.x, self.top_left.y)
|
||||
.contains_pt(pt.to_pt());
|
||||
} else {
|
||||
self.hovering = false;
|
||||
}
|
||||
|
@ -1,24 +1,31 @@
|
||||
use crate::layout::Widget;
|
||||
use crate::{text, EventCtx, GfxCtx, Key, Line, ScreenDims, ScreenPt, Text};
|
||||
use crate::{
|
||||
text, Color, EventCtx, GeomBatch, GfxCtx, Key, Line, ScreenDims, ScreenPt, ScreenRectangle,
|
||||
Text,
|
||||
};
|
||||
use geom::Polygon;
|
||||
|
||||
// TODO right now, only a single line
|
||||
|
||||
pub struct TextBox {
|
||||
// TODO A rope would be cool.
|
||||
line: String,
|
||||
cursor_x: usize,
|
||||
shift_pressed: bool,
|
||||
has_focus: bool,
|
||||
hovering: bool,
|
||||
autofocus: bool,
|
||||
|
||||
top_left: ScreenPt,
|
||||
dims: ScreenDims,
|
||||
}
|
||||
|
||||
impl TextBox {
|
||||
pub fn new(ctx: &EventCtx, max_chars: usize, prefilled: String) -> TextBox {
|
||||
pub fn new(ctx: &EventCtx, max_chars: usize, prefilled: String, autofocus: bool) -> TextBox {
|
||||
TextBox {
|
||||
cursor_x: prefilled.len(),
|
||||
line: prefilled,
|
||||
shift_pressed: false,
|
||||
has_focus: false,
|
||||
hovering: false,
|
||||
autofocus,
|
||||
|
||||
top_left: ScreenPt::new(0.0, 0.0),
|
||||
dims: ScreenDims::new(
|
||||
@ -29,11 +36,26 @@ impl TextBox {
|
||||
}
|
||||
|
||||
pub fn event(&mut self, ctx: &mut EventCtx) {
|
||||
if ctx.redo_mouseover() {
|
||||
if let Some(pt) = ctx.canvas.get_cursor_in_screen_space() {
|
||||
self.hovering = ScreenRectangle::top_left(self.top_left, self.dims).contains(pt);
|
||||
} else {
|
||||
self.hovering = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.normal_left_click() {
|
||||
// Let all textboxes see this event, so they can deactivate their own focus.
|
||||
// TODO But if a button is clicked before this textbox, that event isn't seen here...
|
||||
ctx.input.unconsume_event();
|
||||
self.has_focus = self.hovering;
|
||||
}
|
||||
|
||||
if !self.has_focus && !self.autofocus {
|
||||
return;
|
||||
}
|
||||
if let Some(key) = ctx.input.any_key_pressed() {
|
||||
match key {
|
||||
Key::LeftShift => {
|
||||
self.shift_pressed = true;
|
||||
}
|
||||
Key::LeftArrow => {
|
||||
if self.cursor_x > 0 {
|
||||
self.cursor_x -= 1;
|
||||
@ -49,7 +71,7 @@ impl TextBox {
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
if let Some(c) = key.to_char(self.shift_pressed) {
|
||||
if let Some(c) = key.to_char(ctx.canvas.lshift_held) {
|
||||
self.line.insert(self.cursor_x, c);
|
||||
self.cursor_x += 1;
|
||||
} else {
|
||||
@ -58,12 +80,20 @@ impl TextBox {
|
||||
}
|
||||
};
|
||||
}
|
||||
if ctx.input.key_released(Key::LeftShift) {
|
||||
self.shift_pressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(&self, g: &mut GfxCtx) {
|
||||
let bg = g.upload(GeomBatch::from(vec![(
|
||||
if self.has_focus || self.autofocus {
|
||||
Color::ORANGE
|
||||
} else if self.hovering {
|
||||
Color::ORANGE.alpha(0.5)
|
||||
} else {
|
||||
text::BG_COLOR
|
||||
},
|
||||
Polygon::rectangle(self.dims.width, self.dims.height),
|
||||
)]));
|
||||
g.redraw_at(self.top_left, &bg);
|
||||
g.draw_blocking_text_at_screenspace_topleft(self.calculate_text(), self.top_left);
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ impl Wizard {
|
||||
.margin(5)
|
||||
.align_right(),
|
||||
]),
|
||||
ManagedWidget::text_entry(ctx, prefilled.unwrap_or_else(String::new))
|
||||
ManagedWidget::text_entry(ctx, prefilled.unwrap_or_else(String::new), true)
|
||||
.named("input"),
|
||||
ManagedWidget::btn(Button::text_bg(
|
||||
Text::from(Line("Done").fg(Color::BLACK)),
|
||||
|
@ -61,18 +61,20 @@ impl EditMetadata {
|
||||
"Who mapped this signal? (Feel free to remain anonymous.)",
|
||||
)),
|
||||
),
|
||||
ManagedWidget::text_entry(ctx, data.observed.author).named("observed author"),
|
||||
ManagedWidget::text_entry(ctx, data.observed.author, false)
|
||||
.named("observed author"),
|
||||
ManagedWidget::draw_text(
|
||||
ctx,
|
||||
Text::from(Line("When was this signal mapped? TODO format")),
|
||||
),
|
||||
ManagedWidget::text_entry(ctx, data.observed.datetime)
|
||||
ManagedWidget::text_entry(ctx, data.observed.datetime, false)
|
||||
.named("observed datetime"),
|
||||
ManagedWidget::draw_text(
|
||||
ctx,
|
||||
Text::from(Line("Any other observations about the signal?")),
|
||||
),
|
||||
ManagedWidget::text_entry(ctx, data.observed.notes).named("observed notes"),
|
||||
ManagedWidget::text_entry(ctx, data.observed.notes, false)
|
||||
.named("observed notes"),
|
||||
ManagedWidget::draw_text(
|
||||
ctx,
|
||||
Text::from(
|
||||
@ -86,17 +88,18 @@ impl EditMetadata {
|
||||
"Who audited this signal? (Feel free to remain anonymous.)",
|
||||
)),
|
||||
),
|
||||
ManagedWidget::text_entry(ctx, audited.author).named("audited author"),
|
||||
ManagedWidget::text_entry(ctx, audited.author, false).named("audited author"),
|
||||
ManagedWidget::draw_text(
|
||||
ctx,
|
||||
Text::from(Line("When was this signal audited? TODO format")),
|
||||
),
|
||||
ManagedWidget::text_entry(ctx, audited.datetime).named("audited datetime"),
|
||||
ManagedWidget::text_entry(ctx, audited.datetime, false)
|
||||
.named("audited datetime"),
|
||||
ManagedWidget::draw_text(
|
||||
ctx,
|
||||
Text::from(Line("Any other notes about auditing the signal?")),
|
||||
),
|
||||
ManagedWidget::text_entry(ctx, audited.notes).named("audited notes"),
|
||||
ManagedWidget::text_entry(ctx, audited.notes, false).named("audited notes"),
|
||||
WrappedComposite::text_bg_button(ctx, "Done", hotkey(Key::Enter))
|
||||
.centered_horiz(),
|
||||
])
|
||||
|
Loading…
Reference in New Issue
Block a user