Merge branch 'gpui2' of github.com:zed-industries/zed into gpui2

This commit is contained in:
Marshall Bowers 2023-10-20 11:32:11 -04:00
commit b0b7f27f3a
12 changed files with 90 additions and 51 deletions

View File

@ -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};
pub(crate) use smallvec::SmallVec;
use std::mem;
@ -62,7 +62,7 @@ pub trait ParentElement: Element {
trait ElementObject<V>: 'static + Send + Sync {
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 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> {
@ -145,19 +145,13 @@ where
layout_id
}
fn paint(
&mut self,
view_state: &mut E::ViewState,
offset: Option<Point<Pixels>>,
cx: &mut ViewContext<E::ViewState>,
) {
fn paint(&mut self, view_state: &mut E::ViewState, cx: &mut ViewContext<E::ViewState>) {
self.phase = match mem::take(&mut self.phase) {
ElementRenderPhase::LayoutRequested {
layout_id,
mut frame_state,
} => {
let mut bounds = cx.layout_bounds(layout_id);
offset.map(|offset| bounds.origin += offset);
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();
@ -192,13 +186,8 @@ impl<V: 'static + Send + Sync> AnyElement<V> {
self.0.layout(view_state, cx)
}
pub fn paint(
&mut self,
view_state: &mut V,
offset: Option<Point<Pixels>>,
cx: &mut ViewContext<V>,
) {
self.0.paint(view_state, offset, cx)
pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
self.0.paint(view_state, cx)
}
}

View File

@ -277,7 +277,7 @@ where
for child_layout_id in &element_state.child_layout_ids {
let child_bounds = cx.layout_bounds(*child_layout_id);
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()
};
@ -298,9 +298,11 @@ where
style.apply_text_style(cx, |cx| {
style.apply_overflow(bounds, cx, |cx| {
let scroll_offset = element_state.interactive.scroll_offset();
cx.with_scroll_offset(scroll_offset, |cx| {
for child in &mut this.children {
child.paint(view_state, scroll_offset, cx);
child.paint(view_state, cx);
}
});
})
})
});

View File

@ -97,9 +97,13 @@ impl<V: 'static + Send + Sync> Element for Text<V> {
return Size::default();
};
let line_count = lines
.iter()
.map(|line| line.wrap_count() + 1)
.sum::<usize>();
let size = Size {
width: lines.iter().map(|line| line.layout.width).max().unwrap(),
height: line_height * lines.len(),
height: line_height * line_count,
};
element_state

View File

@ -4,7 +4,7 @@ use refineable::Refineable;
use std::{
cmp::{self, PartialOrd},
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)]
@ -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>
where
T: Div<S, Output = T> + Clone + Default + Debug,
@ -187,7 +167,7 @@ impl Size<Pixels> {
impl<T> Size<T>
where
T: Ord + Clone + Default + Debug,
T: PartialOrd + Clone + Default + Debug,
{
pub fn max(&self, other: &Self) -> Self {
Size {

View File

@ -477,7 +477,7 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
.get_or_insert_with(Arc::default)
.clone();
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| {
if bounds.contains_point(&event.position) {

View File

@ -26,6 +26,10 @@ impl Line {
)
}
pub fn wrap_count(&self) -> usize {
self.layout.wrap_boundaries.len()
}
pub fn paint(
&self,
origin: Point<Pixels>,

View File

@ -90,8 +90,7 @@ impl<V: 'static + Send + Sync> Element for View<V> {
element: &mut Self::ElementState,
cx: &mut ViewContext<()>,
) {
self.state
.update(cx, |state, cx| element.paint(state, None, cx))
self.state.update(cx, |state, cx| element.paint(state, cx))
}
}
@ -186,7 +185,7 @@ impl<V: Send + Sync + 'static> ViewObject for View<V> {
cx.with_element_id(self.entity_id(), |_global_id, cx| {
self.state.update(cx, |state, cx| {
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
element.paint(state, None, cx);
element.paint(state, cx);
});
});
}

View File

@ -159,6 +159,7 @@ pub struct Window {
key_matchers: HashMap<GlobalElementId, KeyMatcher>,
z_index_stack: StackingOrder,
content_mask_stack: Vec<ContentMask<Pixels>>,
scroll_offset_stack: Vec<Point<Pixels>>,
mouse_listeners: HashMap<TypeId, Vec<(StackingOrder, AnyListener)>>,
key_dispatch_stack: Vec<KeyDispatchStackFrame>,
freeze_key_dispatch_stack: bool,
@ -234,6 +235,7 @@ impl Window {
key_matchers: HashMap::default(),
z_index_stack: StackingOrder(SmallVec::new()),
content_mask_stack: Vec::new(),
scroll_offset_stack: Vec::new(),
mouse_listeners: HashMap::default(),
key_dispatch_stack: Vec::new(),
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> {
self.window
let mut bounds = self
.window
.layout_engine
.layout_bounds(layout_id)
.map(Into::into)
.map(Into::into);
bounds.origin -= self.scroll_offset();
bounds
}
pub fn scale_factor(&self) -> f32 {
@ -1136,6 +1141,30 @@ pub trait BorrowWindow: BorrowAppContext {
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>(
&mut self,
id: ElementId,

View File

@ -86,7 +86,7 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
rendered_element: &mut Self::ElementState,
cx: &mut gpui3::ViewContext<Self::ViewState>,
) {
rendered_element.paint(view_state, None, cx)
rendered_element.paint(view_state, cx)
}
}
};

View File

@ -1,9 +1,11 @@
mod focus;
mod kitchen_sink;
mod scroll;
mod text;
mod z_index;
pub use focus::*;
pub use kitchen_sink::*;
pub use scroll::*;
pub use text::*;
pub use z_index::*;

View 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()
})))
})
}
}

View File

@ -19,6 +19,7 @@ pub enum ElementStory {
Icon,
Input,
Label,
Scroll,
Text,
ZIndex,
}
@ -46,6 +47,7 @@ impl ElementStory {
Self::Label => {
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::ZIndex => {
view(cx.entity(|cx| ()), |_, _| ZIndexStory::new().into_any()).into_any()