Working on grid rendering

Mikayla Maki created

Change summary

crates/gpui/src/gpui.rs                 |   2 
crates/gpui/src/scene.rs                |   2 
crates/terminal/src/gpui_func_tools.rs  |  10 ++
crates/terminal/src/terminal.rs         |  20 ++-
crates/terminal/src/terminal_element.rs | 132 +++++++++++++++-----------
5 files changed, 100 insertions(+), 66 deletions(-)

Detailed changes

crates/gpui/src/gpui.rs 🔗

@@ -15,7 +15,7 @@ pub use clipboard::ClipboardItem;
 pub mod fonts;
 pub mod geometry;
 mod presenter;
-mod scene;
+pub mod scene;
 pub use scene::{Border, CursorRegion, MouseRegion, MouseRegionId, Quad, Scene};
 pub mod text_layout;
 pub use text_layout::TextLayoutCache;

crates/gpui/src/scene.rs 🔗

@@ -81,7 +81,7 @@ pub struct Shadow {
     pub color: Color,
 }
 
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
 pub struct Glyph {
     pub font_id: FontId,
     pub font_size: f32,

crates/terminal/src/gpui_func_tools.rs 🔗

@@ -0,0 +1,10 @@
+use gpui::geometry::rect::RectF;
+
+pub fn paint_layer<F>(cx: &mut gpui::PaintContext, clip_bounds: Option<RectF>, f: F)
+where
+    F: FnOnce(&mut gpui::PaintContext) -> (),
+{
+    cx.scene.push_layer(clip_bounds);
+    f(cx);
+    cx.scene.pop_layer()
+}

crates/terminal/src/terminal.rs 🔗

@@ -37,6 +37,7 @@ const UP_SEQ: &str = "\x1b[A";
 const DOWN_SEQ: &str = "\x1b[B";
 const DEFAULT_TITLE: &str = "Terminal";
 
+pub mod gpui_func_tools;
 pub mod terminal_element;
 
 ///Action for carrying the input to the PTY
@@ -479,8 +480,9 @@ fn to_alac_rgb(color: Color) -> AlacRgb {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::terminal_element::{build_chunks, BuiltChunks};
+    use alacritty_terminal::{grid::GridIterator, term::cell::Cell};
     use gpui::TestAppContext;
+    use itertools::Itertools;
 
     ///Basic integration test, can we get the terminal to show up, execute a command,
     //and produce noticable output?
@@ -496,14 +498,18 @@ mod tests {
         terminal
             .condition(cx, |terminal, _cx| {
                 let term = terminal.term.clone();
-                let BuiltChunks { chunks, .. } = build_chunks(
-                    term.lock().renderable_content().display_iter,
-                    &Default::default(),
-                    Default::default(),
-                );
-                let content = chunks.iter().map(|e| e.0.trim()).collect::<String>();
+                let content = grid_as_str(term.lock().renderable_content().display_iter);
                 content.contains("7")
             })
             .await;
     }
+
+    pub(crate) fn grid_as_str(grid_iterator: GridIterator<Cell>) -> String {
+        let lines = grid_iterator.group_by(|i| i.point.line.0);
+        lines
+            .into_iter()
+            .map(|(_, line)| line.map(|i| i.c).collect::<String>())
+            .collect::<Vec<String>>()
+            .join("\n")
+    }
 }

crates/terminal/src/terminal_element.rs 🔗

@@ -17,6 +17,7 @@ use gpui::{
         vector::{vec2f, Vector2F},
     },
     json::json,
+    scene::Glyph,
     text_layout::{Line, RunStyle},
     Event, FontCache, MouseRegion, PaintContext, Quad, SizeConstraint, WeakViewHandle,
 };
@@ -26,7 +27,7 @@ use settings::Settings;
 use std::{iter, rc::Rc};
 use theme::TerminalStyle;
 
-use crate::{Input, ScrollTerminal, Terminal};
+use crate::{gpui_func_tools::paint_layer, Input, ScrollTerminal, Terminal};
 
 ///Scrolling is unbearably sluggish by default. Alacritty supports a configurable
 ///Scroll multiplier that is set to 3 by default. This will be removed when I
@@ -82,6 +83,7 @@ pub struct LayoutState {
     cur_size: SizeInfo,
     background_color: Color,
     background_rects: Vec<(RectF, Color)>, //Vec index == Line index for the LineSpan
+    ccc: Glyph,
 }
 
 impl TerminalEl {
@@ -188,6 +190,14 @@ impl Element for TerminalEl {
             )
         });
 
+        let g = Glyph {
+            font_id: text_style.font_id,
+            font_size: text_style.font_size,
+            id: 50,
+            origin: vec2f(0., 0.),
+            color: Color::red(),
+        };
+
         (
             constraint.max,
             LayoutState {
@@ -198,6 +208,7 @@ impl Element for TerminalEl {
                 cur_size,
                 background_rects,
                 background_color: terminal_theme.background,
+                ccc: g,
             },
         )
     }
