WIP

Nathan Sobo created

Change summary

crates/collab_ui2/src/face_pile.rs       |  2 
crates/gpui2/src/elements/div.rs         | 65 ++++++++++++++++++++------
crates/gpui2/src/style.rs                |  2 
crates/gpui2/src/styled.rs               |  2 
crates/gpui2/src/window.rs               | 24 ++++++---
crates/storybook2/src/stories/z_index.rs |  4 
crates/ui2/src/styles/elevation.rs       | 12 ++--
crates/workspace2/src/modal_layer.rs     |  2 
8 files changed, 77 insertions(+), 36 deletions(-)

Detailed changes

crates/collab_ui2/src/face_pile.rs 🔗

@@ -17,7 +17,7 @@ impl RenderOnce for FacePile {
             let isnt_last = ix < player_count - 1;
 
             div()
-                .z_index((player_count - ix) as u32)
+                .z_index((player_count - ix) as u8)
                 .when(isnt_last, |div| div.neg_mr_1())
                 .child(player)
         });

crates/gpui2/src/elements/div.rs 🔗

@@ -646,7 +646,10 @@ pub struct DivState {
 
 impl DivState {
     pub fn is_active(&self) -> bool {
-        self.interactive_state.pending_mouse_down.borrow().is_some()
+        self.interactive_state
+            .pending_mouse_down
+            .as_ref()
+            .map_or(false, |pending| pending.borrow().is_some())
     }
 }
 
@@ -872,11 +875,17 @@ impl Interactivity {
         let drag_listener = self.drag_listener;
 
         if !click_listeners.is_empty() || drag_listener.is_some() {
-            let pending_mouse_down = element_state.pending_mouse_down.clone();
+            let pending_mouse_down = element_state
+                .pending_mouse_down
+                .get_or_insert_with(Default::default)
+                .clone();
             let mouse_down = pending_mouse_down.borrow().clone();
             if let Some(mouse_down) = mouse_down {
                 if let Some(drag_listener) = drag_listener {
-                    let active_state = element_state.clicked_state.clone();
+                    let active_state = element_state
+                        .clicked_state
+                        .get_or_insert_with(Default::default)
+                        .clone();
                     let interactive_bounds = interactive_bounds.clone();
 
                     cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
@@ -929,8 +938,14 @@ impl Interactivity {
         }
 
         if let Some(hover_listener) = self.hover_listener.take() {
-            let was_hovered = element_state.hover_state.clone();
-            let has_mouse_down = element_state.pending_mouse_down.clone();
+            let was_hovered = element_state
+                .hover_state
+                .get_or_insert_with(Default::default)
+                .clone();
+            let has_mouse_down = element_state
+                .pending_mouse_down
+                .get_or_insert_with(Default::default)
+                .clone();
             let interactive_bounds = interactive_bounds.clone();
 
             cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
@@ -951,8 +966,14 @@ impl Interactivity {
         }
 
         if let Some(tooltip_builder) = self.tooltip_builder.take() {
-            let active_tooltip = element_state.active_tooltip.clone();
-            let pending_mouse_down = element_state.pending_mouse_down.clone();
+            let active_tooltip = element_state
+                .active_tooltip
+                .get_or_insert_with(Default::default)
+                .clone();
+            let pending_mouse_down = element_state
+                .pending_mouse_down
+                .get_or_insert_with(Default::default)
+                .clone();
             let interactive_bounds = interactive_bounds.clone();
 
             cx.on_mouse_event(move |event: &MouseMoveEvent, phase, cx| {
@@ -994,19 +1015,30 @@ impl Interactivity {
                 }
             });
 
-            let active_tooltip = element_state.active_tooltip.clone();
+            let active_tooltip = element_state
+                .active_tooltip
+                .get_or_insert_with(Default::default)
+                .clone();
             cx.on_mouse_event(move |_: &MouseDownEvent, _, _| {
                 active_tooltip.borrow_mut().take();
             });
 
-            if let Some(active_tooltip) = element_state.active_tooltip.borrow().as_ref() {
+            if let Some(active_tooltip) = element_state
+                .active_tooltip
+                .get_or_insert_with(Default::default)
+                .borrow()
+                .as_ref()
+            {
                 if active_tooltip.tooltip.is_some() {
                     cx.active_tooltip = active_tooltip.tooltip.clone()
                 }
             }
         }
 
-        let active_state = element_state.clicked_state.clone();
+        let active_state = element_state
+            .clicked_state
+            .get_or_insert_with(Default::default)
+            .clone();
         if active_state.borrow().is_clicked() {
             cx.on_mouse_event(move |_: &MouseUpEvent, phase, cx| {
                 if phase == DispatchPhase::Capture {
@@ -1180,7 +1212,10 @@ impl Interactivity {
             }
         }
 
-        let clicked_state = element_state.clicked_state.borrow();
+        let clicked_state = element_state
+            .clicked_state
+            .get_or_insert_with(Default::default)
+            .borrow();
         if clicked_state.group {
             if let Some(group) = self.group_active_style.as_ref() {
                 style.refine(&group.style)
@@ -1235,11 +1270,11 @@ impl Default for Interactivity {
 #[derive(Default)]
 pub struct InteractiveElementState {
     pub focus_handle: Option<FocusHandle>,
-    pub clicked_state: Rc<RefCell<ElementClickedState>>,
-    pub hover_state: Rc<RefCell<bool>>,
-    pub pending_mouse_down: Rc<RefCell<Option<MouseDownEvent>>>,
+    pub clicked_state: Option<Rc<RefCell<ElementClickedState>>>,
+    pub hover_state: Option<Rc<RefCell<bool>>>,
+    pub pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
     pub scroll_offset: Option<Rc<RefCell<Point<Pixels>>>>,
-    pub active_tooltip: Rc<RefCell<Option<ActiveTooltip>>>,
+    pub active_tooltip: Option<Rc<RefCell<Option<ActiveTooltip>>>>,
 }
 
 pub struct ActiveTooltip {

crates/gpui2/src/style.rs 🔗

@@ -107,7 +107,7 @@ pub struct Style {
     /// The mouse cursor style shown when the mouse pointer is over an element.
     pub mouse_cursor: Option<CursorStyle>,
 
-    pub z_index: Option<u32>,
+    pub z_index: Option<u8>,
 }
 
 impl Styled for StyleRefinement {

crates/gpui2/src/styled.rs 🔗

@@ -12,7 +12,7 @@ pub trait Styled: Sized {
 
     gpui2_macros::style_helpers!();
 
-    fn z_index(mut self, z_index: u32) -> Self {
+    fn z_index(mut self, z_index: u8) -> Self {
         self.style().z_index = Some(z_index);
         self
     }

crates/gpui2/src/window.rs 🔗

@@ -38,28 +38,34 @@ use std::{
 };
 use util::ResultExt;
 
-const ACTIVE_DRAG_Z_INDEX: u32 = 1;
+const ACTIVE_DRAG_Z_INDEX: u8 = 1;
 
 /// A global stacking order, which is created by stacking successive z-index values.
 /// Each z-index will always be interpreted in the context of its parent z-index.
-#[derive(Deref, DerefMut, Ord, PartialOrd, Eq, PartialEq, Clone, Debug)]
-pub struct StackingOrder(pub(crate) Arc<Vec<u32>>);
+#[derive(Deref, DerefMut, Clone, Debug, Ord, PartialOrd, PartialEq, Eq)]
+pub struct StackingOrder {
+    #[deref]
+    #[deref_mut]
+    z_indices: Arc<SmallVec<[u8; 8]>>,
+}
 
 impl Default for StackingOrder {
     fn default() -> Self {
-        StackingOrder(Arc::new(Vec::new()))
+        StackingOrder {
+            z_indices: Arc::new(SmallVec::new()),
+        }
     }
 }
 
 impl StackingOrder {
     /// Pushes a new z-index onto the stacking order.
-    pub fn push(&mut self, z_index: u32) {
-        Arc::make_mut(&mut self.0).push(z_index);
+    pub fn push(&mut self, z_index: u8) {
+        Arc::make_mut(&mut self.z_indices).push(z_index);
     }
 
     /// Pops the last z-index off the stacking order.
     pub fn pop(&mut self) {
-        Arc::make_mut(&mut self.0).pop();
+        Arc::make_mut(&mut self.z_indices).pop();
     }
 }
 
@@ -905,7 +911,7 @@ impl<'a> WindowContext<'a> {
 
     /// Called during painting to invoke the given closure in a new stacking context. The given
     /// z-index is interpreted relative to the previous call to `stack`.
-    pub fn with_z_index<R>(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R {
+    pub fn with_z_index<R>(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R {
         self.window.next_frame.z_index_stack.push(z_index);
         let result = f(self);
         self.window.next_frame.z_index_stack.pop();
@@ -2233,7 +2239,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
         &mut self.window_cx
     }
 
-    pub fn with_z_index<R>(&mut self, z_index: u32, f: impl FnOnce(&mut Self) -> R) -> R {
+    pub fn with_z_index<R>(&mut self, z_index: u8, f: impl FnOnce(&mut Self) -> R) -> R {
         self.window.next_frame.z_index_stack.push(z_index);
         let result = f(self);
         self.window.next_frame.z_index_stack.pop();

crates/storybook2/src/stories/z_index.rs 🔗

@@ -78,7 +78,7 @@ impl Styles for Div {}
 
 #[derive(IntoElement)]
 struct ZIndexExample {
-    z_index: u32,
+    z_index: u8,
 }
 
 impl RenderOnce for ZIndexExample {
@@ -170,7 +170,7 @@ impl RenderOnce for ZIndexExample {
 }
 
 impl ZIndexExample {
-    pub fn new(z_index: u32) -> Self {
+    pub fn new(z_index: u8) -> Self {
         Self { z_index }
     }
 }

crates/ui2/src/styles/elevation.rs 🔗

@@ -20,14 +20,14 @@ pub enum ElevationIndex {
 }
 
 impl ElevationIndex {
-    pub fn z_index(self) -> u32 {
+    pub fn z_index(self) -> u8 {
         match self {
             ElevationIndex::Background => 0,
-            ElevationIndex::Surface => 100,
-            ElevationIndex::ElevatedSurface => 200,
-            ElevationIndex::Wash => 250,
-            ElevationIndex::ModalSurface => 300,
-            ElevationIndex::DraggedElement => 900,
+            ElevationIndex::Surface => 42,
+            ElevationIndex::ElevatedSurface => 84,
+            ElevationIndex::Wash => 126,
+            ElevationIndex::ModalSurface => 168,
+            ElevationIndex::DraggedElement => 210,
         }
     }