Add Printer::enabled

This commit is contained in:
Alexandre Bury 2018-11-09 14:08:43 -08:00
parent d266f9a637
commit 193f098ee0
9 changed files with 83 additions and 88 deletions

View File

@ -1,6 +1,6 @@
use cursive::vec::Vec2; use cursive::vec::Vec2;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use std::cmp::max; // use std::cmp::max;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct Options { pub struct Options {

View File

@ -23,7 +23,8 @@ fn main() {
.child(Button::new_raw(" New game ", show_options)) .child(Button::new_raw(" New game ", show_options))
.child(Button::new_raw(" Best scores ", |s| { .child(Button::new_raw(" Best scores ", |s| {
s.add_layer(Dialog::info("Not yet!").title("Scores")) s.add_layer(Dialog::info("Not yet!").title("Scores"))
})).child(Button::new_raw(" Exit ", |s| s.quit())), }))
.child(Button::new_raw(" Exit ", |s| s.quit())),
), ),
); );
@ -42,23 +43,27 @@ fn show_options(siv: &mut Cursive) {
size: Vec2::new(8, 8), size: Vec2::new(8, 8),
mines: 10, mines: 10,
}, },
).item( )
.item(
"Medium: 16x16, 40 mines", "Medium: 16x16, 40 mines",
game::Options { game::Options {
size: Vec2::new(16, 16), size: Vec2::new(16, 16),
mines: 40, mines: 40,
}, },
).item( )
.item(
"Difficult: 24x24, 99 mines", "Difficult: 24x24, 99 mines",
game::Options { game::Options {
size: Vec2::new(24, 24), size: Vec2::new(24, 24),
mines: 99, mines: 99,
}, },
).on_submit(|s, option| { )
.on_submit(|s, option| {
s.pop_layer(); s.pop_layer();
new_game(s, *option); new_game(s, *option);
}), }),
).dismiss_button("Back"), )
.dismiss_button("Back"),
); );
} }
@ -77,7 +82,7 @@ struct BoardView {
overlay: Vec<Cell>, overlay: Vec<Cell>,
focused: Option<Vec2>, focused: Option<Vec2>,
missing_mines: usize, _missing_mines: usize,
} }
impl BoardView { impl BoardView {
@ -88,7 +93,7 @@ impl BoardView {
board, board,
overlay, overlay,
focused: None, focused: None,
missing_mines: options.mines, _missing_mines: options.mines,
} }
} }
@ -271,7 +276,8 @@ fn new_game(siv: &mut Cursive, options: game::Options) {
.content( .content(
LinearLayout::horizontal() LinearLayout::horizontal()
.child(Panel::new(BoardView::new(options))), .child(Panel::new(BoardView::new(options))),
).button("Quit game", |s| { )
.button("Quit game", |s| {
s.pop_layer(); s.pop_layer();
}), }),
); );

View File

@ -17,6 +17,7 @@ use with::With;
/// ///
/// The part of the content it will print is defined by `content_offset` /// The part of the content it will print is defined by `content_offset`
/// and `size`. /// and `size`.
#[derive(Clone)]
pub struct Printer<'a, 'b> { pub struct Printer<'a, 'b> {
/// Offset into the window this printer should start drawing at. /// Offset into the window this printer should start drawing at.
/// ///
@ -42,6 +43,9 @@ pub struct Printer<'a, 'b> {
/// Whether the view to draw is currently focused or not. /// Whether the view to draw is currently focused or not.
pub focused: bool, pub focused: bool,
/// Whether the view to draw is currently enabled or not.
pub enabled: bool,
/// Currently used theme /// Currently used theme
pub theme: &'a Theme, pub theme: &'a Theme,
@ -49,20 +53,6 @@ pub struct Printer<'a, 'b> {
backend: &'b Backend, backend: &'b Backend,
} }
impl<'a, 'b> Clone for Printer<'a, 'b> {
fn clone(&self) -> Self {
Printer {
offset: self.offset,
content_offset: self.content_offset,
output_size: self.output_size,
size: self.size,
focused: self.focused,
theme: self.theme,
backend: self.backend,
}
}
}
impl<'a, 'b> Printer<'a, 'b> { impl<'a, 'b> Printer<'a, 'b> {
/// Creates a new printer on the given window. /// Creates a new printer on the given window.
/// ///
@ -78,6 +68,7 @@ impl<'a, 'b> Printer<'a, 'b> {
output_size: size, output_size: size,
size, size,
focused: true, focused: true,
enabled: true,
theme, theme,
backend, backend,
} }
@ -304,16 +295,18 @@ impl<'a, 'b> Printer<'a, 'b> {
where where
F: FnOnce(&Printer), F: FnOnce(&Printer),
{ {
let new_printer = Printer { f(&self.theme(theme));
offset: self.offset, }
size: self.size,
focused: self.focused, /// Create a new sub-printer with the given theme.
pub fn theme<'c>(&self, theme: &'c Theme) -> Printer<'c, 'b>
where
'a: 'c,
{
Printer {
theme, theme,
backend: self.backend, ..self.clone()
output_size: self.output_size, }
content_offset: self.content_offset,
};
f(&new_printer);
} }
/// Call the given closure with a modified printer /// Call the given closure with a modified printer
@ -480,6 +473,15 @@ impl<'a, 'b> Printer<'a, 'b> {
}) })
} }
/// Returns a new sub-printer inheriting the given enabled state.
///
/// If `self` is enabled and `enabled == true`, the child will be enabled.
///
/// Otherwise, he will be disabled.
pub fn enabled(&self, enabled: bool) -> Self {
self.clone().with(|s| s.enabled &= enabled)
}
/// Returns a new sub-printer with a cropped area. /// Returns a new sub-printer with a cropped area.
/// ///
/// The new printer size will be the minimum of `size` and its current size. /// The new printer size will be the minimum of `size` and its current size.