@@ -210,64 +221,71 @@ impl Element for TerminalEl {
         cx: &mut gpui::PaintContext,
     ) -> Self::PaintState {
         //Setup element stuff
-        cx.scene.push_layer(Some(visible_bounds));
-
-        //Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
-        cx.scene.push_mouse_region(MouseRegion {
-            view_id: self.view.id(),
-            mouse_down: Some(Rc::new(|_, cx| cx.focus_parent_view())),
-            bounds: visible_bounds,
-            ..Default::default()
-        });
-
-        let origin = bounds.origin() + vec2f(layout.em_width.0, 0.);
-
-        //Start us off with a nice simple background color
-        cx.scene.push_layer(Some(visible_bounds));
-        cx.scene.push_quad(Quad {
-            bounds: RectF::new(bounds.origin(), bounds.size()),
-            background: Some(layout.background_color),
-            border: Default::default(),
-            corner_radius: 0.,
-        });
-
-        //Draw cell backgrounds
-        for background_rect in &layout.background_rects {
-            let new_origin = origin + background_rect.0.origin();
-            cx.scene.push_quad(Quad {
-                bounds: RectF::new(new_origin, background_rect.0.size()),
-                background: Some(background_rect.1),
-                border: Default::default(),
-                corner_radius: 0.,
-            })
-        }
-        cx.scene.pop_layer();
-
-        //Draw text
-        cx.scene.push_layer(Some(visible_bounds));
-        let mut line_origin = origin.clone();
-        for line in &layout.lines {
-            let boundaries = RectF::new(line_origin, vec2f(bounds.width(), layout.line_height.0));
-            if boundaries.intersects(visible_bounds) {
-                line.paint(line_origin, visible_bounds, layout.line_height.0, cx);
+        let clip_bounds = Some(visible_bounds);
+        paint_layer(cx, clip_bounds, |cx| {
+            //Elements are ephemeral, only at paint time do we know what could be clicked by a mouse
+            cx.scene.push_mouse_region(MouseRegion {
+                view_id: self.view.id(),
+                mouse_down: Some(Rc::new(|_, cx| cx.focus_parent_view())),
+                bounds: visible_bounds,
+                ..Default::default()
+            });
+
+            let origin = bounds.origin() + vec2f(layout.em_width.0, 0.);
+
+            paint_layer(cx, clip_bounds, |cx| {
+                layout.ccc.origin.set_x(visible_bounds.origin_x() + 20.);
+                layout.ccc.origin.set_y(visible_bounds.origin_y() + 20.);
+                cx.scene.push_glyph(layout.ccc)
+            });
+
+            //Start us off with a nice simple background color
+            paint_layer(cx, clip_bounds, |cx| {
+                cx.scene.push_quad(Quad {
+                    bounds: RectF::new(bounds.origin(), bounds.size()),
+                    background: Some(layout.background_color),
+                    border: Default::default(),
+                    corner_radius: 0.,
+                });
+
+                //Draw cell backgrounds
+                for background_rect in &layout.background_rects {
+                    let new_origin = origin + background_rect.0.origin();
+                    cx.scene.push_quad(Quad {
+                        bounds: RectF::new(new_origin, background_rect.0.size()),
+                        background: Some(background_rect.1),
+                        border: Default::default(),
+                        corner_radius: 0.,
+                    })
+                }
+            });
+
+            paint_layer(cx, clip_bounds, |cx| {
+                let mut line_origin = origin.clone();
+                for line in &layout.lines {
+                    let boundaries =
+                        RectF::new(line_origin, vec2f(bounds.width(), layout.line_height.0));
+                    if boundaries.intersects(visible_bounds) {
+                        line.paint(line_origin, visible_bounds, layout.line_height.0, cx);
+                    }
+                    line_origin.set_y(boundaries.max_y());
+                }
+            });
+
+            //Draw cursor
+            if let Some(cursor) = &layout.cursor {
+                paint_layer(cx, clip_bounds, |cx| {
+                    cursor.paint(origin, cx);
+                })
             }
-            line_origin.set_y(boundaries.max_y());
-        }
-        cx.scene.pop_layer();
-
-        //Draw cursor
-        if let Some(cursor) = &layout.cursor {
-            cx.scene.push_layer(Some(visible_bounds));
-            cursor.paint(origin, cx);
-            cx.scene.pop_layer();
-        }
-
-        #[cfg(debug_assertions)]
-        if DEBUG_GRID {
-            draw_debug_grid(bounds, layout, cx);
-        }
 
-        cx.scene.pop_layer();
+            #[cfg(debug_assertions)]
+            if DEBUG_GRID {
+                paint_layer(cx, clip_bounds, |cx| {
+                    draw_debug_grid(bounds, layout, cx);
+                });
+            }
+        });
     }
 
     fn dispatch_event(