mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
More ncurses isolation
Also some renaming in the theme module
This commit is contained in:
parent
4dcb2ea901
commit
985009e51c
@ -6,24 +6,24 @@ borders = "simple" # Alternatives are "none" and "outset"
|
||||
# Base colors are red, green, blue,
|
||||
# cyan, magenta, yellow, white and black.
|
||||
[colors]
|
||||
background = ["#923456", "magenta"]
|
||||
background = ["454", "#923456", "401", "magenta"]
|
||||
# If the value is an array, the first valid color will be used.
|
||||
# If the terminal doesn't support custom color,
|
||||
# non-base colors will be skipped.
|
||||
shadow = ["#222222", "blue"]
|
||||
view = "#888888"
|
||||
shadow = ["#222288", "blue"]
|
||||
view = "111"
|
||||
|
||||
# Array and simple values have the same effect.
|
||||
primary = ["#111111"]
|
||||
primary = ["white"]
|
||||
secondary = "#EEEEEE"
|
||||
tertiary = "#444444"
|
||||
|
||||
# Hex values can use lower or uppercase.
|
||||
# (base color MUST be lowercase)
|
||||
title_primary = "#883333"
|
||||
title_primary = "yellow"
|
||||
title_secondary = "#ffff55"
|
||||
|
||||
# Lower precision values can use only 3 digits.
|
||||
highlight = "#833"
|
||||
highlight = "#F88"
|
||||
highlight_inactive = "#5555FF"
|
||||
|
||||
|
@ -1,31 +1,15 @@
|
||||
use backend;
|
||||
use event;
|
||||
use theme;
|
||||
use utf8;
|
||||
|
||||
use ncurses;
|
||||
|
||||
pub trait Backend {
|
||||
fn init();
|
||||
fn finish();
|
||||
|
||||
fn clear();
|
||||
fn refresh();
|
||||
|
||||
fn print_at((usize, usize), &str);
|
||||
|
||||
fn poll_event() -> event::Event;
|
||||
fn set_refresh_rate(fps: u32);
|
||||
fn screen_size() -> (usize, usize);
|
||||
|
||||
fn with_color<F: FnOnce()>(color: theme::ColorPair, f: F);
|
||||
fn with_effect<F: FnOnce()>(effect: theme::Effect, f: F);
|
||||
}
|
||||
|
||||
|
||||
pub struct NcursesBackend;
|
||||
|
||||
impl Backend for NcursesBackend {
|
||||
impl backend::Backend for NcursesBackend {
|
||||
fn init() {
|
||||
::std::env::set_var("ESCDELAY", "25");
|
||||
ncurses::setlocale(ncurses::LcCategory::all, "");
|
||||
ncurses::initscr();
|
||||
ncurses::keypad(ncurses::stdscr, true);
|
||||
@ -34,7 +18,7 @@ impl Backend for NcursesBackend {
|
||||
ncurses::start_color();
|
||||
ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE);
|
||||
ncurses::wbkgd(ncurses::stdscr,
|
||||
ncurses::COLOR_PAIR(theme::ColorPair::Background.ncurses_id()));
|
||||
ncurses::COLOR_PAIR(theme::ColorStyle::Background.id()));
|
||||
}
|
||||
|
||||
fn screen_size() -> (usize, usize) {
|
||||
@ -44,16 +28,31 @@ impl Backend for NcursesBackend {
|
||||
(x as usize, y as usize)
|
||||
}
|
||||
|
||||
fn has_colors() -> bool {
|
||||
ncurses::has_colors()
|
||||
}
|
||||
|
||||
fn finish() {
|
||||
ncurses::endwin();
|
||||
}
|
||||
|
||||
fn with_color<F: FnOnce()>(color: theme::ColorPair, f: F) {
|
||||
|
||||
fn init_color_style(style: theme::ColorStyle,
|
||||
foreground: &theme::Color,
|
||||
background: &theme::Color) {
|
||||
// TODO: build the color on the spot
|
||||
|
||||
ncurses::init_pair(style.id(),
|
||||
find_closest(foreground) as i16,
|
||||
find_closest(background) as i16);
|
||||
}
|
||||
|
||||
fn with_color<F: FnOnce()>(color: theme::ColorStyle, f: F) {
|
||||
let mut current_style: ncurses::attr_t = 0;
|
||||
let mut current_color: i16 = 0;
|
||||
ncurses::attr_get(&mut current_style, &mut current_color);
|
||||
|
||||
let style = ncurses::COLOR_PAIR(color.ncurses_id());
|
||||
let style = ncurses::COLOR_PAIR(color.id());
|
||||
ncurses::attron(style);
|
||||
f();
|
||||
// ncurses::attroff(style);
|
||||
@ -218,3 +217,25 @@ fn parse_ncurses_char(ch: i32) -> event::Key {
|
||||
_ => event::Key::Unknown(ch),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_closest(color: &theme::Color) -> u8 {
|
||||
match *color {
|
||||
theme::Color::Black => 0,
|
||||
theme::Color::Red => 1,
|
||||
theme::Color::Green => 2,
|
||||
theme::Color::Yellow => 3,
|
||||
theme::Color::Blue => 4,
|
||||
theme::Color::Magenta => 5,
|
||||
theme::Color::Cyan => 6,
|
||||
theme::Color::White => 7,
|
||||
theme::Color::Rgb(r, g, b) => {
|
||||
let r = 6 * r as u16 / 256;
|
||||
let g = 6 * g as u16 / 256;
|
||||
let b = 6 * b as u16 / 256;
|
||||
(16 + 36 * r + 6 * g + b) as u8
|
||||
}
|
||||
theme::Color::RgbLowRes(r, g, b) => {
|
||||
(16 + 36 * r + 6 * g + b) as u8
|
||||
}
|
||||
}
|
||||
}
|
31
src/backend/mod.rs
Normal file
31
src/backend/mod.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use event;
|
||||
use theme;
|
||||
|
||||
// Module is not named `ncurses` to avoir naming conflict
|
||||
mod curses;
|
||||
|
||||
pub use self::curses::NcursesBackend;
|
||||
|
||||
pub trait Backend {
|
||||
|
||||
fn init();
|
||||
fn finish();
|
||||
|
||||
fn clear();
|
||||
fn refresh();
|
||||
|
||||
fn has_colors() -> bool;
|
||||
|
||||
fn init_color_style(style: theme::ColorStyle,
|
||||
foreground: &theme::Color,
|
||||
background: &theme::Color);
|
||||
|
||||
fn print_at((usize, usize), &str);
|
||||
|
||||
fn poll_event() -> event::Event;
|
||||
fn set_refresh_rate(fps: u32);
|
||||
fn screen_size() -> (usize, usize);
|
||||
|
||||
fn with_color<F: FnOnce()>(color: theme::ColorStyle, f: F);
|
||||
fn with_effect<F: FnOnce()>(effect: theme::Effect, f: F);
|
||||
}
|
@ -90,13 +90,11 @@ impl Cursive {
|
||||
/// Creates a new Cursive root, and initialize ncurses.
|
||||
pub fn new() -> Self {
|
||||
// Default delay is way too long. 25 is imperceptible yet works fine.
|
||||
std::env::set_var("ESCDELAY", "25");
|
||||
B::init();
|
||||
|
||||
let theme = theme::load_default();
|
||||
// let theme = theme::load_theme("assets/style.toml").unwrap();
|
||||
|
||||
|
||||
let mut res = Cursive {
|
||||
theme: theme,
|
||||
screens: Vec::new(),
|
||||
|
@ -1,5 +1,5 @@
|
||||
use menu::*;
|
||||
use theme::ColorPair;
|
||||
use theme::ColorStyle;
|
||||
use printer::Printer;
|
||||
use event::*;
|
||||
|
||||
@ -22,7 +22,7 @@ impl Menubar {
|
||||
|
||||
pub fn draw(&mut self, printer: &Printer) {
|
||||
// Draw the bar at the top
|
||||
printer.with_color(ColorPair::Primary, |printer| {
|
||||
printer.with_color(ColorStyle::Primary, |printer| {
|
||||
printer.print_hline((0, 0), printer.size.x, " ");
|
||||
});
|
||||
|
||||
|
@ -6,7 +6,7 @@ use backend::Backend;
|
||||
|
||||
use B;
|
||||
|
||||
use theme::{ColorPair, Theme, Effect};
|
||||
use theme::{ColorStyle, Theme, Effect};
|
||||
use vec::{ToVec2, Vec2};
|
||||
|
||||
/// Convenient interface to draw on a subset of the screen.
|
||||
@ -94,11 +94,11 @@ impl Printer {
|
||||
/// # use cursive::printer::Printer;
|
||||
/// # use cursive::theme;
|
||||
/// # let printer = Printer::new((6,4), theme::load_default());
|
||||
/// printer.with_color(theme::ColorPair::Highlight, |printer| {
|
||||
/// printer.with_color(theme::ColorStyle::Highlight, |printer| {
|
||||
/// printer.print((0,0), "This text is highlighted!");
|
||||
/// });
|
||||
/// ```
|
||||
pub fn with_color<F>(&self, c: ColorPair, f: F)
|
||||
pub fn with_color<F>(&self, c: ColorStyle, f: F)
|
||||
where F: FnOnce(&Printer)
|
||||
{
|
||||
B::with_color(c, || f(self));
|
||||
|
349
src/theme.rs
349
src/theme.rs
@ -5,17 +5,24 @@ use std::io::Read;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use ncurses;
|
||||
use backend::Backend;
|
||||
|
||||
use toml;
|
||||
|
||||
use B;
|
||||
|
||||
pub enum Effect {
|
||||
Simple,
|
||||
Reverse,
|
||||
}
|
||||
|
||||
/// Represents the color of a character and its background.
|
||||
/// Possible color style for a cell.
|
||||
///
|
||||
/// Represents a color pair role to use when printing something.
|
||||
///
|
||||
/// The current theme will assign each role a foreground and background color.
|
||||
#[derive(Clone,Copy)]
|
||||
pub enum ColorPair {
|
||||
pub enum ColorStyle {
|
||||
/// Application background, where no view is present.
|
||||
Background,
|
||||
/// Color used by view shadows. Only background matters.
|
||||
@ -36,19 +43,19 @@ pub enum ColorPair {
|
||||
HighlightInactive,
|
||||
}
|
||||
|
||||
impl ColorPair {
|
||||
impl ColorStyle {
|
||||
/// Returns the ncurses pair ID associated with this color pair.
|
||||
pub fn ncurses_id(self) -> i16 {
|
||||
pub fn id(self) -> i16 {
|
||||
match self {
|
||||
ColorPair::Background => 1,
|
||||
ColorPair::Shadow => 2,
|
||||
ColorPair::Primary => 3,
|
||||
ColorPair::Secondary => 4,
|
||||
ColorPair::Tertiary => 5,
|
||||
ColorPair::TitlePrimary => 6,
|
||||
ColorPair::TitleSecondary => 7,
|
||||
ColorPair::Highlight => 8,
|
||||
ColorPair::HighlightInactive => 9,
|
||||
ColorStyle::Background => 1,
|
||||
ColorStyle::Shadow => 2,
|
||||
ColorStyle::Primary => 3,
|
||||
ColorStyle::Secondary => 4,
|
||||
ColorStyle::Tertiary => 5,
|
||||
ColorStyle::TitlePrimary => 6,
|
||||
ColorStyle::TitleSecondary => 7,
|
||||
ColorStyle::Highlight => 8,
|
||||
ColorStyle::HighlightInactive => 9,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,29 +68,31 @@ pub struct Theme {
|
||||
/// How view borders should be drawn.
|
||||
pub borders: BorderStyle,
|
||||
/// What colors should be used through the application?
|
||||
pub colors: ColorStyle,
|
||||
pub colors: Palette,
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
fn default() -> Theme {
|
||||
impl Default for Theme {
|
||||
fn default() -> Self {
|
||||
Theme {
|
||||
shadow: true,
|
||||
borders: BorderStyle::Simple,
|
||||
colors: ColorStyle {
|
||||
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(),
|
||||
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,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Theme {
|
||||
fn load(&mut self, table: &toml::Table) {
|
||||
if let Some(&toml::Value::Boolean(shadow)) = table.get("shadow") {
|
||||
self.shadow = shadow;
|
||||
@ -100,45 +109,48 @@ impl Theme {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply(&self) {
|
||||
Theme::apply_color(ColorPair::Background,
|
||||
&self.colors.view,
|
||||
&self.colors.background);
|
||||
Theme::apply_color(ColorPair::Shadow, &self.colors.shadow, &self.colors.shadow);
|
||||
Theme::apply_color(ColorPair::Primary, &self.colors.primary, &self.colors.view);
|
||||
Theme::apply_color(ColorPair::Secondary,
|
||||
&self.colors.secondary,
|
||||
&self.colors.view);
|
||||
Theme::apply_color(ColorPair::Tertiary,
|
||||
&self.colors.tertiary,
|
||||
&self.colors.view);
|
||||
Theme::apply_color(ColorPair::TitlePrimary,
|
||||
&self.colors.title_primary,
|
||||
&self.colors.view);
|
||||
Theme::apply_color(ColorPair::TitleSecondary,
|
||||
&self.colors.title_secondary,
|
||||
&self.colors.view);
|
||||
Theme::apply_color(ColorPair::Highlight,
|
||||
&self.colors.view,
|
||||
&self.colors.highlight);
|
||||
Theme::apply_color(ColorPair::HighlightInactive,
|
||||
&self.colors.view,
|
||||
&self.colors.highlight_inactive);
|
||||
}
|
||||
|
||||
fn apply_color(pair: ColorPair, front: &Color, back: &Color) {
|
||||
ncurses::init_pair(pair.ncurses_id(), front.id, back.id);
|
||||
fn activate(&self) {
|
||||
// Initialize each color with the backend
|
||||
B::init_color_style(ColorStyle::Background,
|
||||
&self.colors.view,
|
||||
&self.colors.background);
|
||||
B::init_color_style(ColorStyle::Shadow,
|
||||
&self.colors.shadow,
|
||||
&self.colors.shadow);
|
||||
B::init_color_style(ColorStyle::Primary,
|
||||
&self.colors.primary,
|
||||
&self.colors.view);
|
||||
B::init_color_style(ColorStyle::Secondary,
|
||||
&self.colors.secondary,
|
||||
&self.colors.view);
|
||||
B::init_color_style(ColorStyle::Tertiary,
|
||||
&self.colors.tertiary,
|
||||
&self.colors.view);
|
||||
B::init_color_style(ColorStyle::TitlePrimary,
|
||||
&self.colors.title_primary,
|
||||
&self.colors.view);
|
||||
B::init_color_style(ColorStyle::TitleSecondary,
|
||||
&self.colors.title_secondary,
|
||||
&self.colors.view);
|
||||
B::init_color_style(ColorStyle::Highlight,
|
||||
&self.colors.view,
|
||||
&self.colors.highlight);
|
||||
B::init_color_style(ColorStyle::HighlightInactive,
|
||||
&self.colors.view,
|
||||
&self.colors.highlight_inactive);
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies how View borders should be drawn.
|
||||
/// Specifies how some borders should be drawn.
|
||||
///
|
||||
/// 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 3d effect.
|
||||
/// Outset borders with a simple 3d effect.
|
||||
Outset,
|
||||
}
|
||||
|
||||
@ -156,9 +168,11 @@ impl BorderStyle {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the colors the application will use in various situations.
|
||||
/// Color configuration for the application.
|
||||
///
|
||||
/// Assign each color role an actual color.
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct ColorStyle {
|
||||
pub struct Palette {
|
||||
/// Color used for the application background.
|
||||
pub background: Color,
|
||||
/// Color used for View shadows.
|
||||
@ -181,39 +195,57 @@ pub struct ColorStyle {
|
||||
pub highlight_inactive: Color,
|
||||
}
|
||||
|
||||
impl ColorStyle {
|
||||
impl Palette {
|
||||
fn load(&mut self, table: &toml::Table) {
|
||||
let mut new_id = 16;
|
||||
|
||||
self.background.load(table, "background", &mut new_id);
|
||||
self.shadow.load(table, "shadow", &mut new_id);
|
||||
self.view.load(table, "view", &mut new_id);
|
||||
self.primary.load(table, "primary", &mut new_id);
|
||||
self.secondary.load(table, "secondary", &mut new_id);
|
||||
self.tertiary.load(table, "tertiary", &mut new_id);
|
||||
self.title_primary.load(table, "title_primary", &mut new_id);
|
||||
self.title_secondary.load(table, "title_secondary", &mut new_id);
|
||||
self.highlight.load(table, "highlight", &mut new_id);
|
||||
self.highlight_inactive.load(table, "highlight_inactive", &mut new_id);
|
||||
load_color(&mut self.background, table.get("background"));
|
||||
load_color(&mut self.shadow, table.get("shadow"));
|
||||
load_color(&mut self.view, table.get("view"));
|
||||
load_color(&mut self.primary, table.get("primary"));
|
||||
load_color(&mut self.secondary, table.get("secondary"));
|
||||
load_color(&mut self.tertiary, table.get("tertiary"));
|
||||
load_color(&mut self.title_primary, table.get("title_primary"));
|
||||
load_color(&mut self.title_secondary, table.get("title_secondary"));
|
||||
load_color(&mut self.highlight, table.get("highlight"));
|
||||
load_color(&mut self.highlight_inactive, table.get("highlight_inactive"));
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a color used by the theme.
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct Color {
|
||||
pub enum Color {
|
||||
/// Color ID used by ncurses.
|
||||
pub id: i16,
|
||||
Black,
|
||||
Red,
|
||||
Green,
|
||||
Yellow,
|
||||
Blue,
|
||||
Magenta,
|
||||
Cyan,
|
||||
White,
|
||||
// 24-bit color
|
||||
Rgb(u8, u8, u8),
|
||||
RgbLowRes(u8, u8, u8),
|
||||
}
|
||||
|
||||
impl Color {
|
||||
/// Return the rgb values used by the color.
|
||||
pub fn rgb(&self) -> (i16, i16, i16) {
|
||||
let (mut r, mut g, mut b) = (0, 0, 0);
|
||||
|
||||
ncurses::color_content(self.id, &mut r, &mut g, &mut b);
|
||||
|
||||
(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Possible error returned when loading a theme.
|
||||
@ -232,115 +264,47 @@ impl From<io::Error> for Error {
|
||||
}
|
||||
|
||||
impl Color {
|
||||
fn parse(value: &str, new_id: &mut i16) -> Option<Self> {
|
||||
let color = if value == "black" {
|
||||
Color::black()
|
||||
} else if value == "red" {
|
||||
Color::red()
|
||||
} else if value == "green" {
|
||||
Color::green()
|
||||
} else if value == "yellow" {
|
||||
Color::yellow()
|
||||
} else if value == "blue" {
|
||||
Color::blue()
|
||||
} else if value == "magenta" {
|
||||
Color::magenta()
|
||||
} else if value == "cyan" {
|
||||
Color::cyan()
|
||||
} else if value == "white" {
|
||||
Color::white()
|
||||
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,
|
||||
value => return Color::parse_special(value),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_special(value: &str) -> Option<Color> {
|
||||
if value.starts_with('#') {
|
||||
|
||||
let value = &value[1..];
|
||||
// Compute per-color length, and amplitude
|
||||
let (l, multiplier) = match value.len() {
|
||||
6 => (2, 1),
|
||||
3 => (1, 17),
|
||||
_ => panic!("Cannot parse color: {}", value),
|
||||
};
|
||||
let r = load_hex(&value[0 * l..1 * l]) * multiplier;
|
||||
let g = load_hex(&value[1 * 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?
|
||||
let rgb: Vec<_> = value.chars().map(|c| c as i16 - '0' as i16).collect();
|
||||
println!("{:?}", rgb);
|
||||
if rgb.iter().all(|&i| i >= 0 && i < 6) {
|
||||
Some(Color::RgbLowRes(rgb[0] as u8, rgb[1] as u8, rgb[2] as u8))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
// Let's make a new color
|
||||
return Color::make_new(value, new_id);
|
||||
};
|
||||
|
||||
Some(color)
|
||||
}
|
||||
|
||||
fn load(&mut self, table: &toml::Table, key: &str, new_id: &mut i16) {
|
||||
match table.get(key) {
|
||||
Some(&toml::Value::String(ref value)) => {
|
||||
self.load_value(value, new_id);
|
||||
}
|
||||
Some(&toml::Value::Array(ref array)) => {
|
||||
for color in array.iter() {
|
||||
if let toml::Value::String(ref color) = *color {
|
||||
if self.load_value(color, new_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn load_value(&mut self, value: &str, new_id: &mut i16) -> bool {
|
||||
match Color::parse(value, new_id) {
|
||||
Some(color) => self.id = color.id,
|
||||
None => return false,
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn make_new(value: &str, new_id: &mut i16) -> Option<Self> {
|
||||
// if !ncurses::can_change_color() {
|
||||
if !ncurses::has_colors() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !value.starts_with('#') {
|
||||
return None;
|
||||
}
|
||||
|
||||
if *new_id >= ncurses::COLORS as i16 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let s = &value[1..];
|
||||
let (l, max) = match s.len() {
|
||||
6 => (2, 255),
|
||||
3 => (1, 15),
|
||||
_ => panic!("Cannot parse color: {}", s),
|
||||
};
|
||||
|
||||
let r = (load_hex(&s[0 * l..1 * l]) as i32 * 1000 / max) as i16;
|
||||
let g = (load_hex(&s[1 * l..2 * l]) as i32 * 1000 / max) as i16;
|
||||
let b = (load_hex(&s[2 * l..3 * l]) as i32 * 1000 / max) as i16;
|
||||
|
||||
ncurses::init_color(*new_id, r, g, b);
|
||||
|
||||
let color = Color { id: *new_id };
|
||||
*new_id += 1;
|
||||
|
||||
Some(color)
|
||||
}
|
||||
|
||||
|
||||
pub fn black() -> Self {
|
||||
Color { id: 0 }
|
||||
}
|
||||
pub fn red() -> Self {
|
||||
Color { id: 1 }
|
||||
}
|
||||
pub fn green() -> Self {
|
||||
Color { id: 2 }
|
||||
}
|
||||
pub fn yellow() -> Self {
|
||||
Color { id: 3 }
|
||||
}
|
||||
pub fn blue() -> Self {
|
||||
Color { id: 4 }
|
||||
}
|
||||
pub fn magenta() -> Self {
|
||||
Color { id: 5 }
|
||||
}
|
||||
pub fn cyan() -> Self {
|
||||
Color { id: 6 }
|
||||
}
|
||||
pub fn white() -> Self {
|
||||
Color { id: 7 }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -379,6 +343,7 @@ impl Color {
|
||||
/// highlight_inactive = "#5555FF"
|
||||
/// ```
|
||||
|
||||
/// Loads a theme and sets it as active.
|
||||
pub fn load_theme<P: AsRef<Path>>(filename: P) -> Result<Theme, Error> {
|
||||
let content = {
|
||||
let mut content = String::new();
|
||||
@ -395,7 +360,7 @@ pub fn load_theme<P: AsRef<Path>>(filename: P) -> Result<Theme, Error> {
|
||||
|
||||
let mut theme = Theme::default();
|
||||
theme.load(&table);
|
||||
theme.apply();
|
||||
theme.activate();
|
||||
|
||||
Ok(theme)
|
||||
}
|
||||
@ -403,12 +368,12 @@ pub fn load_theme<P: AsRef<Path>>(filename: P) -> Result<Theme, Error> {
|
||||
/// Loads the default theme, and returns its representation.
|
||||
pub fn load_default() -> Theme {
|
||||
let theme = Theme::default();
|
||||
theme.apply();
|
||||
theme.activate();
|
||||
theme
|
||||
}
|
||||
|
||||
/// Loads a hexadecimal code
|
||||
fn load_hex(s: &str) -> i16 {
|
||||
fn load_hex(s: &str) -> u16 {
|
||||
let mut sum = 0;
|
||||
for c in s.chars() {
|
||||
sum *= 16;
|
||||
@ -420,5 +385,5 @@ fn load_hex(s: &str) -> i16 {
|
||||
};
|
||||
}
|
||||
|
||||
sum
|
||||
sum as u16
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use theme::ColorPair;
|
||||
use theme::ColorStyle;
|
||||
use Cursive;
|
||||
use vec::Vec2;
|
||||
use view::{SizeRequest, View};
|
||||
@ -29,9 +29,9 @@ impl Button {
|
||||
impl View for Button {
|
||||
fn draw(&mut self, printer: &Printer) {
|
||||
let style = if !printer.focused {
|
||||
ColorPair::Primary
|
||||
ColorStyle::Primary
|
||||
} else {
|
||||
ColorPair::Highlight
|
||||
ColorStyle::Highlight
|
||||
};
|
||||
let x = printer.size.x - 1;
|
||||
|
||||
|
@ -4,7 +4,7 @@ use std::any::Any;
|
||||
use Cursive;
|
||||
use align::*;
|
||||
use event::*;
|
||||
use theme::ColorPair;
|
||||
use theme::ColorStyle;
|
||||
use view::{DimensionRequest, Selector, SizeRequest, TextView, View};
|
||||
use view::{Button, SizedView};
|
||||
use vec::{ToVec4, Vec2, Vec4};
|
||||
@ -152,7 +152,7 @@ impl View for Dialog {
|
||||
printer.print((x - 2, 0), "┤ ");
|
||||
printer.print((x + len, 0), " ├");
|
||||
|
||||
printer.with_color(ColorPair::TitlePrimary, |p| p.print((x, 0), &self.title));
|
||||
printer.with_color(ColorStyle::TitlePrimary, |p| p.print((x, 0), &self.title));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
use std::cmp::min;
|
||||
|
||||
use theme::{ColorPair, Effect};
|
||||
use theme::{ColorStyle, Effect};
|
||||
use vec::Vec2;
|
||||
use view::{IdView, SizeRequest, View};
|
||||
use event::*;
|
||||
@ -85,7 +85,7 @@ impl View for EditView {
|
||||
fn draw(&mut self, printer: &Printer) {
|
||||
// let style = if focused { color::HIGHLIGHT } else { color::HIGHLIGHT_INACTIVE };
|
||||
let len = self.content.chars().count();
|
||||
printer.with_color(ColorPair::Secondary, |printer| {
|
||||
printer.with_color(ColorStyle::Secondary, |printer| {
|
||||
printer.with_effect(Effect::Reverse, |printer| {
|
||||
if len < self.last_length {
|
||||
printer.print((0, 0), &self.content);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::cmp::{max, min};
|
||||
|
||||
use theme::ColorPair;
|
||||
use theme::ColorStyle;
|
||||
use vec::Vec2;
|
||||
use printer::Printer;
|
||||
|
||||
@ -129,9 +129,9 @@ impl ScrollBase {
|
||||
let start = steps * self.start_line / (1 + self.content_height - self.view_height);
|
||||
|
||||
let color = if printer.focused {
|
||||
ColorPair::Highlight
|
||||
ColorStyle::Highlight
|
||||
} else {
|
||||
ColorPair::HighlightInactive
|
||||
ColorStyle::HighlightInactive
|
||||
};
|
||||
|
||||
printer.print_vline((printer.size.x - 1, 0), printer.size.y, "|");
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::cmp::min;
|
||||
use std::rc::Rc;
|
||||
|
||||
use theme::ColorPair;
|
||||
use theme::ColorStyle;
|
||||
use Cursive;
|
||||
use align::*;
|
||||
use view::{DimensionRequest, IdView, SizeRequest, View};
|
||||
@ -133,12 +133,12 @@ impl<T: 'static> View for SelectView<T> {
|
||||
self.scrollbase.draw(printer, |printer, i| {
|
||||
let style = if i == self.focus {
|
||||
if printer.focused {
|
||||
ColorPair::Highlight
|
||||
ColorStyle::Highlight
|
||||
} else {
|
||||
ColorPair::HighlightInactive
|
||||
ColorStyle::HighlightInactive
|
||||
}
|
||||
} else {
|
||||
ColorPair::Primary
|
||||
ColorStyle::Primary
|
||||
};
|
||||
printer.with_color(style, |printer| {
|
||||
let l = self.items[i].label.chars().count();
|
||||
|
@ -1,7 +1,7 @@
|
||||
use view::{SizeRequest, View, ViewWrapper};
|
||||
use printer::Printer;
|
||||
use vec::Vec2;
|
||||
use theme::ColorPair;
|
||||
use theme::ColorStyle;
|
||||
|
||||
/// Wrapper view that adds a shadow.
|
||||
///
|
||||
@ -40,7 +40,7 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
||||
let h = printer.size.y - 1;
|
||||
let w = printer.size.x - 1;
|
||||
|
||||
printer.with_color(ColorPair::Shadow, |printer| {
|
||||
printer.with_color(ColorStyle::Shadow, |printer| {
|
||||
printer.print_hline((2, h), w - 1, " ");
|
||||
printer.print_vline((w, 2), h - 1, " ");
|
||||
});
|
||||
|
@ -4,7 +4,7 @@ use vec::Vec2;
|
||||
use view::{DimensionRequest, Selector, ShadowView, SizeRequest, View};
|
||||
use event::{Event, EventResult};
|
||||
use printer::Printer;
|
||||
use theme::ColorPair;
|
||||
use theme::ColorStyle;
|
||||
|
||||
/// Simple stack of views.
|
||||
/// Only the top-most view is active and can receive input.
|
||||
@ -49,7 +49,7 @@ impl StackView {
|
||||
impl View for StackView {
|
||||
fn draw(&mut self, printer: &Printer) {
|
||||
let last = self.layers.len();
|
||||
printer.with_color(ColorPair::Primary, |printer| {
|
||||
printer.with_color(ColorStyle::Primary, |printer| {
|
||||
for (i, v) in self.layers.iter_mut().enumerate() {
|
||||
// Center the view
|
||||
let size = v.size;
|
||||
|
Loading…
Reference in New Issue
Block a user