Fix overlapping block headers when using custom line height (#4071)

Thorsten Ball created

This fixes block headers overlapping over text in the buffer when using
a custom line height of 1.25.

It fixes the issue by making the parent container a v-flex,
vertically-justifying the content and moving from relative padding to
absolute padding for the header itself.

## Before/After

With setting:
```json
  "buffer_line_height": {
    "custom": 1.25
  },
```

### Before

![screenshot-2024-01-16-16 48
48@2x](https://github.com/zed-industries/zed/assets/1185253/8c3b977e-333f-403c-a4d3-0911f3fac5e0)

### After

![screenshot-2024-01-16-16 50
13@2x](https://github.com/zed-industries/zed/assets/1185253/2d854eba-c4c4-4bce-b60b-dd250856b08f)

### Release notes
Release Notes:

- Fixed headers in multi-buffers overlapping over content of the buffer

Change summary

crates/editor/src/element.rs        | 14 +++--
crates/search/src/project_search.rs | 67 +++++++++++++++---------------
2 files changed, 42 insertions(+), 39 deletions(-)

Detailed changes

crates/editor/src/element.rs 🔗

@@ -2288,17 +2288,18 @@ impl EditorElement {
                                 .map(|p| SharedString::from(p.to_string_lossy().to_string() + "/"));
                         }
 
-                        div()
+                        v_flex()
                             .id(("path header container", block_id))
                             .size_full()
-                            .p_1p5()
+                            .justify_center()
+                            .p(gpui::px(6.))
                             .child(
                                 h_flex()
                                     .id("path header block")
-                                    .py_1p5()
-                                    .pl_3()
-                                    .pr_2()
-                                    .rounded_lg()
+                                    .size_full()
+                                    .pl(gpui::px(12.))
+                                    .pr(gpui::px(8.))
+                                    .rounded_md()
                                     .shadow_md()
                                     .border()
                                     .border_color(cx.theme().colors().border)
@@ -2861,6 +2862,7 @@ impl Element for EditorElement {
             cx.with_text_style(
                 Some(gpui::TextStyleRefinement {
                     font_size: Some(self.style.text.font_size),
+                    line_height: Some(self.style.text.line_height),
                     ..Default::default()
                 }),
                 |cx| {

crates/search/src/project_search.rs 🔗

@@ -282,6 +282,8 @@ impl EventEmitter<ViewEvent> for ProjectSearchView {}
 
 impl Render for ProjectSearchView {
     fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
+        const PLEASE_AUTHENTICATE: &str = "API Key Missing: Please set 'OPENAI_API_KEY' in Environment Variables. If you authenticated using the Assistant Panel, please restart Zed to Authenticate.";
+
         if self.has_matches() {
             div()
                 .flex_1()
@@ -303,40 +305,39 @@ impl Render for ProjectSearchView {
             let mut show_minor_text = true;
             let semantic_status = self.semantic_state.as_ref().and_then(|semantic| {
                 let status = semantic.index_status;
-                                match status {
-                                    SemanticIndexStatus::NotAuthenticated => {
-                                        major_text = Label::new("Not Authenticated");
-                                        show_minor_text = false;
-                                        Some(
-                                            "API Key Missing: Please set 'OPENAI_API_KEY' in Environment Variables. If you authenticated using the Assistant Panel, please restart Zed to Authenticate.".to_string())
-                                    }
-                                    SemanticIndexStatus::Indexed => Some("Indexing complete".to_string()),
-                                    SemanticIndexStatus::Indexing {
-                                        remaining_files,
-                                        rate_limit_expiry,
-                                    } => {
-                                        if remaining_files == 0 {
-                                            Some("Indexing...".to_string())
-                                        } else {
-                                            if let Some(rate_limit_expiry) = rate_limit_expiry {
-                                                let remaining_seconds =
-                                                    rate_limit_expiry.duration_since(Instant::now());
-                                                if remaining_seconds > Duration::from_secs(0) {
-                                                    Some(format!(
-                                                        "Remaining files to index (rate limit resets in {}s): {}",
-                                                        remaining_seconds.as_secs(),
-                                                        remaining_files
-                                                    ))
-                                                } else {
-                                                    Some(format!("Remaining files to index: {}", remaining_files))
-                                                }
-                                            } else {
-                                                Some(format!("Remaining files to index: {}", remaining_files))
-                                            }
-                                        }
-                                    }
-                                    SemanticIndexStatus::NotIndexed => None,
+                match status {
+                    SemanticIndexStatus::NotAuthenticated => {
+                        major_text = Label::new("Not Authenticated");
+                        show_minor_text = false;
+                        Some(PLEASE_AUTHENTICATE.to_string())
+                    }
+                    SemanticIndexStatus::Indexed => Some("Indexing complete".to_string()),
+                    SemanticIndexStatus::Indexing {
+                        remaining_files,
+                        rate_limit_expiry,
+                    } => {
+                        if remaining_files == 0 {
+                            Some("Indexing...".to_string())
+                        } else {
+                            if let Some(rate_limit_expiry) = rate_limit_expiry {
+                                let remaining_seconds =
+                                    rate_limit_expiry.duration_since(Instant::now());
+                                if remaining_seconds > Duration::from_secs(0) {
+                                    Some(format!(
+                                        "Remaining files to index (rate limit resets in {}s): {}",
+                                        remaining_seconds.as_secs(),
+                                        remaining_files
+                                    ))
+                                } else {
+                                    Some(format!("Remaining files to index: {}", remaining_files))
                                 }
+                            } else {
+                                Some(format!("Remaining files to index: {}", remaining_files))
+                            }
+                        }
+                    }
+                    SemanticIndexStatus::NotIndexed => None,
+                }
             });
             let major_text = div().justify_center().max_w_96().child(major_text);