diff --git a/src/backend/curses.rs b/src/backend/curses.rs index 21cba50..2ec2904 100644 --- a/src/backend/curses.rs +++ b/src/backend/curses.rs @@ -8,7 +8,7 @@ use ncurses; pub struct NcursesBackend; impl backend::Backend for NcursesBackend { - fn init() { + fn init() -> Self { ::std::env::set_var("ESCDELAY", "25"); ncurses::setlocale(ncurses::LcCategory::all, ""); ncurses::initscr(); @@ -19,25 +19,27 @@ impl backend::Backend for NcursesBackend { ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE); ncurses::wbkgd(unsafe { ncurses::stdscr }, ncurses::COLOR_PAIR(ColorStyle::Background.id())); + + NcursesBackend } - fn screen_size() -> (usize, usize) { + fn screen_size(&self) -> (usize, usize) { let mut x: i32 = 0; let mut y: i32 = 0; ncurses::getmaxyx(unsafe { ncurses::stdscr }, &mut y, &mut x); (x as usize, y as usize) } - fn has_colors() -> bool { + fn has_colors(&self) -> bool { ncurses::has_colors() } - fn finish() { + fn finish(&mut self) { ncurses::endwin(); } - fn init_color_style(style: ColorStyle, foreground: &Color, + fn init_color_style(&mut self, style: ColorStyle, foreground: &Color, background: &Color) { // TODO: build the color on the spot @@ -46,7 +48,7 @@ impl backend::Backend for NcursesBackend { find_closest(background) as i16); } - fn with_color(color: ColorStyle, f: F) { + fn with_color(&self, color: 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); @@ -58,7 +60,7 @@ impl backend::Backend for NcursesBackend { ncurses::attron(current_style); } - fn with_effect(effect: Effect, f: F) { + fn with_effect(&self, effect: Effect, f: F) { let style = match effect { Effect::Reverse => ncurses::A_REVERSE(), Effect::Simple => ncurses::A_NORMAL(), @@ -72,15 +74,15 @@ impl backend::Backend for NcursesBackend { ncurses::clear(); } - fn refresh() { + fn refresh(&self) { ncurses::refresh(); } - fn print_at((x, y): (usize, usize), text: &str) { + fn print_at(&self, (x, y): (usize, usize), text: &str) { ncurses::mvaddstr(y as i32, x as i32, text); } - fn poll_event() -> Event { + fn poll_event(&self) -> Event { let ch: i32 = ncurses::getch(); // Is it a UTF-8 starting point? @@ -92,7 +94,7 @@ impl backend::Backend for NcursesBackend { } } - fn set_refresh_rate(fps: u32) { + fn set_refresh_rate(&mut self, fps: u32) { if fps == 0 { ncurses::timeout(-1); } else { diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 3511322..f6f243a 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -7,23 +7,23 @@ mod curses; pub use self::curses::NcursesBackend; pub trait Backend { - fn init(); - fn finish(); + fn init() -> Self; + fn finish(&mut self); fn clear(); - fn refresh(); + fn refresh(&self); - fn has_colors() -> bool; + fn has_colors(&self) -> bool; - fn init_color_style(style: theme::ColorStyle, foreground: &theme::Color, - background: &theme::Color); + fn init_color_style(&mut self, style: theme::ColorStyle, + foreground: &theme::Color, background: &theme::Color); - fn print_at((usize, usize), &str); + fn print_at(&self, (usize, usize), &str); - fn poll_event() -> event::Event; - fn set_refresh_rate(fps: u32); - fn screen_size() -> (usize, usize); + fn poll_event(&self) -> event::Event; + fn set_refresh_rate(&mut self, fps: u32); + fn screen_size(&self) -> (usize, usize); - fn with_color(color: theme::ColorStyle, f: F); - fn with_effect(effect: theme::Effect, f: F); + fn with_color(&self, color: theme::ColorStyle, f: F); + fn with_effect(&self, effect: theme::Effect, f: F); } diff --git a/src/lib.rs b/src/lib.rs index e811fcd..58bab26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,10 +149,10 @@ 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. - B::init(); + let mut backend = B::init(); let theme = theme::load_default(); - theme.activate(); + theme.activate(&mut backend); // let theme = theme::load_theme("assets/style.toml").unwrap(); let (tx, rx) = mpsc::channel(); @@ -166,7 +166,7 @@ impl Cursive { running: true, cb_source: rx, cb_sink: tx, - backend: NcursesBackend, + backend: backend, }; res.screens.push(views::StackView::new()); @@ -258,7 +258,7 @@ impl Cursive { /// Sets the current theme. pub fn set_theme(&mut self, theme: theme::Theme) { self.theme = theme; - self.theme.activate(); + self.theme.activate(&mut self.backend); B::clear(); } @@ -284,8 +284,8 @@ impl Cursive { /// Regularly redraws everything, even when no input is given. /// Between 0 and 1000. /// Call with fps=0 to disable (default value). - pub fn set_fps(&self, fps: u32) { - B::set_refresh_rate(fps) + pub fn set_fps(&mut self, fps: u32) { + self.backend.set_refresh_rate(fps) } /// Returns a reference to the currently active screen. @@ -430,7 +430,7 @@ impl Cursive { /// Returns the size of the screen, in characters. pub fn screen_size(&self) -> Vec2 { - let (x, y) = B::screen_size(); + let (x, y) = self.backend.screen_size(); Vec2 { x: x as usize, @@ -472,7 +472,7 @@ impl Cursive { let id = self.active_screen; self.screens.get_mut(id).unwrap().draw(&printer); - B::refresh(); + self.backend.refresh(); } /// Runs the event loop. @@ -500,7 +500,7 @@ impl Cursive { // Wait for next event. // (If set_fps was called, this returns -1 now and then) - let event = B::poll_event(); + let event = self.backend.poll_event(); if event == Event::WindowResize { B::clear(); } @@ -535,6 +535,6 @@ impl Cursive { impl Drop for Cursive { fn drop(&mut self) { - B::finish(); + self.backend.finish(); } } diff --git a/src/printer.rs b/src/printer.rs index c42c50c..b453743 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -56,7 +56,7 @@ impl<'a> Printer<'a> { let text = &text[..prefix_len]; let p = p + self.offset; - B::print_at((p.x, p.y), text); + self.backend.print_at((p.x, p.y), text); } /// Prints a vertical line using the given character. @@ -69,7 +69,7 @@ impl<'a> Printer<'a> { let p = p + self.offset; for y in 0..len { - B::print_at((p.x, (p.y + y)), c); + self.backend.print_at((p.x, (p.y + y)), c); } } @@ -83,7 +83,7 @@ impl<'a> Printer<'a> { let p = p + self.offset; for x in 0..len { - B::print_at((p.x + x, p.y), c); + self.backend.print_at((p.x + x, p.y), c); } } @@ -105,7 +105,7 @@ impl<'a> Printer<'a> { pub fn with_color(&self, c: ColorStyle, f: F) where F: FnOnce(&Printer) { - B::with_color(c, || f(self)); + self.backend.with_color(c, || f(self)); } /// Same as `with_color`, but apply a ncurses style instead, @@ -115,7 +115,7 @@ impl<'a> Printer<'a> { pub fn with_effect(&self, effect: Effect, f: F) where F: FnOnce(&Printer) { - B::with_effect(effect, || f(self)); + self.backend.with_effect(effect, || f(self)); } /// Prints a rectangular box. diff --git a/src/theme.rs b/src/theme.rs index 7dd0171..8fe6a80 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -230,33 +230,33 @@ impl Theme { /// **Don't use this directly.** Uses [`Cursive::set_theme`] instead. /// /// [`Cursive::set_theme`]: ../struct.Cursive.html#method.set_theme - pub fn activate(&self) { + pub fn activate(&self, backend: &mut B) { // Initialize each color with the backend - B::init_color_style(ColorStyle::Background, + backend.init_color_style(ColorStyle::Background, &self.colors.view, &self.colors.background); - B::init_color_style(ColorStyle::Shadow, + backend.init_color_style(ColorStyle::Shadow, &self.colors.shadow, &self.colors.shadow); - B::init_color_style(ColorStyle::Primary, + backend.init_color_style(ColorStyle::Primary, &self.colors.primary, &self.colors.view); - B::init_color_style(ColorStyle::Secondary, + backend.init_color_style(ColorStyle::Secondary, &self.colors.secondary, &self.colors.view); - B::init_color_style(ColorStyle::Tertiary, + backend.init_color_style(ColorStyle::Tertiary, &self.colors.tertiary, &self.colors.view); - B::init_color_style(ColorStyle::TitlePrimary, + backend.init_color_style(ColorStyle::TitlePrimary, &self.colors.title_primary, &self.colors.view); - B::init_color_style(ColorStyle::TitleSecondary, + backend.init_color_style(ColorStyle::TitleSecondary, &self.colors.title_secondary, &self.colors.view); - B::init_color_style(ColorStyle::Highlight, + backend.init_color_style(ColorStyle::Highlight, &self.colors.view, &self.colors.highlight); - B::init_color_style(ColorStyle::HighlightInactive, + backend.init_color_style(ColorStyle::HighlightInactive, &self.colors.view, &self.colors.highlight_inactive); }