Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic dimming functionality #2751

Closed
wants to merge 12 commits into from
Next Next commit
adds basic dimming functionality
- option to dim colors of unfocused views
- option to dim buffer background behind overlay components
  • Loading branch information
farwyler committed Jul 2, 2022
commit 8d367d9538510d1386d02ee47e7b1282e44280ff
117 changes: 117 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions helix-term/src/ui/overlay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ fn clip_rect_relative(rect: Rect, percent_horizontal: u8, percent_vertical: u8)

impl<T: Component + 'static> Component for Overlay<T> {
fn render(&mut self, area: Rect, frame: &mut Buffer, ctx: &mut Context) {
if let Some(op) = &ctx.editor.config().dim.overlay_backdrops {
// TODO: optimise. we don't need to dim behind the child content
frame.dim(area, op);
}
let dimensions = (self.calc_child_size)(area);
self.content.render(dimensions, frame, ctx)
}
Expand Down
1 change: 1 addition & 0 deletions helix-tui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ include = ["src/**/*", "README.md"]
default = ["crossterm"]

[dependencies]
palette = "0.6"
bitflags = "1.3"
cassowary = "0.3"
unicode-segmentation = "1.9"
Expand Down
57 changes: 55 additions & 2 deletions helix-tui/src/buffer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::text::{Span, Spans};
use helix_core::unicode::width::UnicodeWidthStr;
use helix_view::graphics::{Color, DimFunction, DimOperation, Modifier, Rect, Style};
use palette::Shade;
use std::cmp::min;
use std::collections::HashMap;
use unicode_segmentation::UnicodeSegmentation;

use helix_view::graphics::{Color, Modifier, Rect, Style};

/// A buffer cell
#[derive(Debug, Clone, PartialEq)]
pub struct Cell {
Expand Down Expand Up @@ -583,6 +584,58 @@ impl Buffer {
}
updates
}

/// Apply DimOperation to all cells in area
pub fn dim(&mut self, area: Rect, op: &DimOperation) {
use DimFunction::*;

type Srgb8 = palette::rgb::Rgb<palette::encoding::Srgb, u8>;

let mut cache: HashMap<Color, Color> = HashMap::new();
let intensity = op.intensity as f32 / 100.0; // TODO: clamp

let mut modify = |col| {
let result = cache.entry(col).or_insert_with(|| {
if let Color::Rgb(r, g, b) = col {
let mut rgb = Srgb8::new(r, g, b).into_format().into_linear();
rgb = match op.func {
Lighten => rgb.lighten(intensity),
Darken => rgb.darken(intensity),
_ => unimplemented!(),
};
let rgb = Srgb8::from(rgb).into_components();
Color::Rgb(rgb.0, rgb.1, rgb.2)
} else {
col
}
});
*result
};
for y in area.top()..area.bottom() {
for x in area.left()..area.right() {
let cell = &mut self[(x, y)];

match op.func {
Dim => {
cell.modifier.insert(Modifier::DIM);
}
Lighten | Darken => {
match cell.fg {
Color::Rgb(..) => {
cell.fg = modify(cell.fg);
}
_ => {
// cell.modifier.insert(Modifier::DIM);
}
};
if let Color::Rgb(..) = cell.bg {
cell.bg = modify(cell.bg);
}
}
}
}
}
}
}

impl std::ops::Index<(u16, u16)> for Buffer {
Expand Down
15 changes: 14 additions & 1 deletion helix-view/src/editor.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
clipboard::{get_clipboard_provider, ClipboardProvider},
document::{Mode, SCRATCH_BUFFER_NAME},
graphics::{CursorKind, Rect},
graphics::{CursorKind, DimOperation, Rect},
info::Info,
input::KeyEvent,
theme::{self, Theme},
Expand Down Expand Up @@ -109,6 +109,15 @@ impl Default for FilePickerConfig {
}
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
pub struct DimConfig {
/// dim function for margin around content of dimmable overlays
pub overlay_backdrops: Option<DimOperation>,
/// dim function for unfocused editor views
pub unfocused_views: Option<DimOperation>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
pub struct Config {
Expand Down Expand Up @@ -163,6 +172,9 @@ pub struct Config {
pub indent_guides: IndentGuidesConfig,
/// Whether to color modes with different colors. Defaults to `false`.
pub color_modes: bool,
/// Dim configuration
#[serde(default)]
pub dim: DimConfig,
}

#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
Expand Down Expand Up @@ -417,6 +429,7 @@ impl Default for Config {
whitespace: WhitespaceConfig::default(),
indent_guides: IndentGuidesConfig::default(),
color_modes: false,
dim: DimConfig::default(),
}
}
}
Expand Down
31 changes: 30 additions & 1 deletion helix-view/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,35 @@ use std::{
str::FromStr,
};

#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum DimFunction {
// Set text modifier DIM
Dim,
// Lighten the shade of an RGB color
Lighten,
// Darken the shade of an RGB color
Darken,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
pub struct DimOperation {
/// Function to perform on cells
pub func: DimFunction,
/// 0-100 Instensity of the applied function. Has no effect with DimFunction.Dim
pub intensity: u8,
}

impl Default for DimOperation {
fn default() -> Self {
Self {
func: DimFunction::Darken,
intensity: 50,
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
/// UNSTABLE
Expand Down Expand Up @@ -262,7 +291,7 @@ impl Rect {
}
}

#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Color {
Reset,
Expand Down