WIP
This commit is contained in:
parent
3de8fe0f87
commit
e115baa60c
94 changed files with 1477 additions and 1310 deletions
|
@ -46,13 +46,13 @@ impl<V: View> Element<V> for Align<V> {
|
|||
|
||||
fn layout(
|
||||
&mut self,
|
||||
view: &mut V,
|
||||
mut constraint: SizeConstraint,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let mut size = constraint.max;
|
||||
constraint.min = Vector2F::zero();
|
||||
let child_size = self.child.layout(view, constraint, cx);
|
||||
let child_size = self.child.layout(constraint, view, cx);
|
||||
if size.x().is_infinite() {
|
||||
size.set_x(child_size.x());
|
||||
}
|
||||
|
@ -64,11 +64,11 @@ impl<V: View> Element<V> for Align<V> {
|
|||
|
||||
fn paint(
|
||||
&mut self,
|
||||
view: &mut V,
|
||||
scene: &mut SceneBuilder,
|
||||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
let my_center = bounds.size() / 2.;
|
||||
|
@ -78,33 +78,33 @@ impl<V: View> Element<V> for Align<V> {
|
|||
let child_target = child_center + child_center * self.alignment;
|
||||
|
||||
self.child.paint(
|
||||
view,
|
||||
scene,
|
||||
bounds.origin() - (child_target - my_target),
|
||||
visible_bounds,
|
||||
view,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
|
||||
fn rect_for_text_range(
|
||||
&self,
|
||||
view: &V,
|
||||
range_utf16: std::ops::Range<usize>,
|
||||
_: RectF,
|
||||
_: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
view: &V,
|
||||
cx: &ViewContext<V>,
|
||||
) -> Option<RectF> {
|
||||
self.child.rect_for_text_range(view, range_utf16, cx)
|
||||
self.child.rect_for_text_range(range_utf16, view, cx)
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
view: &V,
|
||||
bounds: pathfinder_geometry::rect::RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
view: &V,
|
||||
cx: &ViewContext<V>,
|
||||
) -> json::Value {
|
||||
json!({
|
||||
|
|
|
@ -25,7 +25,7 @@ where
|
|||
|
||||
impl<V: View, F> Element<V> for Canvas<V, F>
|
||||
where
|
||||
F: FnMut(RectF, RectF, &mut ViewContext<V>),
|
||||
F: FnMut(&mut SceneBuilder, RectF, RectF, &mut V, &mut ViewContext<V>),
|
||||
{
|
||||
type LayoutState = ();
|
||||
type PaintState = ();
|
||||
|
@ -58,7 +58,7 @@ where
|
|||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
self.0(bounds, visible_bounds, cx)
|
||||
self.0(scene, bounds, visible_bounds, view, cx)
|
||||
}
|
||||
|
||||
fn rect_for_text_range(
|
||||
|
|
|
@ -37,10 +37,10 @@ impl<V: View> Element<V> for Clipped<V> {
|
|||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
cx.scene.push_layer(Some(bounds));
|
||||
self.child
|
||||
.paint(scene, bounds.origin(), visible_bounds, view, cx);
|
||||
cx.scene.pop_layer();
|
||||
scene.paint_layer(Some(bounds), |scene| {
|
||||
self.child
|
||||
.paint(scene, bounds.origin(), visible_bounds, view, cx)
|
||||
})
|
||||
}
|
||||
|
||||
fn rect_for_text_range(
|
||||
|
|
|
@ -157,7 +157,7 @@ impl<V: View> Element<V> for ConstrainedBox<V> {
|
|||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
cx.paint_layer(Some(visible_bounds), |cx| {
|
||||
scene.paint_layer(Some(visible_bounds), |scene| {
|
||||
self.child
|
||||
.paint(scene, bounds.origin(), visible_bounds, view, cx);
|
||||
})
|
||||
|
|
|
@ -221,7 +221,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
);
|
||||
|
||||
if let Some(shadow) = self.style.shadow.as_ref() {
|
||||
cx.scene.push_shadow(scene::Shadow {
|
||||
scene.push_shadow(scene::Shadow {
|
||||
bounds: quad_bounds + shadow.offset,
|
||||
corner_radius: self.style.corner_radius,
|
||||
sigma: shadow.blur,
|
||||
|
@ -231,7 +231,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
|
||||
if let Some(hit_bounds) = quad_bounds.intersection(visible_bounds) {
|
||||
if let Some(style) = self.style.cursor {
|
||||
cx.scene.push_cursor_region(CursorRegion {
|
||||
scene.push_cursor_region(CursorRegion {
|
||||
bounds: hit_bounds,
|
||||
style,
|
||||
});
|
||||
|
@ -242,7 +242,7 @@ impl<V: View> Element<V> for Container<V> {
|
|||
quad_bounds.origin() + vec2f(self.style.padding.left, self.style.padding.top);
|
||||
|
||||
if self.style.border.overlay {
|
||||
cx.scene.push_quad(Quad {
|
||||
scene.push_quad(Quad {
|
||||
bounds: quad_bounds,
|
||||
background: self.style.background_color,
|
||||
border: Default::default(),
|
||||
|
@ -252,16 +252,16 @@ impl<V: View> Element<V> for Container<V> {
|
|||
self.child
|
||||
.paint(scene, child_origin, visible_bounds, view, cx);
|
||||
|
||||
cx.scene.push_layer(None);
|
||||
cx.scene.push_quad(Quad {
|
||||
scene.push_layer(None);
|
||||
scene.push_quad(Quad {
|
||||
bounds: quad_bounds,
|
||||
background: self.style.overlay_color,
|
||||
border: self.style.border,
|
||||
corner_radius: self.style.corner_radius,
|
||||
});
|
||||
cx.scene.pop_layer();
|
||||
scene.pop_layer();
|
||||
} else {
|
||||
cx.scene.push_quad(Quad {
|
||||
scene.push_quad(Quad {
|
||||
bounds: quad_bounds,
|
||||
background: self.style.background_color,
|
||||
border: self.style.border,
|
||||
|
@ -277,14 +277,14 @@ impl<V: View> Element<V> for Container<V> {
|
|||
.paint(scene, child_origin, visible_bounds, view, cx);
|
||||
|
||||
if self.style.overlay_color.is_some() {
|
||||
cx.scene.push_layer(None);
|
||||
cx.scene.push_quad(Quad {
|
||||
scene.push_layer(None);
|
||||
scene.push_quad(Quad {
|
||||
bounds: quad_bounds,
|
||||
background: self.style.overlay_color,
|
||||
border: Default::default(),
|
||||
corner_radius: 0.,
|
||||
});
|
||||
cx.scene.pop_layer();
|
||||
scene.pop_layer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ impl<V: View> Element<V> for Empty {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
_: &V,
|
||||
_: &mut V,
|
||||
_: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let x = if constraint.max.x().is_finite() && !self.collapsed {
|
||||
|
@ -56,6 +56,7 @@ impl<V: View> Element<V> for Empty {
|
|||
_: RectF,
|
||||
_: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut V,
|
||||
_: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ impl<V: View> Element<V> for Expanded<V> {
|
|||
&mut self,
|
||||
mut constraint: SizeConstraint,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<Self>,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
if self.full_width {
|
||||
constraint.min.set_x(constraint.max.x());
|
||||
|
|
|
@ -73,7 +73,7 @@ impl<V: View> Flex<V> {
|
|||
remaining_space: &mut f32,
|
||||
remaining_flex: &mut f32,
|
||||
cross_axis_max: &mut f32,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
let cross_axis = self.axis.invert();
|
||||
|
@ -124,7 +124,7 @@ impl<V: View> Element<V> for Flex<V> {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let mut total_flex = None;
|
||||
|
@ -253,7 +253,7 @@ impl<V: View> Element<V> for Flex<V> {
|
|||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
remaining_space: &mut Self::LayoutState,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
|
||||
|
@ -261,16 +261,16 @@ impl<V: View> Element<V> for Flex<V> {
|
|||
let mut remaining_space = *remaining_space;
|
||||
let overflowing = remaining_space < 0.;
|
||||
if overflowing {
|
||||
cx.scene.push_layer(Some(visible_bounds));
|
||||
scene.push_layer(Some(visible_bounds));
|
||||
}
|
||||
|
||||
if let Some(scroll_state) = &self.scroll_state {
|
||||
cx.scene.push_mouse_region(
|
||||
scene.push_mouse_region(
|
||||
crate::MouseRegion::new::<Self>(scroll_state.1, 0, bounds)
|
||||
.on_scroll({
|
||||
let scroll_state = scroll_state.0.read(cx).clone();
|
||||
let axis = self.axis;
|
||||
move |e, cx| {
|
||||
move |e, _: &mut V, cx| {
|
||||
if remaining_space < 0. {
|
||||
let scroll_delta = e.delta.raw();
|
||||
|
||||
|
@ -298,7 +298,7 @@ impl<V: View> Element<V> for Flex<V> {
|
|||
}
|
||||
}
|
||||
})
|
||||
.on_move(|_, _| { /* Capture move events */ }),
|
||||
.on_move(|_, _: &mut V, _| { /* Capture move events */ }),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,7 @@ impl<V: View> Element<V> for Flex<V> {
|
|||
}
|
||||
|
||||
if overflowing {
|
||||
cx.scene.pop_layer();
|
||||
scene.pop_layer();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,7 +372,7 @@ impl<V: View> Element<V> for Flex<V> {
|
|||
) -> Option<RectF> {
|
||||
self.children
|
||||
.iter()
|
||||
.find_map(|child| child.rect_for_text_range(view, range_utf16.clone(), cx))
|
||||
.find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
|
||||
}
|
||||
|
||||
fn debug(
|
||||
|
@ -431,7 +431,7 @@ impl<V: View> Element<V> for FlexItem<V> {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size = self.child.layout(constraint, view, cx);
|
||||
|
@ -444,7 +444,7 @@ impl<V: View> Element<V> for FlexItem<V> {
|
|||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
self.child
|
||||
|
@ -474,7 +474,6 @@ impl<V: View> Element<V> for FlexItem<V> {
|
|||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
view: &V,
|
||||
|
||||
cx: &ViewContext<V>,
|
||||
) -> Value {
|
||||
json!({
|
||||
|
|
|
@ -35,7 +35,7 @@ impl<V: View> Element<V> for Hook<V> {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size = self.child.layout(constraint, view, cx);
|
||||
|
|
|
@ -62,7 +62,7 @@ impl<V: View> Element<V> for Image {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
view: &V,
|
||||
_: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let data = match &self.source {
|
||||
|
@ -94,8 +94,8 @@ impl<V: View> Element<V> for Image {
|
|||
bounds: RectF,
|
||||
_: RectF,
|
||||
layout: &mut Self::LayoutState,
|
||||
_: &V,
|
||||
cx: &mut ViewContext<V>,
|
||||
_: &mut V,
|
||||
_: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
if let Some(data) = layout {
|
||||
scene.push_image(scene::Image {
|
||||
|
|
|
@ -41,12 +41,11 @@ impl<V: View> Element<V> for KeystrokeLabel {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, ElementBox<V>) {
|
||||
let mut element = if let Some(keystrokes) =
|
||||
cx.app
|
||||
.keystrokes_for_action(self.window_id, self.view_id, self.action.as_ref())
|
||||
cx.keystrokes_for_action(self.window_id, self.view_id, self.action.as_ref())
|
||||
{
|
||||
Flex::row()
|
||||
.with_children(keystrokes.iter().map(|keystroke| {
|
||||
|
@ -70,7 +69,7 @@ impl<V: View> Element<V> for KeystrokeLabel {
|
|||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
element: &mut ElementBox<V>,
|
||||
view: &V,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) {
|
||||
element.paint(scene, bounds.origin(), visible_bounds, view, cx);
|
||||
|
|
|
@ -134,13 +134,15 @@ impl<V: View> Element<V> for Label {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
view: &V,
|
||||
_: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let runs = self.compute_runs();
|
||||
let line =
|
||||
cx.text_layout_cache
|
||||
.layout_str(&self.text, self.style.text.font_size, runs.as_slice());
|
||||
let line = cx.text_layout_cache().layout_str(
|
||||
&self.text,
|
||||
self.style.text.font_size,
|
||||
runs.as_slice(),
|
||||
);
|
||||
|
||||
let size = vec2f(
|
||||
line.width()
|
||||
|
@ -159,8 +161,8 @@ impl<V: View> Element<V> for Label {
|
|||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
line: &mut Self::LayoutState,
|
||||
_: &V,
|
||||
cx: &mut ViewContext<Self>,
|
||||
_: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
line.paint(
|
||||
scene,
|
||||
|
|
|
@ -13,7 +13,6 @@ pub struct List<V: View> {
|
|||
state: ListState<V>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ListState<V: View>(Rc<RefCell<StateInner<V>>>);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
|
@ -42,7 +41,7 @@ pub struct ListOffset {
|
|||
|
||||
enum ListItem<V: View> {
|
||||
Unrendered,
|
||||
Rendered(Rc<ElementBox<V>>),
|
||||
Rendered(Rc<RefCell<ElementBox<V>>>),
|
||||
Removed(f32),
|
||||
}
|
||||
|
||||
|
@ -145,7 +144,7 @@ impl<V: View> Element<V> for List<V> {
|
|||
view,
|
||||
cx,
|
||||
) {
|
||||
rendered_height += element.size().y();
|
||||
rendered_height += element.borrow().size().y();
|
||||
rendered_items.push_back(ListItem::Rendered(element));
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +161,7 @@ impl<V: View> Element<V> for List<V> {
|
|||
if let Some(element) =
|
||||
state.render_item(cursor.start().0, None, item_constraint, view, cx)
|
||||
{
|
||||
rendered_height += element.size().y();
|
||||
rendered_height += element.borrow().size().y();
|
||||
rendered_items.push_front(ListItem::Rendered(element));
|
||||
}
|
||||
} else {
|
||||
|
@ -198,7 +197,7 @@ impl<V: View> Element<V> for List<V> {
|
|||
if let Some(element) =
|
||||
state.render_item(cursor.start().0, Some(item), item_constraint, view, cx)
|
||||
{
|
||||
leading_overdraw += element.size().y();
|
||||
leading_overdraw += element.borrow().size().y();
|
||||
rendered_items.push_front(ListItem::Rendered(element));
|
||||
}
|
||||
} else {
|
||||
|
@ -264,12 +263,13 @@ impl<V: View> Element<V> for List<V> {
|
|||
let state = self.state.clone();
|
||||
let height = bounds.height();
|
||||
let scroll_top = scroll_top.clone();
|
||||
move |e, cx| {
|
||||
move |e, view, cx| {
|
||||
state.0.borrow_mut().scroll(
|
||||
&scroll_top,
|
||||
height,
|
||||
*e.platform_event.delta.raw(),
|
||||
e.platform_event.delta.precise(),
|
||||
view,
|
||||
cx,
|
||||
)
|
||||
}
|
||||
|
@ -277,8 +277,10 @@ impl<V: View> Element<V> for List<V> {
|
|||
);
|
||||
|
||||
let state = &mut *self.state.0.borrow_mut();
|
||||
for (mut element, origin) in state.visible_elements(bounds, scroll_top) {
|
||||
element.paint(scene, origin, visible_bounds, view, cx);
|
||||
for (element, origin) in state.visible_elements(bounds, scroll_top) {
|
||||
element
|
||||
.borrow_mut()
|
||||
.paint(scene, origin, visible_bounds, view, cx);
|
||||
}
|
||||
|
||||
scene.pop_layer();
|
||||
|
@ -304,11 +306,15 @@ impl<V: View> Element<V> for List<V> {
|
|||
}
|
||||
|
||||
if let ListItem::Rendered(element) = item {
|
||||
if let Some(rect) = element.rect_for_text_range(range_utf16.clone(), view, cx) {
|
||||
if let Some(rect) =
|
||||
element
|
||||
.borrow()
|
||||
.rect_for_text_range(range_utf16.clone(), view, cx)
|
||||
{
|
||||
return Some(rect);
|
||||
}
|
||||
|
||||
item_origin.set_y(item_origin.y() + element.size().y());
|
||||
item_origin.set_y(item_origin.y() + element.borrow().size().y());
|
||||
cursor.next(&());
|
||||
} else {
|
||||
unreachable!();
|
||||
|
@ -329,7 +335,7 @@ impl<V: View> Element<V> for List<V> {
|
|||
let state = self.state.0.borrow_mut();
|
||||
let visible_elements = state
|
||||
.visible_elements(bounds, scroll_top)
|
||||
.map(|e| e.0.debug(view, cx))
|
||||
.map(|e| e.0.borrow().debug(view, cx))
|
||||
.collect::<Vec<_>>();
|
||||
let visible_range = scroll_top.item_ix..(scroll_top.item_ix + visible_elements.len());
|
||||
json!({
|
||||
|
@ -345,8 +351,7 @@ impl<V: View> ListState<V> {
|
|||
element_count: usize,
|
||||
orientation: Orientation,
|
||||
overdraw: f32,
|
||||
cx: &mut ViewContext<V>,
|
||||
mut render_item: F,
|
||||
render_item: F,
|
||||
) -> Self
|
||||
where
|
||||
V: View,
|
||||
|
@ -354,14 +359,9 @@ impl<V: View> ListState<V> {
|
|||
{
|
||||
let mut items = SumTree::new();
|
||||
items.extend((0..element_count).map(|_| ListItem::Unrendered), &());
|
||||
let handle = cx.weak_handle();
|
||||
Self(Rc::new(RefCell::new(StateInner {
|
||||
last_layout_width: None,
|
||||
render_item: Box::new(move |ix, view, cx| {
|
||||
render_item(view, ix, cx)
|
||||
// let handle = handle.upgrade(cx)?;
|
||||
// Some(cx.render(&handle, |view, cx| render_item(view, ix, cx)))
|
||||
}),
|
||||
render_item: Box::new(render_item),
|
||||
rendered_range: 0..0,
|
||||
items,
|
||||
logical_scroll_top: None,
|
||||
|
@ -439,6 +439,12 @@ impl<V: View> ListState<V> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<V: View> Clone for ListState<V> {
|
||||
fn clone(&self) -> Self {
|
||||
Self(self.0.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View> StateInner<V> {
|
||||
fn render_item(
|
||||
&mut self,
|
||||
|
@ -447,13 +453,13 @@ impl<V: View> StateInner<V> {
|
|||
constraint: SizeConstraint,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Option<Rc<ElementBox<V>>> {
|
||||
) -> Option<Rc<RefCell<ElementBox<V>>>> {
|
||||
if let Some(ListItem::Rendered(element)) = existing_element {
|
||||
Some(element.clone())
|
||||
} else {
|
||||
let mut element = (self.render_item)(view, ix, cx);
|
||||
element.layout(constraint, view, cx);
|
||||
Some(element.into())
|
||||
Some(Rc::new(RefCell::new(element)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,7 +475,7 @@ impl<V: View> StateInner<V> {
|
|||
&'a self,
|
||||
bounds: RectF,
|
||||
scroll_top: &ListOffset,
|
||||
) -> impl Iterator<Item = (Rc<ElementBox<V>>, Vector2F)> + 'a {
|
||||
) -> impl Iterator<Item = (Rc<RefCell<ElementBox<V>>>, Vector2F)> + 'a {
|
||||
let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item);
|
||||
let mut cursor = self.items.cursor::<Count>();
|
||||
cursor.seek(&Count(scroll_top.item_ix), Bias::Right, &());
|
||||
|
@ -481,7 +487,7 @@ impl<V: View> StateInner<V> {
|
|||
|
||||
if let ListItem::Rendered(element) = item {
|
||||
let result = (element.clone(), item_origin);
|
||||
item_origin.set_y(item_origin.y() + element.size().y());
|
||||
item_origin.set_y(item_origin.y() + element.borrow().size().y());
|
||||
cursor.next(&());
|
||||
return Some(result);
|
||||
}
|
||||
|
@ -526,7 +532,7 @@ impl<V: View> StateInner<V> {
|
|||
|
||||
if self.scroll_handler.is_some() {
|
||||
let visible_range = self.visible_range(height, scroll_top);
|
||||
self.scroll_handler.as_mut().unwrap()(visible_range, cx);
|
||||
self.scroll_handler.as_mut().unwrap()(visible_range, view, cx);
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
|
@ -557,7 +563,7 @@ impl<V: View> ListItem<V> {
|
|||
fn remove(&self) -> Self {
|
||||
match self {
|
||||
ListItem::Unrendered => ListItem::Unrendered,
|
||||
ListItem::Rendered(element) => ListItem::Removed(element.size().y()),
|
||||
ListItem::Rendered(element) => ListItem::Removed(element.borrow().size().y()),
|
||||
ListItem::Removed(height) => ListItem::Removed(*height),
|
||||
}
|
||||
}
|
||||
|
@ -578,7 +584,7 @@ impl<V: View> sum_tree::Item for ListItem<V> {
|
|||
count: 1,
|
||||
rendered_count: 1,
|
||||
unrendered_count: 0,
|
||||
height: element.size().y(),
|
||||
height: element.borrow().size().y(),
|
||||
},
|
||||
ListItem::Removed(height) => ListItemSummary {
|
||||
count: 1,
|
||||
|
@ -642,7 +648,6 @@ mod tests {
|
|||
use super::*;
|
||||
use crate::{elements::Empty, geometry::vector::vec2f, Entity};
|
||||
use rand::prelude::*;
|
||||
use std::env;
|
||||
|
||||
#[crate::test(self)]
|
||||
fn test_layout(cx: &mut crate::AppContext) {
|
||||
|
|
|
@ -7,8 +7,8 @@ use crate::{
|
|||
platform::CursorStyle,
|
||||
platform::MouseButton,
|
||||
scene::{
|
||||
CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover,
|
||||
MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
|
||||
CursorRegion, EventContext, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag,
|
||||
MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut,
|
||||
},
|
||||
Element, ElementBox, MouseRegion, MouseState, SceneBuilder, SizeConstraint, View, ViewContext,
|
||||
};
|
||||
|
@ -31,13 +31,13 @@ pub struct MouseEventHandler<Tag: 'static, V: View> {
|
|||
/// Element which provides a render_child callback with a MouseState and paints a mouse
|
||||
/// region under (or above) it for easy mouse event handling.
|
||||
impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
||||
pub fn new<F>(region_id: usize, view: &mut V, cx: &mut ViewContext<V>, render_child: F) -> Self
|
||||
pub fn new<F>(region_id: usize, cx: &mut ViewContext<V>, render_child: F) -> Self
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&mut MouseState, &mut V, &mut ViewContext<V>) -> ElementBox<V>,
|
||||
F: FnOnce(&mut MouseState, &mut ViewContext<V>) -> ElementBox<V>,
|
||||
{
|
||||
let mut mouse_state = cx.mouse_state::<Tag>(region_id);
|
||||
let child = render_child(&mut mouse_state, view, cx);
|
||||
let child = render_child(&mut mouse_state, cx);
|
||||
let notify_on_hover = mouse_state.accessed_hovered();
|
||||
let notify_on_click = mouse_state.accessed_clicked();
|
||||
Self {
|
||||
|
@ -57,17 +57,12 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
/// Modifies the MouseEventHandler to render the MouseRegion above the child element. Useful
|
||||
/// for drag and drop handling and similar events which should be captured before the child
|
||||
/// gets the opportunity
|
||||
pub fn above<F>(
|
||||
region_id: usize,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
render_child: F,
|
||||
) -> Self
|
||||
pub fn above<F>(region_id: usize, cx: &mut ViewContext<V>, render_child: F) -> Self
|
||||
where
|
||||
V: View,
|
||||
F: FnOnce(&mut MouseState, &mut V, &mut ViewContext<V>) -> ElementBox<V>,
|
||||
F: FnOnce(&mut MouseState, &mut ViewContext<V>) -> ElementBox<V>,
|
||||
{
|
||||
let mut handler = Self::new(region_id, view, cx, render_child);
|
||||
let mut handler = Self::new(region_id, cx, render_child);
|
||||
handler.above = true;
|
||||
handler
|
||||
}
|
||||
|
@ -82,14 +77,17 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn on_move(mut self, handler: impl Fn(MouseMove, &mut ViewContext<V>) + 'static) -> Self {
|
||||
pub fn on_move(
|
||||
mut self,
|
||||
handler: impl Fn(MouseMove, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_move(handler);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_move_out(
|
||||
mut self,
|
||||
handler: impl Fn(MouseMoveOut, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseMoveOut, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_move_out(handler);
|
||||
self
|
||||
|
@ -98,7 +96,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
pub fn on_down(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(MouseDown, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseDown, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_down(button, handler);
|
||||
self
|
||||
|
@ -107,7 +105,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
pub fn on_up(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(MouseUp, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseUp, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_up(button, handler);
|
||||
self
|
||||
|
@ -116,7 +114,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
pub fn on_click(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(MouseClick, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseClick, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_click(button, handler);
|
||||
self
|
||||
|
@ -125,7 +123,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
pub fn on_down_out(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(MouseDownOut, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseDownOut, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_down_out(button, handler);
|
||||
self
|
||||
|
@ -134,7 +132,7 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
pub fn on_up_out(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(MouseUpOut, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseUpOut, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_up_out(button, handler);
|
||||
self
|
||||
|
@ -143,20 +141,23 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
pub fn on_drag(
|
||||
mut self,
|
||||
button: MouseButton,
|
||||
handler: impl Fn(MouseDrag, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseDrag, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_drag(button, handler);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_hover(mut self, handler: impl Fn(MouseHover, &mut ViewContext<V>) + 'static) -> Self {
|
||||
pub fn on_hover(
|
||||
mut self,
|
||||
handler: impl Fn(MouseHover, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_hover(handler);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn on_scroll(
|
||||
mut self,
|
||||
handler: impl Fn(MouseScrollWheel, &mut ViewContext<V>) + 'static,
|
||||
handler: impl Fn(MouseScrollWheel, &mut V, &mut EventContext<V>) + 'static,
|
||||
) -> Self {
|
||||
self.handlers = self.handlers.on_scroll(handler);
|
||||
self
|
||||
|
@ -191,14 +192,14 @@ impl<Tag, V: View> MouseEventHandler<Tag, V> {
|
|||
let hit_bounds = self.hit_bounds(visible_bounds);
|
||||
|
||||
if let Some(style) = self.cursor_style {
|
||||
cx.scene.push_cursor_region(CursorRegion {
|
||||
scene.push_cursor_region(CursorRegion {
|
||||
bounds: hit_bounds,
|
||||
style,
|
||||
});
|
||||
}
|
||||
cx.scene.push_mouse_region(
|
||||
scene.push_mouse_region(
|
||||
MouseRegion::from_handlers::<Tag>(
|
||||
cx.current_view_id(),
|
||||
cx.view_id(),
|
||||
self.region_id,
|
||||
hit_bounds,
|
||||
self.handlers.clone(),
|
||||
|
@ -236,7 +237,7 @@ impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> {
|
|||
self.child
|
||||
.paint(scene, bounds.origin(), visible_bounds, view, cx);
|
||||
|
||||
cx.paint_layer(None, |cx| {
|
||||
scene.paint_layer(None, |scene| {
|
||||
self.paint_regions(scene, bounds, visible_bounds, cx);
|
||||
});
|
||||
} else {
|
||||
|
@ -254,7 +255,7 @@ impl<Tag, V: View> Element<V> for MouseEventHandler<Tag, V> {
|
|||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
view: &V,
|
||||
cx: &ViewContext<Self>,
|
||||
cx: &ViewContext<V>,
|
||||
) -> Option<RectF> {
|
||||
self.child.rect_for_text_range(range_utf16, view, cx)
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ impl<V: View> Element<V> for Overlay<V> {
|
|||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let constraint = if self.anchor_position.is_some() {
|
||||
SizeConstraint::new(Vector2F::zero(), cx.window_size)
|
||||
SizeConstraint::new(Vector2F::zero(), cx.window_size())
|
||||
} else {
|
||||
constraint
|
||||
};
|
||||
|
@ -137,7 +137,7 @@ impl<V: View> Element<V> for Overlay<V> {
|
|||
|
||||
fn paint(
|
||||
&mut self,
|
||||
scene: SceneBuilder,
|
||||
scene: &mut SceneBuilder,
|
||||
bounds: RectF,
|
||||
_: RectF,
|
||||
size: &mut Self::LayoutState,
|
||||
|
@ -163,9 +163,9 @@ impl<V: View> Element<V> for Overlay<V> {
|
|||
OverlayFitMode::SnapToWindow => {
|
||||
// Snap the horizontal edges of the overlay to the horizontal edges of the window if
|
||||
// its horizontal bounds overflow
|
||||
if bounds.max_x() > cx.window_size.x() {
|
||||
if bounds.max_x() > cx.window_size().x() {
|
||||
let mut lower_right = bounds.lower_right();
|
||||
lower_right.set_x(cx.window_size.x());
|
||||
lower_right.set_x(cx.window_size().x());
|
||||
bounds = RectF::from_points(lower_right - *size, lower_right);
|
||||
} else if bounds.min_x() < 0. {
|
||||
let mut upper_left = bounds.origin();
|
||||
|
@ -175,9 +175,9 @@ impl<V: View> Element<V> for Overlay<V> {
|
|||
|
||||
// Snap the vertical edges of the overlay to the vertical edges of the window if
|
||||
// its vertical bounds overflow.
|
||||
if bounds.max_y() > cx.window_size.y() {
|
||||
if bounds.max_y() > cx.window_size().y() {
|
||||
let mut lower_right = bounds.lower_right();
|
||||
lower_right.set_y(cx.window_size.y());
|
||||
lower_right.set_y(cx.window_size().y());
|
||||
bounds = RectF::from_points(lower_right - *size, lower_right);
|
||||
} else if bounds.min_y() < 0. {
|
||||
let mut upper_left = bounds.origin();
|
||||
|
@ -188,11 +188,11 @@ impl<V: View> Element<V> for Overlay<V> {
|
|||
OverlayFitMode::SwitchAnchor => {
|
||||
let mut anchor_corner = self.anchor_corner;
|
||||
|
||||
if bounds.max_x() > cx.window_size.x() {
|
||||
if bounds.max_x() > cx.window_size().x() {
|
||||
anchor_corner = anchor_corner.switch_axis(Axis::Horizontal);
|
||||
}
|
||||
|
||||
if bounds.max_y() > cx.window_size.y() {
|
||||
if bounds.max_y() > cx.window_size().y() {
|
||||
anchor_corner = anchor_corner.switch_axis(Axis::Vertical);
|
||||
}
|
||||
|
||||
|
@ -212,22 +212,21 @@ impl<V: View> Element<V> for Overlay<V> {
|
|||
OverlayFitMode::None => {}
|
||||
}
|
||||
|
||||
cx.paint_stacking_context(None, self.z_index, |cx| {
|
||||
scene.paint_stacking_context(None, self.z_index, |scene| {
|
||||
if self.hoverable {
|
||||
enum OverlayHoverCapture {}
|
||||
// Block hovers in lower stacking contexts
|
||||
cx.scene
|
||||
.push_mouse_region(MouseRegion::new::<OverlayHoverCapture>(
|
||||
cx.current_view_id(),
|
||||
cx.current_view_id(),
|
||||
bounds,
|
||||
));
|
||||
scene.push_mouse_region(MouseRegion::new::<OverlayHoverCapture>(
|
||||
cx.view_id(),
|
||||
cx.view_id(),
|
||||
bounds,
|
||||
));
|
||||
}
|
||||
|
||||
self.child.paint(
|
||||
scene,
|
||||
bounds.origin(),
|
||||
RectF::new(Vector2F::zero(), cx.window_size),
|
||||
RectF::new(Vector2F::zero(), cx.window_size()),
|
||||
view,
|
||||
cx,
|
||||
);
|
||||
|
|
|
@ -154,32 +154,28 @@ impl<V: View> Element<V> for Resizable<V> {
|
|||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
cx.scene.push_stacking_context(None, None);
|
||||
scene.push_stacking_context(None, None);
|
||||
|
||||
let handle_region = self.side.of_rect(bounds, self.handle_size);
|
||||
|
||||
enum ResizeHandle {}
|
||||
cx.scene.push_mouse_region(
|
||||
MouseRegion::new::<ResizeHandle>(
|
||||
cx.current_view_id(),
|
||||
self.side as usize,
|
||||
handle_region,
|
||||
)
|
||||
.on_down(MouseButton::Left, |_, _| {}) // This prevents the mouse down event from being propagated elsewhere
|
||||
.on_drag(MouseButton::Left, {
|
||||
let state = self.state.clone();
|
||||
let side = self.side;
|
||||
move |e, cx| {
|
||||
let prev_width = state.actual_dimension.get();
|
||||
state
|
||||
.custom_dimension
|
||||
.set(0f32.max(prev_width + side.compute_delta(e)).round());
|
||||
cx.notify();
|
||||
}
|
||||
}),
|
||||
scene.push_mouse_region(
|
||||
MouseRegion::new::<ResizeHandle>(cx.view_id(), self.side as usize, handle_region)
|
||||
.on_down(MouseButton::Left, |_, _: &mut V, _| {}) // This prevents the mouse down event from being propagated elsewhere
|
||||
.on_drag(MouseButton::Left, {
|
||||
let state = self.state.clone();
|
||||
let side = self.side;
|
||||
move |e, _: &mut V, cx| {
|
||||
let prev_width = state.actual_dimension.get();
|
||||
state
|
||||
.custom_dimension
|
||||
.set(0f32.max(prev_width + side.compute_delta(e)).round());
|
||||
cx.notify();
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
cx.scene.push_cursor_region(crate::CursorRegion {
|
||||
scene.push_cursor_region(crate::CursorRegion {
|
||||
bounds: handle_region,
|
||||
style: match self.side.axis() {
|
||||
Axis::Horizontal => CursorStyle::ResizeLeftRight,
|
||||
|
@ -187,7 +183,7 @@ impl<V: View> Element<V> for Resizable<V> {
|
|||
},
|
||||
});
|
||||
|
||||
cx.scene.pop_stacking_context();
|
||||
scene.pop_stacking_context();
|
||||
|
||||
self.child
|
||||
.paint(scene, bounds.origin(), visible_bounds, view, cx);
|
||||
|
|
|
@ -8,11 +8,18 @@ use crate::{
|
|||
|
||||
/// Element which renders it's children in a stack on top of each other.
|
||||
/// The first child determines the size of the others.
|
||||
#[derive(Default)]
|
||||
pub struct Stack<V: View> {
|
||||
children: Vec<ElementBox<V>>,
|
||||
}
|
||||
|
||||
impl<V: View> Default for Stack<V> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
children: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<V: View> Stack<V> {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
|
@ -53,7 +60,7 @@ impl<V: View> Element<V> for Stack<V> {
|
|||
cx: &mut ViewContext<V>,
|
||||
) -> Self::PaintState {
|
||||
for child in &mut self.children {
|
||||
cx.paint_layer(None, |cx| {
|
||||
scene.paint_layer(None, |scene| {
|
||||
child.paint(scene, bounds.origin(), visible_bounds, view, cx);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ impl<V: View> Element<V> for Svg {
|
|||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
view: &mut V,
|
||||
_: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
match cx.asset_cache.svg(&self.path) {
|
||||
|
|
|
@ -98,7 +98,7 @@ impl<V: View> Element<V> for Text {
|
|||
let shaped_lines = layout_highlighted_chunks(
|
||||
chunks,
|
||||
&self.style,
|
||||
cx.text_layout_cache,
|
||||
cx.text_layout_cache(),
|
||||
&cx.font_cache,
|
||||
usize::MAX,
|
||||
self.text.matches('\n').count() + 1,
|
||||
|
@ -213,9 +213,9 @@ impl<V: View> Element<V> for Text {
|
|||
/// Perform text layout on a series of highlighted chunks of text.
|
||||
pub fn layout_highlighted_chunks<'a>(
|
||||
chunks: impl Iterator<Item = (&'a str, Option<HighlightStyle>)>,
|
||||
text_style: &'a TextStyle,
|
||||
text_layout_cache: &'a TextLayoutCache,
|
||||
font_cache: &'a Arc<FontCache>,
|
||||
text_style: &TextStyle,
|
||||
text_layout_cache: &TextLayoutCache,
|
||||
font_cache: &Arc<FontCache>,
|
||||
max_line_len: usize,
|
||||
max_line_count: usize,
|
||||
) -> Vec<Line> {
|
||||
|
@ -276,26 +276,22 @@ pub fn layout_highlighted_chunks<'a>(
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
elements::Empty, fonts, platform, AppContext, ElementBox, Entity, View, ViewContext,
|
||||
};
|
||||
use crate::{elements::Empty, fonts, AppContext, ElementBox, Entity, View, ViewContext};
|
||||
|
||||
#[crate::test(self)]
|
||||
fn test_soft_wrapping_with_carriage_returns(cx: &mut AppContext) {
|
||||
let (window_id, root_view) = cx.add_window(Default::default(), |_| TestView);
|
||||
let mut presenter = cx.build_window(
|
||||
window_id,
|
||||
root_view.into_any(),
|
||||
Box::new(platform::test::Window::new(Vector2F::new(800., 600.))),
|
||||
);
|
||||
fonts::with_font_cache(cx.font_cache().clone(), || {
|
||||
let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true);
|
||||
let (_, state) = text.layout(
|
||||
SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)),
|
||||
&mut presenter.build_layout_context(Default::default(), false, cx),
|
||||
);
|
||||
assert_eq!(state.shaped_lines.len(), 2);
|
||||
assert_eq!(state.wrap_boundaries.len(), 2);
|
||||
root_view.update(cx, |view, cx| {
|
||||
let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true);
|
||||
let (_, state) = text.layout(
|
||||
SizeConstraint::new(Default::default(), vec2f(f32::INFINITY, f32::INFINITY)),
|
||||
view,
|
||||
cx,
|
||||
);
|
||||
assert_eq!(state.shaped_lines.len(), 2);
|
||||
assert_eq!(state.wrap_boundaries.len(), 2);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ impl<V: View> Tooltip<V> {
|
|||
action: Option<Box<dyn Action>>,
|
||||
style: TooltipStyle,
|
||||
child: ElementBox<V>,
|
||||
view: &mut V,
|
||||
cx: &mut ViewContext<V>,
|
||||
) -> Self {
|
||||
struct ElementState<Tag>(Tag);
|
||||
|
@ -78,10 +77,10 @@ impl<V: View> Tooltip<V> {
|
|||
Overlay::new(
|
||||
Self::render_tooltip(cx.window_id, focused_view_id, text, style, action, false)
|
||||
.constrained()
|
||||
.dynamically(move |constraint, cx| {
|
||||
.dynamically(move |constraint, view, cx| {
|
||||
SizeConstraint::strict_along(
|
||||
Axis::Vertical,
|
||||
collapsed_tooltip.layout(constraint, cx).y(),
|
||||
collapsed_tooltip.layout(constraint, view, cx).y(),
|
||||
)
|
||||
})
|
||||
.boxed(),
|
||||
|
@ -93,36 +92,34 @@ impl<V: View> Tooltip<V> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let child =
|
||||
MouseEventHandler::<MouseEventHandlerState<Tag>>::new(id, view, cx, |_, _| child)
|
||||
.on_hover(move |e, cx| {
|
||||
let position = e.position;
|
||||
let window_id = cx.window_id();
|
||||
if let Some(view_id) = cx.view_id() {
|
||||
if e.started {
|
||||
if !state.visible.get() {
|
||||
state.position.set(position);
|
||||
let child = MouseEventHandler::<MouseEventHandlerState<Tag>, _>::new(id, cx, |_, _| child)
|
||||
.on_hover(move |e, _, cx| {
|
||||
let position = e.position;
|
||||
let window_id = cx.window_id();
|
||||
let view_id = cx.view_id();
|
||||
if e.started {
|
||||
if !state.visible.get() {
|
||||
state.position.set(position);
|
||||
|
||||
let mut debounce = state.debounce.borrow_mut();
|
||||
if debounce.is_none() {
|
||||
*debounce = Some(cx.spawn({
|
||||
let state = state.clone();
|
||||
|mut cx| async move {
|
||||
cx.background().timer(DEBOUNCE_TIMEOUT).await;
|
||||
state.visible.set(true);
|
||||
cx.update(|cx| cx.notify_view(window_id, view_id));
|
||||
}
|
||||
}));
|
||||
let mut debounce = state.debounce.borrow_mut();
|
||||
if debounce.is_none() {
|
||||
*debounce = Some(cx.spawn({
|
||||
let state = state.clone();
|
||||
|_, mut cx| async move {
|
||||
cx.background().timer(DEBOUNCE_TIMEOUT).await;
|
||||
state.visible.set(true);
|
||||
cx.update(|cx| cx.notify_view(window_id, view_id));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.visible.set(false);
|
||||
state.debounce.take();
|
||||
cx.notify();
|
||||
}));
|
||||
}
|
||||
}
|
||||
})
|
||||
.boxed();
|
||||
} else {
|
||||
state.visible.set(false);
|
||||
state.debounce.take();
|
||||
cx.notify();
|
||||
}
|
||||
})
|
||||
.boxed();
|
||||
Self {
|
||||
child,
|
||||
tooltip,
|
||||
|
@ -137,7 +134,7 @@ impl<V: View> Tooltip<V> {
|
|||
style: TooltipStyle,
|
||||
action: Option<Box<dyn Action>>,
|
||||
measure: bool,
|
||||
) -> impl Element {
|
||||
) -> impl Element<V> {
|
||||
Flex::row()
|
||||
.with_child({
|
||||
let text = Text::new(text, style.text)
|
||||
|
@ -181,7 +178,7 @@ impl<V: View> Element<V> for Tooltip<V> {
|
|||
let size = self.child.layout(constraint, view, cx);
|
||||
if let Some(tooltip) = self.tooltip.as_mut() {
|
||||
tooltip.layout(
|
||||
SizeConstraint::new(Vector2F::zero(), cx.window_size),
|
||||
SizeConstraint::new(Vector2F::zero(), cx.window_size()),
|
||||
view,
|
||||
cx,
|
||||
);
|
||||
|
|
|
@ -6,7 +6,6 @@ use crate::{
|
|||
},
|
||||
json::{self, json},
|
||||
platform::ScrollWheelEvent,
|
||||
scene::MouseScrollWheel,
|
||||
ElementBox, MouseRegion, SceneBuilder, View, ViewContext,
|
||||
};
|
||||
use json::ToJson;
|
||||
|
@ -47,7 +46,7 @@ pub struct UniformList<V: View> {
|
|||
state: UniformListState,
|
||||
item_count: usize,
|
||||
#[allow(clippy::type_complexity)]
|
||||
append_items: Box<dyn Fn(Range<usize>, &mut Vec<ElementBox<V>>, &mut V, &mut ViewContext<V>)>,
|
||||
append_items: Box<dyn Fn(&mut V, Range<usize>, &mut Vec<ElementBox<V>>, &mut ViewContext<V>)>,
|
||||
padding_top: f32,
|
||||
padding_bottom: f32,
|
||||
get_width_from_item: Option<usize>,
|
||||
|
@ -63,19 +62,12 @@ impl<V: View> UniformList<V> {
|
|||
) -> Self
|
||||
where
|
||||
V: View,
|
||||
F: 'static + Fn(&mut V, Range<usize>, &mut Vec<ElementBox<V>>, &mut V, &mut ViewContext<V>),
|
||||
F: 'static + Fn(&mut V, Range<usize>, &mut Vec<ElementBox<V>>, &mut ViewContext<V>),
|
||||
{
|
||||
let handle = cx.handle();
|
||||
Self {
|
||||
state,
|
||||
item_count,
|
||||
append_items: Box::new(move |range, items, cx| {
|
||||
if let Some(handle) = handle.upgrade(cx) {
|
||||
cx.render(&handle, |view, cx| {
|
||||
append_items(view, range, items, cx);
|
||||
});
|
||||
}
|
||||
}),
|
||||
append_items: Box::new(append_items),
|
||||
padding_top: 0.,
|
||||
padding_bottom: 0.,
|
||||
get_width_from_item: None,
|
||||
|
@ -194,18 +186,18 @@ impl<V: View> Element<V> for UniformList<V> {
|
|||
let sample_item_ix;
|
||||
let sample_item;
|
||||
if let Some(sample_ix) = self.get_width_from_item {
|
||||
(self.append_items)(sample_ix..sample_ix + 1, &mut items, cx);
|
||||
(self.append_items)(view, sample_ix..sample_ix + 1, &mut items, cx);
|
||||
sample_item_ix = sample_ix;
|
||||
|
||||
if let Some(mut item) = items.pop() {
|
||||
item_size = item.layout(constraint, cx);
|
||||
item_size = item.layout(constraint, view, cx);
|
||||
size.set_x(item_size.x());
|
||||
sample_item = item;
|
||||
} else {
|
||||
return no_items;
|
||||
}
|
||||
} else {
|
||||
(self.append_items)(0..1, &mut items, cx);
|
||||
(self.append_items)(view, 0..1, &mut items, cx);
|
||||
sample_item_ix = 0;
|
||||
if let Some(mut item) = items.pop() {
|
||||
item_size = item.layout(
|
||||
|
@ -213,6 +205,7 @@ impl<V: View> Element<V> for UniformList<V> {
|
|||
vec2f(constraint.max.x(), 0.0),
|
||||
vec2f(constraint.max.x(), f32::INFINITY),
|
||||
),
|
||||
view,
|
||||
cx,
|
||||
);
|
||||
item_size.set_x(size.x());
|
||||
|
@ -249,16 +242,16 @@ impl<V: View> Element<V> for UniformList<V> {
|
|||
|
||||
if (start..end).contains(&sample_item_ix) {
|
||||
if sample_item_ix > start {
|
||||
(self.append_items)(start..sample_item_ix, &mut items, cx);
|
||||
(self.append_items)(view, start..sample_item_ix, &mut items, cx);
|
||||
}
|
||||
|
||||
items.push(sample_item);
|
||||
|
||||
if sample_item_ix < end {
|
||||
(self.append_items)(sample_item_ix + 1..end, &mut items, cx);
|
||||
(self.append_items)(view, sample_item_ix + 1..end, &mut items, cx);
|
||||
}
|
||||
} else {
|
||||
(self.append_items)(start..end, &mut items, cx);
|
||||
(self.append_items)(view, start..end, &mut items, cx);
|
||||
}
|
||||
|
||||
for item in &mut items {
|
||||
|
@ -289,20 +282,16 @@ impl<V: View> Element<V> for UniformList<V> {
|
|||
) -> Self::PaintState {
|
||||
let visible_bounds = visible_bounds.intersection(bounds).unwrap_or_default();
|
||||
|
||||
cx.scene.push_layer(Some(visible_bounds));
|
||||
scene.push_layer(Some(visible_bounds));
|
||||
|
||||
cx.scene.push_mouse_region(
|
||||
scene.push_mouse_region(
|
||||
MouseRegion::new::<Self>(self.view_id, 0, visible_bounds).on_scroll({
|
||||
let scroll_max = layout.scroll_max;
|
||||
let state = self.state.clone();
|
||||
move |MouseScrollWheel {
|
||||
platform_event:
|
||||
ScrollWheelEvent {
|
||||
position, delta, ..
|
||||
},
|
||||
..
|
||||
},
|
||||
cx| {
|
||||
move |event, _, cx| {
|
||||
let ScrollWheelEvent {
|
||||
position, delta, ..
|
||||
} = event.platform_event;
|
||||
if !Self::scroll(
|
||||
state.clone(),
|
||||
position,
|
||||
|
@ -328,7 +317,7 @@ impl<V: View> Element<V> for UniformList<V> {
|
|||
item_origin += vec2f(0.0, layout.item_height);
|
||||
}
|
||||
|
||||
cx.scene.pop_layer();
|
||||
scene.pop_layer();
|
||||
}
|
||||
|
||||
fn rect_for_text_range(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue