mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Merge branch 'gpui2' of github.com:zed-industries/zed into gpui2
This commit is contained in:
commit
b0b7f27f3a
@ -1,4 +1,4 @@
|
|||||||
use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, Point, ViewContext};
|
use crate::{BorrowWindow, Bounds, ElementId, LayoutId, Pixels, ViewContext};
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
pub(crate) use smallvec::SmallVec;
|
pub(crate) use smallvec::SmallVec;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -62,7 +62,7 @@ pub trait ParentElement: Element {
|
|||||||
trait ElementObject<V>: 'static + Send + Sync {
|
trait ElementObject<V>: 'static + Send + Sync {
|
||||||
fn initialize(&mut self, view_state: &mut V, cx: &mut ViewContext<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 layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId;
|
||||||
fn paint(&mut self, view_state: &mut V, offset: Option<Point<Pixels>>, cx: &mut ViewContext<V>);
|
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RenderedElement<E: Element> {
|
struct RenderedElement<E: Element> {
|
||||||
@ -145,19 +145,13 @@ where
|
|||||||
layout_id
|
layout_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
|
||||||
&mut self,
|
|
||||||
view_state: &mut E::ViewState,
|
|
||||||
offset: Option<Point<Pixels>>,
|
|
||||||
cx: &mut ViewContext<E::ViewState>,
|
|
||||||
) {
|
|
||||||
self.phase = match mem::take(&mut self.phase) {
|
self.phase = match mem::take(&mut self.phase) {
|
||||||
ElementRenderPhase::LayoutRequested {
|
ElementRenderPhase::LayoutRequested {
|
||||||
layout_id,
|
layout_id,
|
||||||
mut frame_state,
|
mut frame_state,
|
||||||
} => {
|
} => {
|
||||||
let mut bounds = cx.layout_bounds(layout_id);
|
let bounds = cx.layout_bounds(layout_id);
|
||||||
offset.map(|offset| bounds.origin += offset);
|
|
||||||
if let Some(id) = self.element.id() {
|
if let Some(id) = self.element.id() {
|
||||||
cx.with_element_state(id, |element_state, cx| {
|
cx.with_element_state(id, |element_state, cx| {
|
||||||
let mut element_state = element_state.unwrap();
|
let mut element_state = element_state.unwrap();
|
||||||
@ -192,13 +186,8 @@ impl<V: 'static + Send + Sync> AnyElement<V> {
|
|||||||
self.0.layout(view_state, cx)
|
self.0.layout(view_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paint(
|
pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
||||||
&mut self,
|
self.0.paint(view_state, cx)
|
||||||
view_state: &mut V,
|
|
||||||
offset: Option<Point<Pixels>>,
|
|
||||||
cx: &mut ViewContext<V>,
|
|
||||||
) {
|
|
||||||
self.0.paint(view_state, offset, cx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ where
|
|||||||
for child_layout_id in &element_state.child_layout_ids {
|
for child_layout_id in &element_state.child_layout_ids {
|
||||||
let child_bounds = cx.layout_bounds(*child_layout_id);
|
let child_bounds = cx.layout_bounds(*child_layout_id);
|
||||||
child_min = child_min.min(&child_bounds.origin);
|
child_min = child_min.min(&child_bounds.origin);
|
||||||
child_max = child_min.max(&child_bounds.lower_right());
|
child_max = child_max.max(&child_bounds.lower_right());
|
||||||
}
|
}
|
||||||
(child_max - child_min).into()
|
(child_max - child_min).into()
|
||||||
};
|
};
|
||||||
@ -298,9 +298,11 @@ where
|
|||||||
style.apply_text_style(cx, |cx| {
|
style.apply_text_style(cx, |cx| {
|
||||||
style.apply_overflow(bounds, cx, |cx| {
|
style.apply_overflow(bounds, cx, |cx| {
|
||||||
let scroll_offset = element_state.interactive.scroll_offset();
|
let scroll_offset = element_state.interactive.scroll_offset();
|
||||||
|
cx.with_scroll_offset(scroll_offset, |cx| {
|
||||||
for child in &mut this.children {
|
for child in &mut this.children {
|
||||||
child.paint(view_state, scroll_offset, cx);
|
child.paint(view_state, cx);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@ -97,9 +97,13 @@ impl<V: 'static + Send + Sync> Element for Text<V> {
|
|||||||
return Size::default();
|
return Size::default();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let line_count = lines
|
||||||
|
.iter()
|
||||||
|
.map(|line| line.wrap_count() + 1)
|
||||||
|
.sum::<usize>();
|
||||||
let size = Size {
|
let size = Size {
|
||||||
width: lines.iter().map(|line| line.layout.width).max().unwrap(),
|
width: lines.iter().map(|line| line.layout.width).max().unwrap(),
|
||||||
height: line_height * lines.len(),
|
height: line_height * line_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
element_state
|
element_state
|
||||||
|
@ -4,7 +4,7 @@ use refineable::Refineable;
|
|||||||
use std::{
|
use std::{
|
||||||
cmp::{self, PartialOrd},
|
cmp::{self, PartialOrd},
|
||||||
fmt,
|
fmt,
|
||||||
ops::{Add, AddAssign, Div, Mul, MulAssign, Sub, SubAssign},
|
ops::{Add, Div, Mul, MulAssign, Sub},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Refineable, Default, Add, AddAssign, Sub, SubAssign, Copy, Debug, PartialEq, Eq, Hash)]
|
#[derive(Refineable, Default, Add, AddAssign, Sub, SubAssign, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
@ -67,26 +67,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> SubAssign<Size<T>> for Point<T>
|
|
||||||
where
|
|
||||||
T: Sub<Output = T> + Clone + Debug + Default,
|
|
||||||
{
|
|
||||||
fn sub_assign(&mut self, rhs: Size<T>) {
|
|
||||||
self.x = self.x.clone() - rhs.width;
|
|
||||||
self.y = self.y.clone() - rhs.height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> AddAssign<T> for Point<T>
|
|
||||||
where
|
|
||||||
T: Add<Output = T> + Clone + Default + Debug,
|
|
||||||
{
|
|
||||||
fn add_assign(&mut self, rhs: T) {
|
|
||||||
self.x = self.x.clone() + rhs.clone();
|
|
||||||
self.y = self.y.clone() + rhs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, S> Div<S> for Point<T>
|
impl<T, S> Div<S> for Point<T>
|
||||||
where
|
where
|
||||||
T: Div<S, Output = T> + Clone + Default + Debug,
|
T: Div<S, Output = T> + Clone + Default + Debug,
|
||||||
@ -187,7 +167,7 @@ impl Size<Pixels> {
|
|||||||
|
|
||||||
impl<T> Size<T>
|
impl<T> Size<T>
|
||||||
where
|
where
|
||||||
T: Ord + Clone + Default + Debug,
|
T: PartialOrd + Clone + Default + Debug,
|
||||||
{
|
{
|
||||||
pub fn max(&self, other: &Self) -> Self {
|
pub fn max(&self, other: &Self) -> Self {
|
||||||
Size {
|
Size {
|
||||||
|
@ -477,7 +477,7 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
|
|||||||
.get_or_insert_with(Arc::default)
|
.get_or_insert_with(Arc::default)
|
||||||
.clone();
|
.clone();
|
||||||
let line_height = cx.line_height();
|
let line_height = cx.line_height();
|
||||||
let scroll_max = content_size - bounds.size;
|
let scroll_max = (content_size - bounds.size).max(&Size::default());
|
||||||
|
|
||||||
cx.on_mouse_event(move |_, event: &ScrollWheelEvent, _, cx| {
|
cx.on_mouse_event(move |_, event: &ScrollWheelEvent, _, cx| {
|
||||||
if bounds.contains_point(&event.position) {
|
if bounds.contains_point(&event.position) {
|
||||||
|
@ -26,6 +26,10 @@ impl Line {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn wrap_count(&self) -> usize {
|
||||||
|
self.layout.wrap_boundaries.len()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn paint(
|
pub fn paint(
|
||||||
&self,
|
&self,
|
||||||
origin: Point<Pixels>,
|
origin: Point<Pixels>,
|
||||||
|
@ -90,8 +90,7 @@ impl<V: 'static + Send + Sync> Element for View<V> {
|
|||||||
element: &mut Self::ElementState,
|
element: &mut Self::ElementState,
|
||||||
cx: &mut ViewContext<()>,
|
cx: &mut ViewContext<()>,
|
||||||
) {
|
) {
|
||||||
self.state
|
self.state.update(cx, |state, cx| element.paint(state, cx))
|
||||||
.update(cx, |state, cx| element.paint(state, None, cx))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +185,7 @@ impl<V: Send + Sync + 'static> ViewObject for View<V> {
|
|||||||
cx.with_element_id(self.entity_id(), |_global_id, cx| {
|
cx.with_element_id(self.entity_id(), |_global_id, cx| {
|
||||||
self.state.update(cx, |state, cx| {
|
self.state.update(cx, |state, cx| {
|
||||||
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
|
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
|
||||||
element.paint(state, None, cx);
|
element.paint(state, cx);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,7 @@ pub struct Window {
|
|||||||
key_matchers: HashMap<GlobalElementId, KeyMatcher>,
|
key_matchers: HashMap<GlobalElementId, KeyMatcher>,
|
||||||
z_index_stack: StackingOrder,
|
z_index_stack: StackingOrder,
|
||||||
content_mask_stack: Vec<ContentMask<Pixels>>,
|
content_mask_stack: Vec<ContentMask<Pixels>>,
|
||||||
|
scroll_offset_stack: Vec<Point<Pixels>>,
|
||||||
mouse_listeners: HashMap<TypeId, Vec<(StackingOrder, AnyListener)>>,
|
mouse_listeners: HashMap<TypeId, Vec<(StackingOrder, AnyListener)>>,
|
||||||
key_dispatch_stack: Vec<KeyDispatchStackFrame>,
|
key_dispatch_stack: Vec<KeyDispatchStackFrame>,
|
||||||
freeze_key_dispatch_stack: bool,
|
freeze_key_dispatch_stack: bool,
|
||||||
@ -234,6 +235,7 @@ impl Window {
|
|||||||
key_matchers: HashMap::default(),
|
key_matchers: HashMap::default(),
|
||||||
z_index_stack: StackingOrder(SmallVec::new()),
|
z_index_stack: StackingOrder(SmallVec::new()),
|
||||||
content_mask_stack: Vec::new(),
|
content_mask_stack: Vec::new(),
|
||||||
|
scroll_offset_stack: Vec::new(),
|
||||||
mouse_listeners: HashMap::default(),
|
mouse_listeners: HashMap::default(),
|
||||||
key_dispatch_stack: Vec::new(),
|
key_dispatch_stack: Vec::new(),
|
||||||
freeze_key_dispatch_stack: false,
|
freeze_key_dispatch_stack: false,
|
||||||
@ -443,10 +445,13 @@ impl<'a, 'w> WindowContext<'a, 'w> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
|
pub fn layout_bounds(&mut self, layout_id: LayoutId) -> Bounds<Pixels> {
|
||||||
self.window
|
let mut bounds = self
|
||||||
|
.window
|
||||||
.layout_engine
|
.layout_engine
|
||||||
.layout_bounds(layout_id)
|
.layout_bounds(layout_id)
|
||||||
.map(Into::into)
|
.map(Into::into);
|
||||||
|
bounds.origin -= self.scroll_offset();
|
||||||
|
bounds
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scale_factor(&self) -> f32 {
|
pub fn scale_factor(&self) -> f32 {
|
||||||
@ -1136,6 +1141,30 @@ pub trait BorrowWindow: BorrowAppContext {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_scroll_offset<R>(
|
||||||
|
&mut self,
|
||||||
|
offset: Option<Point<Pixels>>,
|
||||||
|
f: impl FnOnce(&mut Self) -> R,
|
||||||
|
) -> R {
|
||||||
|
let Some(offset) = offset else {
|
||||||
|
return f(self);
|
||||||
|
};
|
||||||
|
|
||||||
|
let offset = self.scroll_offset() + offset;
|
||||||
|
self.window_mut().scroll_offset_stack.push(offset);
|
||||||
|
let result = f(self);
|
||||||
|
self.window_mut().scroll_offset_stack.pop();
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scroll_offset(&self) -> Point<Pixels> {
|
||||||
|
self.window()
|
||||||
|
.scroll_offset_stack
|
||||||
|
.last()
|
||||||
|
.copied()
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
fn with_element_state<S: 'static + Send + Sync, R>(
|
fn with_element_state<S: 'static + Send + Sync, R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
|
@ -86,7 +86,7 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
|
|||||||
rendered_element: &mut Self::ElementState,
|
rendered_element: &mut Self::ElementState,
|
||||||
cx: &mut gpui3::ViewContext<Self::ViewState>,
|
cx: &mut gpui3::ViewContext<Self::ViewState>,
|
||||||
) {
|
) {
|
||||||
rendered_element.paint(view_state, None, cx)
|
rendered_element.paint(view_state, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
mod focus;
|
mod focus;
|
||||||
mod kitchen_sink;
|
mod kitchen_sink;
|
||||||
|
mod scroll;
|
||||||
mod text;
|
mod text;
|
||||||
mod z_index;
|
mod z_index;
|
||||||
|
|
||||||
pub use focus::*;
|
pub use focus::*;
|
||||||
pub use kitchen_sink::*;
|
pub use kitchen_sink::*;
|
||||||
|
pub use scroll::*;
|
||||||
pub use text::*;
|
pub use text::*;
|
||||||
pub use z_index::*;
|
pub use z_index::*;
|
||||||
|
28
crates/storybook2/src/stories/scroll.rs
Normal file
28
crates/storybook2/src/stories/scroll.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
use crate::themes::rose_pine;
|
||||||
|
use gpui3::{div, view, Context, ParentElement, Styled, View, WindowContext};
|
||||||
|
|
||||||
|
pub struct ScrollStory {
|
||||||
|
text: View<()>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScrollStory {
|
||||||
|
pub fn view(cx: &mut WindowContext) -> View<()> {
|
||||||
|
let theme = rose_pine();
|
||||||
|
|
||||||
|
view(cx.entity(|cx| ()), move |_, cx| {
|
||||||
|
div()
|
||||||
|
.id("parent")
|
||||||
|
.bg(theme.lowest.base.default.background)
|
||||||
|
.size_full()
|
||||||
|
.overflow_x_scroll()
|
||||||
|
.child(div().w_96().flex().flex_row().children((0..3).map(|ix| {
|
||||||
|
let bg = if ix % 2 == 0 {
|
||||||
|
theme.middle.positive.default.background
|
||||||
|
} else {
|
||||||
|
theme.middle.warning.default.background
|
||||||
|
};
|
||||||
|
div().bg(bg).flex_1().h_20()
|
||||||
|
})))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -19,6 +19,7 @@ pub enum ElementStory {
|
|||||||
Icon,
|
Icon,
|
||||||
Input,
|
Input,
|
||||||
Label,
|
Label,
|
||||||
|
Scroll,
|
||||||
Text,
|
Text,
|
||||||
ZIndex,
|
ZIndex,
|
||||||
}
|
}
|
||||||
@ -46,6 +47,7 @@ impl ElementStory {
|
|||||||
Self::Label => {
|
Self::Label => {
|
||||||
view(cx.entity(|cx| ()), |_, _| ui::LabelStory::new().into_any()).into_any()
|
view(cx.entity(|cx| ()), |_, _| ui::LabelStory::new().into_any()).into_any()
|
||||||
}
|
}
|
||||||
|
Self::Scroll => ScrollStory::view(cx).into_any(),
|
||||||
Self::Text => TextStory::view(cx).into_any(),
|
Self::Text => TextStory::view(cx).into_any(),
|
||||||
Self::ZIndex => {
|
Self::ZIndex => {
|
||||||
view(cx.entity(|cx| ()), |_, _| ZIndexStory::new().into_any()).into_any()
|
view(cx.entity(|cx| ()), |_, _| ZIndexStory::new().into_any()).into_any()
|
||||||
|
Loading…
Reference in New Issue
Block a user