-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
141 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
use crossterm::event::Event; | ||
use helix_core::Position; | ||
use helix_view::{ | ||
graphics::{CursorKind, Rect}, | ||
Editor, | ||
}; | ||
use tui::buffer::Buffer; | ||
|
||
use crate::compositor::{Component, Context, EventResult}; | ||
|
||
/// Contains a component placed in the center of the parent component | ||
#[derive(Debug)] | ||
pub struct Overlay<T> { | ||
/// Child component | ||
pub content: T, | ||
/// Fixed margin around the component | ||
pub margin: Margin4, | ||
/// Value between 0 and 1 that indicates how much of the vertical space is used | ||
pub vertical_size: f32, | ||
/// Value between 0 and 1 that indicates how much of the horizontal space is used | ||
pub horizontal_size: f32, | ||
} | ||
|
||
#[derive(Debug, Default, Clone, Copy)] | ||
pub struct Margin4 { | ||
pub top: u16, | ||
pub right: u16, | ||
pub bottom: u16, | ||
pub left: u16, | ||
} | ||
|
||
impl<T> Overlay<T> { | ||
fn get_dimensions(&self, viewport: (u16, u16)) -> Rect { | ||
fn mul_and_cast(size: u16, factor: f32) -> u16 { | ||
let absolute = (size as f32) * factor; | ||
(absolute as i32).try_into().unwrap() | ||
} | ||
|
||
let (outer_w, outer_h) = viewport; | ||
let (margin_w, margin_h) = self.margin.dimensions(); | ||
|
||
let outer_without_margin_w = outer_w.saturating_sub(margin_w); | ||
let outer_without_margin_h = outer_h.saturating_sub(margin_h); | ||
|
||
let inner_w = mul_and_cast(outer_without_margin_w, self.horizontal_size); | ||
let inner_h = mul_and_cast(outer_without_margin_h, self.vertical_size); | ||
|
||
let pos_x = self.margin.left + outer_without_margin_w.saturating_sub(inner_w) / 2; | ||
let pos_y = self.margin.top + outer_without_margin_h.saturating_sub(inner_h) / 2; | ||
|
||
Rect { | ||
x: pos_x, | ||
y: pos_y, | ||
width: inner_w, | ||
height: inner_h, | ||
} | ||
} | ||
|
||
fn get_outer_size_from_inner_size(&self, inner: (u16, u16)) -> (u16, u16) { | ||
fn div_and_cast(size: u16, divisor: f32) -> u16 { | ||
let absolute = (size as f32) / divisor; | ||
(absolute as i32).try_into().unwrap() | ||
} | ||
|
||
let (inner_w, inner_h) = inner; | ||
let (margin_w, margin_h) = self.margin.dimensions(); | ||
( | ||
margin_w + div_and_cast(inner_w, self.horizontal_size), | ||
margin_h + div_and_cast(inner_h, self.vertical_size), | ||
) | ||
} | ||
} | ||
|
||
impl Margin4 { | ||
fn dimensions(&self) -> (u16, u16) { | ||
(self.left + self.right, self.top + self.bottom) | ||
} | ||
} | ||
|
||
impl<T: Component + 'static> Component for Overlay<T> { | ||
fn render(&mut self, area: Rect, frame: &mut Buffer, ctx: &mut Context) { | ||
let dimensions = self.get_dimensions((area.width, area.height)); | ||
self.content.render(dimensions, frame, ctx) | ||
} | ||
|
||
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> { | ||
let dimensions = self.get_dimensions(viewport); | ||
let viewport = (dimensions.width, dimensions.height); | ||
let required = self.content.required_size(viewport)?; | ||
Some(self.get_outer_size_from_inner_size(required)) | ||
} | ||
|
||
fn handle_event(&mut self, event: Event, ctx: &mut Context) -> EventResult { | ||
self.content.handle_event(event, ctx) | ||
} | ||
|
||
fn cursor(&self, area: Rect, ctx: &Editor) -> (Option<Position>, CursorKind) { | ||
let dimensions = self.get_dimensions((area.width, area.height)); | ||
self.content.cursor(dimensions, ctx) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters