mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Actually use Theme::{shadow,borders}
when drawing
Also add the 8 light base colors
This commit is contained in:
parent
db09930fe2
commit
f7a3d821d1
25
examples/theme_manual.rs
Normal file
25
examples/theme_manual.rs
Normal file
@ -0,0 +1,25 @@
|
||||
extern crate cursive;
|
||||
|
||||
use cursive::prelude::*;
|
||||
use cursive::theme::BorderStyle;
|
||||
|
||||
fn main() {
|
||||
let mut siv = Cursive::new();
|
||||
|
||||
siv.add_layer(Dialog::text("This is a dynamic theme example!")
|
||||
.button("Change", |s| {
|
||||
let mut theme = s.current_theme().clone();
|
||||
|
||||
theme.shadow = !theme.shadow;
|
||||
theme.borders = match theme.borders {
|
||||
Some(BorderStyle::Simple) => Some(BorderStyle::Outset),
|
||||
Some(BorderStyle::Outset) => None,
|
||||
None => Some(BorderStyle::Simple),
|
||||
};
|
||||
|
||||
s.set_theme(theme);
|
||||
})
|
||||
.button("Quit", Cursive::quit));
|
||||
|
||||
siv.run();
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
use backend;
|
||||
use event::{Event, Key};
|
||||
use theme::{Color, ColorStyle, Effect};
|
||||
use theme::{Color, ColorStyle, Effect, BaseColor};
|
||||
use utf8;
|
||||
|
||||
use ncurses;
|
||||
@ -225,14 +225,22 @@ fn parse_ncurses_char(ch: i32) -> Event {
|
||||
|
||||
fn find_closest(color: &Color) -> u8 {
|
||||
match *color {
|
||||
Color::Black => 0,
|
||||
Color::Red => 1,
|
||||
Color::Green => 2,
|
||||
Color::Yellow => 3,
|
||||
Color::Blue => 4,
|
||||
Color::Magenta => 5,
|
||||
Color::Cyan => 6,
|
||||
Color::White => 7,
|
||||
Color::Dark(BaseColor::Black) => 0,
|
||||
Color::Dark(BaseColor::Red) => 1,
|
||||
Color::Dark(BaseColor::Green) => 2,
|
||||
Color::Dark(BaseColor::Yellow) => 3,
|
||||
Color::Dark(BaseColor::Blue) => 4,
|
||||
Color::Dark(BaseColor::Magenta) => 5,
|
||||
Color::Dark(BaseColor::Cyan) => 6,
|
||||
Color::Dark(BaseColor::White) => 7,
|
||||
Color::Light(BaseColor::Black) => 8,
|
||||
Color::Light(BaseColor::Red) => 9,
|
||||
Color::Light(BaseColor::Green) => 10,
|
||||
Color::Light(BaseColor::Yellow) => 11,
|
||||
Color::Light(BaseColor::Blue) => 12,
|
||||
Color::Light(BaseColor::Magenta) => 13,
|
||||
Color::Light(BaseColor::Cyan) => 14,
|
||||
Color::Light(BaseColor::White) => 15,
|
||||
Color::Rgb(r, g, b) => {
|
||||
let r = 6 * r as u16 / 256;
|
||||
let g = 6 * g as u16 / 256;
|
||||
|
@ -254,6 +254,7 @@ impl Cursive {
|
||||
pub fn set_theme(&mut self, theme: theme::Theme) {
|
||||
self.theme = theme;
|
||||
self.theme.activate();
|
||||
B::clear();
|
||||
}
|
||||
|
||||
/// Loads a theme from the given file.
|
||||
|
@ -8,7 +8,7 @@ use backend::Backend;
|
||||
|
||||
use B;
|
||||
|
||||
use theme::{ColorStyle, Effect, Theme};
|
||||
use theme::{BorderStyle, ColorStyle, Effect, Theme};
|
||||
use vec::Vec2;
|
||||
|
||||
/// Convenient interface to draw on a subset of the screen.
|
||||
@ -121,7 +121,8 @@ impl Printer {
|
||||
/// # let printer = Printer::new((6,4), theme::load_default());
|
||||
/// printer.print_box((0,0), (6,4));
|
||||
/// ```
|
||||
pub fn print_box<T: Into<Vec2>, S: Into<Vec2>>(&self, start: T, size: S) {
|
||||
pub fn print_box<T: Into<Vec2>, S: Into<Vec2>>(&self, start: T, size: S,
|
||||
invert: bool) {
|
||||
let start = start.into();
|
||||
let size = size.into();
|
||||
if size.x < 2 || size.y < 2 {
|
||||
@ -129,15 +130,37 @@ impl Printer {
|
||||
}
|
||||
let size = size - (1, 1);
|
||||
|
||||
self.print(start, "┌");
|
||||
self.print(start + size.keep_x(), "┐");
|
||||
self.print(start + size.keep_y(), "└");
|
||||
self.print(start + size, "┘");
|
||||
let borders = if let Some(borders) = self.theme.borders {
|
||||
borders
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.print_hline(start + (1, 0), size.x - 1, "─");
|
||||
self.print_vline(start + (0, 1), size.y - 1, "│");
|
||||
self.print_hline(start + (1, 0) + size.keep_y(), size.x - 1, "─");
|
||||
self.print_vline(start + (0, 1) + size.keep_x(), size.y - 1, "│");
|
||||
self.with_color(match borders {
|
||||
BorderStyle::Outset if !invert => {
|
||||
ColorStyle::Tertiary
|
||||
}
|
||||
_ => ColorStyle::Primary,
|
||||
},
|
||||
|s| {
|
||||
s.print(start, "┌");
|
||||
s.print(start + size.keep_y(), "└");
|
||||
s.print_hline(start + (1, 0), size.x - 1, "─");
|
||||
s.print_vline(start + (0, 1), size.y - 1, "│");
|
||||
});
|
||||
|
||||
self.with_color(match borders {
|
||||
BorderStyle::Outset if invert => {
|
||||
ColorStyle::Tertiary
|
||||
}
|
||||
_ => ColorStyle::Primary,
|
||||
},
|
||||
|s| {
|
||||
s.print(start + size.keep_x(), "┐");
|
||||
s.print(start + size, "┘");
|
||||
s.print_hline(start + (1, 0) + size.keep_y(), size.x - 1, "─");
|
||||
s.print_vline(start + (0, 1) + size.keep_x(), size.y - 1, "│");
|
||||
});
|
||||
}
|
||||
|
||||
/// Apply a selection style and call the given function.
|
||||
|
71
src/theme.rs
71
src/theme.rs
@ -184,7 +184,7 @@ pub struct Theme {
|
||||
/// Wheter views in a StackView should have shadows.
|
||||
pub shadow: bool,
|
||||
/// How view borders should be drawn.
|
||||
pub borders: BorderStyle,
|
||||
pub borders: Option<BorderStyle>,
|
||||
/// What colors should be used through the application?
|
||||
pub colors: Palette,
|
||||
}
|
||||
@ -193,18 +193,18 @@ impl Default for Theme {
|
||||
fn default() -> Self {
|
||||
Theme {
|
||||
shadow: true,
|
||||
borders: BorderStyle::Simple,
|
||||
borders: Some(BorderStyle::Simple),
|
||||
colors: Palette {
|
||||
background: Color::Blue,
|
||||
shadow: Color::Black,
|
||||
view: Color::White,
|
||||
primary: Color::Black,
|
||||
secondary: Color::Blue,
|
||||
tertiary: Color::White,
|
||||
title_primary: Color::Red,
|
||||
title_secondary: Color::Yellow,
|
||||
highlight: Color::Red,
|
||||
highlight_inactive: Color::Blue,
|
||||
background: Color::Dark(BaseColor::Blue),
|
||||
shadow: Color::Dark(BaseColor::Black),
|
||||
view: Color::Dark(BaseColor::White),
|
||||
primary: Color::Dark(BaseColor::Black),
|
||||
secondary: Color::Dark(BaseColor::Blue),
|
||||
tertiary: Color::Light(BaseColor::White),
|
||||
title_primary: Color::Dark(BaseColor::Red),
|
||||
title_secondary: Color::Dark(BaseColor::Yellow),
|
||||
highlight: Color::Dark(BaseColor::Red),
|
||||
highlight_inactive: Color::Dark(BaseColor::Blue),
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -217,9 +217,7 @@ impl Theme {
|
||||
}
|
||||
|
||||
if let Some(&toml::Value::String(ref borders)) = table.get("borders") {
|
||||
if let Some(borders) = BorderStyle::from(borders) {
|
||||
self.borders = borders;
|
||||
}
|
||||
self.borders = BorderStyle::from(borders);
|
||||
}
|
||||
|
||||
if let Some(&toml::Value::Table(ref table)) = table.get("colors") {
|
||||
@ -269,8 +267,6 @@ impl Theme {
|
||||
/// Borders are used around Dialogs, select popups, and panels.
|
||||
#[derive(Clone,Copy,Debug)]
|
||||
pub enum BorderStyle {
|
||||
/// Don't draw any border.
|
||||
NoBorder,
|
||||
/// Simple borders.
|
||||
Simple,
|
||||
/// Outset borders with a simple 3d effect.
|
||||
@ -281,8 +277,6 @@ impl BorderStyle {
|
||||
fn from(s: &str) -> Option<Self> {
|
||||
if s == "simple" {
|
||||
Some(BorderStyle::Simple)
|
||||
} else if s == "none" {
|
||||
Some(BorderStyle::NoBorder)
|
||||
} else if s == "outset" {
|
||||
Some(BorderStyle::Outset)
|
||||
} else {
|
||||
@ -357,9 +351,9 @@ fn load_color(target: &mut Color, value: Option<&toml::Value>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a color used by the theme.
|
||||
#[derive(Clone,Debug)]
|
||||
pub enum Color {
|
||||
/// One of the 8 base colors.
|
||||
#[derive(Clone,Copy,Debug)]
|
||||
pub enum BaseColor {
|
||||
/// Black color
|
||||
///
|
||||
/// Color #0
|
||||
@ -392,6 +386,15 @@ pub enum Color {
|
||||
///
|
||||
/// Color #7
|
||||
White,
|
||||
}
|
||||
|
||||
/// Represents a color used by the theme.
|
||||
#[derive(Clone,Copy,Debug)]
|
||||
pub enum Color {
|
||||
/// One of the 8 base colors.
|
||||
Dark(BaseColor),
|
||||
/// Lighter version of a base color.
|
||||
Light(BaseColor),
|
||||
/// True-color, 24-bit.
|
||||
Rgb(u8, u8, u8),
|
||||
/// Low-resolution
|
||||
@ -422,14 +425,22 @@ impl From<io::Error> for Error {
|
||||
impl Color {
|
||||
fn parse(value: &str) -> Option<Self> {
|
||||
Some(match value {
|
||||
"black" => Color::Black,
|
||||
"red" => Color::Red,
|
||||
"green" => Color::Green,
|
||||
"yellow" => Color::Yellow,
|
||||
"blue" => Color::Blue,
|
||||
"magenta" => Color::Magenta,
|
||||
"cyan" => Color::Cyan,
|
||||
"white" => Color::White,
|
||||
"black" => Color::Dark(BaseColor::Black),
|
||||
"red" => Color::Dark(BaseColor::Red),
|
||||
"green" => Color::Dark(BaseColor::Green),
|
||||
"yellow" => Color::Dark(BaseColor::Yellow),
|
||||
"blue" => Color::Dark(BaseColor::Blue),
|
||||
"magenta" => Color::Dark(BaseColor::Magenta),
|
||||
"cyan" => Color::Dark(BaseColor::Cyan),
|
||||
"white" => Color::Dark(BaseColor::White),
|
||||
"light black" => Color::Light(BaseColor::Black),
|
||||
"light red" => Color::Light(BaseColor::Red),
|
||||
"light green" => Color::Light(BaseColor::Green),
|
||||
"light yellow" => Color::Light(BaseColor::Yellow),
|
||||
"light blue" => Color::Light(BaseColor::Blue),
|
||||
"light magenta" => Color::Light(BaseColor::Magenta),
|
||||
"light cyan" => Color::Light(BaseColor::Cyan),
|
||||
"light white" => Color::Light(BaseColor::White),
|
||||
value => return Color::parse_special(value),
|
||||
})
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ impl View for Dialog {
|
||||
inner_size,
|
||||
self.focus == Focus::Content));
|
||||
|
||||
printer.print_box(Vec2::new(0, 0), printer.size);
|
||||
printer.print_box(Vec2::new(0, 0), printer.size, false);
|
||||
|
||||
if !self.title.is_empty() {
|
||||
let len = self.title.width();
|
||||
|
@ -156,7 +156,7 @@ impl View for MenuPopup {
|
||||
&printer.sub_printer(Vec2::new(0, offset), printer.size, true);
|
||||
|
||||
// Start with a box
|
||||
printer.print_box(Vec2::new(0, 0), printer.size);
|
||||
printer.print_box(Vec2::new(0, 0), printer.size, false);
|
||||
|
||||
// We're giving it a reduced size because of borders.
|
||||
// But we're keeping the full width,
|
||||
|
@ -24,7 +24,7 @@ impl<V: View> ViewWrapper for Panel<V> {
|
||||
}
|
||||
|
||||
fn wrap_draw(&self, printer: &Printer) {
|
||||
printer.print_box((0, 0), printer.size);
|
||||
printer.print_box((0, 0), printer.size, true);
|
||||
self.view
|
||||
.draw(&printer.sub_printer((1, 1), printer.size - (2, 2), true));
|
||||
}
|
||||
|
@ -66,11 +66,9 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
||||
}
|
||||
|
||||
// Skip the first row/column
|
||||
let printer =
|
||||
&printer.sub_printer(Vec2::new(self.left_padding as usize,
|
||||
self.top_padding as usize),
|
||||
printer.size,
|
||||
true);
|
||||
let offset = Vec2::new(self.left_padding as usize,
|
||||
self.top_padding as usize);
|
||||
let printer = &printer.offset(offset, true);
|
||||
|
||||
// Draw the view background
|
||||
for y in 0..printer.size.y - 1 {
|
||||
@ -81,6 +79,7 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
||||
printer.size - (1, 1),
|
||||
true));
|
||||
|
||||
if printer.theme.shadow {
|
||||
let h = printer.size.y;
|
||||
let w = printer.size.x;
|
||||
|
||||
@ -90,3 +89,4 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user