diff --git a/crates/gpui2/src/elements/node.rs b/crates/gpui2/src/elements/node.rs index 06d4ae2636..7133997c48 100644 --- a/crates/gpui2/src/elements/node.rs +++ b/crates/gpui2/src/elements/node.rs @@ -386,7 +386,7 @@ pub trait FocusableComponent { where Self: Sized, { - // self.focusability(). (f(StyleRefinement::default())); + self.focusability().in_focus_style = f(StyleRefinement::default()); self } @@ -523,7 +523,6 @@ pub struct FocusEvent { } pub struct Node { - key_context: KeyContext, interactivity: Interactivity, children: Vec>, } @@ -621,24 +620,27 @@ impl Element for Node { (child_max - child_min).into() }; - cx.with_z_index(z_index, |cx| { - cx.with_z_index(0, |cx| { - style.paint(bounds, cx); - self.interactivity.paint(bounds, cx); - }); - cx.with_z_index(1, |cx| { - style.with_text_style(cx, |cx| { - style.apply_overflow(bounds, cx, |cx| { - let scroll_offset = self.interactivity.scroll_offset; - cx.with_element_offset2(scroll_offset, |cx| { - for child in &mut self.children { - child.paint(view_state, cx); - } - }); + let mut interactivity = mem::take(&mut self.interactivity); + interactivity.paint(bounds, cx, |cx| { + cx.with_z_index(z_index, |cx| { + cx.with_z_index(0, |cx| { + style.paint(bounds, cx); + }); + cx.with_z_index(1, |cx| { + style.with_text_style(cx, |cx| { + style.apply_overflow(bounds, cx, |cx| { + let scroll_offset = self.interactivity.scroll_offset; + cx.with_element_offset2(scroll_offset, |cx| { + for child in &mut self.children { + child.paint(view_state, cx); + } + }); + }) }) - }) + }); }); }); + self.interactivity = interactivity; if let Some(group) = self.interactivity.group.as_ref() { GroupBounds::pop(group, cx); @@ -646,19 +648,15 @@ impl Element for Node { } } -pub struct ComputedStyle { - base: StyleRefinement, - focus: StyleRefinement, - hover: StyleRefinement, - active: StyleRefinement, -} - -pub struct StyleCascade { - pub base: StyleRefinement, - pub focus: StyleRefinement, - pub hover: StyleRefinement, - pub dragged_over: StyleRefinement, - pub active: StyleRefinement, +pub enum FocusState { + /// The current element is not focused, and does not contain or descend from the focused element. + None, + /// The current element is focused. + Focus, + /// The current element contains the focused element + FocusIn, + /// The current element descends from the focused element + InFocus, } pub struct Interactivity { @@ -666,10 +664,14 @@ pub struct Interactivity { pub group_active: bool, pub hovered: bool, pub group_hovered: bool, - pub focused: bool, + pub focus: FocusState, + pub key_context: KeyContext, + pub focus_handle: Option, pub scroll_offset: Point, pub base_style: StyleRefinement, pub focus_style: StyleRefinement, + pub focus_in_style: StyleRefinement, + pub in_focus_style: StyleRefinement, pub hover_style: StyleRefinement, pub group_hover_style: Option, pub active_style: StyleRefinement, @@ -696,8 +698,20 @@ impl Interactivity { fn compute_style(&self, bounds: Option>, cx: &mut ViewContext) -> Style { let mut style = Style::default(); style.refine(&self.base_style); - if self.focused { - style.refine(&self.focus_style); + + match self.focus { + FocusState::None => {} + FocusState::Focus => { + style.refine(&self.focus_style); + style.refine(&self.focus_in_style); + style.refine(&self.in_focus_style); + } + FocusState::FocusIn => { + style.refine(&self.focus_in_style); + } + FocusState::InFocus => { + style.refine(&self.in_focus_style); + } } if let Some(bounds) = bounds { @@ -749,7 +763,12 @@ impl Interactivity { style } - fn paint(&mut self, bounds: Bounds, cx: &mut ViewContext) { + fn paint( + &mut self, + bounds: Bounds, + cx: &mut ViewContext, + f: impl FnOnce(&mut ViewContext), + ) { for listener in self.mouse_down_listeners.drain(..) { cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| { listener(state, event, &bounds, phase, cx); @@ -825,6 +844,51 @@ impl Interactivity { } }); } + + cx.with_key_dispatch( + self.key_context.clone(), + self.focus_handle.clone(), + |_, cx| f(cx), + ); + } +} + +impl Default for Interactivity { + fn default() -> Self { + Self { + active: false, + group_active: false, + hovered: false, + group_hovered: false, + focus: FocusState::None, + key_context: KeyContext::default(), + focus_handle: None, + scroll_offset: Point::default(), + base_style: StyleRefinement::default(), + focus_style: StyleRefinement::default(), + focus_in_style: StyleRefinement::default(), + in_focus_style: StyleRefinement::default(), + hover_style: StyleRefinement::default(), + group_hover_style: None, + active_style: StyleRefinement::default(), + group_active_style: None, + drag_over_styles: SmallVec::new(), + group_drag_over_styles: SmallVec::new(), + group: None, + dispatch_context: KeyContext::default(), + mouse_down_listeners: SmallVec::new(), + mouse_up_listeners: SmallVec::new(), + mouse_move_listeners: SmallVec::new(), + scroll_wheel_listeners: SmallVec::new(), + key_down_listeners: SmallVec::new(), + key_up_listeners: SmallVec::new(), + action_listeners: SmallVec::new(), + drop_listeners: SmallVec::new(), + click_listeners: SmallVec::new(), + drag_listener: None, + hover_listener: None, + tooltip_builder: None, + } } }