Add an element to pane to take care of wiring initial mouse handlers

Mikayla Maki created

Change summary

crates/gpui/src/elements/flex.rs |  30 +++--
crates/welcome/src/welcome.rs    | 154 +++++++++++++++------------------
crates/workspace/src/pane.rs     |  91 +++++++++++++++++++
3 files changed, 175 insertions(+), 100 deletions(-)

Detailed changes

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

@@ -324,20 +324,24 @@ impl Element for Flex {
             // overall flex element and each child. We then align these points. So 0 would center
             // each child relative to the overall height/width of the flex. -1 puts children at
             // the start. 1 puts children at the end.
-            let cross_axis = self.axis.invert();
-            let my_center = bounds.size().along(cross_axis) / 2.;
-            let my_target = my_center + my_center * self.child_alignment;
-
-            let child_center = child.size().along(cross_axis) / 2.;
-            let child_target = child_center + child_center * self.child_alignment;
+            let aligned_child_origin = {
+                let cross_axis = self.axis.invert();
+                let my_center = bounds.size().along(cross_axis) / 2.;
+                let my_target = my_center + my_center * self.child_alignment;
+
+                let child_center = child.size().along(cross_axis) / 2.;
+                let child_target = child_center + child_center * self.child_alignment;
+
+                let mut aligned_child_origin = child_origin;
+                match self.axis {
+                    Axis::Horizontal => aligned_child_origin
+                        .set_y(aligned_child_origin.y() - (child_target - my_target)),
+                    Axis::Vertical => aligned_child_origin
+                        .set_x(aligned_child_origin.x() - (child_target - my_target)),
+                }
 
-            let mut aligned_child_origin = child_origin;
-            match self.axis {
-                Axis::Horizontal => aligned_child_origin
-                    .set_y(aligned_child_origin.y() - (child_target - my_target)),
-                Axis::Vertical => aligned_child_origin
-                    .set_x(aligned_child_origin.x() - (child_target - my_target)),
-            }
+                aligned_child_origin
+            };
 
             child.paint(aligned_child_origin, visible_bounds, cx);
 

crates/welcome/src/welcome.rs 🔗

@@ -1,14 +1,13 @@
 use std::borrow::Cow;
 
 use gpui::{
-    elements::{Canvas, Empty, Flex, Image, Label, MouseEventHandler, ParentElement, Stack, Svg},
-    geometry::rect::RectF,
-    Action, Element, ElementBox, Entity, MouseButton, MouseRegion, MutableAppContext,
-    RenderContext, Subscription, View, ViewContext,
+    elements::{Empty, Flex, Image, Label, MouseEventHandler, ParentElement, Svg},
+    Action, Element, ElementBox, Entity, MouseButton, MutableAppContext, RenderContext,
+    Subscription, View, ViewContext,
 };
 use settings::{settings_file::SettingsFile, Settings, SettingsFileContent};
 use theme::CheckboxStyle;
-use workspace::{item::Item, Welcome, Workspace};
+use workspace::{item::Item, PaneBackdrop, Welcome, Workspace, WorkspaceId};
 
 pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(|workspace: &mut Workspace, _: &Welcome, cx| {
@@ -43,89 +42,67 @@ impl View for WelcomePage {
         enum Metrics {}
         enum Diagnostics {}
 
-        let background = theme.editor.background;
-
-        Stack::new()
-            .with_child(
-                // TODO: Can this be moved into the pane?
-                Canvas::new(move |bounds, visible_bounds, cx| {
-                    let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
-
-                    cx.paint_layer(Some(visible_bounds), |cx| {
-                        cx.scene.push_quad(gpui::Quad {
-                            bounds: RectF::new(bounds.origin(), bounds.size()),
-                            background: Some(background),
-                            ..Default::default()
-                        })
-                    });
-
-                    cx.scene.push_mouse_region(
-                        MouseRegion::new::<Self>(self_handle.id(), 0, visible_bounds)
-                            .on_down(gpui::MouseButton::Left, |_, cx| cx.focus_parent_view()),
-                    );
-                })
-                .boxed(),
-            )
-            .with_child(
-                Flex::column()
-                    .with_children([
-                        Flex::row()
-                            .with_children([
-                                Image::new("images/zed-logo-90x90.png")
-                                    .constrained()
-                                    .with_width(90.)
-                                    .with_height(90.)
-                                    .aligned()
-                                    .contained()
-                                    .boxed(),
-                                // Label::new("Zed", theme.editor.hover_popover.prose.clone()).boxed(),
-                            ])
-                            .boxed(),
-                        Label::new(
-                            "Code at the speed of thought",
-                            theme.editor.hover_popover.prose.clone(),
-                        )
-                        .boxed(),
-                        self.render_cta_button(2, "Choose a theme", theme_selector::Toggle, cx),
-                        self.render_cta_button(3, "Choose a keymap", theme_selector::Toggle, cx),
-                        Flex::row()
-                            .with_children([
-                                self.render_settings_checkbox::<Metrics>(
-                                    &theme.welcome.checkbox,
-                                    metrics,
-                                    cx,
-                                    |content, checked| {
-                                        content.telemetry.set_metrics(checked);
-                                    },
-                                ),
-                                Label::new(
-                                    "Do you want to send telemetry?",
-                                    theme.editor.hover_popover.prose.clone(),
-                                )
+        PaneBackdrop::new(
+            self_handle.id(),
+            Flex::column()
+                .with_children([
+                    Flex::row()
+                        .with_children([
+                            Image::new("images/zed-logo-90x90.png")
+                                .constrained()
+                                .with_width(90.)
+                                .with_height(90.)
+                                .aligned()
+                                .contained()
                                 .boxed(),
-                            ])
-                            .align_children_center()
+                            // Label::new("Zed", theme.editor.hover_popover.prose.clone()).boxed(),
+                        ])
+                        .boxed(),
+                    Label::new(
+                        "Code at the speed of thought",
+                        theme.editor.hover_popover.prose.clone(),
+                    )
+                    .boxed(),
+                    self.render_cta_button(2, "Choose a theme", theme_selector::Toggle, cx),
+                    self.render_cta_button(3, "Choose a keymap", theme_selector::Toggle, cx),
+                    Flex::row()
+                        .with_children([
+                            self.render_settings_checkbox::<Metrics>(
+                                &theme.welcome.checkbox,
+                                metrics,
+                                cx,
+                                |content, checked| {
+                                    content.telemetry.set_metrics(checked);
+                                },
+                            ),
+                            Label::new(
+                                "Do you want to send telemetry?",
+                                theme.editor.hover_popover.prose.clone(),
+                            )
                             .boxed(),
-                        Flex::row()
-                            .with_children([
-                                self.render_settings_checkbox::<Diagnostics>(
-                                    &theme.welcome.checkbox,
-                                    diagnostics,
-                                    cx,
-                                    |content, checked| content.telemetry.set_diagnostics(checked),
-                                ),
-                                Label::new(
-                                    "Send crash reports",
-                                    theme.editor.hover_popover.prose.clone(),
-                                )
-                                .boxed(),
-                            ])
-                            .align_children_center()
+                        ])
+                        .align_children_center()
+                        .boxed(),
+                    Flex::row()
+                        .with_children([
+                            self.render_settings_checkbox::<Diagnostics>(
+                                &theme.welcome.checkbox,
+                                diagnostics,
+                                cx,
+                                |content, checked| content.telemetry.set_diagnostics(checked),
+                            ),
+                            Label::new(
+                                "Send crash reports",
+                                theme.editor.hover_popover.prose.clone(),
+                            )
                             .boxed(),
-                    ])
-                    .boxed(),
-            )
-            .boxed()
+                        ])
+                        .align_children_center()
+                        .boxed(),
+                ])
+                .boxed(),
+        )
+        .boxed()
     }
 }
 
@@ -232,4 +209,11 @@ impl Item for WelcomePage {
     fn show_toolbar(&self) -> bool {
         false
     }
+    fn clone_on_split(
+        &self,
+        _workspace_id: WorkspaceId,
+        cx: &mut ViewContext<Self>,
+    ) -> Option<Self> {
+        Some(WelcomePage::new(cx))
+    }
 }

crates/workspace/src/pane.rs 🔗

@@ -24,8 +24,8 @@ use gpui::{
     keymap_matcher::KeymapContext,
     platform::{CursorStyle, NavigationDirection},
     Action, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity, EventContext,
-    ModelHandle, MouseButton, MutableAppContext, PromptLevel, Quad, RenderContext, Task, View,
-    ViewContext, ViewHandle, WeakViewHandle,
+    ModelHandle, MouseButton, MouseRegion, MutableAppContext, PromptLevel, Quad, RenderContext,
+    Task, View, ViewContext, ViewHandle, WeakViewHandle,
 };
 use project::{Project, ProjectEntryId, ProjectPath};
 use serde::Deserialize;
@@ -1706,6 +1706,93 @@ impl NavHistory {
     }
 }
 
+pub struct PaneBackdrop {
+    child_view: usize,
+    child: ElementBox,
+}
+impl PaneBackdrop {
+    pub fn new(pane_item_view: usize, child: ElementBox) -> Self {
+        PaneBackdrop {
+            child,
+            child_view: pane_item_view,
+        }
+    }
+}
+
+impl Element for PaneBackdrop {
+    type LayoutState = ();
+
+    type PaintState = ();
+
+    fn layout(
+        &mut self,
+        constraint: gpui::SizeConstraint,
+        cx: &mut gpui::LayoutContext,
+    ) -> (Vector2F, Self::LayoutState) {
+        let size = self.child.layout(constraint, cx);
+        (size, ())
+    }
+
+    fn paint(
+        &mut self,
+        bounds: RectF,
+        visible_bounds: RectF,
+        _: &mut Self::LayoutState,
+        cx: &mut gpui::PaintContext,
+    ) -> Self::PaintState {
+        let background = cx.global::<Settings>().theme.editor.background;
+
+        let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
+
+        cx.scene.push_quad(gpui::Quad {
+            bounds: RectF::new(bounds.origin(), bounds.size()),
+            background: Some(background),
+            ..Default::default()
+        });
+
+        let child_view_id = self.child_view;
+        cx.scene.push_mouse_region(
+            MouseRegion::new::<Self>(child_view_id, 0, visible_bounds).on_down(
+                gpui::MouseButton::Left,
+                move |_, cx| {
+                    let window_id = cx.window_id;
+                    cx.focus(window_id, Some(child_view_id))
+                },
+            ),
+        );
+
+        cx.paint_layer(Some(bounds), |cx| {
+            self.child.paint(bounds.origin(), visible_bounds, cx)
+        })
+    }
+
+    fn rect_for_text_range(
+        &self,
+        range_utf16: std::ops::Range<usize>,
+        _bounds: RectF,
+        _visible_bounds: RectF,
+        _layout: &Self::LayoutState,
+        _paint: &Self::PaintState,
+        cx: &gpui::MeasurementContext,
+    ) -> Option<RectF> {
+        self.child.rect_for_text_range(range_utf16, cx)
+    }
+
+    fn debug(
+        &self,
+        _bounds: RectF,
+        _layout: &Self::LayoutState,
+        _paint: &Self::PaintState,
+        cx: &gpui::DebugContext,
+    ) -> serde_json::Value {
+        gpui::json::json!({
+            "type": "Pane Back Drop",
+            "view": self.child_view,
+            "child": self.child.debug(cx),
+        })
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use std::sync::Arc;