Finish documenting GPUI

Mikayla created

Change summary

.github/actions/check_style/action.yml      |  1 
crates/gpui/src/keymap/matcher.rs           |  2 
crates/gpui/src/platform.rs                 |  2 
crates/gpui/src/platform/mac/text_system.rs |  4 -
crates/gpui/src/text_system.rs              |  2 
crates/gpui/src/text_system/line.rs         | 15 ++++++++
crates/gpui/src/text_system/line_layout.rs  | 40 +++++++++++++++++++++++
crates/gpui/src/text_system/line_wrapper.rs |  6 +++
crates/gpui/src/window.rs                   |  2 
crates/gpui/src/window/element_cx.rs        | 10 ++++-
10 files changed, 74 insertions(+), 10 deletions(-)

Detailed changes

.github/actions/check_style/action.yml 🔗

@@ -15,6 +15,7 @@ runs:
       # will have more fixes & suppression for the standard lint set
       run: |
         cargo clippy --workspace --all-features --all-targets -- -A clippy::all -D clippy::dbg_macro -D clippy::todo
+        cargo clippy -p gpui
 
     - name: Find modified migrations
       shell: bash -euxo pipefail {0}

crates/gpui/src/keymap/matcher.rs 🔗

@@ -72,7 +72,7 @@ impl KeystrokeMatcher {
             }
         }
 
