From 4dd6307c1201330e2d172bc85cede690a668854a Mon Sep 17 00:00:00 2001 From: mars Date: Thu, 14 Sep 2023 17:41:42 -0600 Subject: [PATCH] Window drawing --- src/buffer.rs | 2 +- src/state.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++- src/theme.rs | 7 +++++- themes/default.toml | 2 ++ 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index dc0cedd..a629ffb 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -71,7 +71,7 @@ impl<'a> LineBuf<'a> { let remaining = if lhs < self.remaining_width { let sub = lhs..self.remaining_width; - self.styled.print_sub(&mut self.buf, sub)? + self.styled.print_sub(&mut self.buf, sub, line_style)? } else { self.remaining_width }; diff --git a/src/state.rs b/src/state.rs index f659b55..62239f9 100644 --- a/src/state.rs +++ b/src/state.rs @@ -31,7 +31,7 @@ use crate::{ buffer::Buffer, config::{Config, ThemeWatcher}, keybinds::{Key, Keybind}, - theme::StyleStore, + theme::{StyleStore, StyledString}, Cursor, Direction, }; @@ -67,6 +67,45 @@ impl Mode { } } +pub struct Rect { + pub position: (usize, usize), + pub size: (usize, usize), +} + +pub struct Window { + pub rect: Rect, + pub contents: Vec, +} + +impl Window { + pub fn draw( + &self, + out: &mut impl QueueableCommand, + styles: &mut StyleStore, + ) -> crossterm::Result<()> { + let x = self.rect.position.0 as u16; + let base = *styles.get_scope("ui.window"); + let width = self.rect.size.0; + let clip = 0..width; + let padding: String = std::iter::repeat(' ').take(width).collect(); + for row in 0..self.rect.size.1 { + let y = self.rect.position.1 as u16 + row as u16; + out.queue(cursor::MoveTo(x, y))?; + + let remaining = if let Some(line) = self.contents.get(row) { + line.print_sub(out, clip.clone(), base)? + } else { + width + }; + + let padding = &padding[0..remaining]; + base.print_styled(out, padding)?; + } + + Ok(()) + } +} + pub struct State { pub styles: Arc>, pub config: Config, @@ -75,6 +114,7 @@ pub struct State { pub redo_buffers: Vec, pub cursor: Cursor, pub file: Option, + pub window: Option, pub mode: Mode, pub submode: Option, pub last_saved: Rope, @@ -109,6 +149,7 @@ impl State { quit: false, error: None, theme_tx, + window: None, }) } @@ -152,6 +193,12 @@ impl State { write!(out, "{:?}", submode)?; } + // draw open window + if let Some(window) = self.window.as_ref() { + let mut styles = self.styles.lock(); + window.draw(out, &mut styles)?; + } + // draw cursor let cursor_pos = set_cursor_pos.unwrap_or_else(|| { // calculate cursor position on buffer @@ -181,6 +228,9 @@ impl State { // reset the error from the last event self.error = None; + // close open window + self.window.take(); + match event { Event::Resize(cols, rows) => { self.size = (cols as usize, rows as usize); diff --git a/src/theme.rs b/src/theme.rs index 54a4c72..28e01e4 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -136,12 +136,14 @@ impl StyledString { } } - pub fn print(&self, out: &mut impl QueueableCommand) -> crossterm::Result<()> { + pub fn print(&self, out: &mut impl QueueableCommand, base: Style) -> crossterm::Result<()> { let mut cursor = 0; for (size, style) in self.styles.iter() { let end = cursor + size; let range = cursor..end; let sub = &self.content[range]; + let mut style = style.clone(); + style.apply(&base); style.print_styled(out, sub)?; cursor = end; } @@ -153,6 +155,7 @@ impl StyledString { &self, out: &mut impl QueueableCommand, clip: Range, + base: Style, ) -> crossterm::Result { let mut remaining = clip.end - clip.start; let mut cursor = 0; @@ -168,6 +171,8 @@ impl StyledString { remaining -= clipped.end - clipped.start; let sub = &self.content[clipped]; + let mut style = style.clone(); + style.apply(&base); style.print_styled(out, sub)?; if cursor >= clip.end { diff --git a/themes/default.toml b/themes/default.toml index 1ce9213..de7f934 100644 --- a/themes/default.toml +++ b/themes/default.toml @@ -2,6 +2,8 @@ "ui.linenr" = "black" "ui.linenr.selected" = "white" +"ui.window" = { bg = "magenta" } + "error" = "red" "comment" = { fg = "black", modifiers = ["italics"] }