View File

@ -142,7 +142,7 @@ impl View for Button {
return; return;
} }
let style = if !self.enabled { let style = if !(self.enabled && printer.enabled) {
ColorStyle::secondary() ColorStyle::secondary()
} else if !printer.focused { } else if !printer.focused {
ColorStyle::primary() ColorStyle::primary()
@ -182,11 +182,8 @@ impl View for Button {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
position, position,
offset, offset,
} } if position
if position.fits_in_rect( .fits_in_rect(offset + (self_offset, 0), self.req_size()) =>
offset + (self_offset, 0),
self.req_size(),
) =>
{ {
EventResult::Consumed(Some(self.callback.clone())) EventResult::Consumed(Some(self.callback.clone()))
} }

View File

@ -114,7 +114,7 @@ impl View for Checkbox {
} }
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if self.enabled { if self.enabled && printer.enabled {
printer.with_selection(printer.focused, |printer| { printer.with_selection(printer.focused, |printer| {
self.draw_internal(printer) self.draw_internal(printer)
}); });
@ -132,11 +132,7 @@ impl View for Checkbox {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
position, position,
offset, offset,
} } if position.fits_in_rect(offset, (3, 1)) => self.toggle(),
if position.fits_in_rect(offset, (3, 1)) =>
{
self.toggle()
}
_ => EventResult::Ignored, _ => EventResult::Ignored,
} }
} }

View File

@ -471,7 +471,8 @@ impl EditView {
let suffix_length = simple_suffix( let suffix_length = simple_suffix(
&self.content[self.offset..self.cursor], &self.content[self.offset..self.cursor],
available, available,
).length; )
.length;
assert!(suffix_length <= self.cursor); assert!(suffix_length <= self.cursor);
self.offset = self.cursor - suffix_length; self.offset = self.cursor - suffix_length;
@ -510,7 +511,7 @@ impl View for EditView {
let width = self.content.width(); let width = self.content.width();
printer.with_color(self.style, |printer| { printer.with_color(self.style, |printer| {
let effect = if self.enabled { let effect = if self.enabled && printer.enabled {
Effect::Reverse Effect::Reverse
} else { } else {
Effect::Simple Effect::Simple
@ -542,7 +543,8 @@ impl View for EditView {
} else { } else {
Some(g) Some(g)
} }
}).map(|g| g.len()) })
.map(|g| g.len())
.sum(); .sum();
let content = &content[..display_bytes]; let content = &content[..display_bytes];
@ -660,14 +662,14 @@ impl View for EditView {
event: MouseEvent::Press(_), event: MouseEvent::Press(_),
position, position,
offset, offset,
} } if position.fits_in_rect(offset, (self.last_length, 1)) => {
if position.fits_in_rect(offset, (self.last_length, 1)) =>
{
if let Some(position) = position.checked_sub(offset) { if let Some(position) = position.checked_sub(offset) {
self.cursor = self.offset + simple_prefix( self.cursor = self.offset
+ simple_prefix(
&self.content[self.offset..], &self.content[self.offset..],
position.x, position.x,
).length; )
.length;
} }
} }
_ => return EventResult::Ignored, _ => return EventResult::Ignored,

View File

@ -163,7 +163,7 @@ impl<T: 'static> View for RadioButton<T> {
} }
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
if self.enabled { if self.enabled && printer.enabled {
printer.with_selection(printer.focused, |printer| { printer.with_selection(printer.focused, |printer| {
self.draw_internal(printer) self.draw_internal(printer)
}); });
@ -184,9 +184,7 @@ impl<T: 'static> View for RadioButton<T> {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
position, position,
offset, offset,
} } if position.fits_in_rect(offset, self.req_size()) => {
if position.fits_in_rect(offset, self.req_size()) =>
{
self.select(); self.select();
EventResult::Consumed(None) EventResult::Consumed(None)
} }