-        if bindings.len() == 0 && pending_key.is_none() && self.pending_keystrokes.len() > 0 {
+        if bindings.is_empty() && pending_key.is_none() && !self.pending_keystrokes.is_empty() {
             drop(keymap);
             self.pending_keystrokes.remove(0);
             return self.match_keystroke(keystroke, context_stack);

crates/gpui/src/platform.rs 🔗

@@ -397,7 +397,7 @@ impl PlatformInputHandler {
         let Some(range) = self.handler.selected_text_range(cx) else {
             return;
         };
-        self.handler.replace_text_in_range(Some(range), &input, cx);
+        self.handler.replace_text_in_range(Some(range), input, cx);
     }
 }
 

crates/gpui/src/platform/mac/text_system.rs 🔗

@@ -225,9 +225,7 @@ impl MacTextSystemState {
     }
 
     fn glyph_for_char(&self, font_id: FontId, ch: char) -> Option<GlyphId> {
-        self.fonts[font_id.0]
-            .glyph_for_char(ch)
-            .map(|glyph_id| GlyphId(glyph_id))
+        self.fonts[font_id.0].glyph_for_char(ch).map(GlyphId)
     }
 
     fn id_for_native_font(&mut self, requested_font: CTFont) -> FontId {

crates/gpui/src/text_system.rs 🔗

@@ -172,7 +172,7 @@ impl TextSystem {
         self.read_metrics(font_id, |metrics| metrics.units_per_em)
     }
 
-    /// Get the height of a captial letter in the given font and size.
+    /// Get the height of a capital letter in the given font and size.
     pub fn cap_height(&self, font_id: FontId, font_size: Pixels) -> Pixels {
         self.read_metrics(font_id, |metrics| metrics.cap_height(font_size))
     }

crates/gpui/src/text_system/line.rs 🔗

@@ -6,19 +6,29 @@ use derive_more::{Deref, DerefMut};
 use smallvec::SmallVec;
 use std::sync::Arc;
 
+/// Set the text decoration for a run of text.
 #[derive(Debug, Clone)]
 pub struct DecorationRun {
+    /// The length of the run in utf-8 bytes.
     pub len: u32,
+
+    /// The color for this run
     pub color: Hsla,
+
+    /// The background color for this run
     pub background_color: Option<Hsla>,
+
+    /// The underline style for this run
     pub underline: Option<UnderlineStyle>,
 }
 
+/// A line of text that has been shaped and decorated.
 #[derive(Clone, Default, Debug, Deref, DerefMut)]
 pub struct ShapedLine {
     #[deref]
     #[deref_mut]
     pub(crate) layout: Arc<LineLayout>,
+    /// The text that was shaped for this line.
     pub text: SharedString,
     pub(crate) decoration_runs: SmallVec<[DecorationRun; 32]>,
 }
@@ -30,6 +40,7 @@ impl ShapedLine {
         self.layout.len
     }
 
+    /// Paint the line of text to the window.
     pub fn paint(
         &self,
         origin: Point<Pixels>,
@@ -49,21 +60,25 @@ impl ShapedLine {
     }
 }
 
+/// A line of text that has been shaped, decorated, and wrapped by the text layout system.
 #[derive(Clone, Default, Debug, Deref, DerefMut)]
 pub struct WrappedLine {
     #[deref]
     #[deref_mut]
     pub(crate) layout: Arc<WrappedLineLayout>,
+    /// The text that was shaped for this line.
     pub text: SharedString,
     pub(crate) decoration_runs: SmallVec<[DecorationRun; 32]>,
 }
 
 impl WrappedLine {
+    /// The length of the underlying, unwrapped layout, in utf-8 bytes.
     #[allow(clippy::len_without_is_empty)]
     pub fn len(&self) -> usize {
         self.layout.len()
     }
 
+    /// Paint this line of text to the window.
     pub fn paint(
         &self,
         origin: Point<Pixels>,

crates/gpui/src/text_system/line_layout.rs 🔗

@@ -8,31 +8,50 @@ use std::{
     sync::Arc,
 };
 
+/// A laid out and styled line of text
 #[derive(Default, Debug)]
 pub struct LineLayout {
+    /// The font size for this line
     pub font_size: Pixels,
+    /// The width of the line
     pub width: Pixels,
+    /// The ascent of the line
     pub ascent: Pixels,
+    /// The descent of the line
     pub descent: Pixels,
+    /// The shaped runs that make up this line
     pub runs: Vec<ShapedRun>,
+    /// The length of the line in utf-8 bytes
     pub len: usize,
 }
 
+/// A run of text that has been shaped .
 #[derive(Debug)]
 pub struct ShapedRun {
+    /// The font id for this run
     pub font_id: FontId,
+    /// The glyphs that make up this run
     pub glyphs: SmallVec<[ShapedGlyph; 8]>,
 }
 
+/// A single glyph, ready to paint.
 #[derive(Clone, Debug)]
 pub struct ShapedGlyph {
+    /// The ID for this glyph, as determined by the text system.
     pub id: GlyphId,
+
+    /// The position of this glyph in it's containing line.
     pub position: Point<Pixels>,
+
+    /// The index of this glyph in the original text.
     pub index: usize,
+
+    /// Whether this glyph is an emoji
     pub is_emoji: bool,
 }
 
 impl LineLayout {
+    /// The index for the character at the given x coordinate
     pub fn index_for_x(&self, x: Pixels) -> Option<usize> {
         if x >= self.width {
             None
@@ -71,6 +90,7 @@ impl LineLayout {
         self.len
     }
 
+    /// The x position of the character at the given index
     pub fn x_for_index(&self, index: usize) -> Pixels {
         for run in &self.runs {
             for glyph in &run.glyphs {
@@ -148,31 +168,44 @@ impl LineLayout {
     }
 }
 
+/// A line of text that has been wrapped to fit a given width
 #[derive(Default, Debug)]
 pub struct WrappedLineLayout {
+    /// The line layout, pre-wrapping.
     pub unwrapped_layout: Arc<LineLayout>,
+
+    /// The boundaries at which the line was wrapped
     pub wrap_boundaries: SmallVec<[WrapBoundary; 1]>,
+
+    /// The width of the line, if it was wrapped
     pub wrap_width: Option<Pixels>,
 }
 
+/// A boundary at which a line was wrapped
 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub struct WrapBoundary {
+    /// The index in the run just before the line was wrapped
     pub run_ix: usize,
+    /// The index of the glyph just before the line was wrapped
     pub glyph_ix: usize,
 }
 
 impl WrappedLineLayout {
+    /// The length of the underlying text, in utf8 bytes.
     #[allow(clippy::len_without_is_empty)]
     pub fn len(&self) -> usize {
         self.unwrapped_layout.len
     }
 
+    /// The width of this line, in pixels, whether or not it was wrapped.
     pub fn width(&self) -> Pixels {
         self.wrap_width
             .unwrap_or(Pixels::MAX)
             .min(self.unwrapped_layout.width)
     }
 
+    /// The size of the whole wrapped text, for the given line_height.
+    /// can span multiple lines if there are multiple wrap boundaries.
     pub fn size(&self, line_height: Pixels) -> Size<Pixels> {
         Size {
             width: self.width(),
@@ -180,26 +213,32 @@ impl WrappedLineLayout {
         }
     }
 
+    /// The ascent of a line in this layout
     pub fn ascent(&self) -> Pixels {
         self.unwrapped_layout.ascent
     }
 
+    /// The descent of a line in this layout
     pub fn descent(&self) -> Pixels {
         self.unwrapped_layout.descent
     }
 
+    /// The wrap boundaries in this layout
     pub fn wrap_boundaries(&self) -> &[WrapBoundary] {
         &self.wrap_boundaries
     }
 
+    /// The font size of this layout
     pub fn font_size(&self) -> Pixels {
         self.unwrapped_layout.font_size
     }
 
+    /// The runs in this layout, sans wrapping
     pub fn runs(&self) -> &[ShapedRun] {
         &self.unwrapped_layout.runs
     }
 
+    /// The index corresponding to a given position in this layout for the given line height.
     pub fn index_for_position(
         &self,
         position: Point<Pixels>,
@@ -377,6 +416,7 @@ impl LineLayoutCache {
     }
 }
 
+/// A run of text with a single font.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
 pub struct FontRun {
     pub(crate) len: usize,

crates/gpui/src/text_system/line_wrapper.rs 🔗

@@ -2,6 +2,7 @@ use crate::{px, FontId, FontRun, Pixels, PlatformTextSystem};
 use collections::HashMap;
 use std::{iter, sync::Arc};
 
+/// The GPUI line wrapper, used to wrap lines of text to a given width.
 pub struct LineWrapper {
     platform_text_system: Arc<dyn PlatformTextSystem>,
     pub(crate) font_id: FontId,
@@ -11,6 +12,7 @@ pub struct LineWrapper {
 }
 
 impl LineWrapper {
+    /// The maximum indent that can be applied to a line.
     pub const MAX_INDENT: u32 = 256;
 
     pub(crate) fn new(
@@ -27,6 +29,7 @@ impl LineWrapper {
         }
     }
 
+    /// Wrap a line of text to the given width with this wrapper's font and font size.
     pub fn wrap_line<'a>(
         &'a mut self,
         line: &'a str,
@@ -122,9 +125,12 @@ impl LineWrapper {
     }
 }
 
+/// A boundary between two lines of text.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 pub struct Boundary {
+    /// The index of the last character in a line
     pub ix: usize,
+    /// The indent of the next line.
     pub next_indent: u32,
 }
 

crates/gpui/src/window.rs 🔗

@@ -1257,7 +1257,7 @@ impl<'a> WindowContext<'a> {
             } else if let Some(currently_pending) = self.window.pending_input.take() {
                 if bindings
                     .iter()
-                    .all(|binding| !currently_pending.used_by_binding(&binding))
+                    .all(|binding| !currently_pending.used_by_binding(binding))
                 {
                     self.replay_pending_input(currently_pending)
                 }

crates/gpui/src/window/element_cx.rs 🔗

@@ -8,7 +8,7 @@
 //! The other main interface is the `paint_*` family of methods, which push basic drawing commands
 //! to the GPU. Everything in a GPUI app is drawn with these methods.
 //!
-//! There are also several internal methds that GPUI uses, such as [`ElementContext::with_element_state`]
+//! There are also several internal methods that GPUI uses, such as [`ElementContext::with_element_state`]
 //! to call the paint and layout methods on elements. These have been included as they're often useful
 //! for taking manual control of the layouting or painting of specialized elements.
 
@@ -733,6 +733,8 @@ impl<'a> ElementContext<'a> {
 
     /// Paint a monochrome (non-emoji) glyph into the scene for the next frame at the current z-index.
     /// The y component of the origin is the baseline of the glyph.
+    /// You should generally prefer to use the [`ShapedLine::paint`] or [`WrappedLine::paint`] methods in the [`text_system`].
+    /// This method is only useful if you need to paint a single glyph that has already been shaped.
     pub fn paint_glyph(
         &mut self,
         origin: Point<Pixels>,
@@ -790,6 +792,8 @@ impl<'a> ElementContext<'a> {
 
     /// Paint an emoji glyph into the scene for the next frame at the current z-index.
     /// The y component of the origin is the baseline of the glyph.
+    /// You should generally prefer to use the [`ShapedLine::paint`] or [`WrappedLine::paint`] methods in the [`text_system`].
+    /// This method is only useful if you need to paint a single emoji that has already been shaped.
     pub fn paint_emoji(
         &mut self,
         origin: Point<Pixels>,
@@ -1058,7 +1062,7 @@ impl<'a> ElementContext<'a> {
         let text_system = self.text_system().clone();
         text_system.with_view(view_id, || {
             if self.window.next_frame.view_stack.last() == Some(&view_id) {
-                return f(self);
+                f(self)
             } else {
                 self.window.next_frame.view_stack.push(view_id);
                 let result = f(self);
@@ -1074,7 +1078,7 @@ impl<'a> ElementContext<'a> {
         let text_system = self.text_system().clone();
         text_system.with_view(view_id, || {
             if self.window.next_frame.view_stack.last() == Some(&view_id) {
-                return f(self);
+                f(self)
             } else {
                 self.window.next_frame.view_stack.push(view_id);
                 self.window