Checkpoint

This commit is contained in:
Antonio Scandurra
2023-10-20 16:31:00 +02:00
parent 47aa387b91
commit 8ad7ebf02f
4 changed files with 119 additions and 57 deletions
+43 -53
View File
@@ -1,35 +1,12 @@
use crate::{
AnyElement, BorrowWindow, Bounds, Element, ElementFocus, ElementId, ElementInteraction,
point, AnyElement, BorrowWindow, Bounds, Element, ElementFocus, ElementId, ElementInteraction,
FocusDisabled, FocusEnabled, FocusHandle, FocusListeners, Focusable, GlobalElementId,
GroupBounds, InteractiveElementState, IntoAnyElement, LayoutId, Overflow, ParentElement,
Pixels, Point, SharedString, StatefulInteraction, StatefulInteractive, StatelessInteraction,
StatelessInteractive, Style, StyleRefinement, Styled, ViewContext,
};
use parking_lot::Mutex;
use refineable::Refineable;
use smallvec::SmallVec;
use std::sync::Arc;
#[derive(Default, Clone)]
pub struct ScrollState(Arc<Mutex<Point<Pixels>>>);
impl ScrollState {
pub fn x(&self) -> Pixels {
self.0.lock().x
}
pub fn set_x(&self, value: Pixels) {
self.0.lock().x = value;
}
pub fn y(&self) -> Pixels {
self.0.lock().y
}
pub fn set_y(&self, value: Pixels) {
self.0.lock().y = value;
}
}
pub struct Div<
V: 'static + Send + Sync,
@@ -104,28 +81,6 @@ where
self
}
pub fn overflow_scroll(mut self, _scroll_state: ScrollState) -> Self {
// todo!("impl scrolling")
// self.scroll_state = Some(scroll_state);
self.base_style.overflow.x = Some(Overflow::Scroll);
self.base_style.overflow.y = Some(Overflow::Scroll);
self
}
pub fn overflow_x_scroll(mut self, _scroll_state: ScrollState) -> Self {
// todo!("impl scrolling")
// self.scroll_state = Some(scroll_state);
self.base_style.overflow.x = Some(Overflow::Scroll);
self
}
pub fn overflow_y_scroll(mut self, _scroll_state: ScrollState) -> Self {
// todo!("impl scrolling")
// self.scroll_state = Some(scroll_state);
self.base_style.overflow.y = Some(Overflow::Scroll);
self
}
fn with_element_id<R>(
&mut self,
cx: &mut ViewContext<V>,
@@ -179,6 +134,22 @@ where
base_style: self.base_style,
}
}
pub fn overflow_scroll(mut self) -> Self {
self.base_style.overflow.x = Some(Overflow::Scroll);
self.base_style.overflow.y = Some(Overflow::Scroll);
self
}
pub fn overflow_x_scroll(mut self) -> Self {
self.base_style.overflow.x = Some(Overflow::Scroll);
self
}
pub fn overflow_y_scroll(mut self) -> Self {
self.base_style.overflow.y = Some(Overflow::Scroll);
self
}
}
impl<V> Div<V, StatelessInteraction<V>, FocusDisabled>
@@ -225,6 +196,7 @@ where
pub struct DivState {
interactive: InteractiveElementState,
focus_handle: Option<FocusHandle>,
child_layout_ids: SmallVec<[LayoutId; 4]>,
}
impl<V, I, F> Element for Div<V, I, F>
@@ -274,7 +246,8 @@ where
.children
.iter_mut()
.map(|child| child.layout(view_state, cx))
.collect::<Vec<_>>();
.collect::<SmallVec<_>>();
element_state.child_layout_ids = layout_ids.clone();
cx.request_layout(&style, layout_ids)
})
})
@@ -295,21 +268,38 @@ where
let style = this.compute_style(bounds, element_state, cx);
let z_index = style.z_index.unwrap_or(0);
// Paint background and event handlers.
let mut child_min = point(Pixels::MAX, Pixels::MAX);
let mut child_max = Point::default();
let content_size = if element_state.child_layout_ids.is_empty() {
bounds.size
} else {
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_min).into()
};
cx.stack(z_index, |cx| {
cx.stack(0, |cx| {
style.paint(bounds, cx);
this.focus.paint(bounds, cx);
this.interaction
.paint(bounds, &element_state.interactive, cx);
this.interaction.paint(
bounds,
content_size,
style.overflow,
&mut element_state.interactive,
cx,
);
});
cx.stack(1, |cx| {
style.apply_text_style(cx, |cx| {
style.apply_overflow(bounds, cx, |cx| {
let scroll_offset = element_state.interactive.scroll_offset();
for child in &mut this.children {
child.paint(view_state, None, cx);
child.paint(view_state, scroll_offset, cx);
}
})
})
+25
View File
@@ -205,6 +205,20 @@ where
}
}
impl<T> Sub for Size<T>
where
T: Sub<Output = T> + Clone + Default + Debug,
{
type Output = Size<T>;
fn sub(self, rhs: Self) -> Self::Output {
Size {
width: self.width - rhs.width,
height: self.height - rhs.height,
}
}
}
impl<T, Rhs> Mul<Rhs> for Size<T>
where
T: Mul<Rhs, Output = Rhs> + Clone + Default + Debug,
@@ -242,6 +256,15 @@ where
}
}
impl<T: Clone + Default + Debug> From<Point<T>> for Size<T> {
fn from(point: Point<T>) -> Self {
Self {
width: point.x,
height: point.y,
}
}
}
impl From<Size<Pixels>> for Size<GlobalPixels> {
fn from(size: Size<Pixels>) -> Self {
Size {
@@ -679,6 +702,8 @@ impl MulAssign<f32> for Pixels {
}
impl Pixels {
pub const MAX: Pixels = Pixels(f32::MAX);
pub fn round(&self) -> Self {
Self(self.0.round())
}
+43 -4
View File
@@ -1,7 +1,7 @@
use crate::{
point, Action, AppContext, BorrowWindow, Bounds, DispatchContext, DispatchPhase, Element,
ElementId, FocusHandle, KeyMatch, Keystroke, Modifiers, Pixels, Point, SharedString, Style,
StyleRefinement, ViewContext,
point, px, Action, AppContext, BorrowWindow, Bounds, DispatchContext, DispatchPhase, Element,
ElementId, FocusHandle, KeyMatch, Keystroke, Modifiers, Overflow, Pixels, Point, SharedString,
Size, Style, StyleRefinement, ViewContext,
};
use collections::HashMap;
use derive_more::{Deref, DerefMut};
@@ -375,7 +375,9 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
fn paint(
&mut self,
bounds: Bounds<Pixels>,
element_state: &InteractiveElementState,
content_size: Size<Pixels>,
overflow: Point<Overflow>,
element_state: &mut InteractiveElementState,
cx: &mut ViewContext<V>,
) {
let stateless = self.as_stateless();
@@ -468,6 +470,34 @@ pub trait ElementInteraction<V: 'static + Send + Sync>: 'static + Send + Sync {
}
});
}
if overflow.x == Overflow::Scroll || overflow.y == Overflow::Scroll {
let scroll_offset = element_state
.scroll_offset
.get_or_insert_with(Arc::default)
.clone();
let line_height = cx.line_height();
let scroll_max = content_size - bounds.size;
cx.on_mouse_event(move |_, event: &ScrollWheelEvent, _, cx| {
if bounds.contains_point(&event.position) {
let mut scroll_offset = scroll_offset.lock();
let delta = event.delta.pixel_delta(line_height);
if overflow.x == Overflow::Scroll {
scroll_offset.x =
(scroll_offset.x - delta.x).clamp(px(0.), scroll_max.width);
}
if overflow.y == Overflow::Scroll {
scroll_offset.y =
(scroll_offset.y - delta.y).clamp(px(0.), scroll_max.height);
}
cx.notify();
}
});
}
}
}
}
@@ -609,6 +639,15 @@ impl ActiveState {
pub struct InteractiveElementState {
active_state: Arc<Mutex<ActiveState>>,
pending_click: Arc<Mutex<Option<MouseDownEvent>>>,
scroll_offset: Option<Arc<Mutex<Point<Pixels>>>>,
}
impl InteractiveElementState {
pub fn scroll_offset(&self) -> Option<Point<Pixels>> {
self.scroll_offset
.as_ref()
.map(|offset| offset.lock().clone())
}
}
impl<V> Default for StatelessInteraction<V> {
+8
View File
@@ -457,6 +457,14 @@ impl<'a, 'w> WindowContext<'a, 'w> {
self.window.rem_size
}
pub fn line_height(&self) -> Pixels {
let rem_size = self.rem_size();
let text_style = self.text_style();
text_style
.line_height
.to_pixels(text_style.font_size.into(), rem_size)
}
pub fn stop_propagation(&mut self) {
self.window.propagate = false;
}