Move self in Element::paint
Remove mutable state borrows in favor of state ownership in render processes to streamline element rendering.
This commit is contained in:
parent
0069dd5ce6
commit
2515bbf990
15 changed files with 262 additions and 231 deletions
|
@ -488,8 +488,8 @@ impl EditorElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ix, fold_indicator) in layout.fold_indicators.iter_mut().enumerate() {
|
for (ix, fold_indicator) in layout.fold_indicators.drain(..).enumerate() {
|
||||||
if let Some(fold_indicator) = fold_indicator.as_mut() {
|
if let Some(mut fold_indicator) = fold_indicator {
|
||||||
let available_space = size(
|
let available_space = size(
|
||||||
AvailableSpace::MinContent,
|
AvailableSpace::MinContent,
|
||||||
AvailableSpace::Definite(line_height * 0.55),
|
AvailableSpace::Definite(line_height * 0.55),
|
||||||
|
@ -509,7 +509,7 @@ impl EditorElement {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(indicator) = layout.code_actions_indicator.as_mut() {
|
if let Some(mut indicator) = layout.code_actions_indicator.take() {
|
||||||
let available_space = size(
|
let available_space = size(
|
||||||
AvailableSpace::MinContent,
|
AvailableSpace::MinContent,
|
||||||
AvailableSpace::Definite(line_height),
|
AvailableSpace::Definite(line_height),
|
||||||
|
@ -840,7 +840,7 @@ impl EditorElement {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some((position, context_menu)) = layout.context_menu.as_mut() {
|
if let Some((position, mut context_menu)) = layout.context_menu.take() {
|
||||||
cx.with_z_index(1, |cx| {
|
cx.with_z_index(1, |cx| {
|
||||||
let line_height = self.style.text.line_height_in_pixels(cx.rem_size());
|
let line_height = self.style.text.line_height_in_pixels(cx.rem_size());
|
||||||
let available_space = size(
|
let available_space = size(
|
||||||
|
@ -1224,7 +1224,7 @@ impl EditorElement {
|
||||||
let scroll_left = scroll_position.x * layout.position_map.em_width;
|
let scroll_left = scroll_position.x * layout.position_map.em_width;
|
||||||
let scroll_top = scroll_position.y * layout.position_map.line_height;
|
let scroll_top = scroll_position.y * layout.position_map.line_height;
|
||||||
|
|
||||||
for block in &mut layout.blocks {
|
for block in layout.blocks.drain(..) {
|
||||||
let mut origin = bounds.origin
|
let mut origin = bounds.origin
|
||||||
+ point(
|
+ point(
|
||||||
Pixels::ZERO,
|
Pixels::ZERO,
|
||||||
|
@ -2389,7 +2389,7 @@ enum Invisible {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Element<Editor> for EditorElement {
|
impl Element<Editor> for EditorElement {
|
||||||
type ElementState = ();
|
type State = ();
|
||||||
|
|
||||||
fn element_id(&self) -> Option<gpui::ElementId> {
|
fn element_id(&self) -> Option<gpui::ElementId> {
|
||||||
Some(self.editor_id.into())
|
Some(self.editor_id.into())
|
||||||
|
@ -2398,9 +2398,9 @@ impl Element<Editor> for EditorElement {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut gpui::ViewContext<Editor>,
|
cx: &mut gpui::ViewContext<Editor>,
|
||||||
) -> (gpui::LayoutId, Self::ElementState) {
|
) -> (gpui::LayoutId, Self::State) {
|
||||||
editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this.
|
editor.style = Some(self.style.clone()); // Long-term, we'd like to eliminate this.
|
||||||
|
|
||||||
let rem_size = cx.rem_size();
|
let rem_size = cx.rem_size();
|
||||||
|
@ -2416,10 +2416,10 @@ impl Element<Editor> for EditorElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
mut self,
|
||||||
bounds: Bounds<gpui::Pixels>,
|
bounds: Bounds<gpui::Pixels>,
|
||||||
editor: &mut Editor,
|
editor: &mut Editor,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut gpui::ViewContext<Editor>,
|
cx: &mut gpui::ViewContext<Editor>,
|
||||||
) {
|
) {
|
||||||
let mut layout = self.compute_layout(editor, cx, bounds);
|
let mut layout = self.compute_layout(editor, cx, bounds);
|
||||||
|
|
|
@ -14,7 +14,7 @@ use smallvec::SmallVec;
|
||||||
pub use test_context::*;
|
pub use test_context::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
current_platform, image_cache::ImageCache, Action, ActionRegistry, AnyBox, AnyView,
|
current_platform, image_cache::ImageCache, Action, ActionRegistry, Any, AnyView,
|
||||||
AnyWindowHandle, AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context,
|
AnyWindowHandle, AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context,
|
||||||
DispatchPhase, DisplayId, Entity, EventEmitter, FocusEvent, FocusHandle, FocusId,
|
DispatchPhase, DisplayId, Entity, EventEmitter, FocusEvent, FocusHandle, FocusId,
|
||||||
ForegroundExecutor, KeyBinding, Keymap, LayoutId, PathPromptOptions, Pixels, Platform,
|
ForegroundExecutor, KeyBinding, Keymap, LayoutId, PathPromptOptions, Pixels, Platform,
|
||||||
|
@ -28,7 +28,7 @@ use futures::{channel::oneshot, future::LocalBoxFuture, Future};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use slotmap::SlotMap;
|
use slotmap::SlotMap;
|
||||||
use std::{
|
use std::{
|
||||||
any::{type_name, Any, TypeId},
|
any::{type_name, TypeId},
|
||||||
cell::{Ref, RefCell, RefMut},
|
cell::{Ref, RefCell, RefMut},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
mem,
|
mem,
|
||||||
|
@ -194,7 +194,7 @@ pub struct AppContext {
|
||||||
asset_source: Arc<dyn AssetSource>,
|
asset_source: Arc<dyn AssetSource>,
|
||||||
pub(crate) image_cache: ImageCache,
|
pub(crate) image_cache: ImageCache,
|
||||||
pub(crate) text_style_stack: Vec<TextStyleRefinement>,
|
pub(crate) text_style_stack: Vec<TextStyleRefinement>,
|
||||||
pub(crate) globals_by_type: HashMap<TypeId, AnyBox>,
|
pub(crate) globals_by_type: HashMap<TypeId, Box<dyn Any>>,
|
||||||
pub(crate) entities: EntityMap,
|
pub(crate) entities: EntityMap,
|
||||||
pub(crate) new_view_observers: SubscriberSet<TypeId, NewViewListener>,
|
pub(crate) new_view_observers: SubscriberSet<TypeId, NewViewListener>,
|
||||||
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
||||||
|
@ -1100,12 +1100,12 @@ pub(crate) enum Effect {
|
||||||
|
|
||||||
/// Wraps a global variable value during `update_global` while the value has been moved to the stack.
|
/// Wraps a global variable value during `update_global` while the value has been moved to the stack.
|
||||||
pub(crate) struct GlobalLease<G: 'static> {
|
pub(crate) struct GlobalLease<G: 'static> {
|
||||||
global: AnyBox,
|
global: Box<dyn Any>,
|
||||||
global_type: PhantomData<G>,
|
global_type: PhantomData<G>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<G: 'static> GlobalLease<G> {
|
impl<G: 'static> GlobalLease<G> {
|
||||||
fn new(global: AnyBox) -> Self {
|
fn new(global: Box<dyn Any>) -> Self {
|
||||||
GlobalLease {
|
GlobalLease {
|
||||||
global,
|
global,
|
||||||
global_type: PhantomData,
|
global_type: PhantomData,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::{private::Sealed, AnyBox, AppContext, Context, Entity, ModelContext};
|
use crate::{private::Sealed, AppContext, Context, Entity, ModelContext};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
use parking_lot::{RwLock, RwLockUpgradableReadGuard};
|
||||||
use slotmap::{SecondaryMap, SlotMap};
|
use slotmap::{SecondaryMap, SlotMap};
|
||||||
use std::{
|
use std::{
|
||||||
any::{type_name, TypeId},
|
any::{type_name, Any, TypeId},
|
||||||
fmt::{self, Display},
|
fmt::{self, Display},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
marker::PhantomData,
|
marker::PhantomData,
|
||||||
|
@ -31,7 +31,7 @@ impl Display for EntityId {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct EntityMap {
|
pub(crate) struct EntityMap {
|
||||||
entities: SecondaryMap<EntityId, AnyBox>,
|
entities: SecondaryMap<EntityId, Box<dyn Any>>,
|
||||||
ref_counts: Arc<RwLock<EntityRefCounts>>,
|
ref_counts: Arc<RwLock<EntityRefCounts>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ impl EntityMap {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_dropped(&mut self) -> Vec<(EntityId, AnyBox)> {
|
pub fn take_dropped(&mut self) -> Vec<(EntityId, Box<dyn Any>)> {
|
||||||
let mut ref_counts = self.ref_counts.write();
|
let mut ref_counts = self.ref_counts.write();
|
||||||
let dropped_entity_ids = mem::take(&mut ref_counts.dropped_entity_ids);
|
let dropped_entity_ids = mem::take(&mut ref_counts.dropped_entity_ids);
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ impl EntityMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Lease<'a, T> {
|
pub struct Lease<'a, T> {
|
||||||
entity: Option<AnyBox>,
|
entity: Option<Box<dyn Any>>,
|
||||||
pub model: &'a Model<T>,
|
pub model: &'a Model<T>,
|
||||||
entity_type: PhantomData<T>,
|
entity_type: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,25 +3,25 @@ use crate::{
|
||||||
};
|
};
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
pub(crate) use smallvec::SmallVec;
|
pub(crate) use smallvec::SmallVec;
|
||||||
use std::{any::Any, fmt::Debug, mem};
|
use std::{any::Any, fmt::Debug};
|
||||||
|
|
||||||
pub trait Element<V: 'static>: 'static + Sized {
|
pub trait Element<V: 'static>: 'static + Sized {
|
||||||
type ElementState: 'static;
|
type State: 'static;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId>;
|
fn element_id(&self) -> Option<ElementId>;
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState);
|
) -> (LayoutId, Self::State);
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -35,32 +35,26 @@ pub trait Element<V: 'static>: 'static + Sized {
|
||||||
available_space: Size<T>,
|
available_space: Size<T>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
f: impl FnOnce(&Self::ElementState, &mut ViewContext<V>) -> R,
|
f: impl FnOnce(&mut Self::State, &mut ViewContext<V>) -> R,
|
||||||
) -> R
|
) -> R
|
||||||
where
|
where
|
||||||
T: Clone + Default + Debug + Into<AvailableSpace>,
|
T: Clone + Default + Debug + Into<AvailableSpace>,
|
||||||
{
|
{
|
||||||
let mut element = RenderedElement {
|
let element_id = self.element_id();
|
||||||
element: self,
|
let element = DrawableElement {
|
||||||
phase: ElementRenderPhase::Start,
|
element: Some(self),
|
||||||
|
phase: ElementDrawPhase::Start,
|
||||||
};
|
};
|
||||||
element.draw(origin, available_space.map(Into::into), view_state, cx);
|
let frame_state = element.draw(origin, available_space.map(Into::into), view_state, cx);
|
||||||
if let ElementRenderPhase::Painted { frame_state } = &element.phase {
|
|
||||||
if let Some(frame_state) = frame_state.as_ref() {
|
if let Some(mut frame_state) = frame_state {
|
||||||
f(&frame_state, cx)
|
f(&mut frame_state, cx)
|
||||||
} else {
|
|
||||||
let element_id = element
|
|
||||||
.element
|
|
||||||
.element_id()
|
|
||||||
.expect("we either have some frame_state or some element_id");
|
|
||||||
cx.with_element_state(element_id, |element_state, cx| {
|
|
||||||
let element_state = element_state.unwrap();
|
|
||||||
let result = f(&element_state, cx);
|
|
||||||
(result, element_state)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
cx.with_element_state(element_id.unwrap(), |element_state, cx| {
|
||||||
|
let mut element_state = element_state.unwrap();
|
||||||
|
let result = f(&mut element_state, cx);
|
||||||
|
(result, element_state)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -107,13 +101,13 @@ trait ElementObject<V> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RenderedElement<V: 'static, E: Element<V>> {
|
pub struct DrawableElement<V: 'static, E: Element<V>> {
|
||||||
element: E,
|
element: Option<E>,
|
||||||
phase: ElementRenderPhase<E::ElementState>,
|
phase: ElementDrawPhase<E::State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
enum ElementRenderPhase<V> {
|
enum ElementDrawPhase<V> {
|
||||||
#[default]
|
#[default]
|
||||||
Start,
|
Start,
|
||||||
LayoutRequested {
|
LayoutRequested {
|
||||||
|
@ -125,83 +119,83 @@ enum ElementRenderPhase<V> {
|
||||||
available_space: Size<AvailableSpace>,
|
available_space: Size<AvailableSpace>,
|
||||||
frame_state: Option<V>,
|
frame_state: Option<V>,
|
||||||
},
|
},
|
||||||
Painted {
|
|
||||||
frame_state: Option<V>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
|
/// Internal struct that wraps an element to store Layout and ElementState after the element is rendered.
|
||||||
/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
|
/// It's allocated as a trait object to erase the element type and wrapped in AnyElement<E::State> for
|
||||||
/// improved usability.
|
/// improved usability.
|
||||||
impl<V, E: Element<V>> RenderedElement<V, E> {
|
impl<V, E: Element<V>> DrawableElement<V, E> {
|
||||||
fn new(element: E) -> Self {
|
fn new(element: E) -> Self {
|
||||||
RenderedElement {
|
DrawableElement {
|
||||||
element,
|
element: Some(element),
|
||||||
phase: ElementRenderPhase::Start,
|
phase: ElementDrawPhase::Start,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<V, E> ElementObject<V> for RenderedElement<V, E>
|
|
||||||
where
|
|
||||||
E: Element<V>,
|
|
||||||
E::ElementState: 'static,
|
|
||||||
{
|
|
||||||
fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
|
fn layout(&mut self, state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
|
||||||
let (layout_id, frame_state) = match mem::take(&mut self.phase) {
|
let (layout_id, frame_state) = if let Some(id) = self.element.as_ref().unwrap().element_id()
|
||||||
ElementRenderPhase::Start => {
|
{
|
||||||
if let Some(id) = self.element.element_id() {
|
let layout_id = cx.with_element_state(id, |element_state, cx| {
|
||||||
let layout_id = cx.with_element_state(id, |element_state, cx| {
|
self.element
|
||||||
self.element.layout(state, element_state, cx)
|
.as_mut()
|
||||||
});
|
.unwrap()
|
||||||
(layout_id, None)
|
.layout(state, element_state, cx)
|
||||||
} else {
|
});
|
||||||
let (layout_id, frame_state) = self.element.layout(state, None, cx);
|
(layout_id, None)
|
||||||
(layout_id, Some(frame_state))
|
} else {
|
||||||
}
|
let (layout_id, frame_state) = self.element.as_mut().unwrap().layout(state, None, cx);
|
||||||
}
|
(layout_id, Some(frame_state))
|
||||||
ElementRenderPhase::LayoutRequested { .. }
|
|
||||||
| ElementRenderPhase::LayoutComputed { .. }
|
|
||||||
| ElementRenderPhase::Painted { .. } => {
|
|
||||||
panic!("element rendered twice")
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.phase = ElementRenderPhase::LayoutRequested {
|
self.phase = ElementDrawPhase::LayoutRequested {
|
||||||
layout_id,
|
layout_id,
|
||||||
frame_state,
|
frame_state,
|
||||||
};
|
};
|
||||||
layout_id
|
layout_id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
fn paint(mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> Option<E::State> {
|
||||||
self.phase = match mem::take(&mut self.phase) {
|
match self.phase {
|
||||||
ElementRenderPhase::LayoutRequested {
|
ElementDrawPhase::LayoutRequested {
|
||||||
layout_id,
|
layout_id,
|
||||||
mut frame_state,
|
frame_state,
|
||||||
}
|
}
|
||||||
| ElementRenderPhase::LayoutComputed {
|
| ElementDrawPhase::LayoutComputed {
|
||||||
layout_id,
|
layout_id,
|
||||||
mut frame_state,
|
frame_state,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
let bounds = cx.layout_bounds(layout_id);
|
let bounds = cx.layout_bounds(layout_id);
|
||||||
if let Some(id) = self.element.element_id() {
|
|
||||||
cx.with_element_state(id, |element_state, cx| {
|
if let Some(mut frame_state) = frame_state {
|
||||||
|
self.element
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.paint(bounds, view_state, &mut frame_state, cx);
|
||||||
|
Some(frame_state)
|
||||||
|
} else {
|
||||||
|
let element_id = self
|
||||||
|
.element
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.element_id()
|
||||||
|
.expect("if we don't have frame state, we should have element state");
|
||||||
|
cx.with_element_state(element_id, |element_state, cx| {
|
||||||
let mut element_state = element_state.unwrap();
|
let mut element_state = element_state.unwrap();
|
||||||
self.element
|
self.element.take().unwrap().paint(
|
||||||
.paint(bounds, view_state, &mut element_state, cx);
|
bounds,
|
||||||
|
view_state,
|
||||||
|
&mut element_state,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
((), element_state)
|
((), element_state)
|
||||||
});
|
});
|
||||||
} else {
|
None
|
||||||
self.element
|
|
||||||
.paint(bounds, view_state, frame_state.as_mut().unwrap(), cx);
|
|
||||||
}
|
}
|
||||||
ElementRenderPhase::Painted { frame_state }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => panic!("must call layout before paint"),
|
_ => panic!("must call layout before paint"),
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn measure(
|
fn measure(
|
||||||
|
@ -210,25 +204,25 @@ where
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> Size<Pixels> {
|
) -> Size<Pixels> {
|
||||||
if matches!(&self.phase, ElementRenderPhase::Start) {
|
if matches!(&self.phase, ElementDrawPhase::Start) {
|
||||||
self.layout(view_state, cx);
|
self.layout(view_state, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let layout_id = match &mut self.phase {
|
let layout_id = match &mut self.phase {
|
||||||
ElementRenderPhase::LayoutRequested {
|
ElementDrawPhase::LayoutRequested {
|
||||||
layout_id,
|
layout_id,
|
||||||
frame_state,
|
frame_state,
|
||||||
} => {
|
} => {
|
||||||
cx.compute_layout(*layout_id, available_space);
|
cx.compute_layout(*layout_id, available_space);
|
||||||
let layout_id = *layout_id;
|
let layout_id = *layout_id;
|
||||||
self.phase = ElementRenderPhase::LayoutComputed {
|
self.phase = ElementDrawPhase::LayoutComputed {
|
||||||
layout_id,
|
layout_id,
|
||||||
available_space,
|
available_space,
|
||||||
frame_state: frame_state.take(),
|
frame_state: frame_state.take(),
|
||||||
};
|
};
|
||||||
layout_id
|
layout_id
|
||||||
}
|
}
|
||||||
ElementRenderPhase::LayoutComputed {
|
ElementDrawPhase::LayoutComputed {
|
||||||
layout_id,
|
layout_id,
|
||||||
available_space: prev_available_space,
|
available_space: prev_available_space,
|
||||||
..
|
..
|
||||||
|
@ -245,6 +239,40 @@ where
|
||||||
cx.layout_bounds(layout_id).size
|
cx.layout_bounds(layout_id).size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
mut self,
|
||||||
|
origin: Point<Pixels>,
|
||||||
|
available_space: Size<AvailableSpace>,
|
||||||
|
view_state: &mut V,
|
||||||
|
cx: &mut ViewContext<V>,
|
||||||
|
) -> Option<E::State> {
|
||||||
|
self.measure(available_space, view_state, cx);
|
||||||
|
cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<V, E> ElementObject<V> for Option<DrawableElement<V, E>>
|
||||||
|
where
|
||||||
|
E: Element<V>,
|
||||||
|
E::State: 'static,
|
||||||
|
{
|
||||||
|
fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
|
||||||
|
DrawableElement::layout(self.as_mut().unwrap(), view_state, cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
||||||
|
DrawableElement::paint(self.take().unwrap(), view_state, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn measure(
|
||||||
|
&mut self,
|
||||||
|
available_space: Size<AvailableSpace>,
|
||||||
|
view_state: &mut V,
|
||||||
|
cx: &mut ViewContext<V>,
|
||||||
|
) -> Size<Pixels> {
|
||||||
|
DrawableElement::measure(self.as_mut().unwrap(), available_space, view_state, cx)
|
||||||
|
}
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
origin: Point<Pixels>,
|
origin: Point<Pixels>,
|
||||||
|
@ -252,8 +280,13 @@ where
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
self.measure(available_space, view_state, cx);
|
DrawableElement::draw(
|
||||||
cx.with_absolute_element_offset(origin, |cx| self.paint(view_state, cx))
|
self.take().unwrap(),
|
||||||
|
origin,
|
||||||
|
available_space,
|
||||||
|
view_state,
|
||||||
|
cx,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,16 +297,16 @@ impl<V> AnyElement<V> {
|
||||||
where
|
where
|
||||||
V: 'static,
|
V: 'static,
|
||||||
E: 'static + Element<V>,
|
E: 'static + Element<V>,
|
||||||
E::ElementState: Any,
|
E::State: Any,
|
||||||
{
|
{
|
||||||
AnyElement(Box::new(RenderedElement::new(element)))
|
AnyElement(Box::new(Some(DrawableElement::new(element))) as Box<dyn ElementObject<V>>)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
|
pub fn layout(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) -> LayoutId {
|
||||||
self.0.layout(view_state, cx)
|
self.0.layout(view_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paint(&mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
pub fn paint(mut self, view_state: &mut V, cx: &mut ViewContext<V>) {
|
||||||
self.0.paint(view_state, cx)
|
self.0.paint(view_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +322,7 @@ impl<V> AnyElement<V> {
|
||||||
|
|
||||||
/// Initializes this element and performs layout in the available space, then paints it at the given origin.
|
/// Initializes this element and performs layout in the available space, then paints it at the given origin.
|
||||||
pub fn draw(
|
pub fn draw(
|
||||||
&mut self,
|
mut self,
|
||||||
origin: Point<Pixels>,
|
origin: Point<Pixels>,
|
||||||
available_space: Size<AvailableSpace>,
|
available_space: Size<AvailableSpace>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
|
@ -343,7 +376,7 @@ where
|
||||||
E: 'static + Component<V>,
|
E: 'static + Component<V>,
|
||||||
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
|
F: FnOnce(&mut V, &mut ViewContext<'_, V>) -> E + 'static,
|
||||||
{
|
{
|
||||||
type ElementState = AnyElement<V>;
|
type State = Option<AnyElement<V>>;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
None
|
None
|
||||||
|
@ -352,23 +385,23 @@ where
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
_: Option<Self::ElementState>,
|
_: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
let render = self.take().unwrap();
|
let render = self.take().unwrap();
|
||||||
let mut rendered_element = (render)(view_state, cx).render();
|
let mut rendered_element = (render)(view_state, cx).render();
|
||||||
let layout_id = rendered_element.layout(view_state, cx);
|
let layout_id = rendered_element.layout(view_state, cx);
|
||||||
(layout_id, rendered_element)
|
(layout_id, Some(rendered_element))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
_bounds: Bounds<Pixels>,
|
_bounds: Bounds<Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
rendered_element: &mut Self::ElementState,
|
rendered_element: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
rendered_element.paint(view_state, cx)
|
rendered_element.take().unwrap().paint(view_state, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -600,7 +600,7 @@ impl<V: 'static> ParentComponent<V> for Div<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for Div<V> {
|
impl<V: 'static> Element<V> for Div<V> {
|
||||||
type ElementState = DivState;
|
type State = DivState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.interactivity.element_id.clone()
|
self.interactivity.element_id.clone()
|
||||||
|
@ -609,9 +609,9 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
let mut child_layout_ids = SmallVec::new();
|
let mut child_layout_ids = SmallVec::new();
|
||||||
let mut interactivity = mem::take(&mut self.interactivity);
|
let mut interactivity = mem::take(&mut self.interactivity);
|
||||||
let (layout_id, interactive_state) = interactivity.layout(
|
let (layout_id, interactive_state) = interactivity.layout(
|
||||||
|
@ -639,10 +639,10 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
let mut child_min = point(Pixels::MAX, Pixels::MAX);
|
let mut child_min = point(Pixels::MAX, Pixels::MAX);
|
||||||
|
@ -658,8 +658,7 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
(child_max - child_min).into()
|
(child_max - child_min).into()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut interactivity = mem::take(&mut self.interactivity);
|
self.interactivity.paint(
|
||||||
interactivity.paint(
|
|
||||||
bounds,
|
bounds,
|
||||||
content_size,
|
content_size,
|
||||||
&mut element_state.interactive_state,
|
&mut element_state.interactive_state,
|
||||||
|
@ -679,7 +678,7 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
cx.with_text_style(style.text_style().cloned(), |cx| {
|
cx.with_text_style(style.text_style().cloned(), |cx| {
|
||||||
cx.with_content_mask(style.overflow_mask(bounds), |cx| {
|
cx.with_content_mask(style.overflow_mask(bounds), |cx| {
|
||||||
cx.with_element_offset(scroll_offset, |cx| {
|
cx.with_element_offset(scroll_offset, |cx| {
|
||||||
for child in &mut self.children {
|
for child in self.children {
|
||||||
child.paint(view_state, cx);
|
child.paint(view_state, cx);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -689,7 +688,6 @@ impl<V: 'static> Element<V> for Div<V> {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.interactivity = interactivity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -770,7 +768,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn paint(
|
pub fn paint(
|
||||||
&mut self,
|
mut self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
content_size: Size<Pixels>,
|
content_size: Size<Pixels>,
|
||||||
element_state: &mut InteractiveElementState,
|
element_state: &mut InteractiveElementState,
|
||||||
|
@ -786,25 +784,25 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for listener in self.mouse_down_listeners.drain(..) {
|
for listener in self.mouse_down_listeners {
|
||||||
cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
|
cx.on_mouse_event(move |state, event: &MouseDownEvent, phase, cx| {
|
||||||
listener(state, event, &bounds, phase, cx);
|
listener(state, event, &bounds, phase, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for listener in self.mouse_up_listeners.drain(..) {
|
for listener in self.mouse_up_listeners {
|
||||||
cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
|
cx.on_mouse_event(move |state, event: &MouseUpEvent, phase, cx| {
|
||||||
listener(state, event, &bounds, phase, cx);
|
listener(state, event, &bounds, phase, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for listener in self.mouse_move_listeners.drain(..) {
|
for listener in self.mouse_move_listeners {
|
||||||
cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
|
cx.on_mouse_event(move |state, event: &MouseMoveEvent, phase, cx| {
|
||||||
listener(state, event, &bounds, phase, cx);
|
listener(state, event, &bounds, phase, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for listener in self.scroll_wheel_listeners.drain(..) {
|
for listener in self.scroll_wheel_listeners {
|
||||||
cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
|
cx.on_mouse_event(move |state, event: &ScrollWheelEvent, phase, cx| {
|
||||||
listener(state, event, &bounds, phase, cx);
|
listener(state, event, &bounds, phase, cx);
|
||||||
})
|
})
|
||||||
|
@ -840,7 +838,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
if cx.active_drag.is_some() {
|
if cx.active_drag.is_some() {
|
||||||
let drop_listeners = mem::take(&mut self.drop_listeners);
|
let drop_listeners = self.drop_listeners;
|
||||||
cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| {
|
cx.on_mouse_event(move |view, event: &MouseUpEvent, phase, cx| {
|
||||||
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
|
||||||
if let Some(drag_state_type) =
|
if let Some(drag_state_type) =
|
||||||
|
@ -1062,24 +1060,24 @@ where
|
||||||
self.key_context.clone(),
|
self.key_context.clone(),
|
||||||
element_state.focus_handle.clone(),
|
element_state.focus_handle.clone(),
|
||||||
|_, cx| {
|
|_, cx| {
|
||||||
for listener in self.key_down_listeners.drain(..) {
|
for listener in self.key_down_listeners {
|
||||||
cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| {
|
cx.on_key_event(move |state, event: &KeyDownEvent, phase, cx| {
|
||||||
listener(state, event, phase, cx);
|
listener(state, event, phase, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for listener in self.key_up_listeners.drain(..) {
|
for listener in self.key_up_listeners {
|
||||||
cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| {
|
cx.on_key_event(move |state, event: &KeyUpEvent, phase, cx| {
|
||||||
listener(state, event, phase, cx);
|
listener(state, event, phase, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for (action_type, listener) in self.action_listeners.drain(..) {
|
for (action_type, listener) in self.action_listeners {
|
||||||
cx.on_action(action_type, listener)
|
cx.on_action(action_type, listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(focus_handle) = element_state.focus_handle.as_ref() {
|
if let Some(focus_handle) = element_state.focus_handle.as_ref() {
|
||||||
for listener in self.focus_listeners.drain(..) {
|
for listener in self.focus_listeners {
|
||||||
let focus_handle = focus_handle.clone();
|
let focus_handle = focus_handle.clone();
|
||||||
cx.on_focus_changed(move |view, event, cx| {
|
cx.on_focus_changed(move |view, event, cx| {
|
||||||
listener(view, &focus_handle, event, cx)
|
listener(view, &focus_handle, event, cx)
|
||||||
|
@ -1291,7 +1289,7 @@ where
|
||||||
V: 'static,
|
V: 'static,
|
||||||
E: Element<V>,
|
E: Element<V>,
|
||||||
{
|
{
|
||||||
type ElementState = E::ElementState;
|
type State = E::State;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.element.element_id()
|
self.element.element_id()
|
||||||
|
@ -1300,20 +1298,20 @@ where
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
self.element.layout(view_state, element_state, cx)
|
self.element.layout(view_state, element_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
self.element.paint(bounds, view_state, element_state, cx);
|
self.element.paint(bounds, view_state, element_state, cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1377,7 +1375,7 @@ where
|
||||||
V: 'static,
|
V: 'static,
|
||||||
E: Element<V>,
|
E: Element<V>,
|
||||||
{
|
{
|
||||||
type ElementState = E::ElementState;
|
type State = E::State;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.element.element_id()
|
self.element.element_id()
|
||||||
|
@ -1386,17 +1384,17 @@ where
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
self.element.layout(view_state, element_state, cx)
|
self.element.layout(view_state, element_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
self.element.paint(bounds, view_state, element_state, cx)
|
self.element.paint(bounds, view_state, element_state, cx)
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl<V> Component<V> for Img<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> Element<V> for Img<V> {
|
impl<V> Element<V> for Img<V> {
|
||||||
type ElementState = InteractiveElementState;
|
type State = InteractiveElementState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<crate::ElementId> {
|
||||||
self.interactivity.element_id.clone()
|
self.interactivity.element_id.clone()
|
||||||
|
@ -51,19 +51,19 @@ impl<V> Element<V> for Img<V> {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
_view_state: &mut V,
|
_view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
self.interactivity.layout(element_state, cx, |style, cx| {
|
self.interactivity.layout(element_state, cx, |style, cx| {
|
||||||
cx.request_layout(&style, None)
|
cx.request_layout(&style, None)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
_view_state: &mut V,
|
_view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
self.interactivity.paint(
|
self.interactivity.paint(
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl<V: 'static> Component<V> for Overlay<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for Overlay<V> {
|
impl<V: 'static> Element<V> for Overlay<V> {
|
||||||
type ElementState = OverlayState;
|
type State = OverlayState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<crate::ElementId> {
|
||||||
None
|
None
|
||||||
|
@ -73,9 +73,9 @@ impl<V: 'static> Element<V> for Overlay<V> {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
_: Option<Self::ElementState>,
|
_: Option<Self::State>,
|
||||||
cx: &mut crate::ViewContext<V>,
|
cx: &mut crate::ViewContext<V>,
|
||||||
) -> (crate::LayoutId, Self::ElementState) {
|
) -> (crate::LayoutId, Self::State) {
|
||||||
let child_layout_ids = self
|
let child_layout_ids = self
|
||||||
.children
|
.children
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
|
@ -92,10 +92,10 @@ impl<V: 'static> Element<V> for Overlay<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: crate::Bounds<crate::Pixels>,
|
bounds: crate::Bounds<crate::Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut crate::ViewContext<V>,
|
cx: &mut crate::ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
if element_state.child_layout_ids.is_empty() {
|
if element_state.child_layout_ids.is_empty() {
|
||||||
|
@ -156,7 +156,7 @@ impl<V: 'static> Element<V> for Overlay<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.with_element_offset(desired.origin - bounds.origin, |cx| {
|
cx.with_element_offset(desired.origin - bounds.origin, |cx| {
|
||||||
for child in &mut self.children {
|
for child in self.children {
|
||||||
child.paint(view_state, cx);
|
child.paint(view_state, cx);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl<V> Component<V> for Svg<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V> Element<V> for Svg<V> {
|
impl<V> Element<V> for Svg<V> {
|
||||||
type ElementState = InteractiveElementState;
|
type State = InteractiveElementState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
self.interactivity.element_id.clone()
|
self.interactivity.element_id.clone()
|
||||||
|
@ -40,19 +40,19 @@ impl<V> Element<V> for Svg<V> {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
_view_state: &mut V,
|
_view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
self.interactivity.layout(element_state, cx, |style, cx| {
|
self.interactivity.layout(element_state, cx, |style, cx| {
|
||||||
cx.request_layout(&style, None)
|
cx.request_layout(&style, None)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
_view_state: &mut V,
|
_view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) where
|
) where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::{cell::Cell, rc::Rc, sync::Arc};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for &'static str {
|
impl<V: 'static> Element<V> for &'static str {
|
||||||
type ElementState = TextState;
|
type State = TextState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
None
|
None
|
||||||
|
@ -18,16 +18,16 @@ impl<V: 'static> Element<V> for &'static str {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &mut V,
|
_: &mut V,
|
||||||
_: Option<Self::ElementState>,
|
_: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
let mut state = TextState::default();
|
let mut state = TextState::default();
|
||||||
let layout_id = state.layout(SharedString::from(*self), None, cx);
|
let layout_id = state.layout(SharedString::from(*self), None, cx);
|
||||||
(layout_id, state)
|
(layout_id, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
_: &mut V,
|
_: &mut V,
|
||||||
state: &mut TextState,
|
state: &mut TextState,
|
||||||
|
@ -38,7 +38,7 @@ impl<V: 'static> Element<V> for &'static str {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for SharedString {
|
impl<V: 'static> Element<V> for SharedString {
|
||||||
type ElementState = TextState;
|
type State = TextState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
Some(self.clone().into())
|
Some(self.clone().into())
|
||||||
|
@ -47,16 +47,16 @@ impl<V: 'static> Element<V> for SharedString {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &mut V,
|
_: &mut V,
|
||||||
_: Option<Self::ElementState>,
|
_: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
let mut state = TextState::default();
|
let mut state = TextState::default();
|
||||||
let layout_id = state.layout(self.clone(), None, cx);
|
let layout_id = state.layout(self.clone(), None, cx);
|
||||||
(layout_id, state)
|
(layout_id, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
_: &mut V,
|
_: &mut V,
|
||||||
state: &mut TextState,
|
state: &mut TextState,
|
||||||
|
@ -93,7 +93,7 @@ impl<V: 'static> Component<V> for Text {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for Text {
|
impl<V: 'static> Element<V> for Text {
|
||||||
type ElementState = TextState;
|
type State = TextState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<crate::ElementId> {
|
||||||
None
|
None
|
||||||
|
@ -102,9 +102,9 @@ impl<V: 'static> Element<V> for Text {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
_view: &mut V,
|
_view: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
let element_state = element_state.unwrap_or_default();
|
let element_state = element_state.unwrap_or_default();
|
||||||
let text_system = cx.text_system().clone();
|
let text_system = cx.text_system().clone();
|
||||||
let text_style = cx.text_style();
|
let text_style = cx.text_style();
|
||||||
|
@ -160,10 +160,10 @@ impl<V: 'static> Element<V> for Text {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
_: &mut V,
|
_: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
let element_state = element_state.lock();
|
let element_state = element_state.lock();
|
||||||
|
@ -280,7 +280,7 @@ struct InteractiveTextState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for InteractiveText {
|
impl<V: 'static> Element<V> for InteractiveText {
|
||||||
type ElementState = InteractiveTextState;
|
type State = InteractiveTextState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
Some(self.id.clone())
|
Some(self.id.clone())
|
||||||
|
@ -289,9 +289,9 @@ impl<V: 'static> Element<V> for InteractiveText {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
if let Some(InteractiveTextState {
|
if let Some(InteractiveTextState {
|
||||||
text_state,
|
text_state,
|
||||||
clicked_range_ixs,
|
clicked_range_ixs,
|
||||||
|
@ -314,10 +314,10 @@ impl<V: 'static> Element<V> for InteractiveText {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<Pixels>,
|
bounds: Bounds<Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
self.text
|
self.text
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
||||||
Point, Size, StyleRefinement, Styled, ViewContext,
|
Point, Size, StyleRefinement, Styled, ViewContext,
|
||||||
};
|
};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::{cell::RefCell, cmp, mem, ops::Range, rc::Rc};
|
use std::{cell::RefCell, cmp, ops::Range, rc::Rc};
|
||||||
use taffy::style::Overflow;
|
use taffy::style::Overflow;
|
||||||
|
|
||||||
/// uniform_list provides lazy rendering for a set of items that are of uniform height.
|
/// uniform_list provides lazy rendering for a set of items that are of uniform height.
|
||||||
|
@ -102,7 +102,7 @@ pub struct UniformListState {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for UniformList<V> {
|
impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
type ElementState = UniformListState;
|
type State = UniformListState;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<crate::ElementId> {
|
fn element_id(&self) -> Option<crate::ElementId> {
|
||||||
Some(self.id.clone())
|
Some(self.id.clone())
|
||||||
|
@ -111,9 +111,9 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
let max_items = self.item_count;
|
let max_items = self.item_count;
|
||||||
let rem_size = cx.rem_size();
|
let rem_size = cx.rem_size();
|
||||||
let item_size = element_state
|
let item_size = element_state
|
||||||
|
@ -159,10 +159,10 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<crate::Pixels>,
|
bounds: Bounds<crate::Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut ViewContext<V>,
|
cx: &mut ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
let style =
|
let style =
|
||||||
|
@ -183,14 +183,17 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
height: item_size.height * self.item_count,
|
height: item_size.height * self.item_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut interactivity = mem::take(&mut self.interactivity);
|
|
||||||
let shared_scroll_offset = element_state
|
let shared_scroll_offset = element_state
|
||||||
.interactive
|
.interactive
|
||||||
.scroll_offset
|
.scroll_offset
|
||||||
.get_or_insert_with(Rc::default)
|
.get_or_insert_with(Rc::default)
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
interactivity.paint(
|
let item_height = self
|
||||||
|
.measure_item(view_state, Some(padded_bounds.size.width), cx)
|
||||||
|
.height;
|
||||||
|
|
||||||
|
self.interactivity.paint(
|
||||||
bounds,
|
bounds,
|
||||||
content_size,
|
content_size,
|
||||||
&mut element_state.interactive,
|
&mut element_state.interactive,
|
||||||
|
@ -209,9 +212,6 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
style.paint(bounds, cx);
|
style.paint(bounds, cx);
|
||||||
|
|
||||||
if self.item_count > 0 {
|
if self.item_count > 0 {
|
||||||
let item_height = self
|
|
||||||
.measure_item(view_state, Some(padded_bounds.size.width), cx)
|
|
||||||
.height;
|
|
||||||
if let Some(scroll_handle) = self.scroll_handle.clone() {
|
if let Some(scroll_handle) = self.scroll_handle.clone() {
|
||||||
scroll_handle.0.borrow_mut().replace(ScrollHandleState {
|
scroll_handle.0.borrow_mut().replace(ScrollHandleState {
|
||||||
item_height,
|
item_height,
|
||||||
|
@ -233,9 +233,9 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
self.item_count,
|
self.item_count,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut items = (self.render_items)(view_state, visible_range.clone(), cx);
|
let items = (self.render_items)(view_state, visible_range.clone(), cx);
|
||||||
cx.with_z_index(1, |cx| {
|
cx.with_z_index(1, |cx| {
|
||||||
for (item, ix) in items.iter_mut().zip(visible_range) {
|
for (item, ix) in items.into_iter().zip(visible_range) {
|
||||||
let item_origin = padded_bounds.origin
|
let item_origin = padded_bounds.origin
|
||||||
+ point(px(0.), item_height * ix + scroll_offset.y);
|
+ point(px(0.), item_height * ix + scroll_offset.y);
|
||||||
let available_space = size(
|
let available_space = size(
|
||||||
|
@ -249,7 +249,6 @@ impl<V: 'static> Element<V> for UniformList<V> {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
self.interactivity = interactivity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,6 @@ use std::{
|
||||||
};
|
};
|
||||||
use taffy::TaffyLayoutEngine;
|
use taffy::TaffyLayoutEngine;
|
||||||
|
|
||||||
type AnyBox = Box<dyn Any>;
|
|
||||||
|
|
||||||
pub trait Context {
|
pub trait Context {
|
||||||
type Result<T>;
|
type Result<T>;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace,
|
private::Sealed, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace, BorrowWindow,
|
||||||
BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, FocusHandle,
|
Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, FocusHandle, FocusableView,
|
||||||
FocusableView, LayoutId, Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel,
|
LayoutId, Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel, WindowContext,
|
||||||
WindowContext,
|
|
||||||
};
|
};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -164,7 +163,7 @@ impl<V> Eq for WeakView<V> {}
|
||||||
pub struct AnyView {
|
pub struct AnyView {
|
||||||
model: AnyModel,
|
model: AnyModel,
|
||||||
layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
|
layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
|
||||||
paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
|
paint: fn(&AnyView, Box<dyn Any>, &mut WindowContext),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnyView {
|
impl AnyView {
|
||||||
|
@ -198,11 +197,11 @@ impl AnyView {
|
||||||
cx: &mut WindowContext,
|
cx: &mut WindowContext,
|
||||||
) {
|
) {
|
||||||
cx.with_absolute_element_offset(origin, |cx| {
|
cx.with_absolute_element_offset(origin, |cx| {
|
||||||
let (layout_id, mut rendered_element) = (self.layout)(self, cx);
|
let (layout_id, rendered_element) = (self.layout)(self, cx);
|
||||||
cx.window
|
cx.window
|
||||||
.layout_engine
|
.layout_engine
|
||||||
.compute_layout(layout_id, available_space);
|
.compute_layout(layout_id, available_space);
|
||||||
(self.paint)(self, &mut rendered_element, cx);
|
(self.paint)(self, rendered_element, cx);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,7 +223,7 @@ impl<V: Render> From<View<V>> for AnyView {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
||||||
type ElementState = Box<dyn Any>;
|
type State = Option<Box<dyn Any>>;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
Some(self.model.entity_id.into())
|
Some(self.model.entity_id.into())
|
||||||
|
@ -233,27 +232,28 @@ impl<ParentViewState: 'static> Element<ParentViewState> for AnyView {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
_view_state: &mut ParentViewState,
|
_view_state: &mut ParentViewState,
|
||||||
_element_state: Option<Self::ElementState>,
|
_element_state: Option<Self::State>,
|
||||||
cx: &mut ViewContext<ParentViewState>,
|
cx: &mut ViewContext<ParentViewState>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
(self.layout)(self, cx)
|
let (layout_id, rendered_element) = (self.layout)(self, cx);
|
||||||
|
(layout_id, Some(rendered_element))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
mut self,
|
||||||
_bounds: Bounds<Pixels>,
|
_bounds: Bounds<Pixels>,
|
||||||
_view_state: &mut ParentViewState,
|
_view_state: &mut ParentViewState,
|
||||||
rendered_element: &mut Self::ElementState,
|
rendered_element: &mut Self::State,
|
||||||
cx: &mut ViewContext<ParentViewState>,
|
cx: &mut ViewContext<ParentViewState>,
|
||||||
) {
|
) {
|
||||||
(self.paint)(self, rendered_element, cx)
|
(self.paint)(&mut self, rendered_element.take().unwrap(), cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AnyWeakView {
|
pub struct AnyWeakView {
|
||||||
model: AnyWeakModel,
|
model: AnyWeakModel,
|
||||||
layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
|
layout: fn(&AnyView, &mut WindowContext) -> (LayoutId, Box<dyn Any>),
|
||||||
paint: fn(&AnyView, &mut AnyBox, &mut WindowContext),
|
paint: fn(&AnyView, Box<dyn Any>, &mut WindowContext),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnyWeakView {
|
impl AnyWeakView {
|
||||||
|
@ -311,7 +311,7 @@ where
|
||||||
ParentViewState: 'static,
|
ParentViewState: 'static,
|
||||||
ViewState: 'static,
|
ViewState: 'static,
|
||||||
{
|
{
|
||||||
type ElementState = AnyElement<ViewState>;
|
type State = Option<AnyElement<ViewState>>;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<ElementId> {
|
fn element_id(&self) -> Option<ElementId> {
|
||||||
Some(self.view.entity_id().into())
|
Some(self.view.entity_id().into())
|
||||||
|
@ -320,24 +320,25 @@ where
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: &mut ParentViewState,
|
_: &mut ParentViewState,
|
||||||
_: Option<Self::ElementState>,
|
_: Option<Self::State>,
|
||||||
cx: &mut ViewContext<ParentViewState>,
|
cx: &mut ViewContext<ParentViewState>,
|
||||||
) -> (LayoutId, Self::ElementState) {
|
) -> (LayoutId, Self::State) {
|
||||||
self.view.update(cx, |view, cx| {
|
self.view.update(cx, |view, cx| {
|
||||||
let mut element = self.component.take().unwrap().render();
|
let mut element = self.component.take().unwrap().render();
|
||||||
let layout_id = element.layout(view, cx);
|
let layout_id = element.layout(view, cx);
|
||||||
(layout_id, element)
|
(layout_id, Some(element))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
_: Bounds<Pixels>,
|
_: Bounds<Pixels>,
|
||||||
_: &mut ParentViewState,
|
_: &mut ParentViewState,
|
||||||
element: &mut Self::ElementState,
|
element: &mut Self::State,
|
||||||
cx: &mut ViewContext<ParentViewState>,
|
cx: &mut ViewContext<ParentViewState>,
|
||||||
) {
|
) {
|
||||||
self.view.update(cx, |view, cx| element.paint(view, cx))
|
self.view
|
||||||
|
.update(cx, |view, cx| element.take().unwrap().paint(view, cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,14 +360,10 @@ mod any_view {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn paint<V: Render>(
|
pub(crate) fn paint<V: Render>(view: &AnyView, element: Box<dyn Any>, cx: &mut WindowContext) {
|
||||||
view: &AnyView,
|
|
||||||
element: &mut Box<dyn Any>,
|
|
||||||
cx: &mut WindowContext,
|
|
||||||
) {
|
|
||||||
cx.with_element_id(Some(view.model.entity_id), |cx| {
|
cx.with_element_id(Some(view.model.entity_id), |cx| {
|
||||||
let view = view.clone().downcast::<V>().unwrap();
|
let view = view.clone().downcast::<V>().unwrap();
|
||||||
let element = element.downcast_mut::<AnyElement<V>>().unwrap();
|
let element = element.downcast::<AnyElement<V>>().unwrap();
|
||||||
view.update(cx, |view, cx| element.paint(view, cx))
|
view.update(cx, |view, cx| element.paint(view, cx))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext,
|
key_dispatch::DispatchActionListener, px, size, Action, AnyDrag, AnyView, AppContext,
|
||||||
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
|
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
|
||||||
DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId,
|
DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId,
|
||||||
EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData,
|
EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData,
|
||||||
|
@ -237,7 +237,7 @@ pub struct Window {
|
||||||
|
|
||||||
// #[derive(Default)]
|
// #[derive(Default)]
|
||||||
pub(crate) struct Frame {
|
pub(crate) struct Frame {
|
||||||
pub(crate) element_states: HashMap<GlobalElementId, AnyBox>,
|
pub(crate) element_states: HashMap<GlobalElementId, Box<dyn Any>>,
|
||||||
mouse_listeners: HashMap<TypeId, Vec<(StackingOrder, AnyMouseListener)>>,
|
mouse_listeners: HashMap<TypeId, Vec<(StackingOrder, AnyMouseListener)>>,
|
||||||
pub(crate) dispatch_tree: DispatchTree,
|
pub(crate) dispatch_tree: DispatchTree,
|
||||||
pub(crate) focus_listeners: Vec<AnyFocusListener>,
|
pub(crate) focus_listeners: Vec<AnyFocusListener>,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
mod action;
|
mod action;
|
||||||
mod derive_component;
|
mod derive_component;
|
||||||
|
mod derive_element;
|
||||||
mod register_action;
|
mod register_action;
|
||||||
mod style_helpers;
|
mod style_helpers;
|
||||||
mod test;
|
mod test;
|
||||||
|
@ -26,6 +27,11 @@ pub fn derive_component(input: TokenStream) -> TokenStream {
|
||||||
derive_component::derive_component(input)
|
derive_component::derive_component(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[proc_macro_derive(Element)]
|
||||||
|
// pub fn derive_element(input: TokenStream) -> TokenStream {
|
||||||
|
// derive_element::derive_element(input)
|
||||||
|
// }
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
|
pub fn test(args: TokenStream, function: TokenStream) -> TokenStream {
|
||||||
test::test(args, function)
|
test::test(args, function)
|
||||||
|
|
|
@ -133,7 +133,7 @@ pub struct MenuHandleState<V, M> {
|
||||||
menu_element: Option<AnyElement<V>>,
|
menu_element: Option<AnyElement<V>>,
|
||||||
}
|
}
|
||||||
impl<V: 'static, M: ManagedView> Element<V> for MenuHandle<V, M> {
|
impl<V: 'static, M: ManagedView> Element<V> for MenuHandle<V, M> {
|
||||||
type ElementState = MenuHandleState<V, M>;
|
type State = MenuHandleState<V, M>;
|
||||||
|
|
||||||
fn element_id(&self) -> Option<gpui::ElementId> {
|
fn element_id(&self) -> Option<gpui::ElementId> {
|
||||||
Some(self.id.clone().expect("menu_handle must have an id()"))
|
Some(self.id.clone().expect("menu_handle must have an id()"))
|
||||||
|
@ -142,9 +142,9 @@ impl<V: 'static, M: ManagedView> Element<V> for MenuHandle<V, M> {
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: Option<Self::ElementState>,
|
element_state: Option<Self::State>,
|
||||||
cx: &mut crate::ViewContext<V>,
|
cx: &mut crate::ViewContext<V>,
|
||||||
) -> (gpui::LayoutId, Self::ElementState) {
|
) -> (gpui::LayoutId, Self::State) {
|
||||||
let (menu, position) = if let Some(element_state) = element_state {
|
let (menu, position) = if let Some(element_state) = element_state {
|
||||||
(element_state.menu, element_state.position)
|
(element_state.menu, element_state.position)
|
||||||
} else {
|
} else {
|
||||||
|
@ -192,22 +192,22 @@ impl<V: 'static, M: ManagedView> Element<V> for MenuHandle<V, M> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
self,
|
||||||
bounds: Bounds<gpui::Pixels>,
|
bounds: Bounds<gpui::Pixels>,
|
||||||
view_state: &mut V,
|
view_state: &mut V,
|
||||||
element_state: &mut Self::ElementState,
|
element_state: &mut Self::State,
|
||||||
cx: &mut crate::ViewContext<V>,
|
cx: &mut crate::ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
if let Some(child) = element_state.child_element.as_mut() {
|
if let Some(child) = element_state.child_element.take() {
|
||||||
child.paint(view_state, cx);
|
child.paint(view_state, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(menu) = element_state.menu_element.as_mut() {
|
if let Some(menu) = element_state.menu_element.take() {
|
||||||
menu.paint(view_state, cx);
|
menu.paint(view_state, cx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(builder) = self.menu_builder.clone() else {
|
let Some(builder) = self.menu_builder else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let menu = element_state.menu.clone();
|
let menu = element_state.menu.clone();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue