Merge pull request #211 from xliiv/dialog-focus

Add get_current_focus to Dialog & make public enum Focus
This commit is contained in:
Alexandre Bury 2018-02-18 14:48:39 -08:00 committed by GitHub
commit 179c804df8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 19 deletions

View File

@ -13,9 +13,14 @@ use vec::{Vec2, Vec4};
use view::{AnyView, Selector, View}; use view::{AnyView, Selector, View};
use views::{Button, DummyView, SizedView, TextView}; use views::{Button, DummyView, SizedView, TextView};
#[derive(PartialEq)] /// Identifies currently focused element in [`Dialog`].
enum Focus { ///
/// [`Dialog`]: struct.Dialog.html
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum DialogFocus {
/// Content element focused
Content, Content,
/// One of buttons focused
Button(usize), Button(usize),
} }
@ -66,7 +71,7 @@ pub struct Dialog {
borders: Vec4, borders: Vec4,
// The current element in focus // The current element in focus
focus: Focus, focus: DialogFocus,
// How to align the buttons under the view. // How to align the buttons under the view.
align: Align, align: Align,
@ -89,7 +94,7 @@ impl Dialog {
buttons: Vec::new(), buttons: Vec::new(),
title: String::new(), title: String::new(),
title_position: HAlign::Center, title_position: HAlign::Center,
focus: Focus::Content, focus: DialogFocus::Content,
padding: Vec4::new(1, 1, 0, 0), padding: Vec4::new(1, 1, 0, 0),
borders: Vec4::new(1, 1, 1, 1), borders: Vec4::new(1, 1, 1, 1),
align: Align::top_right(), align: Align::top_right(),
@ -244,6 +249,11 @@ impl Dialog {
Box::new(self.buttons.iter_mut().map(|b| &mut b.button.view)) Box::new(self.buttons.iter_mut().map(|b| &mut b.button.view))
} }
/// Returns currently focused element
pub fn focus(&self) -> DialogFocus {
self.focus
}
// Private methods // Private methods
// An event is received while the content is in focus // An event is received while the content is in focus
@ -257,7 +267,7 @@ impl Dialog {
| Event::Key(Key::Tab) | Event::Key(Key::Tab)
| Event::Shift(Key::Tab) => { | Event::Shift(Key::Tab) => {
// Default to leftmost button when going down. // Default to leftmost button when going down.
self.focus = Focus::Button(0); self.focus = DialogFocus::Button(0);
EventResult::Consumed(None) EventResult::Consumed(None)
} }
_ => EventResult::Ignored, _ => EventResult::Ignored,
@ -283,7 +293,7 @@ impl Dialog {
// Up goes back to the content // Up goes back to the content
Event::Key(Key::Up) => { Event::Key(Key::Up) => {
if self.content.take_focus(Direction::down()) { if self.content.take_focus(Direction::down()) {
self.focus = Focus::Content; self.focus = DialogFocus::Content;
EventResult::Consumed(None) EventResult::Consumed(None)
} else { } else {
EventResult::Ignored EventResult::Ignored
@ -291,7 +301,7 @@ impl Dialog {
} }
Event::Shift(Key::Tab) => { Event::Shift(Key::Tab) => {
if self.content.take_focus(Direction::back()) { if self.content.take_focus(Direction::back()) {
self.focus = Focus::Content; self.focus = DialogFocus::Content;
EventResult::Consumed(None) EventResult::Consumed(None)
} else { } else {
EventResult::Ignored EventResult::Ignored
@ -299,7 +309,7 @@ impl Dialog {
} }
Event::Key(Key::Tab) => { Event::Key(Key::Tab) => {
if self.content.take_focus(Direction::front()) { if self.content.take_focus(Direction::front()) {
self.focus = Focus::Content; self.focus = DialogFocus::Content;
EventResult::Consumed(None) EventResult::Consumed(None)
} else { } else {
EventResult::Ignored EventResult::Ignored
@ -309,11 +319,11 @@ impl Dialog {
Event::Key(Key::Right) Event::Key(Key::Right)
if button_id + 1 < self.buttons.len() => if button_id + 1 < self.buttons.len() =>
{ {
self.focus = Focus::Button(button_id + 1); self.focus = DialogFocus::Button(button_id + 1);
EventResult::Consumed(None) EventResult::Consumed(None)
} }
Event::Key(Key::Left) if button_id > 0 => { Event::Key(Key::Left) if button_id > 0 => {
self.focus = Focus::Button(button_id - 1); self.focus = DialogFocus::Button(button_id - 1);
EventResult::Consumed(None) EventResult::Consumed(None)
} }
_ => EventResult::Ignored, _ => EventResult::Ignored,
@ -357,7 +367,7 @@ impl Dialog {
button.button.draw(&printer.sub_printer( button.button.draw(&printer.sub_printer(
position, position,
size, size,
self.focus == Focus::Button(i), self.focus == DialogFocus::Button(i),
)); ));
// Keep 1 blank between two buttons // Keep 1 blank between two buttons
offset += size.x + 1; offset += size.x + 1;
@ -381,7 +391,7 @@ impl Dialog {
self.content.draw(&printer.sub_printer( self.content.draw(&printer.sub_printer(
self.borders.top_left() + self.padding.top_left(), self.borders.top_left() + self.padding.top_left(),
inner_size, inner_size,
self.focus == Focus::Content, self.focus == DialogFocus::Content,
)); ));
} }
@ -429,7 +439,7 @@ impl Dialog {
// If position fits there... // If position fits there...
position.fits_in_rect(btn.offset.get(), btn.button.size) position.fits_in_rect(btn.offset.get(), btn.button.size)
}) { }) {
self.focus = Focus::Button(i); self.focus = DialogFocus::Button(i);
} else if position.fits_in_rect( } else if position.fits_in_rect(
(self.padding + self.borders).top_left(), (self.padding + self.borders).top_left(),
self.content.size, self.content.size,
@ -437,7 +447,7 @@ impl Dialog {
&& self.content.take_focus(Direction::none()) && self.content.take_focus(Direction::none())
{ {
// Or did we click the content? // Or did we click the content?
self.focus = Focus::Content; self.focus = DialogFocus::Content;
} }
} }
} }
@ -531,9 +541,9 @@ impl View for Dialog {
match self.focus { match self.focus {
// If we are on the content, we can only go down. // If we are on the content, we can only go down.
// TODO: Careful if/when we add buttons elsewhere on the dialog! // TODO: Careful if/when we add buttons elsewhere on the dialog!
Focus::Content => self.on_event_content(event), DialogFocus::Content => self.on_event_content(event),
// If we are on a button, we have more choice // If we are on a button, we have more choice
Focus::Button(i) => self.on_event_button(event, i), DialogFocus::Button(i) => self.on_event_button(event, i),
} }
} }
@ -541,10 +551,10 @@ impl View for Dialog {
// Dialogs aren't meant to be used in layouts, so... // Dialogs aren't meant to be used in layouts, so...
// Let's be super lazy and not even care about the focus source. // Let's be super lazy and not even care about the focus source.
if self.content.take_focus(source) { if self.content.take_focus(source) {
self.focus = Focus::Content; self.focus = DialogFocus::Content;
true true
} else if !self.buttons.is_empty() { } else if !self.buttons.is_empty() {
self.focus = Focus::Button(0); self.focus = DialogFocus::Button(0);
true true
} else { } else {
false false

View File

@ -65,7 +65,7 @@ pub use self::box_view::BoxView;
pub use self::button::Button; pub use self::button::Button;
pub use self::canvas::Canvas; pub use self::canvas::Canvas;
pub use self::checkbox::Checkbox; pub use self::checkbox::Checkbox;
pub use self::dialog::Dialog; pub use self::dialog::{Dialog, DialogFocus};
pub use self::dummy::DummyView; pub use self::dummy::DummyView;
pub use self::edit_view::EditView; pub use self::edit_view::EditView;
pub use self::id_view::{IdView, ViewRef}; pub use self::id_view::{IdView, ViewRef};