mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-14 13:13:08 +00:00
Set up Custom color in termion and ncurses backends
This commit is contained in:
parent
b799d83077
commit
9e1a83f7cc
@ -1,13 +1,20 @@
|
|||||||
extern crate cursive;
|
extern crate cursive;
|
||||||
|
|
||||||
use cursive::Cursive;
|
use cursive::Cursive;
|
||||||
use cursive::views::Dialog;
|
use cursive::theme::{ColorStyle, BaseColor, Color, BorderStyle};
|
||||||
use cursive::theme::BorderStyle;
|
use cursive::views::{EditView, LinearLayout, Dialog, TextView};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut siv = Cursive::new();
|
let mut siv = Cursive::new();
|
||||||
|
|
||||||
siv.add_layer(Dialog::text("This is a dynamic theme example!")
|
let layout = LinearLayout::vertical()
|
||||||
|
.child(TextView::new("This is a dynamic theme example!"))
|
||||||
|
.child(EditView::new().content("Woo! colors!").style(ColorStyle::Custom {
|
||||||
|
front: Color::Rgb(200, 150, 150),
|
||||||
|
back: Color::Dark(BaseColor::Blue),
|
||||||
|
}));
|
||||||
|
|
||||||
|
siv.add_layer(Dialog::around(layout)
|
||||||
.button("Change", |s| {
|
.button("Change", |s| {
|
||||||
let mut theme = s.current_theme().clone();
|
let mut theme = s.current_theme().clone();
|
||||||
|
|
||||||
|
@ -50,7 +50,6 @@ fn color_id(style: ColorStyle) -> i16 {
|
|||||||
ColorStyle::TitleSecondary => 7,
|
ColorStyle::TitleSecondary => 7,
|
||||||
ColorStyle::Highlight => 8,
|
ColorStyle::Highlight => 8,
|
||||||
ColorStyle::HighlightInactive => 9,
|
ColorStyle::HighlightInactive => 9,
|
||||||
ColorStyle::Custom { front, back } => 10,
|
ColorStyle::Custom { .. } => 10,
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,13 @@ extern crate ncurses;
|
|||||||
use self::super::{color_id, find_closest};
|
use self::super::{color_id, find_closest};
|
||||||
use backend;
|
use backend;
|
||||||
use event::{Event, Key};
|
use event::{Event, Key};
|
||||||
|
use std::cell::Cell;
|
||||||
use theme::{Color, ColorStyle, Effect};
|
use theme::{Color, ColorStyle, Effect};
|
||||||
use utf8;
|
use utf8;
|
||||||
|
|
||||||
pub struct Concrete;
|
pub struct Concrete {
|
||||||
|
current_style: Cell<ColorStyle>,
|
||||||
|
}
|
||||||
|
|
||||||
impl backend::Backend for Concrete {
|
impl backend::Backend for Concrete {
|
||||||
fn init() -> Self {
|
fn init() -> Self {
|
||||||
@ -25,7 +28,7 @@ impl backend::Backend for Concrete {
|
|||||||
ncurses::wbkgd(ncurses::stdscr(),
|
ncurses::wbkgd(ncurses::stdscr(),
|
||||||
ncurses::COLOR_PAIR(color_id(ColorStyle::Background)));
|
ncurses::COLOR_PAIR(color_id(ColorStyle::Background)));
|
||||||
|
|
||||||
Concrete
|
Concrete { current_style: Cell::new(ColorStyle::Background) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn screen_size(&self) -> (usize, usize) {
|
fn screen_size(&self) -> (usize, usize) {
|
||||||
@ -46,7 +49,6 @@ impl backend::Backend for Concrete {
|
|||||||
|
|
||||||
fn init_color_style(&mut self, style: ColorStyle, foreground: &Color,
|
fn init_color_style(&mut self, style: ColorStyle, foreground: &Color,
|
||||||
background: &Color) {
|
background: &Color) {
|
||||||
// TODO: build the color on the spot
|
|
||||||
|
|
||||||
ncurses::init_pair(color_id(style),
|
ncurses::init_pair(color_id(style),
|
||||||
find_closest(foreground) as i16,
|
find_closest(foreground) as i16,
|
||||||
@ -54,15 +56,13 @@ impl backend::Backend for Concrete {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn with_color<F: FnOnce()>(&self, color: ColorStyle, f: F) {
|
fn with_color<F: FnOnce()>(&self, color: ColorStyle, f: F) {
|
||||||
let mut current_style: ncurses::attr_t = 0;
|
let current = self.current_style.get();
|
||||||
let mut current_color: i16 = 0;
|
|
||||||
ncurses::attr_get(&mut current_style, &mut current_color);
|
|
||||||
|
|
||||||
let style = ncurses::COLOR_PAIR(color_id(color));
|
self.current_style.set(color);
|
||||||
ncurses::attron(style);
|
set_colorstyle(color);
|
||||||
f();
|
f();
|
||||||
// ncurses::attroff(style);
|
set_colorstyle(current);
|
||||||
ncurses::attron(current_style);
|
self.current_style.set(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
|
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
|
||||||
@ -109,6 +109,21 @@ impl backend::Backend for Concrete {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_colorstyle(style: ColorStyle) {
|
||||||
|
if let ColorStyle::Custom {
|
||||||
|
ref front,
|
||||||
|
ref back,
|
||||||
|
} = style {
|
||||||
|
|
||||||
|
println_stderr!("Redifining...");
|
||||||
|
ncurses::init_pair(color_id(style),
|
||||||
|
find_closest(front) as i16,
|
||||||
|
find_closest(back) as i16);
|
||||||
|
}
|
||||||
|
let style = ncurses::COLOR_PAIR(color_id(style));
|
||||||
|
ncurses::attron(style);
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the Key enum corresponding to the given ncurses event.
|
/// Returns the Key enum corresponding to the given ncurses event.
|
||||||
fn parse_ncurses_char(ch: i32) -> Event {
|
fn parse_ncurses_char(ch: i32) -> Event {
|
||||||
match ch {
|
match ch {
|
||||||
|
@ -13,7 +13,7 @@ use backend;
|
|||||||
use chan;
|
use chan;
|
||||||
use event::{Event, Key};
|
use event::{Event, Key};
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@ -23,7 +23,7 @@ use theme;
|
|||||||
pub struct Concrete {
|
pub struct Concrete {
|
||||||
terminal: AlternateScreen<termion::raw::RawTerminal<::std::io::Stdout>>,
|
terminal: AlternateScreen<termion::raw::RawTerminal<::std::io::Stdout>>,
|
||||||
current_style: Cell<theme::ColorStyle>,
|
current_style: Cell<theme::ColorStyle>,
|
||||||
colors: BTreeMap<i16, (Box<tcolor::Color>, Box<tcolor::Color>)>,
|
colors: HashMap<theme::ColorStyle, (Box<tcolor::Color>, Box<tcolor::Color>)>,
|
||||||
|
|
||||||
input: chan::Receiver<Event>,
|
input: chan::Receiver<Event>,
|
||||||
resize: chan::Receiver<chan_signal::Signal>,
|
resize: chan::Receiver<chan_signal::Signal>,
|
||||||
@ -35,20 +35,6 @@ trait Effectable {
|
|||||||
fn off(&self);
|
fn off(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ColorRef<'a>(&'a tcolor::Color);
|
|
||||||
|
|
||||||
impl<'a> tcolor::Color for ColorRef<'a> {
|
|
||||||
#[inline]
|
|
||||||
fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
self.0.write_fg(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
self.0.write_bg(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Effectable for theme::Effect {
|
impl Effectable for theme::Effect {
|
||||||
fn on(&self) {
|
fn on(&self) {
|
||||||
match *self {
|
match *self {
|
||||||
@ -66,14 +52,21 @@ impl Effectable for theme::Effect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply_colors(fg: &tcolor::Color, bg: &tcolor::Color) {
|
fn apply_colors(fg: &tcolor::Color, bg: &tcolor::Color) {
|
||||||
print!("{}{}", tcolor::Fg(ColorRef(fg)), tcolor::Bg(ColorRef(bg)));
|
print!("{}{}", tcolor::Fg(fg), tcolor::Bg(bg));
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Concrete {
|
impl Concrete {
|
||||||
fn apply_colorstyle(&self, color_style: theme::ColorStyle) {
|
fn apply_colorstyle(&self, color_style: theme::ColorStyle) {
|
||||||
let (ref fg, ref bg) = self.colors[&color_style.id()];
|
if let theme::ColorStyle::Custom { front, back } = color_style {
|
||||||
|
let fg = colour_to_termion_colour(&front);
|
||||||
|
let bg = colour_to_termion_colour(&back);
|
||||||
|
apply_colors(&*fg, &*bg);
|
||||||
|
} else {
|
||||||
|
let (ref fg, ref bg) = self.colors[&color_style];
|
||||||
apply_colors(&**fg, &**bg);
|
apply_colors(&**fg, &**bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl backend::Backend for Concrete {
|
impl backend::Backend for Concrete {
|
||||||
@ -82,7 +75,9 @@ impl backend::Backend for Concrete {
|
|||||||
|
|
||||||
let resize = chan_signal::notify(&[chan_signal::Signal::WINCH]);
|
let resize = chan_signal::notify(&[chan_signal::Signal::WINCH]);
|
||||||
|
|
||||||
let terminal = AlternateScreen::from(::std::io::stdout().into_raw_mode().unwrap());
|
let terminal = AlternateScreen::from(::std::io::stdout()
|
||||||
|
.into_raw_mode()
|
||||||
|
.unwrap());
|
||||||
let (sender, receiver) = chan::async();
|
let (sender, receiver) = chan::async();
|
||||||
|
|
||||||
thread::spawn(move || for key in ::std::io::stdin().events() {
|
thread::spawn(move || for key in ::std::io::stdin().events() {
|
||||||
@ -94,7 +89,7 @@ impl backend::Backend for Concrete {
|
|||||||
let backend = Concrete {
|
let backend = Concrete {
|
||||||
terminal: terminal,
|
terminal: terminal,
|
||||||
current_style: Cell::new(theme::ColorStyle::Background),
|
current_style: Cell::new(theme::ColorStyle::Background),
|
||||||
colors: BTreeMap::new(),
|
colors: HashMap::new(),
|
||||||
input: receiver,
|
input: receiver,
|
||||||
resize: resize,
|
resize: resize,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
@ -114,7 +109,8 @@ impl backend::Backend for Concrete {
|
|||||||
fn init_color_style(&mut self, style: theme::ColorStyle,
|
fn init_color_style(&mut self, style: theme::ColorStyle,
|
||||||
foreground: &theme::Color, background: &theme::Color) {
|
foreground: &theme::Color, background: &theme::Color) {
|
||||||
// Step 1: convert foreground and background into proper termion Color
|
// Step 1: convert foreground and background into proper termion Color
|
||||||
self.colors.insert(style.id(),
|
self.colors
|
||||||
|
.insert(style,
|
||||||
(colour_to_termion_colour(foreground),
|
(colour_to_termion_colour(foreground),
|
||||||
colour_to_termion_colour(background)));
|
colour_to_termion_colour(background)));
|
||||||
}
|
}
|
||||||
|
@ -138,7 +138,7 @@ pub enum Effect {
|
|||||||
/// Represents a color pair role to use when printing something.
|
/// Represents a color pair role to use when printing something.
|
||||||
///
|
///
|
||||||
/// The current theme will assign each role a foreground and background color.
|
/// The current theme will assign each role a foreground and background color.
|
||||||
#[derive(Clone,Copy)]
|
#[derive(Clone,Copy,Debug,PartialEq,Eq,Hash)]
|
||||||
pub enum ColorStyle {
|
pub enum ColorStyle {
|
||||||
/// Application background, where no view is present.
|
/// Application background, where no view is present.
|
||||||
Background,
|
Background,
|
||||||
@ -342,7 +342,7 @@ fn load_color(target: &mut Color, value: Option<&toml::Value>) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One of the 8 base colors.
|
/// One of the 8 base colors.
|
||||||
#[derive(Clone,Copy,Debug)]
|
#[derive(Clone,Copy,Debug,PartialEq,Eq,Hash)]
|
||||||
pub enum BaseColor {
|
pub enum BaseColor {
|
||||||
/// Black color
|
/// Black color
|
||||||
///
|
///
|
||||||
@ -379,7 +379,7 @@ pub enum BaseColor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a color used by the theme.
|
/// Represents a color used by the theme.
|
||||||
#[derive(Clone,Copy,Debug)]
|
#[derive(Clone,Copy,Debug,PartialEq,Eq,Hash)]
|
||||||
pub enum Color {
|
pub enum Color {
|
||||||
/// One of the 8 base colors.
|
/// One of the 8 base colors.
|
||||||
Dark(BaseColor),
|
Dark(BaseColor),
|
||||||
|
Loading…
Reference in New Issue
Block a user