Scale diagnostic header and message text with editor font

Max Brunsfeld and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

crates/diagnostics/src/diagnostics.rs | 25 ++++++----
crates/editor/src/editor.rs           | 22 ++++++---
crates/editor/src/element.rs          |  2 
crates/gpui/src/elements/label.rs     |  7 +++
crates/gpui/src/fonts.rs              |  5 ++
crates/theme/src/theme.rs             |  6 ++
crates/zed/assets/themes/_base.toml   | 65 ++++++++++++++--------------
7 files changed, 82 insertions(+), 50 deletions(-)

Detailed changes

crates/diagnostics/src/diagnostics.rs 🔗

@@ -654,6 +654,7 @@ fn path_header_renderer(buffer: ModelHandle<Buffer>, build_settings: BuildSettin
     Arc::new(move |cx| {
         let settings = build_settings(cx);
         let style = settings.style.diagnostic_path_header;
+        let font_size = (style.text_scale_factor * settings.style.text.font_size).round();
 
         let mut filename = None;
         let mut path = None;
@@ -672,14 +673,14 @@ fn path_header_renderer(buffer: ModelHandle<Buffer>, build_settings: BuildSettin
             .with_child(
                 Label::new(
                     filename.unwrap_or_else(|| "untitled".to_string()),
-                    style.filename.text.clone(),
+                    style.filename.text.clone().with_font_size(font_size),
                 )
                 .contained()
                 .with_style(style.filename.container)
                 .boxed(),
             )
             .with_children(path.map(|path| {
-                Label::new(path, style.path.text.clone())
+                Label::new(path, style.path.text.clone().with_font_size(font_size))
                     .contained()
                     .with_style(style.path.container)
                     .boxed()
@@ -702,6 +703,7 @@ fn diagnostic_header_renderer(
     Arc::new(move |cx| {
         let settings = build_settings(cx);
         let style = &settings.style.diagnostic_header;
+        let font_size = (style.text_scale_factor * settings.style.text.font_size).round();
         let icon_width = cx.em_width * style.icon_width_factor;
         let icon = if diagnostic.severity == DiagnosticSeverity::ERROR {
             Svg::new("icons/diagnostic-error-10.svg")
@@ -720,16 +722,19 @@ fn diagnostic_header_renderer(
                     .boxed(),
             )
             .with_child(
-                Label::new(message.clone(), style.message.label.clone())
-                    .with_highlights(highlights.clone())
-                    .contained()
-                    .with_style(style.message.container)
-                    .with_margin_left(cx.gutter_padding)
-                    .aligned()
-                    .boxed(),
+                Label::new(
+                    message.clone(),
+                    style.message.label.clone().with_font_size(font_size),
+                )
+                .with_highlights(highlights.clone())
+                .contained()
+                .with_style(style.message.container)
+                .with_margin_left(cx.gutter_padding)
+                .aligned()
+                .boxed(),
             )
             .with_children(diagnostic.code.clone().map(|code| {
-                Label::new(code, style.code.text.clone())
+                Label::new(code, style.code.text.clone().with_font_size(font_size))
                     .contained()
                     .with_style(style.code.container)
                     .aligned()

crates/editor/src/editor.rs 🔗

@@ -3828,6 +3828,7 @@ impl EditorSettings {
                 let default_diagnostic_style = DiagnosticStyle {
                     message: text.clone().into(),
                     header: Default::default(),
+                    text_scale_factor: 1.,
                 };
                 EditorStyle {
                     text: text.clone(),
@@ -3852,6 +3853,7 @@ impl EditorSettings {
                             container: Default::default(),
                             text: text.clone(),
                         },
+                        text_scale_factor: 1.,
                     },
                     diagnostic_header: DiagnosticHeader {
                         container: Default::default(),
@@ -3863,7 +3865,8 @@ impl EditorSettings {
                             container: Default::default(),
                             text: text.clone(),
                         },
-                        icon_width_factor: Default::default(),
+                        icon_width_factor: 1.,
+                        text_scale_factor: 1.,
                     },
                     error_diagnostic: default_diagnostic_style.clone(),
                     invalid_error_diagnostic: default_diagnostic_style.clone(),
@@ -4020,14 +4023,18 @@ pub fn diagnostic_block_renderer(
 
     Arc::new(move |cx: &BlockContext| {
         let settings = build_settings(cx);
-        let style = diagnostic_style(diagnostic.severity, is_valid, &settings.style).message;
+        let style = diagnostic_style(diagnostic.severity, is_valid, &settings.style);
+        let font_size = (style.text_scale_factor * settings.style.text.font_size).round();
         Flex::column()
             .with_children(highlighted_lines.iter().map(|(line, highlights)| {
-                Label::new(line.clone(), style.clone())
-                    .with_highlights(highlights.clone())
-                    .contained()
-                    .with_margin_left(cx.anchor_x)
-                    .boxed()
+                Label::new(
+                    line.clone(),
+                    style.message.clone().with_font_size(font_size),
+                )
+                .with_highlights(highlights.clone())
+                .contained()
+                .with_margin_left(cx.anchor_x)
+                .boxed()
             }))
             .aligned()
             .left()
@@ -4074,6 +4081,7 @@ pub fn diagnostic_style(
         _ => DiagnosticStyle {
             message: style.text.clone().into(),
             header: Default::default(),
+            text_scale_factor: 1.,
         },
     }
 }

crates/editor/src/element.rs 🔗

@@ -649,7 +649,7 @@ impl Element for EditorElement {
 
         let snapshot = self.snapshot(cx.app);
         let style = self.settings.style.clone();
-        let line_height = dbg!(style.text.line_height(cx.font_cache));
+        let line_height = style.text.line_height(cx.font_cache);
 
         let gutter_padding;
         let gutter_width;

crates/gpui/src/elements/label.rs 🔗

@@ -33,6 +33,13 @@ impl From<TextStyle> for LabelStyle {
     }
 }
 
+impl LabelStyle {
+    pub fn with_font_size(mut self, font_size: f32) -> Self {
+        self.text.font_size = font_size;
+        self
+    }
+}
+
 impl Label {
     pub fn new(text: String, style: impl Into<LabelStyle>) -> Self {
         Self {

crates/gpui/src/fonts.rs 🔗

@@ -107,6 +107,11 @@ impl TextStyle {
         })
     }
 
+    pub fn with_font_size(mut self, font_size: f32) -> Self {
+        self.font_size = font_size;
+        self
+    }
+
     pub fn to_run(&self) -> RunStyle {
         RunStyle {
             font_id: self.font_id,

crates/theme/src/theme.rs 🔗

@@ -270,6 +270,7 @@ pub struct DiagnosticPathHeader {
     pub container: ContainerStyle,
     pub filename: ContainedText,
     pub path: ContainedText,
+    pub text_scale_factor: f32,
 }
 
 #[derive(Clone, Deserialize, Default)]
@@ -278,6 +279,7 @@ pub struct DiagnosticHeader {
     pub container: ContainerStyle,
     pub message: ContainedLabel,
     pub code: ContainedText,
+    pub text_scale_factor: f32,
     pub icon_width_factor: f32,
 }
 
@@ -286,6 +288,7 @@ pub struct DiagnosticStyle {
     pub message: LabelStyle,
     #[serde(default)]
     pub header: ContainerStyle,
+    pub text_scale_factor: f32,
 }
 
 #[derive(Clone, Copy, Default, Deserialize)]
@@ -324,6 +327,7 @@ impl InputEditorStyle {
         let default_diagnostic_style = DiagnosticStyle {
             message: self.text.clone().into(),
             header: Default::default(),
+            text_scale_factor: 1.,
         };
         EditorStyle {
             text: self.text.clone(),
@@ -351,6 +355,7 @@ impl InputEditorStyle {
                     container: Default::default(),
                     text: self.text.clone(),
                 },
+                text_scale_factor: 1.,
             },
             diagnostic_header: DiagnosticHeader {
                 container: Default::default(),
@@ -363,6 +368,7 @@ impl InputEditorStyle {
                     text: self.text.clone(),
                 },
                 icon_width_factor: Default::default(),
+                text_scale_factor: 1.,
             },
             error_diagnostic: default_diagnostic_style.clone(),
             invalid_error_diagnostic: default_diagnostic_style.clone(),

crates/zed/assets/themes/_base.toml 🔗

@@ -187,7 +187,7 @@ corner_radius = 6
 
 [project_panel]
 extends = "$panel"
-padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
+padding.top = 6    # ($workspace.tab.height - $project_panel.entry.height) / 2
 
 [project_panel.entry]
 text = "$text.1"
@@ -256,12 +256,14 @@ error_color = "$status.bad"
 [editor.diagnostic_path_header]
 filename = { extends = "$text.0", size = 14 }
 path = { extends = "$text.2", size = 14, margin.left = 12 }
+text_scale_factor = 0.857
 
 [editor.diagnostic_header]
 background = "$state.active_line"
 border = { width = 1, top = true, bottom = true, color = "$border.0" }
 code = { extends = "$text.2", size = 14, margin.left = 10 }
 icon_width_factor = 1.5
+text_scale_factor = 0.857
 
 [editor.diagnostic_header.message]
 text = { extends = "$text.1", size = 14 }
@@ -269,47 +271,46 @@ highlight_text = { extends = "$text.0", size = 14, weight = "bold" }
 
 [editor.error_diagnostic]
 header.border = { width = 1, top = true, color = "$border.0" }
+text_scale_factor = 0.857
 
 [editor.error_diagnostic.message]
 text = { extends = "$editor.text", size = 14, color = "$status.bad" }
 highlight_text = { extends = "$editor.text", size = 14, color = "$status.bad", weight = "bold" }
 
 [editor.warning_diagnostic]
-header.border = { width = 1, top = true, color = "$border.0" }
-
-[editor.warning_diagnostic.message]
-text = { extends = "$editor.text", size = 14, color = "$status.warn" }
-highlight_text = { extends = "$editor.text", size = 14, color = "$status.warn", weight = "bold" }
+extends = "$editor.error_diagnostic"
+message.text.color = "$status.warn"
+message.highlight_text.color = "$status.warn"
 
 [editor.information_diagnostic]
-border = { width = 1, top = true, color = "$border.0" }
-
-[editor.information_diagnostic.message]
-text = { extends = "$editor.text", size = 14, color = "$status.info" }
-highlight_text = { extends = "$editor.text", size = 14, color = "$status.info", weight = "bold" }
+extends = "$editor.error_diagnostic"
+message.text.color = "$status.info"
+message.highlight_text.color = "$status.info"
 
 [editor.hint_diagnostic]
-border = { width = 1, top = true, color = "$border.0" }
-
-[editor.hint_diagnostic.message]
-text = { extends = "$editor.text", size = 14, color = "$status.info" }
-highlight_text = { extends = "$editor.text", size = 14, color = "$status.info", weight = "bold" }
-
-[editor.invalid_error_diagnostic.message]
-text = { extends = "$editor.text", size = 14, color = "$text.3.color" }
-highlight_text = { extends = "$editor.text", size = 14, color = "$text.3.color", weight = "bold" }
-
-[editor.invalid_warning_diagnostic.message]
-text = { extends = "$editor.text", size = 14, color = "$text.3.color" }
-highlight_text = { extends = "$editor.text", size = 14, color = "$text.3.color", weight = "bold" }
-
-[editor.invalid_information_diagnostic.message]
-text = { extends = "$editor.text", size = 14, color = "$text.3.color" }
-highlight_text = { extends = "$editor.text", size = 14, color = "$text.3.color", weight = "bold" }
-
-[editor.invalid_hint_diagnostic.message]
-text = { extends = "$editor.text", size = 14, color = "$text.3.color" }
-highlight_text = { extends = "$editor.text", size = 14, color = "$text.3.color", weight = "bold" }
+extends = "$editor.error_diagnostic"
+message.text.color = "$status.info"
+message.highlight_text.color = "$status.info"
+
+[editor.invalid_error_diagnostic]
+extends = "$editor.error_diagnostic"
+message.text.color = "$text.3.color"
+message.highlight_text.color = "$text.3.color"
+
+[editor.invalid_warning_diagnostic]
+extends = "$editor.warning_diagnostic"
+message.text.color = "$text.3.color"
+message.highlight_text.color = "$text.3.color"
+
+[editor.invalid_information_diagnostic]
+extends = "$editor.information_diagnostic"
+message.text.color = "$text.3.color"
+message.highlight_text.color = "$text.3.color"
+
+[editor.invalid_hint_diagnostic]
+extends = "$editor.hint_diagnostic"
+message.text.color = "$text.3.color"
+message.highlight_text.color = "$text.3.color"
 
 [project_diagnostics]
 background = "$surface.1"