diff options
author | qkzk <qu3nt1n@gmail.com> | 2024-01-24 21:45:22 +0100 |
---|---|---|
committer | qkzk <qu3nt1n@gmail.com> | 2024-01-24 21:45:22 +0100 |
commit | c4eae466c106d19118401076ad25d6aee8fbb509 (patch) | |
tree | d9ef41a17ec4df07ced5151d001f490b1fd5a10e | |
parent | e56fec6d45df7f0cd3171e216b9d64d57fdef810 (diff) |
gradient over listing
-rw-r--r-- | development.md | 1 | ||||
-rw-r--r-- | src/config/colors.rs | 72 | ||||
-rw-r--r-- | src/config/mod.rs | 2 | ||||
-rw-r--r-- | src/io/display.rs | 43 |
4 files changed, 100 insertions, 18 deletions
diff --git a/development.md b/development.md index fc618df..52e5d1f 100644 --- a/development.md +++ b/development.md @@ -917,6 +917,7 @@ New view: Tree ! Toggle with 't', fold with 'z'. Navigate normally. - [x] merge both bulkthing modes. If more files, just create them. Like [oil](https://github.com/stevearc/oil.nvim) - [x] allow different ports in remote - [x] sort trash by reversed deletion date +- [x] gradient over listing - [ ] ??? ## TODO diff --git a/src/config/colors.rs b/src/config/colors.rs index 7f56e85..0554e28 100644 --- a/src/config/colors.rs +++ b/src/config/colors.rs @@ -43,3 +43,75 @@ pub fn extension_color(extension: &str) -> Color { hasher.write(extension.as_bytes()); COLORER(hasher.finish() as usize) } + +#[derive(Debug, Clone, Copy)] +pub struct ColorG { + r: u8, + g: u8, + b: u8, +} + +impl Default for ColorG { + fn default() -> Self { + Self { + r: 255, + g: 255, + b: 0, + } + } +} + +impl ColorG { + /// Parse a tuikit color into it's rgb values. + /// Non parsable colors returns None. + pub fn from_tuikit(color: Color) -> Option<Self> { + match color { + Color::Rgb(r, g, b) => Some(Self { r, g, b }), + _ => None, + } + } + + fn to_tuikit(&self) -> Color { + Color::Rgb(self.r, self.g, self.b) + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Gradient { + start: ColorG, + end: ColorG, + step_ratio: f32, + len: usize, +} + +impl Gradient { + pub fn new(start: ColorG, end: ColorG, len: usize) -> Self { + let step_ratio = 1 as f32 / len as f32; + Self { + start, + end, + step_ratio, + len, + } + } + + fn gradient_step(&self, step: usize) -> ColorG { + let position = self.step_ratio * step as f32; + + let r = self.start.r as f32 + (self.end.r as f32 - self.start.r as f32) * position; + let g = self.start.g as f32 + (self.end.g as f32 - self.start.g as f32) * position; + let b = self.start.b as f32 + (self.end.b as f32 - self.start.b as f32) * position; + + ColorG { + r: r.round() as u8, + g: g.round() as u8, + b: b.round() as u8, + } + } + + pub fn gradient(&self) -> Vec<Color> { + (0..self.len) + .map(|step| self.gradient_step(step).to_tuikit()) + .collect() + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index e14762c..9184636 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -2,6 +2,6 @@ mod colors; mod configuration; mod keybindings; -pub use colors::{extension_color, Colorer}; +pub use colors::{extension_color, ColorG, Colorer, Gradient}; pub use configuration::{load_config, Config, COLORER, COLORS, MENU_COLORS, START_FOLDER}; pub use keybindings::{Bindings, REFRESH_EVENT, REFRESH_KEY}; diff --git a/src/io/display.rs b/src/io/display.rs index adf3f5a..e5beea3 100644 --- a/src/io/display.rs +++ b/src/io/display.rs @@ -14,7 +14,7 @@ use crate::app::{ClickableLine, ClickableString, FlaggedFooter, FlaggedHeader}; use crate::app::{Header, PreviewHeader}; use crate::common::path_to_string; use crate::common::ENCRYPTED_DEVICE_BINDS; -use crate::config::MENU_COLORS; +use crate::config::{ColorG, Gradient, MENU_COLORS}; use crate::io::read_last_log_line; use crate::log_info; use crate::modes::BinaryContent; @@ -43,11 +43,20 @@ use crate::modes::{parse_input_mode, SecondLine}; /// Iter over the content, returning a triplet of `(index, line, attr)`. macro_rules! enumerated_colored_iter { ($t:ident) => { - std::iter::zip($t.iter().enumerate(), MENU_COLORS.palette().iter().cycle()) - .map(|((index, line), attr)| (index, line, attr)) + std::iter::zip( + $t.iter().enumerate(), + Gradient::new( + ColorG::from_tuikit(MENU_COLORS.first).unwrap_or_default(), + ColorG::from_tuikit(MENU_COLORS.palette_3).unwrap_or_default(), + $t.len(), + ) + .gradient() + .iter() + .map(|color| color_to_attr(*color)), + ) + .map(|((index, line), attr)| (index, line, attr)) }; } - /// Draw every line of the preview macro_rules! impl_preview { ($text:ident, $tab:ident, $length:ident, $canvas:ident, $line_number_width:ident, $window:ident, $height:ident) => { @@ -772,7 +781,7 @@ impl<'a> WinSecondary<'a> { .skip(top) .take(min(bottom, len)) { - let attr = self.status.menu.completion.attr(row, attr); + let attr = self.status.menu.completion.attr(row, &attr); Self::draw_content_line(canvas, row + 1 - top, candidate, attr)?; } Ok(()) @@ -780,7 +789,7 @@ impl<'a> WinSecondary<'a> { fn draw_static_lines(lines: &[&str], canvas: &mut dyn Canvas) -> Result<()> { for (row, line, attr) in enumerated_colored_iter!(lines) { - Self::draw_content_line(canvas, row, line, *attr)?; + Self::draw_content_line(canvas, row, line, attr)?; } Ok(()) } @@ -827,7 +836,7 @@ impl<'a> WinSecondary<'a> { .skip(top) .take(min(bottom, len)) { - let attr = selectable.attr(row, attr); + let attr = selectable.attr(row, &attr); Self::draw_content_line( canvas, row + 1 - top, @@ -842,7 +851,7 @@ impl<'a> WinSecondary<'a> { let selectable = &self.tab.history; let content = selectable.content(); for (row, pair, attr) in enumerated_colored_iter!(content) { - let attr = selectable.attr(row, attr); + let attr = selectable.attr(row, &attr); Self::draw_content_line( canvas, row + 1, @@ -877,7 +886,7 @@ impl<'a> WinSecondary<'a> { .skip(top) .take(min(bottom, len)) { - let attr = trash.attr(row, attr); + let attr = trash.attr(row, &attr); let _ = Self::draw_content_line(canvas, row + 1 - top, &trashinfo.to_string(), attr); } } @@ -886,7 +895,7 @@ impl<'a> WinSecondary<'a> { let selectable = &self.status.menu.compression; let content = selectable.content(); for (row, compression_method, attr) in enumerated_colored_iter!(content) { - let attr = selectable.attr(row, attr); + let attr = selectable.attr(row, &attr); Self::draw_content_line(canvas, row + 1, &compression_method.to_string(), attr)?; } Ok(()) @@ -897,7 +906,7 @@ impl<'a> WinSecondary<'a> { canvas.print_with_attr(1, 2, "Pick an action.", color_to_attr(MENU_COLORS.second))?; let content = selectable.content(); for (row, desc, attr) in enumerated_colored_iter!(content) { - let attr = selectable.attr(row, attr); + let attr = selectable.attr(row, &attr); Self::draw_content_line(canvas, row + 1, desc, attr)?; } Ok(()) @@ -914,7 +923,7 @@ impl<'a> WinSecondary<'a> { .skip(top) .take(min(bottom, len)) { - let attr = self.status.menu.marks.attr(row, attr); + let attr = self.status.menu.marks.attr(row, &attr); Self::draw_content_line(canvas, row + 1 - top, line, attr)?; } Ok(()) @@ -936,7 +945,7 @@ impl<'a> WinSecondary<'a> { .skip(top) .take(min(bottom, len)) { - let attr = self.status.menu.tui_applications.attr(row, attr); + let attr = self.status.menu.tui_applications.attr(row, &attr); Self::draw_content_line(canvas, row + 1 - top, command, attr)?; } Ok(()) @@ -958,7 +967,7 @@ impl<'a> WinSecondary<'a> { .skip(top) .take(min(bottom, len)) { - let attr = self.status.menu.cli_applications.attr(row, attr); + let attr = self.status.menu.cli_applications.attr(row, &attr); canvas.print_with_attr( row + 1 + ContentWindow::WINDOW_MARGIN_TOP - top, 4, @@ -1057,7 +1066,7 @@ impl<'a> WinSecondary<'a> { canvas, row + 2, path.to_str().context("Unreadable filename")?, - *attr, + attr, )?; } Ok(()) @@ -1066,7 +1075,7 @@ impl<'a> WinSecondary<'a> { fn draw_confirm_bulk(&self, canvas: &mut dyn Canvas) -> Result<()> { let content = self.status.menu.bulk.format_confirmation(); for (row, line, attr) in enumerated_colored_iter!(content) { - Self::draw_content_line(canvas, row + 2, line, *attr)?; + Self::draw_content_line(canvas, row + 2, line, attr)?; } Ok(()) } @@ -1092,7 +1101,7 @@ impl<'a> WinSecondary<'a> { fn draw_confirm_non_empty_trash(&self, canvas: &mut dyn Canvas) -> Result<()> { let content = self.status.menu.trash.content(); for (row, trashinfo, attr) in enumerated_colored_iter!(content) { - let attr = self.status.menu.trash.attr(row, attr); + let attr = self.status.menu.trash.attr(row, &attr); Self::draw_content_line(canvas, row + 4, &trashinfo.to_string(), attr)?; } Ok(()) |