Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/src/ui/text_decorations.rs')
-rw-r--r--helix-term/src/ui/text_decorations.rs175
1 files changed, 0 insertions, 175 deletions
diff --git a/helix-term/src/ui/text_decorations.rs b/helix-term/src/ui/text_decorations.rs
deleted file mode 100644
index 931ea431..00000000
--- a/helix-term/src/ui/text_decorations.rs
+++ /dev/null
@@ -1,175 +0,0 @@
-use std::cmp::Ordering;
-
-use helix_core::doc_formatter::FormattedGrapheme;
-use helix_core::Position;
-use helix_view::editor::CursorCache;
-
-use crate::ui::document::{LinePos, TextRenderer};
-
-pub use diagnostics::InlineDiagnostics;
-
-mod diagnostics;
-
-/// Decorations are the primary mechanism for extending the text rendering.
-///
-/// Any on-screen element which is anchored to the rendered text in some form
-/// should be implemented using this trait. Translating char positions to
-/// on-screen positions can be expensive and should not be done manually in the
-/// ui loop. Instead such translations are automatically performed on the fly
-/// while the text is being rendered. The results are provided to this trait by
-/// the rendering infrastructure.
-///
-/// To reserve space for virtual text lines (which is then filled by this trait) emit appropriate
-/// [`LineAnnotation`](helix_core::text_annotations::LineAnnotation)s in [`helix_view::View::text_annotations`]
-pub trait Decoration {
- /// Called **before** a **visual** line is rendered. A visual line does not
- /// necessarily correspond to a single line in a document as soft wrapping can
- /// spread a single document line across multiple visual lines.
- ///
- /// This function is called before text is rendered as any decorations should
- /// never overlap the document text. That means that setting the forground color
- /// here is (essentially) useless as the text color is overwritten by the
- /// rendered text. This _of course_ doesn't apply when rendering inside virtual lines
- /// below the line reserved by `LineAnnotation`s as no text will be rendered here.
- fn decorate_line(&mut self, _renderer: &mut TextRenderer, _pos: LinePos) {}
-
- /// Called **after** a **visual** line is rendered. A visual line does not
- /// necessarily correspond to a single line in a document as soft wrapping can
- /// spread a single document line across multiple visual lines.
- ///
- /// This function is called after text is rendered so that decorations can collect
- /// horizontal positions on the line (see [`Decoration::decorate_grapheme`]) first and
- /// use those positions` while rendering
- /// virtual text.
- /// That means that setting the forground color
- /// here is (essentially) useless as the text color is overwritten by the
- /// rendered text. This -ofcourse- doesn't apply when rendering inside virtual lines
- /// below the line reserved by `LineAnnotation`s. e as no text will be rendered here.
- /// **Note**: To avoid overlapping decorations in the virtual lines, each decoration
- /// must return the number of virtual text lines it has taken up. Each `Decoration` recieves
- /// an offset `virt_off` based on these return values where it can render virtual text:
- ///
- /// That means that a `render_line` implementation that returns `X` can render virtual text
- /// in the following area:
- /// ``` no-compile
- /// let start = inner.y + pos.virtual_line + virt_off;
- /// start .. start + X
- /// ````
- fn render_virt_lines(
- &mut self,
- _renderer: &mut TextRenderer,
- _pos: LinePos,
- _virt_off: Position,
- ) -> Position {
- Position::new(0, 0)
- }
-
- fn reset_pos(&mut self, _pos: usize) -> usize {
- usize::MAX
- }
-
- fn skip_concealed_anchor(&mut self, conceal_end_char_idx: usize) -> usize {
- self.reset_pos(conceal_end_char_idx)
- }
-
- /// This function is called **before** the grapheme at `char_idx` is rendered.
- ///
- /// # Returns
- ///
- /// The char idx of the next grapheme that this function should be called for
- fn decorate_grapheme(
- &mut self,
- _renderer: &mut TextRenderer,
- _grapheme: &FormattedGrapheme,
- ) -> usize {
- usize::MAX
- }
-}
-
-impl<F: FnMut(&mut TextRenderer, LinePos)> Decoration for F {
- fn decorate_line(&mut self, renderer: &mut TextRenderer, pos: LinePos) {
- self(renderer, pos);
- }
-}
-
-#[derive(Default)]
-pub struct DecorationManager<'a> {
- decorations: Vec<(Box<dyn Decoration + 'a>, usize)>,
-}
-
-impl<'a> DecorationManager<'a> {
- pub fn add_decoration(&mut self, decoration: impl Decoration + 'a) {
- self.decorations.push((Box::new(decoration), 0));
- }
-
- pub fn prepare_for_rendering(&mut self, first_visible_char: usize) {
- for (decoration, next_position) in &mut self.decorations {
- *next_position = decoration.reset_pos(first_visible_char)
- }
- }
-
- pub fn decorate_grapheme(&mut self, renderer: &mut TextRenderer, grapheme: &FormattedGrapheme) {
- for (decoration, hook_char_idx) in &mut self.decorations {
- loop {
- match (*hook_char_idx).cmp(&grapheme.char_idx) {
- // this grapheme has been concealed or we are at the first grapheme
- Ordering::Less => {
- *hook_char_idx = decoration.skip_concealed_anchor(grapheme.char_idx)
- }
- Ordering::Equal => {
- *hook_char_idx = decoration.decorate_grapheme(renderer, grapheme)
- }
- Ordering::Greater => break,
- }
- }
- }
- }
-
- pub fn decorate_line(&mut self, renderer: &mut TextRenderer, pos: LinePos) {
- for (decoration, _) in &mut self.decorations {
- decoration.decorate_line(renderer, pos);
- }
- }
-
- pub fn render_virtual_lines(
- &mut self,
- renderer: &mut TextRenderer,
- pos: LinePos,
- line_width: usize,
- ) {
- let mut virt_off = Position::new(1, line_width); // start at 1 so the line is never overwritten
- for (decoration, _) in &mut self.decorations {
- virt_off += decoration.render_virt_lines(renderer, pos, virt_off);
- }
- }
-}
-
-/// Cursor rendering is done externally so all the cursor decoration
-/// does is save the position of primary cursor
-pub struct Cursor<'a> {
- pub cache: &'a CursorCache,
- pub primary_cursor: usize,
-}
-impl Decoration for Cursor<'_> {
- fn reset_pos(&mut self, pos: usize) -> usize {
- if pos <= self.primary_cursor {
- self.primary_cursor
- } else {
- usize::MAX
- }
- }
-
- fn decorate_grapheme(
- &mut self,
- renderer: &mut TextRenderer,
- grapheme: &FormattedGrapheme,
- ) -> usize {
- if renderer.column_in_bounds(grapheme.visual_pos.col, grapheme.width())
- && renderer.offset.row < grapheme.visual_pos.row
- {
- let position = grapheme.visual_pos - renderer.offset;
- self.cache.set(Some(position));
- }
- usize::MAX
- }
-}