Merge branch 'pre-merge' into clean-up-doc-elements

This commit is contained in:
Nathan Sobo
2024-01-01 12:21:33 -07:00
88 changed files with 237 additions and 478 deletions
+2 -4
View File
@@ -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()
}
}
+4 -29
View File
@@ -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),
+5 -9
View File
@@ -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")
-12
View File
@@ -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};