View File

@ -505,8 +505,7 @@ impl<T: 'static> SelectView<T> {
event: MouseEvent::Press(_), event: MouseEvent::Press(_),
position, position,
offset, offset,
} } if position
if position
.checked_sub(offset) .checked_sub(offset)
.map(|position| { .map(|position| {
position < self.last_size && position.y < self.len() position < self.last_size && position.y < self.len()
@ -519,8 +518,8 @@ impl<T: 'static> SelectView<T> {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
position, position,
offset, offset,
} } if self.on_submit.is_some()
if self.on_submit.is_some() && position && position
.checked_sub(offset) .checked_sub(offset)
.map(|position| { .map(|position| {
position < self.last_size && position.y == self.focus() position < self.last_size && position.y == self.focus()
@ -610,9 +609,7 @@ impl<T: 'static> SelectView<T> {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
position, position,
offset, offset,
} } if position.fits_in_rect(offset, self.last_size) => {
if position.fits_in_rect(offset, self.last_size) =>
{
self.open_popup() self.open_popup()
} }
_ => EventResult::Ignored, _ => EventResult::Ignored,
@ -679,7 +676,7 @@ impl<T: 'static> View for SelectView<T> {
if self.popup { if self.popup {
// Popup-select only draw the active element. // Popup-select only draw the active element.
// We'll draw the full list in a popup if needed. // We'll draw the full list in a popup if needed.
let style = if !self.enabled { let style = if !(self.enabled && printer.enabled) {
ColorStyle::secondary() ColorStyle::secondary()
} else if !printer.focused { } else if !printer.focused {
ColorStyle::primary() ColorStyle::primary()
@ -715,7 +712,9 @@ impl<T: 'static> View for SelectView<T> {
printer.offset((0, i)).with_selection( printer.offset((0, i)).with_selection(
i == self.focus(), i == self.focus(),
|printer| { |printer| {
if i != self.focus() && !self.enabled { if i != self.focus()
&& !(self.enabled && printer.enabled)
{
printer.with_color( printer.with_color(
ColorStyle::secondary(), ColorStyle::secondary(),
|printer| self.draw_item(printer, i), |printer| self.draw_item(printer, i),

View File

@ -461,7 +461,7 @@ impl View for TextArea {
fn draw(&self, printer: &Printer) { fn draw(&self, printer: &Printer) {
printer.with_color(ColorStyle::secondary(), |printer| { printer.with_color(ColorStyle::secondary(), |printer| {
let effect = if self.enabled { let effect = if self.enabled && printer.enabled {
Effect::Reverse Effect::Reverse
} else { } else {
Effect::Simple Effect::Simple
@ -545,18 +545,14 @@ impl View for TextArea {
Event::Mouse { Event::Mouse {
event: MouseEvent::WheelUp, event: MouseEvent::WheelUp,
.. ..
} } if self.scrollbase.can_scroll_up() => {
if self.scrollbase.can_scroll_up() =>
{
fix_scroll = false; fix_scroll = false;
self.scrollbase.scroll_up(5); self.scrollbase.scroll_up(5);
} }
Event::Mouse { Event::Mouse {
event: MouseEvent::WheelDown, event: MouseEvent::WheelDown,
.. ..
} } if self.scrollbase.can_scroll_down() => {
if self.scrollbase.can_scroll_down() =>
{
fix_scroll = false; fix_scroll = false;
self.scrollbase.scroll_down(5); self.scrollbase.scroll_down(5);
} }
@ -564,12 +560,12 @@ impl View for TextArea {
event: MouseEvent::Press(MouseButton::Left), event: MouseEvent::Press(MouseButton::Left),
position, position,
offset, offset,
} } if position
if position
.checked_sub(offset) .checked_sub(offset)
.map(|position| { .map(|position| {
self.scrollbase.start_drag(position, self.last_size.x) self.scrollbase.start_drag(position, self.last_size.x)
}).unwrap_or(false) => })
.unwrap_or(false) =>
{ {
fix_scroll = false; fix_scroll = false;
} }
@ -586,8 +582,7 @@ impl View for TextArea {
event: MouseEvent::Press(_), event: MouseEvent::Press(_),
position, position,
offset, offset,
} } if !self.rows.is_empty()
if !self.rows.is_empty()
&& position.fits_in_rect(offset, self.last_size) => && position.fits_in_rect(offset, self.last_size) =>
{ {
if let Some(position) = position.checked_sub(offset) { if let Some(position) = position.checked_sub(offset) {