Merge branch 'pre-merge' into clean-up-doc-elements
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
div, Action, AnyView, AnyWindowHandle, AppCell, AppContext, AsyncAppContext,
|
||||
BackgroundExecutor, Bounds, ClipboardItem, Context, Div, Entity, EventEmitter,
|
||||
BackgroundExecutor, Bounds, ClipboardItem, Context, Element, Entity, EventEmitter,
|
||||
ForegroundExecutor, InputEvent, KeyDownEvent, Keystroke, Model, ModelContext, Pixels, Platform,
|
||||
PlatformWindow, Point, Render, Result, Size, Task, TestDispatcher, TestPlatform, TestWindow,
|
||||
TestWindowHandlers, TextSystem, View, ViewContext, VisualContext, WindowBounds, WindowContext,
|
||||
@@ -733,9 +733,7 @@ impl AnyWindowHandle {
|
||||
pub struct EmptyView {}
|
||||
|
||||
impl Render for EmptyView {
|
||||
type Output = Div;
|
||||
|
||||
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> Self::Output {
|
||||
fn render(&mut self, _cx: &mut crate::ViewContext<Self>) -> impl Element {
|
||||
div()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,36 +6,17 @@ use derive_more::{Deref, DerefMut};
|
||||
pub(crate) use smallvec::SmallVec;
|
||||
use std::{any::Any, fmt::Debug};
|
||||
|
||||
/// Elements describe the contents of a window for a given frame.
|
||||
/// Like HTML elements, elements form a tree and participate in layout.
|
||||
/// In GPUI, elements are single-use objects that do not outlive a single frame.
|
||||
/// Elements are associated with state.
|
||||
/// If the element has an identifier, the element's state persists across frames in which the element appears.
|
||||
/// If the element is anonymous, the state only persists across from layout request to paint in is referred to as "frame state".
|
||||
/// A potential improvement would be to separate this temporary frame state from persistent element state at the type level, and request element state from the context with an id. /cc @as-cii\
|
||||
/// To render the contents of a window, we first walk over the tree of elements recursively via [request_layout], giving each an opportunity to register with the layout engine.
|
||||
/// Then we compute the requested layout and use the computed bounds to paint the element tree recursively with [paint].
|
||||
/// You can implement this trait yourself for performance or other special situations, but you'll typically compose existing elements such as `Div`, `Img`, etc.
|
||||
pub trait Element: 'static + IntoElement {
|
||||
/// State that is carried from [request_layout] to [paint] for anonymous elements, and between frames for elements that have an id.
|
||||
type State: 'static;
|
||||
|
||||
/// Recursively register this element and all its descendants with the layout engine.
|
||||
/// If this element has an id, you'll receive the [State] from the previous frame if an element with this id existed in that frame.
|
||||
/// Return the [LayoutId] you requested from the engine and whatever state you want to carry over to [paint], and also the next frame if this element has an id.
|
||||
fn request_layout(
|
||||
fn layout(
|
||||
&mut self,
|
||||
state: Option<Self::State>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::State);
|
||||
|
||||
/// Recursively paint this element by populating the current frame's [Scene] with geometric primitives such as quads, sprites, paths, etc.
|
||||
/// Receives the state from layout, and potentially the previous frame if this element has an id.
|
||||
fn paint(&mut self, bounds: Bounds<Pixels>, state: &mut Self::State, cx: &mut WindowContext);
|
||||
|
||||
/// Convert into a dynamically-typed [AnyElement].
|
||||
/// Before an element can be painted, it must be converted into an [AnyElement].
|
||||
/// It's also useful in situations where you need to own an element, but don't care about its specific type.
|
||||
fn into_any(self) -> AnyElement {
|
||||
AnyElement::new(self)
|
||||
}
|
||||
@@ -125,14 +106,8 @@ pub trait IntoElement: Sized {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait that all [View] types must implement.
|
||||
/// This trait tells the framework how a particular type is displayed on screen.
|
||||
/// For any type `V` implementing `Render`, you can create a `View<V>` handle, which can be used as an element in another view or as the root of a window.
|
||||
pub trait Render: 'static + Sized {
|
||||
type Output: IntoElement;
|
||||
|
||||
/// Describes how this type is displayed on screen.
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Output;
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element;
|
||||
}
|
||||
|
||||
/// You can derive [IntoElement] on any type that implements this trait.
|
||||
@@ -192,7 +167,7 @@ impl<C: RenderOnce> Element for Component<C> {
|
||||
let mut element = self.component.take().unwrap().render(cx).into_element();
|
||||
if let Some(element_id) = element.element_id() {
|
||||
let layout_id =
|
||||
cx.with_element_state(element_id, |state, cx| element.request_layout(state, cx));
|
||||
cx.with_element_state(element_id, |state, cx| element.layout(state, cx));
|
||||
let state = ComponentState {
|
||||
rendered_element: Some(element),
|
||||
rendered_element_state: None,
|
||||
@@ -200,7 +175,7 @@ impl<C: RenderOnce> Element for Component<C> {
|
||||
(layout_id, state)
|
||||
} else {
|
||||
let (layout_id, state) =
|
||||
element.request_layout(state.and_then(|s| s.rendered_element_state), cx);
|
||||
element.layout(state.and_then(|s| s.rendered_element_state), cx);
|
||||
let state = ComponentState {
|
||||
rendered_element: Some(element),
|
||||
rendered_element_state: Some(state),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
div, point, Div, Element, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
|
||||
div, point, Element, IntoElement, Keystroke, Modifiers, Pixels, Point, Render, ViewContext,
|
||||
};
|
||||
use smallvec::SmallVec;
|
||||
use std::{any::Any, fmt::Debug, marker::PhantomData, ops::Deref, path::PathBuf};
|
||||
@@ -205,9 +205,7 @@ impl ExternalPaths {
|
||||
}
|
||||
|
||||
impl Render for ExternalPaths {
|
||||
type Output = Div;
|
||||
|
||||
fn render(&mut self, _: &mut ViewContext<Self>) -> Self::Output {
|
||||
fn render(&mut self, _: &mut ViewContext<Self>) -> impl Element {
|
||||
div() // Intentionally left empty because the platform will render icons for the dragged files
|
||||
}
|
||||
}
|
||||
@@ -292,8 +290,8 @@ impl InputEvent {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{
|
||||
self as gpui, div, Div, FocusHandle, InteractiveElement, IntoElement, KeyBinding,
|
||||
Keystroke, ParentElement, Render, Stateful, TestAppContext, VisualContext,
|
||||
self as gpui, div, Element, FocusHandle, InteractiveElement, IntoElement, KeyBinding,
|
||||
Keystroke, ParentElement, Render, TestAppContext, VisualContext,
|
||||
};
|
||||
|
||||
struct TestView {
|
||||
@@ -305,9 +303,7 @@ mod test {
|
||||
actions!(test, [TestAction]);
|
||||
|
||||
impl Render for TestView {
|
||||
type Output = Stateful<Div>;
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> Self::Output {
|
||||
fn render(&mut self, cx: &mut gpui::ViewContext<Self>) -> impl Element {
|
||||
div().id("testview").child(
|
||||
div()
|
||||
.key_context("parent")
|
||||
|
||||
@@ -312,18 +312,6 @@ impl std::fmt::Debug for AnyWeakView {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> Render for T
|
||||
where
|
||||
T: 'static + FnMut(&mut WindowContext) -> E,
|
||||
E: 'static + Send + Element,
|
||||
{
|
||||
type Output = E;
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Output {
|
||||
(self)(cx)
|
||||
}
|
||||
}
|
||||
|
||||
mod any_view {
|
||||
use crate::{AnyElement, AnyView, IntoElement, LayoutId, Render, WindowContext};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user