2016-10-02 22:22:29 +00:00
|
|
|
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2016-03-15 22:37:57 +00:00
|
|
|
use Cursive;
|
2016-10-02 22:22:29 +00:00
|
|
|
use Printer;
|
2016-07-26 03:43:01 +00:00
|
|
|
use With;
|
2015-06-03 02:36:22 +00:00
|
|
|
use align::*;
|
2016-10-02 22:22:29 +00:00
|
|
|
use direction::Direction;
|
2015-05-28 01:04:33 +00:00
|
|
|
use event::*;
|
2016-10-02 22:22:29 +00:00
|
|
|
use std::any::Any;
|
|
|
|
use std::cmp::max;
|
2016-07-01 06:38:01 +00:00
|
|
|
use theme::ColorStyle;
|
2015-05-16 21:02:15 +00:00
|
|
|
|
2016-07-04 23:04:32 +00:00
|
|
|
use unicode_width::UnicodeWidthStr;
|
2016-10-02 22:22:29 +00:00
|
|
|
use vec::{Vec2, Vec4};
|
|
|
|
use view::{Selector, View};
|
|
|
|
use views::{Button, DummyView, SizedView, TextView};
|
2016-07-04 23:04:32 +00:00
|
|
|
|
2015-05-19 17:58:42 +00:00
|
|
|
#[derive(PartialEq)]
|
2015-05-16 21:02:15 +00:00
|
|
|
enum Focus {
|
|
|
|
Content,
|
|
|
|
Button(usize),
|
|
|
|
}
|
|
|
|
|
2015-05-20 00:31:52 +00:00
|
|
|
/// Popup-like view with a main content, and optional buttons under it.
|
|
|
|
///
|
|
|
|
/// # Examples
|
|
|
|
///
|
|
|
|
/// ```
|
2016-07-28 23:36:01 +00:00
|
|
|
/// # use cursive::views::{Dialog,TextView};
|
2016-10-02 22:15:30 +00:00
|
|
|
/// let dialog = Dialog::around(TextView::new("Hello!"))
|
2016-07-10 01:36:07 +00:00
|
|
|
/// .button("Ok", |s| s.quit());
|
2015-05-20 00:31:52 +00:00
|
|
|
/// ```
|
2015-05-16 21:02:15 +00:00
|
|
|
pub struct Dialog {
|
2015-05-22 06:29:49 +00:00
|
|
|
title: String,
|
2015-05-16 21:02:15 +00:00
|
|
|
content: Box<View>,
|
2015-05-19 02:41:35 +00:00
|
|
|
|
|
|
|
buttons: Vec<SizedView<Button>>,
|
|
|
|
|
2015-05-25 21:56:51 +00:00
|
|
|
padding: Vec4,
|
|
|
|
borders: Vec4,
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2015-05-16 21:02:15 +00:00
|
|
|
focus: Focus,
|
2015-06-03 02:36:22 +00:00
|
|
|
|
|
|
|
align: Align,
|
2015-05-16 21:02:15 +00:00
|
|
|
}
|
|
|
|
|
2016-10-02 23:03:31 +00:00
|
|
|
new_default!(Dialog);
|
|
|
|
|
2015-05-16 21:02:15 +00:00
|
|
|
impl Dialog {
|
2016-07-26 03:43:01 +00:00
|
|
|
/// Creates a new `Dialog` with empty content.
|
|
|
|
///
|
|
|
|
/// You should probably call `content()` next.
|
2016-10-02 22:15:30 +00:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self::around(DummyView)
|
2016-07-26 03:43:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new `Dialog` with the given content.
|
2016-10-02 22:15:30 +00:00
|
|
|
pub fn around<V: View + 'static>(view: V) -> Self {
|
2015-05-16 21:02:15 +00:00
|
|
|
Dialog {
|
|
|
|
content: Box::new(view),
|
|
|
|
buttons: Vec::new(),
|
2015-05-22 06:29:49 +00:00
|
|
|
title: String::new(),
|
2015-05-19 17:58:42 +00:00
|
|
|
focus: Focus::Content,
|
2016-03-15 22:37:57 +00:00
|
|
|
padding: Vec4::new(1, 1, 0, 0),
|
|
|
|
borders: Vec4::new(1, 1, 1, 1),
|
2015-06-03 02:36:22 +00:00
|
|
|
align: Align::top_right(),
|
2015-05-16 21:02:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-26 03:43:01 +00:00
|
|
|
/// Sets the content for this dialog.
|
|
|
|
///
|
|
|
|
/// Chainable variant.
|
|
|
|
pub fn content<V: View + 'static>(self, view: V) -> Self {
|
|
|
|
self.with(|s| s.set_content(view))
|
|
|
|
}
|
|
|
|
|
2016-07-25 06:00:13 +00:00
|
|
|
/// Sets the content for this dialog.
|
|
|
|
///
|
|
|
|
/// Previous content will be dropped.
|
|
|
|
pub fn set_content<V: View + 'static>(&mut self, view: V) {
|
|
|
|
self.content = Box::new(view);
|
|
|
|
}
|
|
|
|
|
2016-08-04 07:11:16 +00:00
|
|
|
/// Convenient method to create a dialog with a simple text content.
|
|
|
|
pub fn text<S: Into<String>>(text: S) -> Self {
|
2016-10-02 22:15:30 +00:00
|
|
|
Self::around(TextView::new(text))
|
2016-08-04 07:11:16 +00:00
|
|
|
}
|
|
|
|
|
2016-07-12 03:26:33 +00:00
|
|
|
/// Convenient method to create an infobox.
|
|
|
|
///
|
|
|
|
/// It will contain the given text and a `Ok` dismiss button.
|
2016-07-30 19:58:25 +00:00
|
|
|
pub fn info<S: Into<String>>(text: S) -> Self {
|
2016-08-04 07:11:16 +00:00
|
|
|
Dialog::text(text).dismiss_button("Ok")
|
2016-06-28 05:10:59 +00:00
|
|
|
}
|
|
|
|
|
2015-05-20 00:31:52 +00:00
|
|
|
/// Adds a button to the dialog with the given label and callback.
|
|
|
|
///
|
|
|
|
/// Consumes and returns self for easy chaining.
|
2016-07-30 19:58:25 +00:00
|
|
|
pub fn button<F, S: Into<String>>(mut self, label: S, cb: F) -> Self
|
2015-05-24 00:07:22 +00:00
|
|
|
where F: Fn(&mut Cursive) + 'static
|
2015-05-16 21:02:15 +00:00
|
|
|
{
|
2015-05-19 02:41:35 +00:00
|
|
|
self.buttons.push(SizedView::new(Button::new(label, cb)));
|
|
|
|
|
2015-05-16 21:02:15 +00:00
|
|
|
self
|
|
|
|
}
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2015-06-03 22:36:51 +00:00
|
|
|
/// Sets the horizontal alignment for the buttons, if any.
|
2016-08-13 08:03:40 +00:00
|
|
|
///
|
2015-06-03 22:36:51 +00:00
|
|
|
/// Only works if the buttons are as a row at the bottom of the dialog.
|
2015-06-03 02:36:22 +00:00
|
|
|
pub fn h_align(mut self, h: HAlign) -> Self {
|
|
|
|
self.align.h = h;
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2015-06-03 22:36:51 +00:00
|
|
|
/// Sets the vertical alignment for the buttons, if any.
|
2016-08-13 08:03:40 +00:00
|
|
|
///
|
2015-06-03 22:36:51 +00:00
|
|
|
/// Only works if the buttons are as a column to the right of the dialog.
|
2015-06-03 02:36:22 +00:00
|
|
|
pub fn v_align(mut self, v: VAlign) -> Self {
|
|
|
|
self.align.v = v;
|
|
|
|
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2015-05-22 07:01:23 +00:00
|
|
|
/// Shortcut method to add a button that will dismiss the dialog.
|
2016-07-30 19:58:25 +00:00
|
|
|
pub fn dismiss_button<S: Into<String>>(self, label: S) -> Self {
|
2015-05-24 00:07:22 +00:00
|
|
|
self.button(label, |s| s.screen_mut().pop_layer())
|
2015-05-22 07:01:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the title of the dialog.
|
2016-08-13 08:03:40 +00:00
|
|
|
///
|
2015-05-22 07:01:23 +00:00
|
|
|
/// If not empty, it will be visible at the top.
|
2016-08-13 08:03:40 +00:00
|
|
|
pub fn title<S: Into<String>>(self, label: S) -> Self {
|
|
|
|
self.with(|s| s.set_title(label))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the title of the dialog.
|
|
|
|
pub fn set_title<S: Into<String>>(&mut self, label: S) {
|
2016-07-30 19:58:25 +00:00
|
|
|
self.title = label.into();
|
2015-05-22 06:29:49 +00:00
|
|
|
}
|
|
|
|
|
2015-05-26 23:48:27 +00:00
|
|
|
/// Sets the padding in the dialog (around content and buttons).
|
2016-07-12 02:24:00 +00:00
|
|
|
pub fn padding<T: Into<Vec4>>(mut self, padding: T) -> Self {
|
|
|
|
self.padding = padding.into();
|
2015-05-25 21:56:51 +00:00
|
|
|
|
|
|
|
self
|
|
|
|
}
|
2016-07-25 06:00:13 +00:00
|
|
|
|
|
|
|
/// Sets the top padding in the dialog (under the title).
|
|
|
|
pub fn padding_top(mut self, padding: usize) -> Self {
|
|
|
|
self.padding.top = padding;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the bottom padding in the dialog (under buttons).
|
|
|
|
pub fn padding_bottom(mut self, padding: usize) -> Self {
|
|
|
|
self.padding.bottom = padding;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the left padding in the dialog.
|
|
|
|
pub fn padding_left(mut self, padding: usize) -> Self {
|
|
|
|
self.padding.left = padding;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the right padding in the dialog.
|
|
|
|
pub fn padding_right(mut self, padding: usize) -> Self {
|
|
|
|
self.padding.right = padding;
|
|
|
|
self
|
|
|
|
}
|
2015-05-16 21:02:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl View for Dialog {
|
2016-07-16 06:44:38 +00:00
|
|
|
fn draw(&self, printer: &Printer) {
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2016-07-10 01:36:07 +00:00
|
|
|
// This will be the buttons_height used by the buttons.
|
|
|
|
let mut buttons_height = 0;
|
2015-05-22 07:43:58 +00:00
|
|
|
// Current horizontal position of the next button we'll draw.
|
2015-06-03 02:36:22 +00:00
|
|
|
|
2015-06-08 22:11:36 +00:00
|
|
|
// Sum of the sizes + len-1 for margins
|
2015-07-28 19:54:32 +00:00
|
|
|
let width = if self.buttons.is_empty() {
|
|
|
|
0
|
|
|
|
} else {
|
2016-03-15 22:37:57 +00:00
|
|
|
self.buttons
|
|
|
|
.iter()
|
2015-07-28 19:54:32 +00:00
|
|
|
.map(|button| button.size.x)
|
2016-03-15 22:37:57 +00:00
|
|
|
.fold(0, |a, b| a + b) + self.buttons.len() - 1
|
2015-07-28 19:54:32 +00:00
|
|
|
};
|
2015-06-03 02:36:22 +00:00
|
|
|
let overhead = self.padding + self.borders;
|
2016-07-17 05:05:28 +00:00
|
|
|
if printer.size.x < overhead.horizontal() {
|
|
|
|
return;
|
|
|
|
}
|
2015-07-28 19:54:32 +00:00
|
|
|
let mut offset = overhead.left +
|
2016-07-10 01:36:07 +00:00
|
|
|
self.align
|
|
|
|
.h
|
|
|
|
.get_offset(width, printer.size.x - overhead.horizontal());
|
2016-07-17 05:05:28 +00:00
|
|
|
|
|
|
|
let overhead_bottom = self.padding.bottom + self.borders.bottom + 1;
|
|
|
|
if overhead_bottom > printer.size.y {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let y = printer.size.y - overhead_bottom;
|
2015-06-03 02:36:22 +00:00
|
|
|
|
2016-07-16 06:44:38 +00:00
|
|
|
for (i, button) in self.buttons.iter().enumerate() {
|
2015-05-19 02:41:35 +00:00
|
|
|
let size = button.size;
|
2015-05-19 22:54:11 +00:00
|
|
|
// Add some special effect to the focused button
|
2016-03-15 22:37:57 +00:00
|
|
|
button.draw(&printer.sub_printer(Vec2::new(offset, y),
|
|
|
|
size,
|
|
|
|
self.focus == Focus::Button(i)));
|
2015-05-22 07:43:58 +00:00
|
|
|
// Keep 1 blank between two buttons
|
2015-06-03 02:36:22 +00:00
|
|
|
offset += size.x + 1;
|
2015-05-22 07:43:58 +00:00
|
|
|
// Also keep 1 blank above the buttons
|
2016-07-10 01:36:07 +00:00
|
|
|
buttons_height = max(buttons_height, size.y + 1);
|
2015-05-19 02:41:35 +00:00
|
|
|
}
|
|
|
|
|
2015-05-22 07:43:58 +00:00
|
|
|
// What do we have left?
|
2016-07-20 03:44:20 +00:00
|
|
|
let taken = Vec2::new(0, buttons_height) + self.borders.combined() +
|
|
|
|
self.padding.combined();
|
2016-07-17 05:05:28 +00:00
|
|
|
if !taken.fits_in(printer.size) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let inner_size = printer.size - taken;
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2016-07-10 01:36:07 +00:00
|
|
|
self.content
|
|
|
|
.draw(&printer.sub_printer(self.borders.top_left() +
|
|
|
|
self.padding.top_left(),
|
|
|
|
inner_size,
|
|
|
|
self.focus == Focus::Content));
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2016-08-05 00:27:04 +00:00
|
|
|
printer.print_box(Vec2::new(0, 0), printer.size, false);
|
2015-05-22 06:29:49 +00:00
|
|
|
|
2016-06-28 05:40:11 +00:00
|
|
|
if !self.title.is_empty() {
|
2016-07-04 23:04:32 +00:00
|
|
|
let len = self.title.width();
|
2016-07-17 08:20:41 +00:00
|
|
|
if len + 4 > printer.size.x {
|
|
|
|
return;
|
|
|
|
}
|
2015-05-29 00:32:28 +00:00
|
|
|
let x = (printer.size.x - len) / 2;
|
2016-08-05 17:49:16 +00:00
|
|
|
printer.with_high_border(false, |printer| {
|
|
|
|
printer.print((x - 2, 0), "┤ ");
|
|
|
|
printer.print((x + len, 0), " ├");
|
|
|
|
});
|
2015-05-22 06:29:49 +00:00
|
|
|
|
2016-07-10 01:36:07 +00:00
|
|
|
printer.with_color(ColorStyle::TitlePrimary,
|
|
|
|
|p| p.print((x, 0), &self.title));
|
2015-05-22 06:29:49 +00:00
|
|
|
}
|
2015-05-20 17:31:38 +00:00
|
|
|
|
2015-05-16 21:02:15 +00:00
|
|
|
}
|
|
|
|
|
2017-01-24 06:52:29 +00:00
|
|
|
fn required_size(&mut self, req: Vec2) -> Vec2 {
|
2015-05-22 07:43:58 +00:00
|
|
|
// Padding and borders are not available for kids.
|
2016-07-10 01:36:07 +00:00
|
|
|
let nomans_land = self.padding.combined() + self.borders.combined();
|
2015-05-16 21:02:15 +00:00
|
|
|
|
2016-07-10 01:36:07 +00:00
|
|
|
// Buttons are not flexible, so their size doesn't depend on ours.
|
2016-03-15 22:37:57 +00:00
|
|
|
let mut buttons_size = Vec2::new(0, 0);
|
2015-07-28 19:54:32 +00:00
|
|
|
if !self.buttons.is_empty() {
|
|
|
|
buttons_size.x += self.buttons.len() - 1;
|
|
|
|
}
|
2016-07-10 01:23:58 +00:00
|
|
|
for button in &mut self.buttons {
|
2017-01-24 06:52:29 +00:00
|
|
|
let s = button.view.required_size(req);
|
2015-06-09 05:24:59 +00:00
|
|
|
buttons_size.x += s.x;
|
2015-05-19 02:41:35 +00:00
|
|
|
buttons_size.y = max(buttons_size.y, s.y + 1);
|
|
|
|
}
|
|
|
|
|
2016-07-10 01:36:07 +00:00
|
|
|
// We also remove one row for the buttons.
|
2016-07-17 05:05:28 +00:00
|
|
|
let taken = nomans_land + Vec2::new(0, buttons_size.y);
|
|
|
|
if !taken.fits_in(req) {
|
|
|
|
// Bad!!
|
|
|
|
return taken;
|
|
|
|
}
|
|
|
|
let content_req = req - taken;
|
|
|
|
|
2017-01-24 06:52:29 +00:00
|
|
|
let content_size = self.content.required_size(content_req);
|
2016-07-10 01:36:07 +00:00
|
|
|
|
2015-05-22 07:43:58 +00:00
|
|
|
// On the Y axis, we add buttons and content.
|
|
|
|
// On the X axis, we take the max.
|
2015-05-22 06:29:49 +00:00
|
|
|
let mut inner_size = Vec2::new(max(content_size.x, buttons_size.x),
|
2016-03-15 22:37:57 +00:00
|
|
|
content_size.y + buttons_size.y) +
|
|
|
|
self.padding.combined() +
|
|
|
|
self.borders.combined();
|
2015-05-22 06:29:49 +00:00
|
|
|
|
2016-06-28 05:40:11 +00:00
|
|
|
if !self.title.is_empty() {
|
2015-05-22 07:43:58 +00:00
|
|
|
// If we have a title, we have to fit it too!
|
2016-07-04 23:04:32 +00:00
|
|
|
inner_size.x = max(inner_size.x, self.title.width() + 6);
|
2015-05-22 06:29:49 +00:00
|
|
|
}
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2015-05-22 06:29:49 +00:00
|
|
|
inner_size
|
2015-05-19 02:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn layout(&mut self, mut size: Vec2) {
|
2015-05-22 07:43:58 +00:00
|
|
|
// Padding and borders are taken, sorry.
|
2016-07-02 07:47:38 +00:00
|
|
|
// TODO: handle border-less themes?
|
2016-07-17 05:05:28 +00:00
|
|
|
let taken = self.borders.combined() + self.padding.combined();
|
|
|
|
size = if taken.fits_in(size) {
|
|
|
|
size - taken
|
|
|
|
} else {
|
|
|
|
Vec2::zero()
|
|
|
|
};
|
2015-05-19 02:41:35 +00:00
|
|
|
|
2015-05-22 07:43:58 +00:00
|
|
|
// Buttons are kings, we give them everything they want.
|
2015-05-19 02:41:35 +00:00
|
|
|
let mut buttons_height = 0;
|
|
|
|
for button in self.buttons.iter_mut().rev() {
|
2017-01-24 06:52:29 +00:00
|
|
|
let size = button.required_size(size);
|
2016-03-15 22:37:57 +00:00
|
|
|
buttons_height = max(buttons_height, size.y + 1);
|
2015-05-19 02:41:35 +00:00
|
|
|
button.layout(size);
|
|
|
|
}
|
|
|
|
|
2015-05-22 07:43:58 +00:00
|
|
|
// Poor content will have to make do with what's left.
|
2016-07-17 05:05:28 +00:00
|
|
|
if buttons_height > size.y {
|
|
|
|
buttons_height = size.y;
|
|
|
|
}
|
2015-05-19 02:41:35 +00:00
|
|
|
self.content.layout(size - Vec2::new(0, buttons_height));
|
|
|
|
}
|
|
|
|
|
2015-05-28 01:04:33 +00:00
|
|
|
fn on_event(&mut self, event: Event) -> EventResult {
|
2015-05-19 02:41:35 +00:00
|
|
|
match self.focus {
|
2015-05-22 07:43:58 +00:00
|
|
|
// If we are on the content, we can only go down.
|
2016-06-25 23:36:22 +00:00
|
|
|
Focus::Content => {
|
2017-03-25 18:01:25 +00:00
|
|
|
match self.content.on_event(event.clone()) {
|
2016-06-25 23:36:22 +00:00
|
|
|
EventResult::Ignored if !self.buttons.is_empty() => {
|
|
|
|
match event {
|
2016-06-28 05:40:11 +00:00
|
|
|
Event::Key(Key::Down) |
|
|
|
|
Event::Key(Key::Tab) |
|
2016-07-11 01:27:26 +00:00
|
|
|
Event::Shift(Key::Tab) => {
|
2016-06-25 23:36:22 +00:00
|
|
|
// Default to leftmost button when going down.
|
|
|
|
self.focus = Focus::Button(0);
|
|
|
|
EventResult::Consumed(None)
|
|
|
|
}
|
|
|
|
_ => EventResult::Ignored,
|
2015-05-20 17:31:38 +00:00
|
|
|
}
|
2016-03-15 22:37:57 +00:00
|
|
|
}
|
2016-06-25 23:36:22 +00:00
|
|
|
res => res,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// If we are on a button, we have more choice
|
|
|
|
Focus::Button(i) => {
|
2017-03-25 18:01:25 +00:00
|
|
|
match self.buttons[i].on_event(event.clone()) {
|
2016-06-25 23:36:22 +00:00
|
|
|
EventResult::Ignored => {
|
|
|
|
match event {
|
|
|
|
// Up goes back to the content
|
2016-07-15 03:27:15 +00:00
|
|
|
Event::Key(Key::Up) => {
|
|
|
|
if self.content
|
2016-07-15 05:32:43 +00:00
|
|
|
.take_focus(Direction::down()) {
|
2016-07-15 03:27:15 +00:00
|
|
|
self.focus = Focus::Content;
|
|
|
|
EventResult::Consumed(None)
|
|
|
|
} else {
|
|
|
|
EventResult::Ignored
|
|
|
|
}
|
|
|
|
}
|
2016-07-11 01:27:26 +00:00
|
|
|
Event::Shift(Key::Tab) => {
|
2016-07-15 03:27:15 +00:00
|
|
|
if self.content
|
2016-07-15 05:32:43 +00:00
|
|
|
.take_focus(Direction::back()) {
|
2016-06-25 23:36:22 +00:00
|
|
|
self.focus = Focus::Content;
|
|
|
|
EventResult::Consumed(None)
|
|
|
|
} else {
|
|
|
|
EventResult::Ignored
|
|
|
|
}
|
|
|
|
}
|
2016-07-15 03:27:15 +00:00
|
|
|
Event::Key(Key::Tab) => {
|
|
|
|
if self.content
|
2016-07-15 05:32:43 +00:00
|
|
|
.take_focus(Direction::front()) {
|
2016-07-15 03:27:15 +00:00
|
|
|
self.focus = Focus::Content;
|
|
|
|
EventResult::Consumed(None)
|
|
|
|
} else {
|
|
|
|
EventResult::Ignored
|
|
|
|
}
|
|
|
|
}
|
2016-06-25 23:36:22 +00:00
|
|
|
// Left and Right move to other buttons
|
2016-06-28 05:40:11 +00:00
|
|
|
Event::Key(Key::Right) if i + 1 <
|
2016-06-30 00:36:20 +00:00
|
|
|
self.buttons
|
2016-07-10 01:36:07 +00:00
|
|
|
.len() => {
|
2016-06-25 23:36:22 +00:00
|
|
|
self.focus = Focus::Button(i + 1);
|
|
|
|
EventResult::Consumed(None)
|
|
|
|
}
|
2016-06-28 05:40:11 +00:00
|
|
|
Event::Key(Key::Left) if i > 0 => {
|
2016-06-25 23:36:22 +00:00
|
|
|
self.focus = Focus::Button(i - 1);
|
|
|
|
EventResult::Consumed(None)
|
|
|
|
}
|
|
|
|
_ => EventResult::Ignored,
|
2015-05-31 04:05:34 +00:00
|
|
|
}
|
2016-03-15 22:37:57 +00:00
|
|
|
}
|
2016-06-25 23:36:22 +00:00
|
|
|
res => res,
|
|
|
|
}
|
|
|
|
}
|
2015-05-19 22:54:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-15 05:32:43 +00:00
|
|
|
fn take_focus(&mut self, source: Direction) -> bool {
|
2016-07-15 03:27:15 +00:00
|
|
|
// Dialogs aren't meant to be used in layouts, so...
|
|
|
|
// Let's be super lazy and not even care about the focus source.
|
|
|
|
if self.content.take_focus(source) {
|
2015-05-27 00:10:47 +00:00
|
|
|
self.focus = Focus::Content;
|
|
|
|
true
|
|
|
|
} else if !self.buttons.is_empty() {
|
2015-05-19 22:54:11 +00:00
|
|
|
self.focus = Focus::Button(0);
|
|
|
|
true
|
|
|
|
} else {
|
2015-05-27 00:10:47 +00:00
|
|
|
false
|
2015-05-19 02:41:35 +00:00
|
|
|
}
|
2015-05-16 21:02:15 +00:00
|
|
|
}
|
2015-05-26 22:46:05 +00:00
|
|
|
|
2017-03-27 03:50:50 +00:00
|
|
|
fn call_on_any<'a>(&mut self, selector: &Selector,
|
2017-02-07 02:18:17 +00:00
|
|
|
callback: Box<FnMut(&mut Any) + 'a>) {
|
2017-03-27 03:50:50 +00:00
|
|
|
self.content.call_on_any(selector, callback);
|
2015-05-26 22:46:05 +00:00
|
|
|
}
|
2017-03-25 21:50:52 +00:00
|
|
|
|
|
|
|
fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
|
|
|
|
self.content.focus_view(selector)
|
|
|
|
}
|
2015-05-16 21:02:15 +00:00
|
|
|
}
|