From d4ced015f62ed3a3bce502cdffa06f486d57b5e1 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Thu, 3 May 2018 08:36:17 -0700 Subject: [PATCH 01/10] EditView: keep cursor in view after key event --- src/views/edit_view.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/views/edit_view.rs b/src/views/edit_view.rs index 6641ab4..3bd3321 100644 --- a/src/views/edit_view.rs +++ b/src/views/edit_view.rs @@ -1,4 +1,3 @@ -use {Cursive, Printer, With}; use direction::Direction; use event::{Callback, Event, EventResult, Key, MouseEvent}; use std::cell::RefCell; @@ -9,6 +8,7 @@ use unicode_width::{UnicodeWidthChar, UnicodeWidthStr}; use utils::lines::simple::{simple_prefix, simple_suffix}; use vec::Vec2; use view::View; +use {Cursive, Printer, With}; /// Closure type for callbacks when the content is modified. /// @@ -367,7 +367,8 @@ impl EditView { self.offset = 0; self.set_cursor(len); - self.make_edit_cb().unwrap_or_else(Callback::dummy) + self.make_edit_cb() + .unwrap_or_else(Callback::dummy) } /// Get the current text. @@ -419,7 +420,8 @@ impl EditView { self.keep_cursor_in_view(); - self.make_edit_cb().unwrap_or_else(Callback::dummy) + self.make_edit_cb() + .unwrap_or_else(Callback::dummy) } /// Remove the character at the current cursor position. @@ -434,7 +436,8 @@ impl EditView { self.keep_cursor_in_view(); - self.make_edit_cb().unwrap_or_else(Callback::dummy) + self.make_edit_cb() + .unwrap_or_else(Callback::dummy) } fn make_edit_cb(&self) -> Option { @@ -615,15 +618,20 @@ impl View for EditView { return EventResult::Consumed(Some(self.insert(ch))); } // TODO: handle ctrl-key? - Event::Key(Key::Home) => self.cursor = 0, - Event::Key(Key::End) => self.cursor = self.content.len(), + Event::Key(Key::Home) => self.set_cursor(0), + Event::Key(Key::End) => { + // When possible, NLL to the rescue! + let len = self.content.len(); + self.set_cursor(len); + } Event::Key(Key::Left) if self.cursor > 0 => { let len = self.content[..self.cursor] .graphemes(true) .last() .unwrap() .len(); - self.cursor -= len; + let cursor = self.cursor - len; + self.set_cursor(cursor); } Event::Key(Key::Right) if self.cursor < self.content.len() => { let len = self.content[self.cursor..] @@ -631,7 +639,8 @@ impl View for EditView { .next() .unwrap() .len(); - self.cursor += len; + let cursor = self.cursor + len; + self.set_cursor(cursor); } Event::Key(Key::Backspace) if self.cursor > 0 => { let len = self.content[..self.cursor] From 20cb033b8d3c1edab642d9c068443cdd4d7c38b1 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Sat, 5 May 2018 09:04:32 -0700 Subject: [PATCH 02/10] Give wrapped rows full width --- src/utils/lines/spans/chunk.rs | 11 +++++++++ src/utils/lines/spans/lines_iterator.rs | 33 +++++++++++++++++-------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/utils/lines/spans/chunk.rs b/src/utils/lines/spans/chunk.rs index 838317a..bd87783 100644 --- a/src/utils/lines/spans/chunk.rs +++ b/src/utils/lines/spans/chunk.rs @@ -1,11 +1,22 @@ use super::segment::Segment; /// Non-splittable piece of text. +/// +/// It is made of a list of segments of text. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Chunk { + /// Total width of this chunk. pub width: usize, + + /// This is the segments this chunk contains. pub segments: Vec, + + /// Hard stops are non-optional line breaks (newlines). pub hard_stop: bool, + + /// If a chunk of text ends in a space, it can be compressed a bit. + /// + /// (We can omit the space if it would result in a perfect fit.) pub ends_with_space: bool, } diff --git a/src/utils/lines/spans/lines_iterator.rs b/src/utils/lines/spans/lines_iterator.rs index e14e831..36c9ffc 100644 --- a/src/utils/lines/spans/lines_iterator.rs +++ b/src/utils/lines/spans/lines_iterator.rs @@ -111,16 +111,14 @@ where offset = end; Chunk { width, - segments: vec![ - Segment { - width, - span_id: seg.span_id, - start, - end, - }, - ], + segments: vec![Segment { + width, + span_id: seg.span_id, + start, + end, + }], hard_stop: false, - ends_with_space: false, + ends_with_space: false, // should we? } }) }); @@ -152,7 +150,22 @@ where } } - let width = chunks.iter().map(|c| c.width).sum(); + // We can know text was wrapped if the stop was optional, + // and there's more coming. + let text_wrap = !chunks + .last() + .map(|c| c.hard_stop) + .unwrap_or(true) + && self.iter.peek().is_some(); + + // If we had to break a line in two, then at least pretent we're + // taking the full width. + let width = if text_wrap { + self.width + } else { + chunks.iter().map(|c| c.width).sum() + }; + assert!(width <= self.width); // Concatenate all segments From 4a3bbbb9983209e31caed9736101d82db348d256 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Mon, 7 May 2018 23:17:07 -0700 Subject: [PATCH 03/10] lorem example: remove unnecessary full_screen() --- examples/lorem.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/examples/lorem.rs b/examples/lorem.rs index a76a9e3..4c4a0ca 100644 --- a/examples/lorem.rs +++ b/examples/lorem.rs @@ -1,9 +1,8 @@ extern crate cursive; -use cursive::Cursive; use cursive::align::HAlign; -use cursive::view::Boxable; use cursive::views::{Dialog, Panel, TextView}; +use cursive::Cursive; fn main() { // Read some long text from a file. @@ -18,11 +17,10 @@ fn main() { // and will adapt to the terminal size. siv.add_fullscreen_layer( Dialog::around(Panel::new(TextView::new(content))) + .title("Unicode and wide-character support") // This is the alignment for the button .h_align(HAlign::Center) - .button("Quit", |s| s.quit()) - .title("Unicode and wide-character support") - .full_screen(), + .button("Quit", |s| s.quit()), ); // Show a popup on top of the view. siv.add_layer(Dialog::info( From cabeef1d1689f0155dc3a122b5b359b3f52b870e Mon Sep 17 00:00:00 2001 From: Andrzej J Skalski Date: Mon, 21 May 2018 15:53:38 +0200 Subject: [PATCH 04/10] added with_theme to Printer --- src/printer.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/printer.rs b/src/printer.rs index 8ac6825..029a3ab 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -11,7 +11,7 @@ use utils::lines::simple::prefix; use vec::Vec2; /// Convenient interface to draw on a subset of the screen. -pub struct Printer<'a> { +pub struct Printer<'a, 'b> { /// Offset into the window this printer should start drawing at. pub offset: Vec2, /// Size of the area we are allowed to draw on. @@ -24,16 +24,16 @@ pub struct Printer<'a> { /// `true` if nothing has been drawn yet. new: Rc>, /// Backend used to actually draw things - backend: &'a Backend, + backend: &'b Backend, } -impl<'a> Printer<'a> { +impl<'a, 'b> Printer<'a, 'b> { /// Creates a new printer on the given window. /// /// But nobody needs to know that. #[doc(hidden)] pub fn new>( - size: T, theme: &'a Theme, backend: &'a Backend + size: T, theme: &'a Theme, backend: &'b Backend ) -> Self { Printer { offset: Vec2::zero(), @@ -171,6 +171,23 @@ impl<'a> Printer<'a> { self.backend.unset_effect(effect); } + /// Call the given closure with a modified printer + /// that will apply the given theme on prints. + pub fn with_theme(&self, theme: &Theme, f: F) + where + F: FnOnce(&Printer), + { + let new_printer = Printer { + offset: self.offset, + size: self.size, + focused: self.focused, + theme : theme, + new: self.new.clone(), + backend : self.backend + }; + f(&new_printer); + } + /// Call the given closure with a modified printer /// that will apply each given effect on prints. pub fn with_effects(&self, effects: EnumSet, f: F) @@ -302,8 +319,8 @@ impl<'a> Printer<'a> { /// Returns a printer on a subset of this one's area. pub fn sub_printer, T: Into>( - &'a self, offset: S, size: T, focused: bool - ) -> Printer<'a> { + &self, offset: S, size: T, focused: bool + ) -> Printer<'a, 'b> { let size = size.into(); let offset = offset.into().or_min(self.size); let available = if !offset.fits_in(self.size) { From 8aa67aa321e1ec56701b055c08d5d31e2f9a5844 Mon Sep 17 00:00:00 2001 From: Steven Portzer Date: Mon, 4 Jun 2018 21:32:02 -0700 Subject: [PATCH 05/10] Don't require num default features --- Cargo.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e098758..a43e4b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,6 @@ repository = "gyscos/Cursive" enum-map = "0.2.24" enumset = "0.3.3" log = "0.4" -num = "0.1" owning_ref = "0.3.3" toml = "0.4" unicode-segmentation = "1.0" @@ -25,6 +24,10 @@ unicode-width = "0.1" xi-unicode = "0.1.0" libc = "0.2" +[dependencies.num] +default-features = false +version = "0.1" + [dependencies.maplit] optional = true version = "1.0.0" From e81e67cebee5b3a639c7cf7f71e68af5084b1b95 Mon Sep 17 00:00:00 2001 From: Robin Stumm Date: Wed, 30 May 2018 00:27:33 +0200 Subject: [PATCH 06/10] add transparent layer to StackView test StackView::get() --- src/views/stack_view.rs | 85 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 80 insertions(+), 5 deletions(-) diff --git a/src/views/stack_view.rs b/src/views/stack_view.rs index 6bffaf1..01d9f3b 100644 --- a/src/views/stack_view.rs +++ b/src/views/stack_view.rs @@ -57,8 +57,10 @@ impl Placement { enum ChildWrapper { // Some views include a shadow around. Shadow(ShadowView>), + // Some include a background. + Backfilled(Layer), // Some views don't (fullscreen views mostly) - Plain(Layer), + Plain(T), } impl ChildWrapper { @@ -68,7 +70,11 @@ impl ChildWrapper { ChildWrapper::Shadow(shadow) => { shadow.into_inner().ok().unwrap().into_inner().ok().unwrap() } - ChildWrapper::Plain(layer) => layer.into_inner().ok().unwrap(), + // Layer::into_inner can never fail. + ChildWrapper::Backfilled(background) => { + background.into_inner().ok().unwrap() + } + ChildWrapper::Plain(layer) => layer, } } } @@ -78,7 +84,8 @@ impl ChildWrapper { pub fn get_inner(&self) -> &View { match *self { ChildWrapper::Shadow(ref shadow) => shadow.get_inner().get_inner(), - ChildWrapper::Plain(ref layer) => layer.get_inner(), + ChildWrapper::Backfilled(ref background) => background.get_inner(), + ChildWrapper::Plain(ref layer) => layer, } } @@ -88,7 +95,10 @@ impl ChildWrapper { ChildWrapper::Shadow(ref mut shadow) => { shadow.get_inner_mut().get_inner_mut() } - ChildWrapper::Plain(ref mut layer) => layer.get_inner_mut(), + ChildWrapper::Backfilled(ref mut background) => { + background.get_inner_mut() + } + ChildWrapper::Plain(ref mut layer) => layer, } } } @@ -98,6 +108,7 @@ impl View for ChildWrapper { fn draw(&self, printer: &Printer) { match *self { ChildWrapper::Shadow(ref v) => v.draw(printer), + ChildWrapper::Backfilled(ref v) => v.draw(printer), ChildWrapper::Plain(ref v) => v.draw(printer), } } @@ -105,6 +116,7 @@ impl View for ChildWrapper { fn on_event(&mut self, event: Event) -> EventResult { match *self { ChildWrapper::Shadow(ref mut v) => v.on_event(event), + ChildWrapper::Backfilled(ref mut v) => v.on_event(event), ChildWrapper::Plain(ref mut v) => v.on_event(event), } } @@ -112,6 +124,7 @@ impl View for ChildWrapper { fn layout(&mut self, size: Vec2) { match *self { ChildWrapper::Shadow(ref mut v) => v.layout(size), + ChildWrapper::Backfilled(ref mut v) => v.layout(size), ChildWrapper::Plain(ref mut v) => v.layout(size), } } @@ -119,6 +132,7 @@ impl View for ChildWrapper { fn required_size(&mut self, size: Vec2) -> Vec2 { match *self { ChildWrapper::Shadow(ref mut v) => v.required_size(size), + ChildWrapper::Backfilled(ref mut v) => v.required_size(size), ChildWrapper::Plain(ref mut v) => v.required_size(size), } } @@ -126,6 +140,7 @@ impl View for ChildWrapper { fn take_focus(&mut self, source: Direction) -> bool { match *self { ChildWrapper::Shadow(ref mut v) => v.take_focus(source), + ChildWrapper::Backfilled(ref mut v) => v.take_focus(source), ChildWrapper::Plain(ref mut v) => v.take_focus(source), } } @@ -137,6 +152,9 @@ impl View for ChildWrapper { ChildWrapper::Shadow(ref mut v) => { v.call_on_any(selector, callback) } + ChildWrapper::Backfilled(ref mut v) => { + v.call_on_any(selector, callback) + } ChildWrapper::Plain(ref mut v) => { v.call_on_any(selector, callback) } @@ -146,6 +164,7 @@ impl View for ChildWrapper { fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> { match *self { ChildWrapper::Shadow(ref mut v) => v.focus_view(selector), + ChildWrapper::Backfilled(ref mut v) => v.focus_view(selector), ChildWrapper::Plain(ref mut v) => v.focus_view(selector), } } @@ -184,7 +203,7 @@ impl StackView { { let boxed = ViewBox::boxed(view); self.layers.push(Child { - view: ChildWrapper::Plain(Layer::new(boxed)), + view: ChildWrapper::Backfilled(Layer::new(boxed)), size: Vec2::zero(), placement: Placement::Fullscreen, virgin: true, @@ -270,6 +289,16 @@ impl StackView { self.with(|s| s.add_fullscreen_layer(view)) } + /// Adds a new transparent layer on top of the stack. + /// + /// Chainable variant. + pub fn transparent_layer(self, view: T) -> Self + where + T: IntoBoxedView, + { + self.with(|s| s.add_transparent_layer(view)) + } + /// Adds a view on top of the stack. pub fn add_layer_at(&mut self, position: Position, view: T) where @@ -289,6 +318,28 @@ impl StackView { }); } + /// Adds a transparent view on top of the stack in the center of the screen. + pub fn add_transparent_layer(&mut self, view: T) + where + T: IntoBoxedView, + { + self.add_transparent_layer_at(Position::center(), view); + } + + /// Adds a transparent view on top of the stack. + pub fn add_transparent_layer_at(&mut self, position: Position, view: T) + where + T: IntoBoxedView, + { + let boxed = ViewBox::boxed(view); + self.layers.push(Child { + view: ChildWrapper::Plain(boxed), + size: Vec2::new(0, 0), + placement: Placement::Floating(position), + virgin: true, + }); + } + /// Adds a view on top of the stack. /// /// Chainable variant. @@ -617,4 +668,28 @@ mod tests { assert!(stack.pop_layer().is_none()); } + + #[test] + fn get() { + let mut stack = StackView::new() + .layer(TextView::new("1")) + .layer(TextView::new("2")); + + assert!(stack.get(LayerPosition::FromFront(0)).unwrap() + .as_any().downcast_ref::().unwrap() + .with_view(|v| v.as_any().is::()).unwrap() + ); + assert!(stack.get(LayerPosition::FromBack(0)).unwrap() + .as_any().downcast_ref::().unwrap() + .with_view(|v| v.as_any().is::()).unwrap() + ); + assert!(stack.get_mut(LayerPosition::FromFront(0)).unwrap() + .as_any_mut().downcast_mut::().unwrap() + .with_view_mut(|v| v.as_any_mut().is::()).unwrap() + ); + assert!(stack.get_mut(LayerPosition::FromBack(0)).unwrap() + .as_any_mut().downcast_mut::().unwrap() + .with_view_mut(|v| v.as_any_mut().is::()).unwrap() + ); + } } From 017e100b1b4be67b1f3df55e89e3b675a4438a42 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Sun, 10 Jun 2018 23:24:58 -0700 Subject: [PATCH 07/10] Add custom values to Palette This updates `Palette` to add a tree of custom values. Branches from this tree can be copied back to the root with Palette::merge. This can be used to group related values together. --- src/cursive.rs | 6 +- src/theme/color.rs | 11 ++ src/theme/mod.rs | 14 +-- src/theme/palette.rs | 234 ++++++++++++++++++++++++++++++------------- 4 files changed, 186 insertions(+), 79 deletions(-) diff --git a/src/cursive.rs b/src/cursive.rs index 784d0ac..783c996 100644 --- a/src/cursive.rs +++ b/src/cursive.rs @@ -92,7 +92,7 @@ impl Cursive { pub fn new(backend: Box) -> Self { let theme = theme::load_default(); // theme.activate(&mut backend); - // let theme = theme::load_theme("assets/style.toml").unwrap(); + // let theme = theme::load_toml("assets/style.toml").unwrap(); let (tx, rx) = mpsc::channel(); @@ -270,8 +270,8 @@ impl Cursive { /// Loads a theme from the given string content. /// /// Content must be valid toml. - pub fn load_theme(&mut self, content: &str) -> Result<(), theme::Error> { - self.set_theme(try!(theme::load_theme(content))); + pub fn load_toml(&mut self, content: &str) -> Result<(), theme::Error> { + self.set_theme(try!(theme::load_toml(content))); Ok(()) } diff --git a/src/theme/color.rs b/src/theme/color.rs index 43fe6f1..9c84543 100644 --- a/src/theme/color.rs +++ b/src/theme/color.rs @@ -114,6 +114,13 @@ impl Color { } } + /// Parse a string into a color. + /// + /// Examples: + /// * `"red"` becomes `Color::Dark(BaseColor::Red)` + /// * `"light green"` becomes `Color::Light(BaseColor::Green)` + /// * `"default"` becomes `Color::TerminalDefault` + /// * `"#123456"` becomes `Color::Rgb(0x12, 0x34, 0x56)` pub(crate) fn parse(value: &str) -> Option { Some(match value { "black" => Color::Dark(BaseColor::Black), @@ -149,11 +156,15 @@ impl Color { let r = load_hex(&value[0..l]) * multiplier; let g = load_hex(&value[l..2 * l]) * multiplier; let b = load_hex(&value[2 * l..3 * l]) * multiplier; + Some(Color::Rgb(r as u8, g as u8, b as u8)) } else if value.len() == 3 { // RGB values between 0 and 5 maybe? + // Like 050 for green let rgb: Vec<_> = value.chars().map(|c| c as i16 - '0' as i16).collect(); + + assert_eq!(rgb.len(), 3); if rgb.iter().all(|&i| i >= 0 && i < 6) { Some(Color::RgbLowRes( rgb[0] as u8, diff --git a/src/theme/mod.rs b/src/theme/mod.rs index b915e3c..07ddc5c 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -169,7 +169,7 @@ pub use self::color::{BaseColor, Color}; pub use self::color_pair::ColorPair; pub use self::color_style::{ColorStyle, ColorType}; pub use self::effect::Effect; -pub use self::palette::{default_palette, Palette, PaletteColor}; +pub use self::palette::{Palette, PaletteColor}; pub use self::style::Style; use std::fs::File; use std::io; @@ -193,13 +193,13 @@ impl Default for Theme { Theme { shadow: true, borders: BorderStyle::Simple, - palette: default_palette(), + palette: Palette::default(), } } } impl Theme { - fn load(&mut self, table: &toml::value::Table) { + fn load_toml(&mut self, table: &toml::value::Table) { if let Some(&toml::Value::Boolean(shadow)) = table.get("shadow") { self.shadow = shadow; } @@ -209,7 +209,7 @@ impl Theme { } if let Some(&toml::Value::Table(ref table)) = table.get("colors") { - palette::load_table(&mut self.palette, table); + palette::load_toml(&mut self.palette, table); } } } @@ -244,15 +244,15 @@ pub fn load_theme_file>(filename: P) -> Result { content }; - load_theme(&content) + load_toml(&content) } /// Loads a theme string and sets it as active. -pub fn load_theme(content: &str) -> Result { +pub fn load_toml(content: &str) -> Result { let table = toml::de::from_str(content)?; let mut theme = Theme::default(); - theme.load(&table); + theme.load_toml(&table); Ok(theme) } diff --git a/src/theme/palette.rs b/src/theme/palette.rs index 4273839..c0b95ee 100644 --- a/src/theme/palette.rs +++ b/src/theme/palette.rs @@ -2,6 +2,9 @@ use super::Color; use enum_map::EnumMap; use toml; +use std::collections::HashMap; +use std::ops::{Index, IndexMut}; + /// Color configuration for the application. /// /// Assign each color role an actual color. @@ -11,17 +14,112 @@ use toml; /// # Example /// /// ```rust -/// # use cursive::theme; +/// # use cursive::theme::Palette; /// use cursive::theme::PaletteColor::*; /// use cursive::theme::Color::*; /// use cursive::theme::BaseColor::*; /// -/// let mut palette = theme::default_palette(); +/// let mut palette = Palette::default(); /// /// assert_eq!(palette[Background], Dark(Blue)); /// palette[Shadow] = Light(Red); /// ``` -pub type Palette = EnumMap; +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct Palette { + basic: EnumMap, + custom: HashMap, +} + +/// A node in the palette tree. +/// +/// This can either be a color, or a nested namespace with its own mapping. +#[derive(PartialEq, Eq, Clone, Debug)] +enum PaletteNode { + Color(Color), + Namespace(HashMap), +} + +// Basic usage: only use basic colors +impl Index for Palette { + type Output = Color; + + fn index(&self, palette_color: PaletteColor) -> &Color { + &self.basic[palette_color] + } +} + +// We can alter existing color if needed (but why?...) +impl IndexMut for Palette { + fn index_mut(&mut self, palette_color: PaletteColor) -> &mut Color { + &mut self.basic[palette_color] + } +} + +impl Palette { + /// Returns a custom color from this palette. + /// + /// Returns `None` if the given key was not found. + pub fn custom<'a>(&'a self, key: &str) -> Option<&'a Color> { + self.custom.get(key).and_then(|node| { + if let &PaletteNode::Color(ref color) = node { + Some(color) + } else { + None + } + }) + } + + /// Returns a new palette where the given namespace has been merged. + /// + /// All values in the namespace will override previous values. + pub fn merge(&self, namespace: &str) -> Palette { + let mut result = self.clone(); + + if let Some(&PaletteNode::Namespace(ref palette)) = + self.custom.get(namespace) + { + // Merge `result` and `palette` + for (key, value) in palette.iter() { + match *value { + PaletteNode::Color(color) => result.set_color(key, color), + PaletteNode::Namespace(ref map) => + result.add_namespace(key, map.clone()), + } + } + } + + result + } + + /// Sets the color for the given key. + /// + /// This will update either the basic palette or the custom values. + pub fn set_color(&mut self, key: &str, color: Color) { + use theme::PaletteColor::*; + + match key { + "background" => self.basic[Background] = color, + "shadow" => self.basic[Shadow] = color, + "view" => self.basic[View] = color, + "primary" => self.basic[Primary] = color, + "secondary" => self.basic[Secondary] = color, + "tertiary" => self.basic[Tertiary] = color, + "title_primary" => self.basic[TitlePrimary] = color, + "title_secondary" => self.basic[TitleSecondary] = color, + "highlight" => self.basic[Highlight] = color, + "highlight_inactive" => self.basic[HighlightInactive] = color, + other => { + self.custom + .insert(other.to_string(), PaletteNode::Color(color)); + } + } + } + + /// Adds a color namespace to this palette. + fn add_namespace(&mut self, key: &str, namespace: HashMap) { + self.custom.insert(key.to_string(), PaletteNode::Namespace(namespace)); + } +} /// Returns the default palette for a cursive application. /// @@ -35,57 +133,77 @@ pub type Palette = EnumMap; /// * `TitleSecondary` => `Dark(Yellow)` /// * `Highlight` => `Dark(Red)` /// * `HighlightInactive` => `Dark(Blue)` -pub fn default_palette() -> Palette { - use self::PaletteColor::*; - use theme::BaseColor::*; - use theme::Color::*; +impl Default for Palette { + fn default() -> Palette { + use self::PaletteColor::*; + use theme::BaseColor::*; + use theme::Color::*; - enum_map!{ - Background => Dark(Blue), - Shadow => Dark(Black), - View => Dark(White), - Primary => Dark(Black), - Secondary => Dark(Blue), - Tertiary => Dark(White), - TitlePrimary => Dark(Red), - TitleSecondary => Dark(Yellow), - Highlight => Dark(Red), - HighlightInactive => Dark(Blue), + Palette { + basic: enum_map!{ + Background => Dark(Blue), + Shadow => Dark(Black), + View => Dark(White), + Primary => Dark(Black), + Secondary => Dark(Blue), + Tertiary => Dark(White), + TitlePrimary => Dark(Red), + TitleSecondary => Dark(Yellow), + Highlight => Dark(Red), + HighlightInactive => Dark(Blue), + }, + custom: HashMap::new(), + } } } +// Iterate over a toml +fn iterate_toml<'a>(table: &'a toml::value::Table) -> impl Iterator + 'a { + table.iter().flat_map(|(key, value)| { + let node = match value { + toml::Value::Table(table) => { + // This should define a new namespace + // Treat basic colors as simple string. + // We'll convert them back in the merge method. + let map = iterate_toml(table).map(|(key, value)| (key.to_string(), value)).collect(); + // Should we only return something if it's non-empty? + Some(PaletteNode::Namespace(map)) + } + toml::Value::Array(colors) => { + // This should be a list of colors - just pick the first valid one. + colors + .iter() + .flat_map(toml::Value::as_str) + .flat_map(Color::parse) + .map(PaletteNode::Color) + .next() + } + toml::Value::String(color) => { + // This describe a new color - easy! + Color::parse(color).map(PaletteNode::Color) + } + other => { + // Other - error? + debug!("Found unexpected value in theme: {} = {:?}", key, other); + None + } + }; + + node.map(|node| (key.as_str(), node)) + }) +} + /// Fills `palette` with the colors from the given `table`. -pub(crate) fn load_table(palette: &mut Palette, table: &toml::value::Table) { +pub(crate) fn load_toml(palette: &mut Palette, table: &toml::value::Table) { // TODO: use serde for that? // Problem: toml-rs doesn't do well with Enums... - load_color( - &mut palette[PaletteColor::Background], - table.get("background"), - ); - load_color(&mut palette[PaletteColor::Shadow], table.get("shadow")); - load_color(&mut palette[PaletteColor::View], table.get("view")); - load_color(&mut palette[PaletteColor::Primary], table.get("primary")); - load_color( - &mut palette[PaletteColor::Secondary], - table.get("secondary"), - ); - load_color(&mut palette[PaletteColor::Tertiary], table.get("tertiary")); - load_color( - &mut palette[PaletteColor::TitlePrimary], - table.get("title_primary"), - ); - load_color( - &mut palette[PaletteColor::TitleSecondary], - table.get("title_secondary"), - ); - load_color( - &mut palette[PaletteColor::Highlight], - table.get("highlight"), - ); - load_color( - &mut palette[PaletteColor::HighlightInactive], - table.get("highlight_inactive"), - ); + + for (key, value) in iterate_toml(table) { + match value { + PaletteNode::Color(color) => palette.set_color(key, color), + PaletteNode::Namespace(map) => palette.add_namespace(key, map), + } + } } /// Color entry in a palette. @@ -121,25 +239,3 @@ impl PaletteColor { palette[self] } } - -/// Parses `value` and fills `target` if it's a valid color. -fn load_color(target: &mut Color, value: Option<&toml::Value>) -> bool { - if let Some(value) = value { - match *value { - toml::Value::String(ref value) => { - if let Some(color) = Color::parse(value) { - *target = color; - true - } else { - false - } - } - toml::Value::Array(ref array) => { - array.iter().any(|item| load_color(target, Some(item))) - } - _ => false, - } - } else { - false - } -} From 8acc08f340c94bd821256ce7fbe19b20eed61bef Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Sun, 10 Jun 2018 23:29:10 -0700 Subject: [PATCH 08/10] Rustfmt --- examples/colors.rs | 2 +- examples/dialog.rs | 2 +- examples/edit.rs | 2 +- examples/hello_world.rs | 2 +- examples/key_codes.rs | 2 +- examples/linear.rs | 2 +- examples/list_view.rs | 7 +-- examples/logs.rs | 2 +- examples/markup.rs | 2 +- examples/menubar.rs | 2 +- examples/mines/main.rs | 4 +- examples/mutation.rs | 2 +- examples/position.rs | 2 +- examples/progress.rs | 4 +- examples/radio.rs | 2 +- examples/refcell_view.rs | 2 +- examples/select.rs | 2 +- examples/slider.rs | 2 +- examples/terminal_default.rs | 2 +- examples/text_area.rs | 10 ++-- examples/theme.rs | 2 +- examples/theme_manual.rs | 2 +- examples/vpv.rs | 11 ++--- src/backend/blt.rs | 31 +++++++------ src/backend/curses/mod.rs | 2 +- src/backend/curses/n.rs | 10 ++-- src/backend/curses/pan.rs | 9 ++-- src/backend/dummy.rs | 2 +- src/backend/mod.rs | 5 +- src/cursive.rs | 26 ++++++++--- src/direction.rs | 2 +- src/event.rs | 2 +- src/lib.rs | 14 +++--- src/menu.rs | 4 +- src/printer.rs | 20 ++++---- src/rect.rs | 5 +- src/theme/mod.rs | 6 +-- src/theme/palette.rs | 25 +++++++--- src/traits.rs | 4 +- src/utils/counter.rs | 2 +- src/utils/lines/simple/lines_iterator.rs | 6 +-- src/utils/lines/simple/mod.rs | 25 +++++----- src/utils/lines/spans/chunk_iterator.rs | 15 ++---- src/utils/lines/spans/lines_iterator.rs | 17 ++----- src/utils/lines/spans/prefix.rs | 2 +- src/utils/lines/spans/tests.rs | 34 ++++++-------- src/utils/markup/markdown.rs | 16 +++---- src/utils/span.rs | 14 +++--- src/vec.rs | 2 +- src/view/boxable.rs | 2 +- src/view/finder.rs | 3 +- src/view/margins.rs | 7 +-- src/view/mod.rs | 8 ++-- src/view/position.rs | 6 +-- src/view/scroll.rs | 2 +- src/view/size_cache.rs | 5 +- src/view/view.rs | 4 +- src/view/view_wrapper.rs | 6 +-- src/views/box_view.rs | 9 ++-- src/views/button.rs | 2 +- src/views/canvas.rs | 4 +- src/views/checkbox.rs | 10 ++-- src/views/dialog.rs | 24 ++++++---- src/views/dummy.rs | 2 +- src/views/edit_view.rs | 9 ++-- src/views/id_view.rs | 5 +- src/views/layer.rs | 2 +- src/views/linear_layout.rs | 31 +++++++------ src/views/list_view.rs | 48 ++++++++++---------- src/views/menu_popup.rs | 34 +++++++------- src/views/menubar.rs | 12 +++-- src/views/mod.rs | 8 ++-- src/views/on_event_view.rs | 4 +- src/views/panel.rs | 2 +- src/views/progress_bar.rs | 6 +-- src/views/radio.rs | 8 ++-- src/views/select_view.rs | 17 ++++--- src/views/shadow_view.rs | 2 +- src/views/slider_view.rs | 4 +- src/views/stack_view.rs | 58 +++++++++++++++++------- src/views/text_area.rs | 5 +- src/views/text_view.rs | 11 +++-- src/views/tracked_view.rs | 2 +- 83 files changed, 378 insertions(+), 356 deletions(-) diff --git a/examples/colors.rs b/examples/colors.rs index 1f7213b..b5fb862 100644 --- a/examples/colors.rs +++ b/examples/colors.rs @@ -1,9 +1,9 @@ extern crate cursive; -use cursive::{Cursive, Printer}; use cursive::theme::{Color, ColorStyle}; use cursive::view::Boxable; use cursive::views::Canvas; +use cursive::{Cursive, Printer}; // This example will draw a colored square with a gradient. // diff --git a/examples/dialog.rs b/examples/dialog.rs index 126ad32..bf8ce28 100644 --- a/examples/dialog.rs +++ b/examples/dialog.rs @@ -1,7 +1,7 @@ extern crate cursive; -use cursive::Cursive; use cursive::views::{Dialog, TextView}; +use cursive::Cursive; fn main() { // Creates the cursive root - required for every application. diff --git a/examples/edit.rs b/examples/edit.rs index b6d695f..bcafbb5 100644 --- a/examples/edit.rs +++ b/examples/edit.rs @@ -1,8 +1,8 @@ extern crate cursive; -use cursive::Cursive; use cursive::traits::*; use cursive::views::{Dialog, EditView, TextView}; +use cursive::Cursive; fn main() { let mut siv = Cursive::default(); diff --git a/examples/hello_world.rs b/examples/hello_world.rs index fb5fae7..e0ba7c6 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -1,7 +1,7 @@ extern crate cursive; -use cursive::Cursive; use cursive::views::TextView; +use cursive::Cursive; fn main() { let mut siv = Cursive::default(); diff --git a/examples/key_codes.rs b/examples/key_codes.rs index 65b1a6b..0be8385 100644 --- a/examples/key_codes.rs +++ b/examples/key_codes.rs @@ -1,8 +1,8 @@ extern crate cursive; -use cursive::{Cursive, Printer}; use cursive::event::{Event, EventResult}; use cursive::traits::*; +use cursive::{Cursive, Printer}; // This example define a custom view that prints any event it receives. // This is a handy way to check the input received by cursive. diff --git a/examples/linear.rs b/examples/linear.rs index 1d38f9d..bc0fa1f 100644 --- a/examples/linear.rs +++ b/examples/linear.rs @@ -1,9 +1,9 @@ extern crate cursive; -use cursive::Cursive; use cursive::align::HAlign; use cursive::traits::*; use cursive::views::{Dialog, DummyView, LinearLayout, TextView}; +use cursive::Cursive; // This example uses a LinearLayout to stick multiple views next to each other. diff --git a/examples/list_view.rs b/examples/list_view.rs index a87ed11..0c04251 100644 --- a/examples/list_view.rs +++ b/examples/list_view.rs @@ -1,9 +1,10 @@ extern crate cursive; -use cursive::Cursive; use cursive::traits::*; -use cursive::views::{Checkbox, Dialog, EditView, LinearLayout, ListView, - SelectView, TextView}; +use cursive::views::{ + Checkbox, Dialog, EditView, LinearLayout, ListView, SelectView, TextView, +}; +use cursive::Cursive; // This example uses a ListView. // diff --git a/examples/logs.rs b/examples/logs.rs index a37add2..846fbf4 100644 --- a/examples/logs.rs +++ b/examples/logs.rs @@ -1,8 +1,8 @@ extern crate cursive; -use cursive::{Cursive, Printer}; use cursive::traits::*; use cursive::vec::Vec2; +use cursive::{Cursive, Printer}; use std::collections::VecDeque; use std::sync::mpsc; use std::thread; diff --git a/examples/markup.rs b/examples/markup.rs index bc260fe..4ea2e61 100644 --- a/examples/markup.rs +++ b/examples/markup.rs @@ -1,12 +1,12 @@ extern crate cursive; -use cursive::Cursive; use cursive::theme::BaseColor; use cursive::theme::Color; use cursive::theme::Effect; use cursive::theme::Style; use cursive::utils::markup::StyledString; use cursive::views::{Dialog, TextView}; +use cursive::Cursive; fn main() { let mut siv = Cursive::default(); diff --git a/examples/menubar.rs b/examples/menubar.rs index fb063ff..1482de5 100644 --- a/examples/menubar.rs +++ b/examples/menubar.rs @@ -1,10 +1,10 @@ extern crate cursive; -use cursive::Cursive; use cursive::event::Key; use cursive::menu::MenuTree; use cursive::traits::*; use cursive::views::Dialog; +use cursive::Cursive; use std::sync::atomic::{AtomicUsize, Ordering}; // This examples shows how to configure and use a menubar at the top of the diff --git a/examples/mines/main.rs b/examples/mines/main.rs index 0937183..3a5e152 100644 --- a/examples/mines/main.rs +++ b/examples/mines/main.rs @@ -3,13 +3,13 @@ extern crate rand; mod game; -use cursive::Cursive; -use cursive::Printer; use cursive::direction::Direction; use cursive::event::{Event, EventResult, MouseButton, MouseEvent}; use cursive::theme::{BaseColor, Color, ColorStyle}; use cursive::vec::Vec2; use cursive::views::{Button, Dialog, LinearLayout, Panel, SelectView}; +use cursive::Cursive; +use cursive::Printer; fn main() { let mut siv = Cursive::default(); diff --git a/examples/mutation.rs b/examples/mutation.rs index db65c26..32cf39b 100644 --- a/examples/mutation.rs +++ b/examples/mutation.rs @@ -1,9 +1,9 @@ extern crate cursive; -use cursive::Cursive; use cursive::traits::*; use cursive::view::{Offset, Position}; use cursive::views::{Dialog, OnEventView, TextView}; +use cursive::Cursive; // This example modifies a view after creation. diff --git a/examples/position.rs b/examples/position.rs index cf4dff4..4957102 100644 --- a/examples/position.rs +++ b/examples/position.rs @@ -1,9 +1,9 @@ extern crate cursive; -use cursive::Cursive; use cursive::view::Position; use cursive::views::LayerPosition; use cursive::views::TextView; +use cursive::Cursive; /// Moves top layer by the specified amount fn move_top(c: &mut Cursive, x_in: isize, y_in: isize) { diff --git a/examples/progress.rs b/examples/progress.rs index 107b036..5fcf9ba 100644 --- a/examples/progress.rs +++ b/examples/progress.rs @@ -1,10 +1,10 @@ extern crate cursive; extern crate rand; -use cursive::Cursive; use cursive::traits::*; -use cursive::views::{Button, Dialog, LinearLayout, ProgressBar, TextView}; use cursive::utils::Counter; +use cursive::views::{Button, Dialog, LinearLayout, ProgressBar, TextView}; +use cursive::Cursive; use rand::Rng; use std::cmp::min; use std::thread; diff --git a/examples/radio.rs b/examples/radio.rs index f7ccfbc..ef3b060 100644 --- a/examples/radio.rs +++ b/examples/radio.rs @@ -1,7 +1,7 @@ extern crate cursive; -use cursive::Cursive; use cursive::views::{Dialog, DummyView, LinearLayout, RadioGroup}; +use cursive::Cursive; // This example uses radio buttons. diff --git a/examples/refcell_view.rs b/examples/refcell_view.rs index 44f16e3..e20c159 100644 --- a/examples/refcell_view.rs +++ b/examples/refcell_view.rs @@ -1,8 +1,8 @@ extern crate cursive; -use cursive::Cursive; use cursive::view::{Boxable, Identifiable}; use cursive::views::{Dialog, EditView, LinearLayout, TextView}; +use cursive::Cursive; // This example shows a way to access multiple views at the same time. diff --git a/examples/select.rs b/examples/select.rs index d930be6..961481a 100644 --- a/examples/select.rs +++ b/examples/select.rs @@ -1,10 +1,10 @@ extern crate cursive; -use cursive::Cursive; use cursive::align::HAlign; use cursive::event::EventResult; use cursive::traits::*; use cursive::views::{Dialog, OnEventView, SelectView, TextView}; +use cursive::Cursive; // We'll use a SelectView here. // diff --git a/examples/slider.rs b/examples/slider.rs index b84a2e3..8442c7f 100644 --- a/examples/slider.rs +++ b/examples/slider.rs @@ -1,8 +1,8 @@ extern crate cursive; -use cursive::Cursive; use cursive::traits::*; use cursive::views::{Dialog, SliderView}; +use cursive::Cursive; fn main() { let mut siv = Cursive::default(); diff --git a/examples/terminal_default.rs b/examples/terminal_default.rs index 57f4c36..eb96433 100644 --- a/examples/terminal_default.rs +++ b/examples/terminal_default.rs @@ -1,8 +1,8 @@ extern crate cursive; -use cursive::Cursive; use cursive::theme::{Color, PaletteColor, Theme}; use cursive::views::TextView; +use cursive::Cursive; // This example sets the background color to the terminal default. // diff --git a/examples/text_area.rs b/examples/text_area.rs index e72f4a1..84de991 100644 --- a/examples/text_area.rs +++ b/examples/text_area.rs @@ -1,9 +1,9 @@ extern crate cursive; -use cursive::Cursive; use cursive::event::{Event, Key}; use cursive::traits::*; use cursive::views::{Dialog, EditView, OnEventView, TextArea}; +use cursive::Cursive; fn main() { let mut siv = Cursive::default(); @@ -35,10 +35,10 @@ fn main() { .min_width(10), ) .button("Ok", |s| { - let text = s.call_on_id( - "edit", - |view: &mut EditView| view.get_content(), - ).unwrap(); + let text = + s.call_on_id("edit", |view: &mut EditView| { + view.get_content() + }).unwrap(); find(s, &text); }) .dismiss_button("Cancel"), diff --git a/examples/theme.rs b/examples/theme.rs index 02e694a..4798e54 100644 --- a/examples/theme.rs +++ b/examples/theme.rs @@ -1,7 +1,7 @@ extern crate cursive; -use cursive::Cursive; use cursive::views::{Dialog, TextView}; +use cursive::Cursive; fn main() { let mut siv = Cursive::default(); diff --git a/examples/theme_manual.rs b/examples/theme_manual.rs index 4168b83..80e99a1 100644 --- a/examples/theme_manual.rs +++ b/examples/theme_manual.rs @@ -1,8 +1,8 @@ extern crate cursive; -use cursive::Cursive; use cursive::theme::{BaseColor, BorderStyle, Color, ColorStyle}; use cursive::views::{Dialog, EditView, LinearLayout, TextView}; +use cursive::Cursive; fn main() { let mut siv = Cursive::default(); diff --git a/examples/vpv.rs b/examples/vpv.rs index c3ba833..50b693d 100644 --- a/examples/vpv.rs +++ b/examples/vpv.rs @@ -3,10 +3,10 @@ extern crate pretty_bytes; use std::io; -use cursive::Cursive; use cursive::traits::{Boxable, With}; use cursive::utils; use cursive::views::{Canvas, Dialog, LinearLayout, ProgressBar}; +use cursive::Cursive; use pretty_bytes::converter::convert; use std::thread; use std::time; @@ -31,10 +31,7 @@ fn main() { let meta = std::fs::metadata(&source).unwrap(); // If possible, read the file size to have a progress bar. let len = meta.len(); - ( - Some(source), - if len > 0 { Some(len) } else { None }, - ) + (Some(source), if len > 0 { Some(len) } else { None }) } None => (None, None), }; @@ -68,9 +65,7 @@ fn main() { } // When we're done, shut down the application - cb_sink - .send(Box::new(|s: &mut Cursive| s.quit())) - .unwrap(); + cb_sink.send(Box::new(|s: &mut Cursive| s.quit())).unwrap(); }); // Add a single view: progress status diff --git a/src/backend/blt.rs b/src/backend/blt.rs index fcc9997..1792f22 100644 --- a/src/backend/blt.rs +++ b/src/backend/blt.rs @@ -5,10 +5,11 @@ extern crate bear_lib_terminal; -use self::bear_lib_terminal::Color as BltColor; use self::bear_lib_terminal::geometry::Size; -use self::bear_lib_terminal::terminal::{self, state, Event as BltEvent, - KeyCode}; +use self::bear_lib_terminal::terminal::{ + self, state, Event as BltEvent, KeyCode, +}; +use self::bear_lib_terminal::Color as BltColor; use backend; use event::{Event, Key, MouseButton, MouseEvent}; use std::collections::HashSet; @@ -49,7 +50,7 @@ impl Backend { } fn blt_keycode_to_ev( - &mut self, kc: KeyCode, shift: bool, ctrl: bool + &mut self, kc: KeyCode, shift: bool, ctrl: bool, ) -> Event { match kc { KeyCode::F1 @@ -179,12 +180,12 @@ impl backend::Backend for Backend { fn set_color(&self, color: ColorPair) -> ColorPair { let current = ColorPair { front: blt_colour_to_colour(state::foreground()), - back: blt_colour_to_colour(state::background()) + back: blt_colour_to_colour(state::background()), }; - + let fg = colour_to_blt_colour(color.front, ColorRole::Foreground); let bg = colour_to_blt_colour(color.back, ColorRole::Background); - + terminal::set_colors(fg, bg); current @@ -196,14 +197,14 @@ impl backend::Backend for Backend { Effect::Bold | Effect::Italic | Effect::Underline - | Effect::Simple => {}, + | Effect::Simple => {} // TODO: how to do this correctly?` // BLT itself doesn't do this kind of thing, // we'd need the colours in our position, // but `f()` can do whatever - Effect::Reverse => terminal::set_colors( - state::background(), state::foreground() - ), + Effect::Reverse => { + terminal::set_colors(state::background(), state::foreground()) + } } } @@ -213,11 +214,11 @@ impl backend::Backend for Backend { Effect::Bold | Effect::Italic | Effect::Underline - | Effect::Simple => {}, + | Effect::Simple => {} // The process of reversing is the same as unreversing - Effect::Reverse => terminal::set_colors( - state::background(), state::foreground() - ), + Effect::Reverse => { + terminal::set_colors(state::background(), state::foreground()) + } } } diff --git a/src/backend/curses/mod.rs b/src/backend/curses/mod.rs index 7458b31..7f24df5 100644 --- a/src/backend/curses/mod.rs +++ b/src/backend/curses/mod.rs @@ -63,7 +63,7 @@ where fn find_closest_pair(pair: &ColorPair, max_colors: i16) -> (i16, i16) { ( - find_closest(&pair.front,max_colors), + find_closest(&pair.front, max_colors), find_closest(&pair.back, max_colors), ) } diff --git a/src/backend/curses/n.rs b/src/backend/curses/n.rs index 6d38bff..aae0bb4 100644 --- a/src/backend/curses/n.rs +++ b/src/backend/curses/n.rs @@ -1,7 +1,7 @@ extern crate ncurses; -use self::ncurses::mmask_t; use self::super::split_i32; +use self::ncurses::mmask_t; use backend; use event::{Event, Key, MouseButton, MouseEvent}; use libc; @@ -10,7 +10,7 @@ use std::collections::HashMap; use std::ffi::CString; use std::fs::File; use std::io; -use std::io::{Write}; +use std::io::Write; use theme::{Color, ColorPair, Effect}; use utf8; use vec::Vec2; @@ -95,10 +95,9 @@ impl Backend { Box::new(c) } - /// Save a new color pair. fn insert_color( - &self, pairs: &mut HashMap<(i16, i16), i16>, (front, back): (i16, i16) + &self, pairs: &mut HashMap<(i16, i16), i16>, (front, back): (i16, i16), ) -> i16 { let n = 1 + pairs.len() as i16; @@ -157,7 +156,8 @@ impl Backend { let _alt = (mevent.bstate & ncurses::BUTTON_ALT as mmask_t) != 0; let _ctrl = (mevent.bstate & ncurses::BUTTON_CTRL as mmask_t) != 0; - mevent.bstate &= !(ncurses::BUTTON_SHIFT | ncurses::BUTTON_ALT + mevent.bstate &= !(ncurses::BUTTON_SHIFT + | ncurses::BUTTON_ALT | ncurses::BUTTON_CTRL) as mmask_t; diff --git a/src/backend/curses/pan.rs b/src/backend/curses/pan.rs index 0f350dd..e39e005 100644 --- a/src/backend/curses/pan.rs +++ b/src/backend/curses/pan.rs @@ -1,7 +1,7 @@ extern crate pancurses; -use self::pancurses::mmask_t; use self::super::split_i32; +use self::pancurses::mmask_t; use backend; use event::{Event, Key, MouseButton, MouseEvent}; use std::cell::{Cell, RefCell}; @@ -65,9 +65,7 @@ impl Backend { /// Save a new color pair. fn insert_color( - &self, - pairs: &mut HashMap<(i16,i16), i32>, - (front, back): (i16, i16), + &self, pairs: &mut HashMap<(i16, i16), i32>, (front, back): (i16, i16), ) -> i32 { let n = 1 + pairs.len() as i32; @@ -119,7 +117,8 @@ impl Backend { let _alt = (mevent.bstate & pancurses::BUTTON_ALT as mmask_t) != 0; let _ctrl = (mevent.bstate & pancurses::BUTTON_CTRL as mmask_t) != 0; - mevent.bstate &= !(pancurses::BUTTON_SHIFT | pancurses::BUTTON_ALT + mevent.bstate &= !(pancurses::BUTTON_SHIFT + | pancurses::BUTTON_ALT | pancurses::BUTTON_CTRL) as mmask_t; let make_event = |event| Event::Mouse { diff --git a/src/backend/dummy.rs b/src/backend/dummy.rs index 0d7e907..d1c5cdf 100644 --- a/src/backend/dummy.rs +++ b/src/backend/dummy.rs @@ -1,7 +1,7 @@ //! Dummy backend use backend; -use theme; use event; +use theme; use vec::Vec2; pub struct Backend; diff --git a/src/backend/mod.rs b/src/backend/mod.rs index e2a82bd..dda6143 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -4,7 +4,7 @@ //! backend library, which handles all actual input and output. //! //! This module defines the `Backend` trait, as well as a few implementations -//! using some common libraries. Each of those included backends needs a +//! using some common libraries. Each of those included backends needs a //! corresonding feature to be enabled. use event; @@ -14,9 +14,9 @@ use vec::Vec2; pub mod dummy; -pub mod termion; pub mod blt; pub mod curses; +pub mod termion; /// Trait defining the required methods to be a backend. pub trait Backend { @@ -58,7 +58,6 @@ pub trait Backend { /// Enables the given effect. fn set_effect(&self, effect: theme::Effect); - /// Disables the given effect. fn unset_effect(&self, effect: theme::Effect); } diff --git a/src/cursive.rs b/src/cursive.rs index 783c996..04a7770 100644 --- a/src/cursive.rs +++ b/src/cursive.rs @@ -46,14 +46,27 @@ impl Default for Cursive { } } -#[cfg(all(not(feature = "termion"), not(feature = "pancurses"), feature = "bear-lib-terminal"))] +#[cfg( + all( + not(feature = "termion"), + not(feature = "pancurses"), + feature = "bear-lib-terminal" + ) +)] impl Default for Cursive { fn default() -> Self { Self::blt() } } -#[cfg(all(not(feature = "termion"), not(feature = "pancurses"), not(feature = "bear-lib-terminal"), feature = "ncurses"))] +#[cfg( + all( + not(feature = "termion"), + not(feature = "pancurses"), + not(feature = "bear-lib-terminal"), + feature = "ncurses" + ) +)] impl Default for Cursive { fn default() -> Self { Self::ncurses() @@ -261,7 +274,7 @@ impl Cursive { /// /// `filename` must point to a valid toml file. pub fn load_theme_file>( - &mut self, filename: P + &mut self, filename: P, ) -> Result<(), theme::Error> { self.set_theme(try!(theme::load_theme_file(filename))); Ok(()) @@ -366,7 +379,7 @@ impl Cursive { /// # } /// ``` pub fn call_on( - &mut self, sel: &view::Selector, callback: F + &mut self, sel: &view::Selector, callback: F, ) -> Option where V: View + Any, @@ -532,7 +545,7 @@ impl Cursive { /// Convenient stub forwarding layer repositioning. pub fn reposition_layer( - &mut self, layer: LayerPosition, position: Position + &mut self, layer: LayerPosition, position: Position, ) { self.screen_mut().reposition_layer(layer, position); } @@ -661,7 +674,8 @@ impl Cursive { event, position, .. } = event { - if event.grabs_focus() && !self.menubar.autohide + if event.grabs_focus() + && !self.menubar.autohide && !self.menubar.has_submenu() && position.y == 0 { diff --git a/src/direction.rs b/src/direction.rs index 55f71fa..6b5c68b 100644 --- a/src/direction.rs +++ b/src/direction.rs @@ -15,8 +15,8 @@ //! * Relative direction: front or back. //! Its actual direction depends on the orientation. -use XY; use vec::Vec2; +use XY; /// Describes a vertical or horizontal orientation for a view. #[derive(Clone, Copy, Debug, PartialEq)] diff --git a/src/event.rs b/src/event.rs index 353ad88..d952178 100644 --- a/src/event.rs +++ b/src/event.rs @@ -13,10 +13,10 @@ //! [global callback](../struct.Cursive.html#method.add_global_callback) //! table is checked. -use Cursive; use std::ops::Deref; use std::rc::Rc; use vec::Vec2; +use Cursive; /// Callback is a function that can be triggered by an event. /// It has a mutable access to the cursive root. diff --git a/src/lib.rs b/src/lib.rs index 968b752..ef86ca2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,8 +72,8 @@ extern crate log; #[macro_use] extern crate maplit; -extern crate num; extern crate libc; +extern crate num; extern crate owning_ref; extern crate toml; extern crate unicode_segmentation; @@ -100,20 +100,20 @@ pub mod event; #[macro_use] pub mod view; -pub mod views; -pub mod vec; +pub mod align; +pub mod direction; +pub mod menu; pub mod rect; pub mod theme; -pub mod align; -pub mod menu; -pub mod direction; pub mod utils; +pub mod vec; +pub mod views; // This probably doesn't need to be public? mod cursive; mod printer; -mod xy; mod with; +mod xy; mod div; mod utf8; diff --git a/src/menu.rs b/src/menu.rs index 3759ee9..88fbe84 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -12,10 +12,10 @@ //! //! [menubar]: ../struct.Cursive.html#method.menubar -use Cursive; -use With; use event::Callback; use std::rc::Rc; +use Cursive; +use With; /// Root of a menu tree. #[derive(Default, Clone)] diff --git a/src/printer.rs b/src/printer.rs index 029a3ab..850b9d3 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -33,7 +33,7 @@ impl<'a, 'b> Printer<'a, 'b> { /// But nobody needs to know that. #[doc(hidden)] pub fn new>( - size: T, theme: &'a Theme, backend: &'b Backend + size: T, theme: &'a Theme, backend: &'b Backend, ) -> Self { Printer { offset: Vec2::zero(), @@ -93,7 +93,7 @@ impl<'a, 'b> Printer<'a, 'b> { let p = p + self.offset; for y in 0..len { - self.backend.print_at(p + (0,y), c); + self.backend.print_at(p + (0, y), c); } } @@ -178,12 +178,12 @@ impl<'a, 'b> Printer<'a, 'b> { F: FnOnce(&Printer), { let new_printer = Printer { - offset: self.offset, - size: self.size, - focused: self.focused, - theme : theme, - new: self.new.clone(), - backend : self.backend + offset: self.offset, + size: self.size, + focused: self.focused, + theme: theme, + new: self.new.clone(), + backend: self.backend, }; f(&new_printer); } @@ -222,7 +222,7 @@ impl<'a, 'b> Printer<'a, 'b> { /// printer.print_box((0,0), (6,4), false); /// ``` pub fn print_box, S: Into>( - &self, start: T, size: S, invert: bool + &self, start: T, size: S, invert: bool, ) { self.new.set(false); @@ -319,7 +319,7 @@ impl<'a, 'b> Printer<'a, 'b> { /// Returns a printer on a subset of this one's area. pub fn sub_printer, T: Into>( - &self, offset: S, size: T, focused: bool + &self, offset: S, size: T, focused: bool, ) -> Printer<'a, 'b> { let size = size.into(); let offset = offset.into().or_min(self.size); diff --git a/src/rect.rs b/src/rect.rs index 536755b..19ebb60 100644 --- a/src/rect.rs +++ b/src/rect.rs @@ -80,7 +80,10 @@ impl Rect { } /// Adds the given offset to this rectangle. - pub fn offset(&mut self, offset: V) where V: Into { + pub fn offset(&mut self, offset: V) + where + V: Into, + { let offset = offset.into(); self.top_left = self.top_left + offset; self.bottom_right = self.bottom_right + offset; diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 07ddc5c..ddfe2e6 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -156,13 +156,13 @@ //! highlight = "#F00" //! highlight_inactive = "#5555FF" //! ``` -mod style; -mod effect; +mod border_style; mod color; mod color_pair; mod color_style; -mod border_style; +mod effect; mod palette; +mod style; pub use self::border_style::BorderStyle; pub use self::color::{BaseColor, Color}; diff --git a/src/theme/palette.rs b/src/theme/palette.rs index c0b95ee..3265df6 100644 --- a/src/theme/palette.rs +++ b/src/theme/palette.rs @@ -82,8 +82,9 @@ impl Palette { for (key, value) in palette.iter() { match *value { PaletteNode::Color(color) => result.set_color(key, color), - PaletteNode::Namespace(ref map) => - result.add_namespace(key, map.clone()), + PaletteNode::Namespace(ref map) => { + result.add_namespace(key, map.clone()) + } } } } @@ -116,8 +117,11 @@ impl Palette { } /// Adds a color namespace to this palette. - fn add_namespace(&mut self, key: &str, namespace: HashMap) { - self.custom.insert(key.to_string(), PaletteNode::Namespace(namespace)); + fn add_namespace( + &mut self, key: &str, namespace: HashMap, + ) { + self.custom + .insert(key.to_string(), PaletteNode::Namespace(namespace)); } } @@ -158,14 +162,18 @@ impl Default for Palette { } // Iterate over a toml -fn iterate_toml<'a>(table: &'a toml::value::Table) -> impl Iterator + 'a { +fn iterate_toml<'a>( + table: &'a toml::value::Table, +) -> impl Iterator + 'a { table.iter().flat_map(|(key, value)| { let node = match value { toml::Value::Table(table) => { // This should define a new namespace // Treat basic colors as simple string. // We'll convert them back in the merge method. - let map = iterate_toml(table).map(|(key, value)| (key.to_string(), value)).collect(); + let map = iterate_toml(table) + .map(|(key, value)| (key.to_string(), value)) + .collect(); // Should we only return something if it's non-empty? Some(PaletteNode::Namespace(map)) } @@ -184,7 +192,10 @@ fn iterate_toml<'a>(table: &'a toml::value::Table) -> impl Iterator { // Other - error? - debug!("Found unexpected value in theme: {} = {:?}", key, other); + debug!( + "Found unexpected value in theme: {} = {:?}", + key, other + ); None } }; diff --git a/src/traits.rs b/src/traits.rs index 8588a0d..b4ca93c 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -8,7 +8,7 @@ //! use cursive::traits::*; //! ``` -#[doc(no_inline)] -pub use With; #[doc(no_inline)] pub use view::{Boxable, Finder, Identifiable, View}; +#[doc(no_inline)] +pub use With; diff --git a/src/utils/counter.rs b/src/utils/counter.rs index 5a13875..3c74c26 100644 --- a/src/utils/counter.rs +++ b/src/utils/counter.rs @@ -1,5 +1,5 @@ -use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; +use std::sync::Arc; /// Atomic counter used by [`ProgressBar`]. /// diff --git a/src/utils/lines/simple/lines_iterator.rs b/src/utils/lines/simple/lines_iterator.rs index c14696d..8305739 100644 --- a/src/utils/lines/simple/lines_iterator.rs +++ b/src/utils/lines/simple/lines_iterator.rs @@ -70,10 +70,6 @@ impl<'a> Iterator for LinesIterator<'a> { let width = row.width; - Some(Row { - start, - end, - width, - }) + Some(Row { start, end, width }) } } diff --git a/src/utils/lines/simple/mod.rs b/src/utils/lines/simple/mod.rs index 55dc1bd..c190964 100644 --- a/src/utils/lines/simple/mod.rs +++ b/src/utils/lines/simple/mod.rs @@ -61,18 +61,19 @@ where // `current_width` is the width of everything // before the next token, including any space. let mut current_width = 0; - let sum: usize = iter.take_while(|token| { - let width = token.width(); - if current_width + width > available_width { - false - } else { - // Include the delimiter after this token. - current_width += width; - current_width += delimiter_width; - true - } - }).map(|token| token.len() + delimiter_len) - .sum(); + let sum: usize = + iter.take_while(|token| { + let width = token.width(); + if current_width + width > available_width { + false + } else { + // Include the delimiter after this token. + current_width += width; + current_width += delimiter_width; + true + } + }).map(|token| token.len() + delimiter_len) + .sum(); // We counted delimiter once too many times, // but only if the iterator was non empty. diff --git a/src/utils/lines/spans/chunk_iterator.rs b/src/utils/lines/spans/chunk_iterator.rs index 9034279..a92fa73 100644 --- a/src/utils/lines/spans/chunk_iterator.rs +++ b/src/utils/lines/spans/chunk_iterator.rs @@ -47,10 +47,7 @@ where } // Skip empty spans - if self.source.spans()[self.current_span] - .as_ref() - .is_empty() - { + if self.source.spans()[self.current_span].as_ref().is_empty() { self.current_span += 1; return self.next(); } @@ -123,13 +120,9 @@ where self.current_span += 1; // Skip empty spans - while let Some(true) = self.source - .spans() - .get(self.current_span) - .map(|span| { - span.as_ref() - .resolve(self.source.source()) - .is_empty() + while let Some(true) = + self.source.spans().get(self.current_span).map(|span| { + span.as_ref().resolve(self.source.source()).is_empty() }) { self.current_span += 1; } diff --git a/src/utils/lines/spans/lines_iterator.rs b/src/utils/lines/spans/lines_iterator.rs index 36c9ffc..ebfaff5 100644 --- a/src/utils/lines/spans/lines_iterator.rs +++ b/src/utils/lines/spans/lines_iterator.rs @@ -76,11 +76,8 @@ where self.width }; - let mut chunks = prefix( - &mut self.iter, - allowed_width, - &mut self.chunk_offset, - ); + let mut chunks = + prefix(&mut self.iter, allowed_width, &mut self.chunk_offset); // println!("Chunks..: {:?}", chunks); @@ -152,10 +149,7 @@ where // We can know text was wrapped if the stop was optional, // and there's more coming. - let text_wrap = !chunks - .last() - .map(|c| c.hard_stop) - .unwrap_or(true) + let text_wrap = !chunks.last().map(|c| c.hard_stop).unwrap_or(true) && self.iter.peek().is_some(); // If we had to break a line in two, then at least pretent we're @@ -178,9 +172,6 @@ where // TODO: merge consecutive segments of the same span - Some(Row { - segments, - width, - }) + Some(Row { segments, width }) } } diff --git a/src/utils/lines/spans/prefix.rs b/src/utils/lines/spans/prefix.rs index ddece70..7c7d5fa 100644 --- a/src/utils/lines/spans/prefix.rs +++ b/src/utils/lines/spans/prefix.rs @@ -3,7 +3,7 @@ use std::iter::Peekable; /// Concatenates chunks as long as they fit in the given width. pub fn prefix( - tokens: &mut Peekable, width: usize, offset: &mut ChunkPart + tokens: &mut Peekable, width: usize, offset: &mut ChunkPart, ) -> Vec where I: Iterator, diff --git a/src/utils/lines/spans/tests.rs b/src/utils/lines/spans/tests.rs index 32fe742..7528e1d 100644 --- a/src/utils/lines/spans/tests.rs +++ b/src/utils/lines/spans/tests.rs @@ -8,9 +8,7 @@ fn input() -> StyledString { text.append(StyledString::styled("didn't", Effect::Bold)); text.append(StyledString::plain(" say ")); text.append(StyledString::styled("half", Effect::Italic)); - text.append(StyledString::plain( - " the things people say I did.", - )); + text.append(StyledString::plain(" the things people say I did.")); text.append(StyledString::plain("\n")); text.append(StyledString::plain("\n")); text.append(StyledString::plain(" - A. Einstein")); @@ -49,25 +47,19 @@ fn test_line_breaks() { attr: &Style::from(Effect::Italic), }, ], - vec![ - Span { - content: "the things people", - attr: &Style::none(), - }, - ], - vec![ - Span { - content: "say I did.", - attr: &Style::none(), - }, - ], + vec![Span { + content: "the things people", + attr: &Style::none(), + }], + vec![Span { + content: "say I did.", + attr: &Style::none(), + }], vec![], - vec![ - Span { - content: " - A. Einstein", - attr: &Style::none(), - }, - ], + vec![Span { + content: " - A. Einstein", + attr: &Style::none(), + }], ] ); } diff --git a/src/utils/markup/markdown.rs b/src/utils/markup/markdown.rs index 0bf983e..715eef4 100644 --- a/src/utils/markup/markdown.rs +++ b/src/utils/markup/markdown.rs @@ -73,10 +73,12 @@ impl<'a> Iterator for Parser<'a> { self.stack.push(Style::from(Effect::Italic)) } Tag::Header(level) => { - return Some(self.literal(format!( - "{} ", - header(level as usize) - ))) + return Some( + self.literal(format!( + "{} ", + header(level as usize) + )), + ) } Tag::Rule => return Some(self.literal("---")), Tag::BlockQuote => return Some(self.literal("> ")), @@ -139,10 +141,8 @@ Attention ==== I *really* love __Cursive__!"; let spans = parse_spans(input); - let spans: Vec<_> = spans - .iter() - .map(|span| span.resolve(input)) - .collect(); + let spans: Vec<_> = + spans.iter().map(|span| span.resolve(input)).collect(); // println!("{:?}", spans); assert_eq!( diff --git a/src/utils/span.rs b/src/utils/span.rs index d9cabab..61404a6 100644 --- a/src/utils/span.rs +++ b/src/utils/span.rs @@ -195,15 +195,13 @@ impl SpannedString { { let source = source.into(); - let spans = vec![ - IndexedSpan { - content: IndexedCow::Borrowed { - start: 0, - end: source.len(), - }, - attr, + let spans = vec![IndexedSpan { + content: IndexedCow::Borrowed { + start: 0, + end: source.len(), }, - ]; + attr, + }]; Self::with_spans(source, spans) } diff --git a/src/vec.rs b/src/vec.rs index c08b539..af8c235 100644 --- a/src/vec.rs +++ b/src/vec.rs @@ -1,9 +1,9 @@ //! Points on the 2D character grid. -use XY; use num::traits::Zero; use std::cmp::{max, min, Ordering}; use std::ops::{Add, Div, Mul, Sub}; +use XY; /// Simple 2D size, in cells. /// diff --git a/src/view/boxable.rs b/src/view/boxable.rs index b46d662..275949a 100644 --- a/src/view/boxable.rs +++ b/src/view/boxable.rs @@ -8,7 +8,7 @@ use views::BoxView; pub trait Boxable: View + Sized { /// Wraps `self` in a `BoxView` with the given size constraints. fn boxed( - self, width: SizeConstraint, height: SizeConstraint + self, width: SizeConstraint, height: SizeConstraint, ) -> BoxView { BoxView::new(width, height, self) } diff --git a/src/view/finder.rs b/src/view/finder.rs index 2e81423..89f2e3f 100644 --- a/src/view/finder.rs +++ b/src/view/finder.rs @@ -46,7 +46,8 @@ impl Finder for T { *result_ref = v.downcast_mut::().map(|v| callback(v)); } else if v.is::>() { - *result_ref = v.downcast_mut::>() + *result_ref = v + .downcast_mut::>() .and_then(|v| v.with_view_mut(callback)); } } diff --git a/src/view/margins.rs b/src/view/margins.rs index e358bda..0070804 100644 --- a/src/view/margins.rs +++ b/src/view/margins.rs @@ -61,12 +61,7 @@ impl From<(usize, usize, usize, usize)> for Margins { impl From<(i32, i32, i32, i32)> for Margins { fn from((left, right, top, bottom): (i32, i32, i32, i32)) -> Margins { - ( - left as usize, - right as usize, - top as usize, - bottom as usize, - ).into() + (left as usize, right as usize, top as usize, bottom as usize).into() } } diff --git a/src/view/mod.rs b/src/view/mod.rs index d04f1e0..4e16b05 100644 --- a/src/view/mod.rs +++ b/src/view/mod.rs @@ -41,17 +41,17 @@ mod view_wrapper; // Essentials components mod any; mod finder; -mod position; mod margins; +mod position; mod size_cache; mod size_constraint; -mod view_path; mod view; +mod view_path; // Helper bases -mod scroll; -mod identifiable; mod boxable; +mod identifiable; +mod scroll; mod into_boxed_view; diff --git a/src/view/position.rs b/src/view/position.rs index d6e116e..7d9bbf9 100644 --- a/src/view/position.rs +++ b/src/view/position.rs @@ -1,6 +1,6 @@ -use XY; use std::cmp::min; use vec::Vec2; +use XY; /// Location of the view on screen pub type Position = XY; @@ -30,7 +30,7 @@ impl Position { /// child with its top-left corner at the returned coordinates will /// position him appropriately. pub fn compute_offset( - &self, size: S, available: A, parent: P + &self, size: S, available: A, parent: P, ) -> Vec2 where S: Into, @@ -65,7 +65,7 @@ pub enum Offset { impl Offset { /// Computes a single-dimension offset requred to draw a view. pub fn compute_offset( - &self, size: usize, available: usize, parent: usize + &self, size: usize, available: usize, parent: usize, ) -> usize { if size > available { 0 diff --git a/src/view/scroll.rs b/src/view/scroll.rs index 0ee3097..5f89978 100644 --- a/src/view/scroll.rs +++ b/src/view/scroll.rs @@ -1,8 +1,8 @@ -use Printer; use div::div_up; use std::cmp::{max, min}; use theme::ColorStyle; use vec::Vec2; +use Printer; /// Provide scrolling functionalities to a view. /// diff --git a/src/view/size_cache.rs b/src/view/size_cache.rs index 3786eab..8094128 100644 --- a/src/view/size_cache.rs +++ b/src/view/size_cache.rs @@ -18,10 +18,7 @@ pub struct SizeCache { impl SizeCache { /// Creates a new sized cache pub fn new(value: usize, constrained: bool) -> Self { - SizeCache { - value, - constrained, - } + SizeCache { value, constrained } } /// Returns `true` if `self` is still valid for the given `request`. diff --git a/src/view/view.rs b/src/view/view.rs index b6221db..48da32b 100644 --- a/src/view/view.rs +++ b/src/view/view.rs @@ -1,15 +1,14 @@ -use Printer; use direction::Direction; use event::{Event, EventResult}; use std::any::Any; use vec::Vec2; use view::{AnyView, Selector}; +use Printer; /// Main trait defining a view behaviour. /// /// This is what you should implement to define a custom View. pub trait View: Any + AnyView { - /// Draws the view with the given printer (includes bounds) and focus. /// /// This is the only *required* method to implement. @@ -63,7 +62,6 @@ pub trait View: Any + AnyView { EventResult::Ignored } - /// Runs a closure on the view identified by the given selector. /// /// See [`Finder::call_on`] for a nicer interface, implemented for all diff --git a/src/view/view_wrapper.rs b/src/view/view_wrapper.rs index 980fc12..c228a20 100644 --- a/src/view/view_wrapper.rs +++ b/src/view/view_wrapper.rs @@ -1,9 +1,9 @@ -use Printer; use direction::Direction; use event::{Event, EventResult}; use std::any::Any; use vec::Vec2; use view::{Selector, View}; +use Printer; /// Generic wrapper around a view. /// @@ -78,7 +78,7 @@ pub trait ViewWrapper: 'static { /// Wraps the `find` method. fn wrap_call_on_any<'a>( - &mut self, selector: &Selector, callback: Box + &mut self, selector: &Selector, callback: Box, ) { self.with_view_mut(|v| v.call_on_any(selector, callback)); } @@ -118,7 +118,7 @@ impl View for T { } fn call_on_any<'a>( - &mut self, selector: &Selector, callback: Box + &mut self, selector: &Selector, callback: Box, ) { self.wrap_call_on_any(selector, callback) } diff --git a/src/views/box_view.rs b/src/views/box_view.rs index af55c6a..823e96c 100644 --- a/src/views/box_view.rs +++ b/src/views/box_view.rs @@ -1,6 +1,6 @@ -use XY; use vec::Vec2; use view::{SizeConstraint, View, ViewWrapper}; +use XY; /// Wrapper around another view, with a controlled size. /// @@ -39,7 +39,7 @@ impl BoxView { /// /// `None` values will use the wrapped view's preferences. pub fn new( - width: SizeConstraint, height: SizeConstraint, view: T + width: SizeConstraint, height: SizeConstraint, view: T, ) -> Self { BoxView { size: (width, height).into(), @@ -50,7 +50,7 @@ impl BoxView { /// Sets the size constraints for this view. pub fn set_constraints( - &mut self, width: SizeConstraint, height: SizeConstraint + &mut self, width: SizeConstraint, height: SizeConstraint, ) { self.set_width(width); self.set_height(height); @@ -195,7 +195,8 @@ impl ViewWrapper for BoxView { let req = self.size.zip_map(req, SizeConstraint::available); let child_size = self.view.required_size(req); - let result = self.size + let result = self + .size .zip_map(child_size.zip(req), SizeConstraint::result); debug!("{:?}", result); diff --git a/src/views/button.rs b/src/views/button.rs index 4e5afaf..5ff8b81 100644 --- a/src/views/button.rs +++ b/src/views/button.rs @@ -1,4 +1,3 @@ -use {Cursive, Printer, With}; use align::HAlign; use direction::Direction; use event::*; @@ -6,6 +5,7 @@ use theme::ColorStyle; use unicode_width::UnicodeWidthStr; use vec::Vec2; use view::View; +use {Cursive, Printer, With}; /// Simple text label with a callback when is pressed. /// diff --git a/src/views/canvas.rs b/src/views/canvas.rs index f89be69..b865cb0 100644 --- a/src/views/canvas.rs +++ b/src/views/canvas.rs @@ -1,9 +1,9 @@ -use Printer; -use With; use direction::Direction; use event::{Event, EventResult}; use vec::Vec2; use view::View; +use Printer; +use With; /// A blank view that forwards calls to closures. /// diff --git a/src/views/checkbox.rs b/src/views/checkbox.rs index 6f8aef4..b695c28 100644 --- a/src/views/checkbox.rs +++ b/src/views/checkbox.rs @@ -1,12 +1,12 @@ -use Cursive; -use Printer; -use With; use direction::Direction; use event::{Event, EventResult, Key, MouseButton, MouseEvent}; use std::rc::Rc; use theme::ColorStyle; use vec::Vec2; use view::View; +use Cursive; +use Printer; +use With; /// Checkable box. pub struct Checkbox { @@ -32,7 +32,7 @@ impl Checkbox { /// Sets a callback to be used when the state changes. pub fn set_on_change( - &mut self, on_change: F + &mut self, on_change: F, ) { self.on_change = Some(Rc::new(on_change)); } @@ -41,7 +41,7 @@ impl Checkbox { /// /// Chainable variant. pub fn on_change( - self, on_change: F + self, on_change: F, ) -> Self { self.with(|s| s.set_on_change(on_change)) } diff --git a/src/views/dialog.rs b/src/views/dialog.rs index 7222678..8dc6085 100644 --- a/src/views/dialog.rs +++ b/src/views/dialog.rs @@ -1,6 +1,3 @@ -use Cursive; -use Printer; -use With; use align::*; use direction::Direction; use event::*; @@ -12,6 +9,9 @@ use unicode_width::UnicodeWidthStr; use vec::Vec2; use view::{Margins, Selector, View}; use views::{Button, DummyView, SizedView, TextView, ViewBox}; +use Cursive; +use Printer; +use With; /// Identifies currently focused element in [`Dialog`]. /// @@ -246,7 +246,7 @@ impl Dialog { /// Returns an iterator on this buttons for this dialog. pub fn buttons_mut<'a>( - &'a mut self + &'a mut self, ) -> Box<'a + Iterator> { Box::new(self.buttons.iter_mut().map(|b| &mut b.button.view)) } @@ -281,7 +281,7 @@ impl Dialog { // An event is received while a button is in focus fn on_event_button( - &mut self, event: Event, button_id: usize + &mut self, event: Event, button_id: usize, ) -> EventResult { let result = { let button = &mut self.buttons[button_id]; @@ -340,7 +340,8 @@ impl Dialog { // Current horizontal position of the next button we'll draw. // Sum of the sizes + len-1 for margins - let width = self.buttons + let width = self + .buttons .iter() .map(|button| button.button.size.x) .sum::() @@ -350,7 +351,8 @@ impl Dialog { return None; } let mut offset = overhead.left - + self.align + + self + .align .h .get_offset(width, printer.size.x - overhead.horizontal()); @@ -382,7 +384,8 @@ impl Dialog { fn draw_content(&self, printer: &Printer, buttons_height: usize) { // What do we have left? - let taken = Vec2::new(0, buttons_height) + self.borders.combined() + let taken = Vec2::new(0, buttons_height) + + self.borders.combined() + self.padding.combined(); let inner_size = match printer.size.checked_sub(taken) { @@ -405,7 +408,8 @@ impl Dialog { } let spacing = 3; //minimum distance to borders let x = spacing - + self.title_position + + self + .title_position .get_offset(len, printer.size.x - 2 * spacing); printer.with_high_border(false, |printer| { printer.print((x - 2, 0), "┤ "); @@ -564,7 +568,7 @@ impl View for Dialog { } fn call_on_any<'a>( - &mut self, selector: &Selector, callback: Box + &mut self, selector: &Selector, callback: Box, ) { self.content.call_on_any(selector, callback); } diff --git a/src/views/dummy.rs b/src/views/dummy.rs index 5b88176..c59cca9 100644 --- a/src/views/dummy.rs +++ b/src/views/dummy.rs @@ -1,5 +1,5 @@ -use Printer; use view::View; +use Printer; /// Dummy view. /// diff --git a/src/views/edit_view.rs b/src/views/edit_view.rs index 3bd3321..ce5a85e 100644 --- a/src/views/edit_view.rs +++ b/src/views/edit_view.rs @@ -367,8 +367,7 @@ impl EditView { self.offset = 0; self.set_cursor(len); - self.make_edit_cb() - .unwrap_or_else(Callback::dummy) + self.make_edit_cb().unwrap_or_else(Callback::dummy) } /// Get the current text. @@ -420,8 +419,7 @@ impl EditView { self.keep_cursor_in_view(); - self.make_edit_cb() - .unwrap_or_else(Callback::dummy) + self.make_edit_cb().unwrap_or_else(Callback::dummy) } /// Remove the character at the current cursor position. @@ -436,8 +434,7 @@ impl EditView { self.keep_cursor_in_view(); - self.make_edit_cb() - .unwrap_or_else(Callback::dummy) + self.make_edit_cb().unwrap_or_else(Callback::dummy) } fn make_edit_cb(&self) -> Option { diff --git a/src/views/id_view.rs b/src/views/id_view.rs index 5b957da..faef974 100644 --- a/src/views/id_view.rs +++ b/src/views/id_view.rs @@ -77,7 +77,7 @@ impl ViewWrapper for IdView { // Some for<'b> weirdness here to please the borrow checker gods... fn wrap_call_on_any<'a>( - &mut self, selector: &Selector, mut callback: BoxedCallback<'a> + &mut self, selector: &Selector, mut callback: BoxedCallback<'a>, ) { match selector { &Selector::Id(id) if id == self.id => callback(self), @@ -93,7 +93,8 @@ impl ViewWrapper for IdView { fn wrap_focus_view(&mut self, selector: &Selector) -> Result<(), ()> { match selector { &Selector::Id(id) if id == self.id => Ok(()), - s => self.view + s => self + .view .try_borrow_mut() .map_err(|_| ()) .and_then(|mut v| v.deref_mut().focus_view(s)), diff --git a/src/views/layer.rs b/src/views/layer.rs index 14ee200..b75756f 100644 --- a/src/views/layer.rs +++ b/src/views/layer.rs @@ -1,5 +1,5 @@ -use Printer; use view::{View, ViewWrapper}; +use Printer; /// Wrapper view that fills the background. /// diff --git a/src/views/linear_layout.rs b/src/views/linear_layout.rs index 1dc406f..12ad117 100644 --- a/src/views/linear_layout.rs +++ b/src/views/linear_layout.rs @@ -1,6 +1,3 @@ -use Printer; -use With; -use XY; use direction; use event::{Event, EventResult, Key}; use std::any::Any; @@ -8,6 +5,9 @@ use std::cmp::min; use std::ops::Deref; use vec::Vec2; use view::{Selector, SizeCache, View}; +use Printer; +use With; +use XY; /// Arranges its children linearly according to its orientation. pub struct LinearLayout { @@ -57,7 +57,7 @@ struct ChildItem { impl ChildIterator { fn new( - inner: T, orientation: direction::Orientation, available: usize + inner: T, orientation: direction::Orientation, available: usize, ) -> Self { ChildIterator { inner, @@ -195,7 +195,8 @@ impl LinearLayout { } fn children_are_sleeping(&self) -> bool { - !self.children + !self + .children .iter() .map(Child::as_view) .any(View::needs_relayout) @@ -203,7 +204,7 @@ impl LinearLayout { /// Returns a cyclic mutable iterator starting with the child in focus fn iter_mut<'a>( - &'a mut self, from_focus: bool, source: direction::Relative + &'a mut self, from_focus: bool, source: direction::Relative, ) -> Box + 'a> { match source { direction::Relative::Front => { @@ -292,7 +293,7 @@ impl LinearLayout { } fn try_focus( - (i, child): (usize, &mut Child), source: direction::Direction + (i, child): (usize, &mut Child), source: direction::Direction, ) -> Option { if child.view.take_focus(source) { Some(i) @@ -358,7 +359,8 @@ impl View for LinearLayout { } // First, make a naive scenario: everything will work fine. - let ideal_sizes: Vec = self.children + let ideal_sizes: Vec = self + .children .iter_mut() .map(|c| c.required_size(req)) .collect(); @@ -382,7 +384,8 @@ impl View for LinearLayout { // See how they like it that way. // This is, hopefully, the absolute minimum these views will accept. - let min_sizes: Vec = self.children + let min_sizes: Vec = self + .children .iter_mut() .map(|c| c.required_size(budget_req)) .collect(); @@ -462,7 +465,8 @@ impl View for LinearLayout { // Let's ask everyone one last time. Everyone should be happy. // (But they may ask more on the other axis.) - let final_sizes: Vec = self.children + let final_sizes: Vec = self + .children .iter_mut() .enumerate() .map(|(i, c)| c.required_size(final_lengths[i])) @@ -482,10 +486,9 @@ impl View for LinearLayout { // In what order will we iterate on the children? let rel = source.relative(self.orientation); // We activate from_focus only if coming from the "sides". - let i = if let Some(i) = self.iter_mut( - rel.is_none(), - rel.unwrap_or(direction::Relative::Front), - ).filter_map(|p| try_focus(p, source)) + let i = if let Some(i) = self + .iter_mut(rel.is_none(), rel.unwrap_or(direction::Relative::Front)) + .filter_map(|p| try_focus(p, source)) .next() { // ... we can't update `self.focus` here, diff --git a/src/views/list_view.rs b/src/views/list_view.rs index 3671372..728455e 100644 --- a/src/views/list_view.rs +++ b/src/views/list_view.rs @@ -1,6 +1,3 @@ -use Cursive; -use Printer; -use With; use direction; use event::{Callback, Event, EventResult, Key, MouseButton, MouseEvent}; use std::any::Any; @@ -8,6 +5,9 @@ use std::rc::Rc; use unicode_width::UnicodeWidthStr; use vec::Vec2; use view::{ScrollBase, Selector, View}; +use Cursive; +use Printer; +use With; /// Represents a child from a [`ListView`]. /// @@ -148,7 +148,7 @@ impl ListView { } fn iter_mut<'a>( - &'a mut self, from_focus: bool, source: direction::Relative + &'a mut self, from_focus: bool, source: direction::Relative, ) -> Box + 'a> { match source { direction::Relative::Front => { @@ -172,7 +172,7 @@ impl ListView { } fn move_focus( - &mut self, n: usize, source: direction::Direction + &mut self, n: usize, source: direction::Direction, ) -> EventResult { let i = if let Some(i) = source .relative(direction::Orientation::Vertical) @@ -246,7 +246,7 @@ impl ListView { } fn try_focus( - (i, child): (usize, &mut ListChild), source: direction::Direction + (i, child): (usize, &mut ListChild), source: direction::Direction, ) -> Option { match *child { ListChild::Delimiter => None, @@ -279,14 +279,16 @@ impl View for ListView { fn required_size(&mut self, req: Vec2) -> Vec2 { // We'll show 2 columns: the labels, and the views. - let label_width = self.children + let label_width = self + .children .iter() .map(ListChild::label) .map(UnicodeWidthStr::width) .max() .unwrap_or(0); - let view_size = self.children + let view_size = self + .children .iter_mut() .filter_map(ListChild::view) .map(|v| v.required_size(req).x) @@ -306,7 +308,8 @@ impl View for ListView { self.scrollbase.set_heights(size.y, self.children.len()); // We'll show 2 columns: the labels, and the views. - let label_width = self.children + let label_width = self + .children .iter() .map(ListChild::label) .map(UnicodeWidthStr::width) @@ -316,7 +319,8 @@ impl View for ListView { let spacing = 1; let scrollbar_width = if self.children.len() > size.y { 2 } else { 0 }; - let available = size.x + let available = size + .x .saturating_sub(label_width + spacing + scrollbar_width); debug!("Available: {}", available); @@ -399,16 +403,10 @@ impl View for ListView { Event::Key(Key::PageDown) => { self.move_focus(10, direction::Direction::up()) } - Event::Key(Key::Home) | Event::Ctrl(Key::Home) => { - self.move_focus( - usize::max_value(), - direction::Direction::back(), - ) - } - Event::Key(Key::End) | Event::Ctrl(Key::End) => self.move_focus( - usize::max_value(), - direction::Direction::front(), - ), + Event::Key(Key::Home) | Event::Ctrl(Key::Home) => self + .move_focus(usize::max_value(), direction::Direction::back()), + Event::Key(Key::End) | Event::Ctrl(Key::End) => self + .move_focus(usize::max_value(), direction::Direction::front()), Event::Key(Key::Tab) => { self.move_focus(1, direction::Direction::front()) } @@ -437,10 +435,9 @@ impl View for ListView { fn take_focus(&mut self, source: direction::Direction) -> bool { let rel = source.relative(direction::Orientation::Vertical); - let i = if let Some(i) = self.iter_mut( - rel.is_none(), - rel.unwrap_or(direction::Relative::Front), - ).filter_map(|p| try_focus(p, source)) + let i = if let Some(i) = self + .iter_mut(rel.is_none(), rel.unwrap_or(direction::Relative::Front)) + .filter_map(|p| try_focus(p, source)) .next() { i @@ -463,7 +460,8 @@ impl View for ListView { } fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> { - if let Some(i) = self.children + if let Some(i) = self + .children .iter_mut() .enumerate() .filter_map(|(i, v)| v.view().map(|v| (i, v))) diff --git a/src/views/menu_popup.rs b/src/views/menu_popup.rs index e255a09..2c266b7 100644 --- a/src/views/menu_popup.rs +++ b/src/views/menu_popup.rs @@ -1,6 +1,3 @@ -use Cursive; -use Printer; -use With; use align::Align; use event::{Callback, Event, EventResult, Key, MouseButton, MouseEvent}; use menu::{MenuItem, MenuTree}; @@ -10,6 +7,9 @@ use unicode_width::UnicodeWidthStr; use vec::Vec2; use view::{Position, ScrollBase, View}; use views::OnEventView; +use Cursive; +use Printer; +use With; /// Popup that shows a list of items. pub struct MenuPopup { @@ -137,13 +137,13 @@ impl MenuPopup { fn make_subtree_cb(&self, tree: &Rc) -> EventResult { let tree = Rc::clone(tree); - let max_width = 4 - + self.menu - .children - .iter() - .map(Self::item_width) - .max() - .unwrap_or(1); + let max_width = 4 + self + .menu + .children + .iter() + .map(Self::item_width) + .max() + .unwrap_or(1); let offset = Vec2::new(max_width, self.focus); let action_cb = self.on_action.clone(); @@ -250,13 +250,13 @@ impl View for MenuPopup { fn required_size(&mut self, req: Vec2) -> Vec2 { // We can't really shrink our items here, so it's not flexible. - let w = 4 - + self.menu - .children - .iter() - .map(Self::item_width) - .max() - .unwrap_or(1); + let w = 4 + self + .menu + .children + .iter() + .map(Self::item_width) + .max() + .unwrap_or(1); let h = 2 + self.menu.children.len(); let scrolling = req.y < h; diff --git a/src/views/menubar.rs b/src/views/menubar.rs index abb83fc..83b625a 100644 --- a/src/views/menubar.rs +++ b/src/views/menubar.rs @@ -1,5 +1,3 @@ -use Cursive; -use Printer; use direction; use event::*; use menu::{MenuItem, MenuTree}; @@ -9,6 +7,8 @@ use unicode_width::UnicodeWidthStr; use vec::Vec2; use view::{Position, View}; use views::{MenuPopup, OnEventView}; +use Cursive; +use Printer; /// Current state of the menubar #[derive(PartialEq, Debug)] @@ -106,7 +106,7 @@ impl Menubar { /// Insert a new item at the given position. pub fn insert_subtree( - &mut self, i: usize, title: S, menu: MenuTree + &mut self, i: usize, title: S, menu: MenuTree, ) -> &mut Self where S: Into, @@ -341,7 +341,8 @@ impl View for Menubar { .checked_sub(offset) .and_then(|pos| self.child_at(pos.x)) { - if self.focus == child && btn == MouseButton::Left + if self.focus == child + && btn == MouseButton::Left && self.root.children[child].is_leaf() { return self.select_child(false); @@ -371,7 +372,8 @@ impl View for Menubar { // We add 2 to the length of every label for marin. // Also, we add 1 at the beginning. // (See the `draw()` method) - let width = self.root + let width = self + .root .children .iter() .map(|item| item.label().len() + 2) diff --git a/src/views/mod.rs b/src/views/mod.rs index 3661037..24d1de0 100644 --- a/src/views/mod.rs +++ b/src/views/mod.rs @@ -35,7 +35,6 @@ macro_rules! impl_enabled { } } -mod view_box; mod box_view; mod button; mod canvas; @@ -44,23 +43,24 @@ mod dialog; mod dummy; mod edit_view; mod id_view; -mod on_event_view; mod layer; mod linear_layout; mod list_view; -mod menubar; mod menu_popup; +mod menubar; +mod on_event_view; mod panel; mod progress_bar; mod radio; mod select_view; -mod slider_view; mod shadow_view; mod sized_view; +mod slider_view; mod stack_view; mod text_area; mod text_view; mod tracked_view; +mod view_box; pub use self::box_view::BoxView; pub use self::button::Button; diff --git a/src/views/on_event_view.rs b/src/views/on_event_view.rs index 4db522a..ae86df3 100644 --- a/src/views/on_event_view.rs +++ b/src/views/on_event_view.rs @@ -1,9 +1,9 @@ -use Cursive; -use With; use event::{Callback, Event, EventResult}; use std::collections::HashMap; use std::rc::Rc; use view::{View, ViewWrapper}; +use Cursive; +use With; /// A wrapper view that can react to events. /// diff --git a/src/views/panel.rs b/src/views/panel.rs index 63e577f..68f1d97 100644 --- a/src/views/panel.rs +++ b/src/views/panel.rs @@ -1,7 +1,7 @@ -use Printer; use event::{Event, EventResult}; use vec::Vec2; use view::{View, ViewWrapper}; +use Printer; /// Draws a border around a wrapped view. #[derive(Debug)] diff --git a/src/views/progress_bar.rs b/src/views/progress_bar.rs index 3377024..414d37a 100644 --- a/src/views/progress_bar.rs +++ b/src/views/progress_bar.rs @@ -1,10 +1,10 @@ -use Printer; use align::HAlign; use std::cmp; use std::thread; use theme::{ColorStyle, Effect}; use utils::Counter; use view::View; +use Printer; // pub type CbPromise = Option>; @@ -96,7 +96,7 @@ impl ProgressBar { /// /// Chainable variant. pub fn with_task( - mut self, task: F + mut self, task: F, ) -> Self { self.start(task); self @@ -116,7 +116,7 @@ impl ProgressBar { /// } /// ``` pub fn with_label String + 'static>( - mut self, label_maker: F + mut self, label_maker: F, ) -> Self { self.label_maker = Box::new(label_maker); self diff --git a/src/views/radio.rs b/src/views/radio.rs index 9afb823..733026f 100644 --- a/src/views/radio.rs +++ b/src/views/radio.rs @@ -1,4 +1,3 @@ -use {Printer, With}; use direction::Direction; use event::{Event, EventResult, Key, MouseButton, MouseEvent}; use std::cell::RefCell; @@ -6,6 +5,7 @@ use std::rc::Rc; use theme::ColorStyle; use vec::Vec2; use view::View; +use {Printer, With}; struct SharedState { selection: usize, @@ -52,7 +52,7 @@ impl RadioGroup { /// /// The button will display `label` next to it, and will embed `value`. pub fn button>( - &mut self, value: T, label: S + &mut self, value: T, label: S, ) -> RadioButton { let count = self.state.borrow().values.len(); self.state.borrow_mut().values.push(Rc::new(value)); @@ -75,7 +75,7 @@ impl RadioGroup { impl RadioGroup { /// Adds a button, using the label itself as value. pub fn button_str>( - &mut self, text: S + &mut self, text: S, ) -> RadioButton { let text = text.into(); self.button(text.clone(), text) @@ -104,7 +104,7 @@ impl RadioButton { impl_enabled!(self.enabled); fn new( - state: Rc>>, id: usize, label: String + state: Rc>>, id: usize, label: String, ) -> Self { RadioButton { state, diff --git a/src/views/select_view.rs b/src/views/select_view.rs index edc44e8..f3f092e 100644 --- a/src/views/select_view.rs +++ b/src/views/select_view.rs @@ -1,6 +1,3 @@ -use Cursive; -use Printer; -use With; use align::{Align, HAlign, VAlign}; use direction::Direction; use event::{Callback, Event, EventResult, Key, MouseButton, MouseEvent}; @@ -14,6 +11,9 @@ use unicode_width::UnicodeWidthStr; use vec::Vec2; use view::{Position, ScrollBase, View}; use views::MenuPopup; +use Cursive; +use Printer; +use With; /// View to select an item among a list. /// @@ -526,7 +526,8 @@ impl SelectView { // the list when we reach the end. // This is achieved by chaining twice the iterator let iter = self.items.iter().chain(self.items.iter()); - if let Some((i, _)) = iter.enumerate() + if let Some((i, _)) = iter + .enumerate() .skip(self.focus() + 1) .find(|&(_, item)| item.label.starts_with(c)) { @@ -640,7 +641,10 @@ impl SelectView { } /// Convenient method to use the label as value. - pub fn insert_item_str(&mut self, index: usize, label: S) where S: Into { + pub fn insert_item_str(&mut self, index: usize, label: S) + where + S: Into, + { let label = label.into(); self.insert_item(index, label.clone(), label); } @@ -732,7 +736,8 @@ impl View for SelectView { // Items here are not compressible. // So no matter what the horizontal requirements are, // we'll still return our longest item. - let w = self.items + let w = self + .items .iter() .map(|item| item.label.width()) .max() diff --git a/src/views/shadow_view.rs b/src/views/shadow_view.rs index a0f31cd..0e0f2e3 100644 --- a/src/views/shadow_view.rs +++ b/src/views/shadow_view.rs @@ -1,8 +1,8 @@ -use Printer; use event::{Event, EventResult}; use theme::ColorStyle; use vec::Vec2; use view::{View, ViewWrapper}; +use Printer; /// Wrapper view that adds a shadow. /// diff --git a/src/views/slider_view.rs b/src/views/slider_view.rs index 01476ef..9732173 100644 --- a/src/views/slider_view.rs +++ b/src/views/slider_view.rs @@ -1,11 +1,11 @@ -use {Cursive, Printer}; -use With; use direction::{Direction, Orientation}; use event::{Callback, Event, EventResult, Key, MouseButton, MouseEvent}; use std::rc::Rc; use theme::ColorStyle; use vec::Vec2; use view::View; +use With; +use {Cursive, Printer}; /// A horizontal or vertical slider. pub struct SliderView { diff --git a/src/views/stack_view.rs b/src/views/stack_view.rs index 01d9f3b..a2495d9 100644 --- a/src/views/stack_view.rs +++ b/src/views/stack_view.rs @@ -1,5 +1,3 @@ -use Printer; -use With; use direction::Direction; use event::{Event, EventResult}; use std::any::Any; @@ -9,6 +7,8 @@ use theme::ColorStyle; use vec::Vec2; use view::{IntoBoxedView, Offset, Position, Selector, View, ViewWrapper}; use views::{Layer, ShadowView, ViewBox}; +use Printer; +use With; /// Simple stack of views. /// Only the top-most view is active and can receive input. @@ -37,7 +37,7 @@ pub enum LayerPosition { impl Placement { pub fn compute_offset( - &self, size: S, available: A, parent: P + &self, size: S, available: A, parent: P, ) -> Vec2 where S: Into, @@ -146,7 +146,7 @@ impl View for ChildWrapper { } fn call_on_any<'a>( - &mut self, selector: &Selector, callback: Box + &mut self, selector: &Selector, callback: Box, ) { match *self { ChildWrapper::Shadow(ref mut v) => { @@ -415,7 +415,7 @@ impl StackView { /// Has no effect on fullscreen layers /// Has no effect if layer is not found pub fn reposition_layer( - &mut self, layer: LayerPosition, position: Position + &mut self, layer: LayerPosition, position: Position, ) { let i = self.get_index(layer); let child = match self.layers.get_mut(i) { @@ -675,21 +675,45 @@ mod tests { .layer(TextView::new("1")) .layer(TextView::new("2")); - assert!(stack.get(LayerPosition::FromFront(0)).unwrap() - .as_any().downcast_ref::().unwrap() - .with_view(|v| v.as_any().is::()).unwrap() + assert!( + stack + .get(LayerPosition::FromFront(0)) + .unwrap() + .as_any() + .downcast_ref::() + .unwrap() + .with_view(|v| v.as_any().is::()) + .unwrap() ); - assert!(stack.get(LayerPosition::FromBack(0)).unwrap() - .as_any().downcast_ref::().unwrap() - .with_view(|v| v.as_any().is::()).unwrap() + assert!( + stack + .get(LayerPosition::FromBack(0)) + .unwrap() + .as_any() + .downcast_ref::() + .unwrap() + .with_view(|v| v.as_any().is::()) + .unwrap() ); - assert!(stack.get_mut(LayerPosition::FromFront(0)).unwrap() - .as_any_mut().downcast_mut::().unwrap() - .with_view_mut(|v| v.as_any_mut().is::()).unwrap() + assert!( + stack + .get_mut(LayerPosition::FromFront(0)) + .unwrap() + .as_any_mut() + .downcast_mut::() + .unwrap() + .with_view_mut(|v| v.as_any_mut().is::()) + .unwrap() ); - assert!(stack.get_mut(LayerPosition::FromBack(0)).unwrap() - .as_any_mut().downcast_mut::().unwrap() - .with_view_mut(|v| v.as_any_mut().is::()).unwrap() + assert!( + stack + .get_mut(LayerPosition::FromBack(0)) + .unwrap() + .as_any_mut() + .downcast_mut::() + .unwrap() + .with_view_mut(|v| v.as_any_mut().is::()) + .unwrap() ); } } diff --git a/src/views/text_area.rs b/src/views/text_area.rs index 08e248c..6ea256f 100644 --- a/src/views/text_area.rs +++ b/src/views/text_area.rs @@ -1,4 +1,3 @@ -use {Printer, With, XY}; use direction::Direction; use event::{Event, EventResult, Key, MouseButton, MouseEvent}; use std::cmp::min; @@ -8,6 +7,7 @@ use unicode_width::UnicodeWidthStr; use utils::lines::simple::{prefix, simple_prefix, LinesIterator, Row}; use vec::Vec2; use view::{ScrollBase, SizeCache, View}; +use {Printer, With, XY}; /// Multi-lines text editor. /// @@ -437,7 +437,8 @@ impl View for TextArea { debug!("{:?}", self.rows); let scroll_width = if self.rows.len() > constraint.y { 1 } else { 0 }; Vec2::new( - scroll_width + 1 + scroll_width + + 1 + self.rows.iter().map(|r| r.width).max().unwrap_or(1), self.rows.len(), ) diff --git a/src/views/text_view.rs b/src/views/text_view.rs index e661791..43a8f4b 100644 --- a/src/views/text_view.rs +++ b/src/views/text_view.rs @@ -1,19 +1,19 @@ -use Printer; -use With; -use XY; use align::*; use direction::Direction; use event::*; use owning_ref::{ArcRef, OwningHandle}; use std::ops::Deref; -use std::sync::{Mutex, MutexGuard}; use std::sync::Arc; +use std::sync::{Mutex, MutexGuard}; use theme::Effect; use unicode_width::UnicodeWidthStr; use utils::lines::spans::{LinesIterator, Row}; use utils::markup::StyledString; use vec::Vec2; use view::{ScrollBase, ScrollStrategy, SizeCache, View}; +use Printer; +use With; +use XY; /// Provides access to the content of a [`TextView`]. /// @@ -421,7 +421,8 @@ impl TextView { } // Desired width, including the scrollbar_width. - self.width = self.rows + self.width = self + .rows .iter() .map(|row| row.width) .max() diff --git a/src/views/tracked_view.rs b/src/views/tracked_view.rs index 8378ce5..1dac79a 100644 --- a/src/views/tracked_view.rs +++ b/src/views/tracked_view.rs @@ -1,8 +1,8 @@ -use Printer; use std::cell::Cell; use vec::Vec2; use view::{View, ViewWrapper}; use views::IdView; +use Printer; /// Wrapper around a view that remembers its position. pub struct TrackedView { From 9569e991bfebd610b0fa7d5605cb126a1c76b132 Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Sun, 10 Jun 2018 23:35:31 -0700 Subject: [PATCH 09/10] Make Palette::add_namespace public --- src/theme/palette.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/theme/palette.rs b/src/theme/palette.rs index 3265df6..2fb344e 100644 --- a/src/theme/palette.rs +++ b/src/theme/palette.rs @@ -32,10 +32,16 @@ pub struct Palette { /// A node in the palette tree. /// +/// This describes a value attached to a custom keyword in the palette. +/// /// This can either be a color, or a nested namespace with its own mapping. #[derive(PartialEq, Eq, Clone, Debug)] -enum PaletteNode { +pub enum PaletteNode { + /// A single color. Color(Color), + /// A group of values bundled in the same namespace. + /// + /// Namespaces can be merged in the palette with `Palette::merge`. Namespace(HashMap), } @@ -117,7 +123,7 @@ impl Palette { } /// Adds a color namespace to this palette. - fn add_namespace( + pub fn add_namespace( &mut self, key: &str, namespace: HashMap, ) { self.custom From d52299a6e1fdc65d76105810653ed5340c3ad16f Mon Sep 17 00:00:00 2001 From: Alexandre Bury Date: Wed, 13 Jun 2018 21:35:37 -0700 Subject: [PATCH 10/10] Add HideableView --- .gitignore | 1 + src/views/hideable_view.rs | 94 ++++++++++++++++++++++++++++++++++++++ src/views/mod.rs | 2 + 3 files changed, 97 insertions(+) create mode 100644 src/views/hideable_view.rs diff --git a/.gitignore b/.gitignore index 80dd7e1..a6d358e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ tags .ctags *.bk TODO.txt +*.rustfmt diff --git a/src/views/hideable_view.rs b/src/views/hideable_view.rs new file mode 100644 index 0000000..cab64b7 --- /dev/null +++ b/src/views/hideable_view.rs @@ -0,0 +1,94 @@ +use view::{Selector, View, ViewWrapper}; +use With; + +use std::any::Any; + +/// Wrapper around another view that can be hidden at will. +/// +/// By default, it simply forwards all calls to the inner view. +/// +/// When hidden (with `HideableView::hide()`), it will appear as a zero-sized +/// invisible view, will not take focus and will not accept input. +/// +/// It can be made visible again with `HideableView::unhide()`. +pub struct HideableView { + view: V, + visible: bool, +} + +impl HideableView { + /// Creates a new HideableView around `view`. + /// + /// It will be visible by default. + pub fn new(view: V) -> Self { + HideableView { + view, + visible: true, + } + } + + /// Sets the visibility for this view. + pub fn set_visible(&mut self, visible: bool) { + self.visible = visible; + } + + /// Sets the visibility for this view to `false`. + pub fn hide(&mut self) { + self.set_visible(false); + } + + /// Sets the visibility for this view to `true`. + pub fn unhide(&mut self) { + self.set_visible(true); + } + + /// Sets the visibility for this view to `false`. + /// + /// Chainable variant. + pub fn hidden(self) -> Self { + self.with(Self::hide) + } + + inner_getters!(self.view: V); +} + +impl ViewWrapper for HideableView { + type V = V; + + fn with_view(&self, f: F) -> Option + where + F: FnOnce(&Self::V) -> R, + { + if self.visible { + Some(f(&self.view)) + } else { + None + } + } + + fn with_view_mut(&mut self, f: F) -> Option + where + F: FnOnce(&mut Self::V) -> R, + { + if self.visible { + Some(f(&mut self.view)) + } else { + None + } + } + + fn wrap_call_on_any<'a>( + &mut self, selector: &Selector, callback: Box, + ) { + // We always run callbacks, even when invisible. + self.view.call_on_any(selector, callback) + } + + fn into_inner(self) -> Result + where + Self: Sized, + Self::V: Sized, + { + Ok(self.view) + } +} diff --git a/src/views/mod.rs b/src/views/mod.rs index 24d1de0..9977d4c 100644 --- a/src/views/mod.rs +++ b/src/views/mod.rs @@ -42,6 +42,7 @@ mod checkbox; mod dialog; mod dummy; mod edit_view; +mod hideable_view; mod id_view; mod layer; mod linear_layout; @@ -69,6 +70,7 @@ pub use self::checkbox::Checkbox; pub use self::dialog::{Dialog, DialogFocus}; pub use self::dummy::DummyView; pub use self::edit_view::EditView; +pub use self::hideable_view::HideableView; pub use self::id_view::{IdView, ViewRef}; pub use self::layer::Layer; pub use self::linear_layout::LinearLayout;