WIP
This commit is contained in:
parent
8573c6e8c6
commit
a53c0b9472
7 changed files with 88 additions and 43 deletions
|
@ -29,6 +29,7 @@ impl App {
|
||||||
pub struct AppContext {
|
pub struct AppContext {
|
||||||
platform: Rc<dyn Platform>,
|
platform: Rc<dyn Platform>,
|
||||||
text_system: Arc<TextSystem>,
|
text_system: Arc<TextSystem>,
|
||||||
|
pub(crate) unit_entity_id: EntityId,
|
||||||
pub(crate) entities: SlotMap<EntityId, Option<Box<dyn Any>>>,
|
pub(crate) entities: SlotMap<EntityId, Option<Box<dyn Any>>>,
|
||||||
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
|
||||||
// We recycle this memory across layout requests.
|
// We recycle this memory across layout requests.
|
||||||
|
@ -38,10 +39,14 @@ pub struct AppContext {
|
||||||
impl AppContext {
|
impl AppContext {
|
||||||
pub fn new(platform: Rc<dyn Platform>) -> Self {
|
pub fn new(platform: Rc<dyn Platform>) -> Self {
|
||||||
let text_system = Arc::new(TextSystem::new(platform.text_system()));
|
let text_system = Arc::new(TextSystem::new(platform.text_system()));
|
||||||
|
let mut entities = SlotMap::with_key();
|
||||||
|
let unit_entity_id = entities.insert(Some(Box::new(()) as Box<dyn Any>));
|
||||||
|
|
||||||
AppContext {
|
AppContext {
|
||||||
platform,
|
platform,
|
||||||
text_system,
|
text_system,
|
||||||
entities: SlotMap::with_key(),
|
unit_entity_id,
|
||||||
|
entities,
|
||||||
windows: SlotMap::with_key(),
|
windows: SlotMap::with_key(),
|
||||||
layout_id_buffer: Default::default(),
|
layout_id_buffer: Default::default(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
mod div;
|
mod div;
|
||||||
mod img;
|
mod img;
|
||||||
|
mod stateless;
|
||||||
mod svg;
|
mod svg;
|
||||||
mod text;
|
mod text;
|
||||||
|
|
||||||
pub use div::*;
|
pub use div::*;
|
||||||
pub use img::*;
|
pub use img::*;
|
||||||
|
pub use stateless::*;
|
||||||
pub use svg::*;
|
pub use svg::*;
|
||||||
pub use text::*;
|
pub use text::*;
|
||||||
|
|
31
crates/gpui3/src/elements/stateless.rs
Normal file
31
crates/gpui3/src/elements/stateless.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::Element;
|
||||||
|
|
||||||
|
pub struct Stateless<E: Element<State = ()>, S> {
|
||||||
|
element: E,
|
||||||
|
parent_state_type: PhantomData<S>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Element<State = ()>, S: 'static> Element for Stateless<E, S> {
|
||||||
|
type State = S;
|
||||||
|
type FrameState = E::FrameState;
|
||||||
|
|
||||||
|
fn layout(
|
||||||
|
&mut self,
|
||||||
|
_: &mut Self::State,
|
||||||
|
cx: &mut crate::ViewContext<Self::State>,
|
||||||
|
) -> anyhow::Result<(crate::LayoutId, Self::FrameState)> {
|
||||||
|
cx.erase_state(|cx| self.element.layout(&mut (), cx))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn paint(
|
||||||
|
&mut self,
|
||||||
|
layout: crate::Layout,
|
||||||
|
_: &mut Self::State,
|
||||||
|
frame_state: &mut Self::FrameState,
|
||||||
|
cx: &mut crate::ViewContext<Self::State>,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
|
cx.erase_state(|cx| self.element.paint(layout, &mut (), frame_state, cx))
|
||||||
|
}
|
||||||
|
}
|
|
@ -220,6 +220,16 @@ impl<'a, 'w, T: 'static> ViewContext<'a, 'w, T> {
|
||||||
entity_type: PhantomData,
|
entity_type: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
|
||||||
|
let unit_entity_id = self.unit_entity_id;
|
||||||
|
let mut cx = ViewContext::mutable(
|
||||||
|
&mut *self.window_cx.app,
|
||||||
|
&mut *self.window_cx.window,
|
||||||
|
unit_entity_id,
|
||||||
|
);
|
||||||
|
f(&mut cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> {
|
impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> {
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::Ident;
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse_macro_input, parse_quote, DeriveInput, GenericParam};
|
use syn::{parse_macro_input, DeriveInput, GenericParam};
|
||||||
|
|
||||||
pub fn derive_element(input: TokenStream) -> TokenStream {
|
pub fn derive_element(input: TokenStream) -> TokenStream {
|
||||||
let ast = parse_macro_input!(input as DeriveInput);
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
let type_name = ast.ident;
|
let type_name = ast.ident;
|
||||||
let mut state_type: Option<Ident> = None;
|
|
||||||
|
|
||||||
for param in ast.generics.params.iter() {
|
let mut state_type = quote! { () };
|
||||||
|
|
||||||
|
for param in &ast.generics.params {
|
||||||
if let GenericParam::Type(type_param) = param {
|
if let GenericParam::Type(type_param) = param {
|
||||||
state_type = Some(type_param.ident.clone())
|
let type_ident = &type_param.ident;
|
||||||
|
state_type = quote! {#type_ident};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let state_type_name = state_type.unwrap_or_else(|| parse_quote! { () });
|
|
||||||
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||||
|
|
||||||
let gen = quote! {
|
let gen = quote! {
|
||||||
impl #impl_generics gpui3::Element for #type_name #ty_generics
|
impl #impl_generics gpui3::Element for #type_name #ty_generics
|
||||||
#where_clause
|
#where_clause
|
||||||
{
|
{
|
||||||
type State = #state_type_name;
|
type State = #state_type;
|
||||||
type FrameState = gpui3::AnyElement<#state_type_name>;
|
type FrameState = gpui3::AnyElement<#state_type>;
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
&mut self,
|
&mut self,
|
||||||
state: &mut #state_type_name,
|
state: &mut #state_type,
|
||||||
cx: &mut gpui3::ViewContext<V>,
|
cx: &mut gpui3::ViewContext<V>,
|
||||||
) -> anyhow::Result<(gpui3::LayoutId, Self::FrameState)> {
|
) -> anyhow::Result<(gpui3::LayoutId, Self::FrameState)> {
|
||||||
let mut rendered_element = self.render(state, cx).into_element().into_any();
|
let mut rendered_element = self.render(state, cx).into_element().into_any();
|
||||||
|
@ -37,7 +37,7 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
|
||||||
fn paint(
|
fn paint(
|
||||||
&mut self,
|
&mut self,
|
||||||
layout: &gpui3::Layout,
|
layout: &gpui3::Layout,
|
||||||
state: &mut #state_type_name,
|
state: &mut #state_type,
|
||||||
rendered_element: &mut Self::FrameState,
|
rendered_element: &mut Self::FrameState,
|
||||||
cx: &mut gpui3::ViewContext<V>,
|
cx: &mut gpui3::ViewContext<V>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1,26 +1,29 @@
|
||||||
use crate::theme::{theme, Theme};
|
use crate::theme::{theme, Theme};
|
||||||
use gpui3::{
|
use gpui3::{
|
||||||
div, img, svg, ArcCow, Element, IntoAnyElement, ParentElement, ScrollState, StyleHelpers,
|
div, img, svg, view, AppContext, ArcCow, Context, Element, IntoAnyElement, ParentElement,
|
||||||
ViewContext,
|
ScrollState, StyleHelpers, View, ViewContext, WindowContext,
|
||||||
};
|
};
|
||||||
use std::marker::PhantomData;
|
|
||||||
|
|
||||||
pub struct CollabPanelElement<V: 'static> {
|
struct CollabPanel {
|
||||||
view_type: PhantomData<V>,
|
|
||||||
scroll_state: ScrollState,
|
scroll_state: ScrollState,
|
||||||
}
|
}
|
||||||
|
|
||||||
// When I improve child view rendering, I'd like to have V implement a trait that
|
pub fn collab_panel(cx: &mut WindowContext) -> View<CollabPanel> {
|
||||||
// provides the scroll state, among other things.
|
view(cx.entity(|cx| CollabPanel::new(cx)), |panel, cx| {
|
||||||
pub fn collab_panel<V: 'static>(scroll_state: ScrollState) -> CollabPanelElement<V> {
|
panel.render(cx)
|
||||||
CollabPanelElement {
|
})
|
||||||
view_type: PhantomData,
|
}
|
||||||
scroll_state,
|
|
||||||
|
impl CollabPanel {
|
||||||
|
fn new(_: &mut AppContext) -> Self {
|
||||||
|
CollabPanel {
|
||||||
|
scroll_state: ScrollState::default(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> CollabPanelElement<V> {
|
impl CollabPanel {
|
||||||
fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl Element<State = Self> {
|
||||||
let theme = theme(cx);
|
let theme = theme(cx);
|
||||||
|
|
||||||
// Panel
|
// Panel
|
||||||
|
@ -115,10 +118,10 @@ impl<V: 'static> CollabPanelElement<V> {
|
||||||
|
|
||||||
fn list_section_header(
|
fn list_section_header(
|
||||||
&self,
|
&self,
|
||||||
label: impl IntoAnyElement<V>,
|
label: impl IntoAnyElement<Self>,
|
||||||
expanded: bool,
|
expanded: bool,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
) -> impl Element<State = V> {
|
) -> impl Element<State = Self> {
|
||||||
div()
|
div()
|
||||||
.h_7()
|
.h_7()
|
||||||
.px_2()
|
.px_2()
|
||||||
|
@ -144,9 +147,9 @@ impl<V: 'static> CollabPanelElement<V> {
|
||||||
fn list_item(
|
fn list_item(
|
||||||
&self,
|
&self,
|
||||||
avatar_uri: impl Into<ArcCow<'static, str>>,
|
avatar_uri: impl Into<ArcCow<'static, str>>,
|
||||||
label: impl IntoAnyElement<V>,
|
label: impl IntoAnyElement<Self>,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
) -> impl Element<State = V> {
|
) -> impl Element<State = Self> {
|
||||||
div()
|
div()
|
||||||
.h_7()
|
.h_7()
|
||||||
.px_2()
|
.px_2()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{collab_panel::collab_panel, theme::theme};
|
use crate::{collab_panel::collab_panel, theme::theme};
|
||||||
use gpui3::{div, img, svg, Element, ParentElement, ScrollState, StyleHelpers, ViewContext};
|
use gpui3::{div, img, svg, Element, ParentElement, ScrollState, StyleHelpers, ViewContext};
|
||||||
|
|
||||||
#[derive(Element, Default)]
|
#[derive(Default)]
|
||||||
struct WorkspaceElement {
|
struct WorkspaceElement {
|
||||||
left_scroll_state: ScrollState,
|
left_scroll_state: ScrollState,
|
||||||
right_scroll_state: ScrollState,
|
right_scroll_state: ScrollState,
|
||||||
|
@ -271,18 +271,12 @@ impl TitleBar {
|
||||||
|
|
||||||
// ================================================================================ //
|
// ================================================================================ //
|
||||||
|
|
||||||
struct StatusBar;
|
mod statusbar {
|
||||||
|
use gpui3::WindowContext;
|
||||||
|
|
||||||
pub fn statusbar<V: 'static>() -> impl Element<State = V> {
|
use super::*;
|
||||||
StatusBar
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StatusBar {
|
pub fn statusbar<V: 'static>(_: &mut V, cx: &mut ViewContext<V>) -> impl Element<State = V> {
|
||||||
fn render<V: 'static>(
|
|
||||||
&mut self,
|
|
||||||
_: &mut V,
|
|
||||||
cx: &mut ViewContext<V>,
|
|
||||||
) -> impl Element<State = V> {
|
|
||||||
let theme = theme(cx);
|
let theme = theme(cx);
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
|
@ -291,11 +285,11 @@ impl StatusBar {
|
||||||
.w_full()
|
.w_full()
|
||||||
.h_8()
|
.h_8()
|
||||||
.fill(theme.lowest.base.default.background)
|
.fill(theme.lowest.base.default.background)
|
||||||
.child(self.left_group(cx))
|
.child(left_group(cx))
|
||||||
.child(self.right_group(cx))
|
.child(right_group(cx))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn left_group<V: 'static>(&mut self, cx: &mut ViewContext<V>) -> impl Element<State = V> {
|
fn left_group<V: 'static>(cx: &mut ViewContext<V>) -> impl Element<State = V> {
|
||||||
let theme = theme(cx);
|
let theme = theme(cx);
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
|
@ -392,7 +386,7 @@ impl StatusBar {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn right_group<V: 'static>(&mut self, cx: &mut ViewContext<V>) -> impl Element<State = V> {
|
fn right_group<S: 'static>(cx: &mut ViewContext<S>) -> impl Element<State = S> {
|
||||||
let theme = theme(cx);
|
let theme = theme(cx);
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue