mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-04 07:29:32 +00:00
WIP
This commit is contained in:
parent
aec7955ccf
commit
76754c559c
11 changed files with 296 additions and 22 deletions
|
@ -2640,6 +2640,15 @@ impl Element<Editor> for EditorElement {
|
|||
cx.request_layout(&style, None)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut Editor,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<gpui::Pixels>,
|
||||
|
|
|
@ -26,6 +26,14 @@ pub trait Element<V: 'static> {
|
|||
cx: &mut ViewContext<V>,
|
||||
) -> LayoutId;
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
);
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
|
@ -62,6 +70,7 @@ pub trait ParentElement<V: 'static> {
|
|||
trait ElementObject<V> {
|
||||
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||
fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
|
||||
fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||
fn measure(
|
||||
&mut self,
|
||||
|
@ -199,6 +208,36 @@ where
|
|||
};
|
||||
}
|
||||
|
||||
fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
||||
self.phase = match mem::take(&mut self.phase) {
|
||||
ElementRenderPhase::LayoutRequested {
|
||||
layout_id,
|
||||
mut frame_state,
|
||||
}
|
||||
| ElementRenderPhase::LayoutComputed {
|
||||
layout_id,
|
||||
mut frame_state,
|
||||
..
|
||||
} => {
|
||||
let bounds = cx.layout_bounds(layout_id);
|
||||
if let Some(id) = self.element.id() {
|
||||
cx.with_element_state(id, |element_state, cx| {
|
||||
let mut element_state = element_state.unwrap();
|
||||
self.element
|
||||
.prepaint(bounds, view_state, &mut element_state, cx);
|
||||
((), element_state)
|
||||
});
|
||||
} else {
|
||||
self.element
|
||||
.prepaint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
|
||||
}
|
||||
ElementRenderPhase::Painted
|
||||
}
|
||||
|
||||
_ => panic!("must call layout before paint"),
|
||||
};
|
||||
}
|
||||
|
||||
fn measure(
|
||||
&mut self,
|
||||
available_space: Size<AvailableSpace>,
|
||||
|
@ -283,6 +322,10 @@ impl<V> AnyElement<V> {
|
|||
self.0.paint(view_state, cx)
|
||||
}
|
||||
|
||||
pub fn prepaint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
||||
self.0.prepaint(view_state, cx)
|
||||
}
|
||||
|
||||
/// Initializes this element and performs layout within the given available space to determine its size.
|
||||
pub fn measure(
|
||||
&mut self,
|
||||
|
@ -376,6 +419,16 @@ where
|
|||
rendered_element.layout(view_state, cx)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
_bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
rendered_element: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
rendered_element.prepaint(view_state, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
_bounds: Bounds<Pixels>,
|
||||
|
|
|
@ -265,6 +265,16 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
|
@ -309,7 +319,7 @@ where
|
|||
cx.with_z_index(0, |cx| {
|
||||
style.paint(bounds, cx);
|
||||
this.key_dispatch.paint(bounds, cx);
|
||||
this.interactivity.paint(
|
||||
this.interactivity.handle_events(
|
||||
bounds,
|
||||
content_size,
|
||||
style.overflow,
|
||||
|
|
|
@ -94,6 +94,15 @@ where
|
|||
self.base.layout(view_state, element_state, cx)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
|
|
|
@ -10,6 +10,7 @@ use smallvec::SmallVec;
|
|||
use std::{
|
||||
any::{Any, TypeId},
|
||||
marker::PhantomData,
|
||||
mem,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
|
@ -530,24 +531,6 @@ pub struct Node<V> {
|
|||
children: Vec<AnyElement<V>>,
|
||||
}
|
||||
|
||||
pub struct Interactivity<V> {
|
||||
group: Option<SharedString>,
|
||||
pub dispatch_context: KeyContext,
|
||||
pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
|
||||
pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
|
||||
pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
|
||||
pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
|
||||
pub key_down_listeners: SmallVec<[KeyDownListener<V>; 2]>,
|
||||
pub key_up_listeners: SmallVec<[KeyUpListener<V>; 2]>,
|
||||
pub action_listeners: SmallVec<[(TypeId, ActionListener<V>); 8]>,
|
||||
pub hover_style: StyleRefinement,
|
||||
pub group_hover_style: Option<GroupStyle>,
|
||||
drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
||||
group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
||||
drop_listeners: SmallVec<[(TypeId, Box<DropListener<V>>); 2]>,
|
||||
scroll_offset: Point<Pixels>,
|
||||
}
|
||||
|
||||
impl<V> Node<V> {
|
||||
fn compute_style(&self) -> Style {
|
||||
let mut style = Style::default();
|
||||
|
@ -610,6 +593,20 @@ impl<V: 'static> Element<V> for Node<V> {
|
|||
})
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
_: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
for child in &mut self.children {
|
||||
child.prepaint(view_state, cx);
|
||||
}
|
||||
self.interactivity
|
||||
.refine_style(&mut self.style, bounds, view_state, cx);
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
|
@ -652,6 +649,7 @@ impl<V: 'static> Element<V> for Node<V> {
|
|||
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| {
|
||||
|
@ -673,6 +671,144 @@ impl<V: 'static> Element<V> for Node<V> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Interactivity<V> {
|
||||
pub hover_style: StyleRefinement,
|
||||
pub group_hover_style: Option<GroupStyle>,
|
||||
pub drag_over_styles: SmallVec<[(TypeId, StyleRefinement); 2]>,
|
||||
pub group_drag_over_styles: SmallVec<[(TypeId, GroupStyle); 2]>,
|
||||
group: Option<SharedString>,
|
||||
pub dispatch_context: KeyContext,
|
||||
pub mouse_down_listeners: SmallVec<[MouseDownListener<V>; 2]>,
|
||||
pub mouse_up_listeners: SmallVec<[MouseUpListener<V>; 2]>,
|
||||
pub mouse_move_listeners: SmallVec<[MouseMoveListener<V>; 2]>,
|
||||
pub scroll_wheel_listeners: SmallVec<[ScrollWheelListener<V>; 2]>,
|
||||
pub key_down_listeners: SmallVec<[KeyDownListener<V>; 2]>,
|
||||
pub key_up_listeners: SmallVec<[KeyUpListener<V>; 2]>,
|
||||
pub action_listeners: SmallVec<[(TypeId, ActionListener<V>); 8]>,
|
||||
drop_listeners: SmallVec<[(TypeId, Box<DropListener<V>>); 2]>,
|
||||
scroll_offset: Point<Pixels>,
|
||||
}
|
||||
|
||||
impl<V: 'static> Interactivity<V> {
|
||||
fn refine_style(
|
||||
&self,
|
||||
style: &mut StyleRefinement,
|
||||
bounds: Bounds<Pixels>,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
let mouse_position = cx.mouse_position();
|
||||
if let Some(group_hover) = self.group_hover_style.as_ref() {
|
||||
if let Some(group_bounds) = GroupBounds::get(&group_hover.group, cx) {
|
||||
if group_bounds.contains_point(&mouse_position) {
|
||||
style.refine(&group_hover.style);
|
||||
}
|
||||
}
|
||||
}
|
||||
if bounds.contains_point(&mouse_position) {
|
||||
style.refine(&self.hover_style);
|
||||
}
|
||||
|
||||
if let Some(drag) = cx.active_drag.take() {
|
||||
for (state_type, group_drag_style) in &self.group_drag_over_styles {
|
||||
if let Some(group_bounds) = GroupBounds::get(&group_drag_style.group, cx) {
|
||||
if *state_type == drag.view.entity_type()
|
||||
&& group_bounds.contains_point(&mouse_position)
|
||||
{
|
||||
style.refine(&group_drag_style.style);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (state_type, drag_over_style) in &self.drag_over_styles {
|
||||
if *state_type == drag.view.entity_type() && bounds.contains_point(&mouse_position)
|
||||
{
|
||||
style.refine(drag_over_style);
|
||||
}
|
||||
}
|
||||
|
||||
cx.active_drag = Some(drag);
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(&mut self, bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) {
|
||||
for listener in self.mouse_down_listeners.drain(..) {
|
||||
cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
}
|
||||
|
||||
for listener in self.mouse_up_listeners.drain(..) {
|
||||
cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
}
|
||||
|
||||
for listener in self.mouse_move_listeners.drain(..) {
|
||||
cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
}
|
||||
|
||||
for listener in self.scroll_wheel_listeners.drain(..) {
|
||||
cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
|
||||
listener(state, event, &bounds, phase, cx);
|
||||
})
|
||||
}
|
||||
|
||||
let hover_group_bounds = self
|
||||
.group_hover_style
|
||||
.as_ref()
|
||||
.and_then(|group_hover| GroupBounds::get(&group_hover.group, cx));
|
||||
|
||||
if let Some(group_bounds) = hover_group_bounds {
|
||||
let hovered = group_bounds.contains_point(&cx.mouse_position());
|
||||
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Capture {
|
||||
if group_bounds.contains_point(&event.position) != hovered {
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if self.hover_style.is_some()
|
||||
|| (cx.active_drag.is_some() && !self.drag_over_styles.is_empty())
|
||||
{
|
||||
let hovered = bounds.contains_point(&cx.mouse_position());
|
||||
cx.on_mouse_event(move |_, event: &MouseMoveEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Capture {
|
||||
if bounds.contains_point(&event.position) != hovered {
|
||||
cx.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if cx.active_drag.is_some() {
|
||||
let drop_listeners = mem::take(&mut self.drop_listeners);
|
||||
cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| {
|
||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
||||
if let Some(drag_state_type) =
|
||||
cx.active_drag.as_ref().map(|drag| drag.view.entity_type())
|
||||
{
|
||||
for (drop_state_type, listener) in &drop_listeners {
|
||||
if *drop_state_type == drag_state_type {
|
||||
let drag = cx
|
||||
.active_drag
|
||||
.take()
|
||||
.expect("checked for type drag state type above");
|
||||
listener(view, drag.view.clone(), cx);
|
||||
cx.notify();
|
||||
cx.stop_propagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct GroupBounds(HashMap<SharedString, SmallVec<[Bounds<Pixels>; 1]>>);
|
||||
|
||||
|
|
|
@ -84,6 +84,15 @@ where
|
|||
self.base.layout(view_state, element_state, cx)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
|
|
|
@ -121,6 +121,15 @@ impl<V: 'static> Element<V> for Text<V> {
|
|||
layout_id
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
|
|
|
@ -152,6 +152,16 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
|||
)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut V,
|
||||
element_state: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: crate::Bounds<crate::Pixels>,
|
||||
|
@ -229,7 +239,7 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
|||
let overflow = point(style.overflow.x, Overflow::Scroll);
|
||||
|
||||
cx.with_z_index(0, |cx| {
|
||||
self.interactivity.paint(
|
||||
self.interactivity.handle_events(
|
||||
bounds,
|
||||
content_size,
|
||||
overflow,
|
||||
|
|
|
@ -450,7 +450,7 @@ pub trait ElementInteractivity<V: 'static>: 'static {
|
|||
}
|
||||
}
|
||||
|
||||
fn paint(
|
||||
fn handle_events(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
content_size: Size<Pixels>,
|
||||
|
|
|
@ -147,6 +147,7 @@ pub struct AnyView {
|
|||
model: AnyModel,
|
||||
initialize: fn(&AnyView, &mut WindowContext) -> AnyBox,
|
||||
layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
|
||||
prepaint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
|
||||
paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
|
||||
}
|
||||
|
||||
|
@ -156,6 +157,7 @@ impl AnyView {
|
|||
model: self.model.downgrade(),
|
||||
initialize: self.initialize,
|
||||
layout: self.layout,
|
||||
prepaint: self.prepaint,
|
||||
paint: self.paint,
|
||||
}
|
||||
}
|
||||
|
@ -167,6 +169,7 @@ impl AnyView {
|
|||
model,
|
||||
initialize: self.initialize,
|
||||
layout: self.layout,
|
||||
prepaint: self.prepaint,
|
||||
paint: self.paint,
|
||||
}),
|
||||
}
|
||||
|
@ -198,6 +201,7 @@ impl<V: Render> From<View<V>> for AnyView {
|
|||
model: value.model.into_any(),
|
||||
initialize: any_view::initialize::<V>,
|
||||
layout: any_view::layout::<V>,
|
||||
prepaint: any_view::prepaint::<V>,
|
||||
paint: any_view::paint::<V>,
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +232,16 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
|||
(self.layout)(self, rendered_element, cx)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
view_state: &mut ParentViewState,
|
||||
rendered_element: &mut Self::ElementState,
|
||||
cx: &mut ViewContext<ParentViewState>,
|
||||
) {
|
||||
(self.prepaint)(self, rendered_element, cx)
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
_bounds: Bounds<Pixels>,
|
||||
|
@ -243,6 +257,7 @@ pub struct AnyWeakView {
|
|||
model: AnyWeakModel,
|
||||
initialize: fn(&AnyView, &mut WindowContext) -> AnyBox,
|
||||
layout: fn(&AnyView, &mut AnyBox, &mut WindowContext) -> LayoutId,
|
||||
prepaint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
|
||||
paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
|
||||
}
|
||||
|
||||
|
@ -253,6 +268,7 @@ impl AnyWeakView {
|
|||
model,
|
||||
initialize: self.initialize,
|
||||
layout: self.layout,
|
||||
prepaint: self.prepaint,
|
||||
paint: self.paint,
|
||||
})
|
||||
}
|
||||
|
@ -264,6 +280,7 @@ impl<V: Render> From<WeakView<V>> for AnyWeakView {
|
|||
model: view.model.into(),
|
||||
initialize: any_view::initialize::<V>,
|
||||
layout: any_view::layout::<V>,
|
||||
prepaint: any_view::prepaint::<V>,
|
||||
paint: any_view::paint::<V>,
|
||||
}
|
||||
}
|
||||
|
@ -309,6 +326,18 @@ mod any_view {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn prepaint<V: Render>(
|
||||
view: &AnyView,
|
||||
element: &mut Box<dyn Any>,
|
||||
cx: &mut WindowContext,
|
||||
) {
|
||||
cx.with_element_id(view.model.entity_id, |_, cx| {
|
||||
let view = view.clone().downcast::<V>().unwrap();
|
||||
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
|
||||
view.update(cx, |view, cx| element.prepaint(view, cx))
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn paint<V: Render>(
|
||||
view: &AnyView,
|
||||
element: &mut Box<dyn Any>,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use gpui::AnyElement;
|
||||
use gpui::{AnyElement, Pixels};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::{h_stack, prelude::*, v_stack, Button, Icon, IconButton, Label};
|
||||
|
|
Loading…
Reference in a new issue