WIP
co-authored-by: conrad <conrad@zed.dev> co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use crate::{
|
||||
point, px, size, AnyElement, AvailableSpace, Bounds, Element, ElementId, InteractiveElement,
|
||||
InteractiveElementState, Interactivity, LayoutId, Pixels, Point, RenderOnce, Size,
|
||||
StyleRefinement, Styled, WindowContext,
|
||||
InteractiveElementState, Interactivity, LayoutId, Pixels, Point, Render, RenderOnce, Size,
|
||||
StyleRefinement, Styled, View, ViewContext, WindowContext,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
|
||||
@@ -10,30 +10,36 @@ use taffy::style::Overflow;
|
||||
/// uniform_list provides lazy rendering for a set of items that are of uniform height.
|
||||
/// When rendered into a container with overflow-y: hidden and a fixed (or max) height,
|
||||
/// uniform_list will only render the visibile subset of items.
|
||||
pub fn uniform_list<I, R>(
|
||||
pub fn uniform_list<I, R, V>(
|
||||
view: View<V>,
|
||||
id: I,
|
||||
item_count: usize,
|
||||
f: impl 'static + Fn(Range<usize>, &mut WindowContext) -> Vec<R>,
|
||||
f: impl 'static + Fn(&mut V, Range<usize>, &mut ViewContext<V>) -> Vec<R>,
|
||||
) -> UniformList
|
||||
where
|
||||
I: Into<ElementId>,
|
||||
R: RenderOnce,
|
||||
V: Render,
|
||||
{
|
||||
let id = id.into();
|
||||
let mut style = StyleRefinement::default();
|
||||
style.overflow.y = Some(Overflow::Hidden);
|
||||
|
||||
let render_range = move |range, cx: &mut WindowContext| {
|
||||
view.update(cx, |this, cx| {
|
||||
f(this, range, cx)
|
||||
.into_iter()
|
||||
.map(|component| component.render_into_any())
|
||||
.collect()
|
||||
})
|
||||
};
|
||||
|
||||
UniformList {
|
||||
id: id.clone(),
|
||||
style,
|
||||
item_count,
|
||||
item_to_measure_index: 0,
|
||||
render_items: Box::new(move |visible_range, cx| {
|
||||
f(visible_range, cx)
|
||||
.into_iter()
|
||||
.map(|component| component.render_into_any())
|
||||
.collect()
|
||||
}),
|
||||
render_items: Box::new(render_range),
|
||||
interactivity: Interactivity {
|
||||
element_id: Some(id.into()),
|
||||
..Default::default()
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use crate::{AsyncWindowContext, Bounds, Pixels, PlatformInputHandler, View, ViewContext};
|
||||
use crate::{
|
||||
AsyncWindowContext, Bounds, Pixels, PlatformInputHandler, View, ViewContext, WindowContext,
|
||||
};
|
||||
use std::ops::Range;
|
||||
|
||||
/// Implement this trait to allow views to handle textual input when implementing an editor, field, etc.
|
||||
@@ -43,9 +45,9 @@ pub struct ElementInputHandler<V> {
|
||||
impl<V: 'static> ElementInputHandler<V> {
|
||||
/// Used in [Element::paint] with the element's bounds and a view context for its
|
||||
/// containing view.
|
||||
pub fn new(element_bounds: Bounds<Pixels>, cx: &mut ViewContext<V>) -> Self {
|
||||
pub fn new(element_bounds: Bounds<Pixels>, view: View<V>, cx: &mut WindowContext) -> Self {
|
||||
ElementInputHandler {
|
||||
view: cx.view().clone(),
|
||||
view,
|
||||
element_bounds,
|
||||
cx: cx.to_async(),
|
||||
}
|
||||
|
||||
@@ -309,50 +309,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
// pub struct RenderViewWith<E, V> {
|
||||
// view: View<V>,
|
||||
// element: Option<E>,
|
||||
// }
|
||||
|
||||
// impl<E> Element for RenderViewWith<E>
|
||||
// where
|
||||
// E: 'static + Element,
|
||||
// {
|
||||
// type State = Option<AnyElement>;
|
||||
|
||||
// fn layout(
|
||||
// &mut self,
|
||||
// _: Option<Self::State>,
|
||||
// cx: &mut WindowContext,
|
||||
// ) -> (LayoutId, Self::State) {
|
||||
// self.view.update(cx, |view, cx| {
|
||||
// let mut element = self.element.take().unwrap().into_any();
|
||||
// let layout_id = element.layout(view, cx);
|
||||
// (layout_id, Some(element))
|
||||
// })
|
||||
// }
|
||||
|
||||
// fn paint(self, _: Bounds<Pixels>, element: &mut Self::ElementState, cx: &mut WindowContext) {
|
||||
// element.paint(cx)
|
||||
// }
|
||||
// }
|
||||
|
||||
// impl<E> RenderOnce for RenderViewWith<E>
|
||||
// where
|
||||
// E: 'static + Element<V>,
|
||||
// ParentV: 'static,
|
||||
// {
|
||||
// type Element = Self;
|
||||
|
||||
// fn element_id(&self) -> Option<ElementId> {
|
||||
// self.element.as_ref().unwrap().element_id()
|
||||
// }
|
||||
|
||||
// fn render_once(self) -> Self::Element {
|
||||
// self
|
||||
// }
|
||||
// }
|
||||
|
||||
mod any_view {
|
||||
use crate::{AnyElement, AnyView, BorrowWindow, Element, LayoutId, Render, WindowContext};
|
||||
|
||||
|
||||
+42
-26
@@ -1437,7 +1437,27 @@ impl<'a> WindowContext<'a> {
|
||||
.bindings_for_action(action)
|
||||
}
|
||||
|
||||
///========== ELEMENT RELATED FUNCTIONS ===========
|
||||
pub fn listener_for<V: Render, E>(
|
||||
&self,
|
||||
view: &View<V>,
|
||||
f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
|
||||
) -> impl Fn(&E, &mut WindowContext) + 'static {
|
||||
let view = view.downgrade();
|
||||
move |e: &E, cx: &mut WindowContext| {
|
||||
view.update(cx, |view, cx| f(view, e, cx)).ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn constructor_for<V: Render, R>(
|
||||
&self,
|
||||
view: &View<V>,
|
||||
f: impl Fn(&mut V, &mut ViewContext<V>) -> R + 'static,
|
||||
) -> impl Fn(&mut WindowContext) -> R + 'static {
|
||||
let view = view.clone();
|
||||
move |cx: &mut WindowContext| view.update(cx, |view, cx| f(view, cx))
|
||||
}
|
||||
|
||||
//========== ELEMENT RELATED FUNCTIONS ===========
|
||||
pub fn with_key_dispatch<R>(
|
||||
&mut self,
|
||||
context: KeyContext,
|
||||
@@ -1477,6 +1497,21 @@ impl<'a> WindowContext<'a> {
|
||||
listener(event, cx);
|
||||
}));
|
||||
}
|
||||
|
||||
/// Set an input handler, such as [ElementInputHandler], which interfaces with the
|
||||
/// platform to receive textual input with proper integration with concerns such
|
||||
/// as IME interactions.
|
||||
pub fn handle_input(
|
||||
&mut self,
|
||||
focus_handle: &FocusHandle,
|
||||
input_handler: impl PlatformInputHandler,
|
||||
) {
|
||||
if focus_handle.is_focused(self) {
|
||||
self.window
|
||||
.platform_window
|
||||
.set_input_handler(Box::new(input_handler));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Context for WindowContext<'_> {
|
||||
@@ -1658,6 +1693,10 @@ pub trait BorrowWindow: BorrowMut<Window> + BorrowMut<AppContext> {
|
||||
self.borrow_mut()
|
||||
}
|
||||
|
||||
fn app(&self) -> &AppContext {
|
||||
self.borrow()
|
||||
}
|
||||
|
||||
fn window(&self) -> &Window {
|
||||
self.borrow()
|
||||
}
|
||||
@@ -2241,21 +2280,6 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Set an input handler, such as [ElementInputHandler], which interfaces with the
|
||||
/// platform to receive textual input with proper integration with concerns such
|
||||
/// as IME interactions.
|
||||
pub fn handle_input(
|
||||
&mut self,
|
||||
focus_handle: &FocusHandle,
|
||||
input_handler: impl PlatformInputHandler,
|
||||
) {
|
||||
if focus_handle.is_focused(self) {
|
||||
self.window
|
||||
.platform_window
|
||||
.set_input_handler(Box::new(input_handler));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit<Evt>(&mut self, event: Evt)
|
||||
where
|
||||
Evt: 'static,
|
||||
@@ -2287,19 +2311,11 @@ impl<'a, V: 'static> ViewContext<'a, V> {
|
||||
&self,
|
||||
f: impl Fn(&mut V, &E, &mut ViewContext<V>) + 'static,
|
||||
) -> impl Fn(&E, &mut WindowContext) + 'static {
|
||||
let view = self.view().clone();
|
||||
let view = self.view().downgrade();
|
||||
move |e: &E, cx: &mut WindowContext| {
|
||||
view.update(cx, |view, cx| f(view, e, cx));
|
||||
view.update(cx, |view, cx| f(view, e, cx)).ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn constructor<R>(
|
||||
&self,
|
||||
f: impl Fn(&mut V, &mut ViewContext<V>) -> R + 'static,
|
||||
) -> impl Fn(&mut WindowContext) -> R {
|
||||
let view = self.view().clone();
|
||||
move |cx: &mut WindowContext| view.update(cx, |view, cx| f(view, cx))
|
||||
}
|
||||
}
|
||||
|
||||
impl<V> Context for ViewContext<'_, V> {
|
||||
|
||||
Reference in New Issue
Block a user