mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-28 20:42:09 +03:00
Add a proc macro for deriving override structs with optional fields
This commit is contained in:
parent
b95b2af3e0
commit
ab9356e9d8
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
div,
|
||||||
element::{Element, ElementMetadata},
|
element::{Element, ElementMetadata},
|
||||||
frame,
|
|
||||||
text::ArcCow,
|
text::ArcCow,
|
||||||
themes::rose_pine,
|
themes::rose_pine,
|
||||||
};
|
};
|
||||||
@ -82,8 +82,9 @@ pub fn button<V>() -> Button<V, ()> {
|
|||||||
impl<V: 'static, D: 'static> Button<V, D> {
|
impl<V: 'static, D: 'static> Button<V, D> {
|
||||||
fn render(&mut self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
|
fn render(&mut self, view: &mut V, cx: &mut ViewContext<V>) -> impl Element<V> {
|
||||||
// TODO: Drive theme from the context
|
// TODO: Drive theme from the context
|
||||||
let button = frame()
|
let button = div()
|
||||||
.fill(rose_pine::dawn().error(0.5))
|
.fill(rose_pine::dawn().error(0.5))
|
||||||
|
// .hover_fill(rose_pine::dawn().error(0.6))
|
||||||
.h_4()
|
.h_4()
|
||||||
.children(self.label.clone());
|
.children(self.label.clone());
|
||||||
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
use crate::{
|
use crate::element::{
|
||||||
element::{
|
AnyElement, Element, ElementMetadata, IntoElement, Layout, LayoutContext, NodeId, PaintContext,
|
||||||
AnyElement, Element, EventHandler, IntoElement, Layout, LayoutContext, NodeId, PaintContext,
|
|
||||||
},
|
|
||||||
style::ElementStyle,
|
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use gpui::LayoutNodeId;
|
use gpui::LayoutNodeId;
|
||||||
@ -10,29 +7,23 @@ use playground_macros::IntoElement;
|
|||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
#[element_crate = "crate"]
|
#[element_crate = "crate"]
|
||||||
pub struct Frame<V: 'static> {
|
pub struct Div<V: 'static> {
|
||||||
style: ElementStyle,
|
metadata: ElementMetadata<V>,
|
||||||
handlers: Vec<EventHandler<V>>,
|
|
||||||
children: Vec<AnyElement<V>>,
|
children: Vec<AnyElement<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame<V>() -> Frame<V> {
|
pub fn div<V>() -> Div<V> {
|
||||||
Frame {
|
Div {
|
||||||
style: ElementStyle::default(),
|
metadata: ElementMetadata::default(),
|
||||||
handlers: Vec::new(),
|
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Element<V> for Frame<V> {
|
impl<V: 'static> Element<V> for Div<V> {
|
||||||
type Layout = ();
|
type Layout = ();
|
||||||
|
|
||||||
fn style_mut(&mut self) -> &mut ElementStyle {
|
fn metadata(&mut self) -> &mut ElementMetadata<V> {
|
||||||
&mut self.style
|
&mut self.metadata
|
||||||
}
|
|
||||||
|
|
||||||
fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>> {
|
|
||||||
&mut self.handlers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
@ -50,7 +41,10 @@ impl<V: 'static> Element<V> for Frame<V> {
|
|||||||
let node_id = cx
|
let node_id = cx
|
||||||
.layout_engine()
|
.layout_engine()
|
||||||
.ok_or_else(|| anyhow!("no layout engine"))?
|
.ok_or_else(|| anyhow!("no layout engine"))?
|
||||||
.add_node(self.style.to_taffy(rem_size), child_layout_node_ids)?;
|
.add_node(
|
||||||
|
self.metadata.style.to_taffy(rem_size),
|
||||||
|
child_layout_node_ids,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok((node_id, ()))
|
Ok((node_id, ()))
|
||||||
}
|
}
|
||||||
@ -58,7 +52,7 @@ impl<V: 'static> Element<V> for Frame<V> {
|
|||||||
fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
|
fn paint(&mut self, layout: Layout<()>, view: &mut V, cx: &mut PaintContext<V>) -> Result<()> {
|
||||||
cx.scene.push_quad(gpui::scene::Quad {
|
cx.scene.push_quad(gpui::scene::Quad {
|
||||||
bounds: layout.from_engine.bounds,
|
bounds: layout.from_engine.bounds,
|
||||||
background: self.style.fill.color().map(Into::into),
|
background: self.metadata.style.fill.color().map(Into::into),
|
||||||
border: Default::default(),
|
border: Default::default(),
|
||||||
corner_radii: Default::default(),
|
corner_radii: Default::default(),
|
||||||
});
|
});
|
||||||
@ -70,7 +64,7 @@ impl<V: 'static> Element<V> for Frame<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static> Frame<V> {
|
impl<V: 'static> Div<V> {
|
||||||
pub fn child(mut self, child: impl IntoElement<V>) -> Self {
|
pub fn child(mut self, child: impl IntoElement<V>) -> Self {
|
||||||
self.children.push(child.into_any_element());
|
self.children.push(child.into_any_element());
|
||||||
self
|
self
|
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
adapter::Adapter,
|
adapter::Adapter,
|
||||||
color::Hsla,
|
color::Hsla,
|
||||||
style::{Display, ElementStyle, Fill, Overflow, Position},
|
style::{Display, ElementStyle, ElementStyleOverrides, Fill, Overflow, Position},
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
pub use gpui::LayoutContext;
|
pub use gpui::LayoutContext;
|
||||||
@ -27,6 +27,7 @@ pub struct Layout<'a, E: ?Sized> {
|
|||||||
|
|
||||||
pub struct ElementMetadata<V> {
|
pub struct ElementMetadata<V> {
|
||||||
pub style: ElementStyle,
|
pub style: ElementStyle,
|
||||||
|
pub hover_style: ElementStyleOverrides,
|
||||||
pub handlers: Vec<EventHandler<V>>,
|
pub handlers: Vec<EventHandler<V>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +51,7 @@ impl<V> Default for ElementMetadata<V> {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
style: ElementStyle::default(),
|
style: ElementStyle::default(),
|
||||||
|
hover_style: ElementStyleOverrides::default(),
|
||||||
handlers: Vec::new(),
|
handlers: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,8 +60,7 @@ impl<V> Default for ElementMetadata<V> {
|
|||||||
pub trait Element<V: 'static>: 'static {
|
pub trait Element<V: 'static>: 'static {
|
||||||
type Layout: 'static;
|
type Layout: 'static;
|
||||||
|
|
||||||
fn style_mut(&mut self) -> &mut ElementStyle;
|
fn metadata(&mut self) -> &mut ElementMetadata<V>;
|
||||||
fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>>;
|
|
||||||
|
|
||||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
|
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
|
||||||
-> Result<(NodeId, Self::Layout)>;
|
-> Result<(NodeId, Self::Layout)>;
|
||||||
@ -126,7 +127,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.handlers_mut().push(EventHandler {
|
self.metadata().handlers.push(EventHandler {
|
||||||
handler: Rc::new(move |view, event, event_cx| {
|
handler: Rc::new(move |view, event, event_cx| {
|
||||||
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
||||||
if event.button == button && event.is_down {
|
if event.button == button && event.is_down {
|
||||||
@ -147,7 +148,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.handlers_mut().push(EventHandler {
|
self.metadata().handlers.push(EventHandler {
|
||||||
handler: Rc::new(move |view, event, event_cx| {
|
handler: Rc::new(move |view, event, event_cx| {
|
||||||
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
||||||
if event.button == button && event.is_down {
|
if event.button == button && event.is_down {
|
||||||
@ -168,7 +169,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.handlers_mut().push(EventHandler {
|
self.metadata().handlers.push(EventHandler {
|
||||||
handler: Rc::new(move |view, event, event_cx| {
|
handler: Rc::new(move |view, event, event_cx| {
|
||||||
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
||||||
if event.button == button && !event.is_down {
|
if event.button == button && !event.is_down {
|
||||||
@ -189,7 +190,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.handlers_mut().push(EventHandler {
|
self.metadata().handlers.push(EventHandler {
|
||||||
handler: Rc::new(move |view, event, event_cx| {
|
handler: Rc::new(move |view, event, event_cx| {
|
||||||
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
let event = event.downcast_ref::<MouseButtonEvent>().unwrap();
|
||||||
if event.button == button && !event.is_down {
|
if event.button == button && !event.is_down {
|
||||||
@ -208,7 +209,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().display = Display::Block;
|
self.metadata().style.display = Display::Block;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +217,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().display = Display::Flex;
|
self.metadata().style.display = Display::Flex;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +225,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().display = Display::Grid;
|
self.metadata().style.display = Display::Grid;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,8 +235,8 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.x = Overflow::Visible;
|
self.metadata().style.overflow.x = Overflow::Visible;
|
||||||
self.style_mut().overflow.y = Overflow::Visible;
|
self.metadata().style.overflow.y = Overflow::Visible;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,8 +244,8 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.x = Overflow::Hidden;
|
self.metadata().style.overflow.x = Overflow::Hidden;
|
||||||
self.style_mut().overflow.y = Overflow::Hidden;
|
self.metadata().style.overflow.y = Overflow::Hidden;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,8 +253,8 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.x = Overflow::Scroll;
|
self.metadata().style.overflow.x = Overflow::Scroll;
|
||||||
self.style_mut().overflow.y = Overflow::Scroll;
|
self.metadata().style.overflow.y = Overflow::Scroll;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +262,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.x = Overflow::Visible;
|
self.metadata().style.overflow.x = Overflow::Visible;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +270,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.x = Overflow::Hidden;
|
self.metadata().style.overflow.x = Overflow::Hidden;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,7 +278,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.x = Overflow::Scroll;
|
self.metadata().style.overflow.x = Overflow::Scroll;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +286,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.y = Overflow::Visible;
|
self.metadata().style.overflow.y = Overflow::Visible;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,7 +294,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.y = Overflow::Hidden;
|
self.metadata().style.overflow.y = Overflow::Hidden;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +302,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().overflow.y = Overflow::Scroll;
|
self.metadata().style.overflow.y = Overflow::Scroll;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +312,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().position = Position::Relative;
|
self.metadata().style.position = Position::Relative;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +320,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().position = Position::Absolute;
|
self.metadata().style.position = Position::Absolute;
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -329,10 +330,10 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().inset.top = length;
|
self.metadata().style.inset.top = length;
|
||||||
self.style_mut().inset.right = length;
|
self.metadata().style.inset.right = length;
|
||||||
self.style_mut().inset.bottom = length;
|
self.metadata().style.inset.bottom = length;
|
||||||
self.style_mut().inset.left = length;
|
self.metadata().style.inset.left = length;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,7 +341,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().size.width = width.into();
|
self.metadata().style.size.width = width.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,7 +349,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().size.width = Length::Auto;
|
self.metadata().style.size.width = Length::Auto;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,7 +358,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().size.width = length;
|
self.metadata().style.size.width = length;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,7 +367,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().min_size.width = length;
|
self.metadata().style.min_size.width = length;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -374,7 +375,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().size.height = height.into();
|
self.metadata().style.size.height = height.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,7 +383,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().size.height = Length::Auto;
|
self.metadata().style.size.height = Length::Auto;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,7 +392,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().size.height = height;
|
self.metadata().style.size.height = height;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -400,7 +401,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().min_size.height = length;
|
self.metadata().style.min_size.height = length;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,7 +409,7 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().fill = fill.into();
|
self.metadata().style.fill = fill.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,15 +417,14 @@ pub trait Element<V: 'static>: 'static {
|
|||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
self.style_mut().text_color = Some(color.into());
|
self.metadata().style.text_color = Some(color.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Object-safe counterpart of Element used by AnyElement to store elements as trait objects.
|
// Object-safe counterpart of Element used by AnyElement to store elements as trait objects.
|
||||||
trait ElementObject<V> {
|
trait ElementObject<V> {
|
||||||
fn style_mut(&mut self) -> &mut ElementStyle;
|
fn metadata(&mut self) -> &mut ElementMetadata<V>;
|
||||||
fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>>;
|
|
||||||
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
|
fn layout(&mut self, view: &mut V, cx: &mut LayoutContext<V>)
|
||||||
-> Result<(NodeId, Box<dyn Any>)>;
|
-> Result<(NodeId, Box<dyn Any>)>;
|
||||||
fn paint(
|
fn paint(
|
||||||
@ -436,12 +436,8 @@ trait ElementObject<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<V: 'static, E: Element<V>> ElementObject<V> for E {
|
impl<V: 'static, E: Element<V>> ElementObject<V> for E {
|
||||||
fn style_mut(&mut self) -> &mut ElementStyle {
|
fn metadata(&mut self) -> &mut ElementMetadata<V> {
|
||||||
Element::style_mut(self)
|
Element::metadata(self)
|
||||||
}
|
|
||||||
|
|
||||||
fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>> {
|
|
||||||
Element::handlers_mut(self)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
@ -490,7 +486,7 @@ impl<V: 'static> AnyElement<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_text_style(&mut self, cx: &mut impl RenderContext) -> bool {
|
pub fn push_text_style(&mut self, cx: &mut impl RenderContext) -> bool {
|
||||||
let text_style = self.element.style_mut().text_style();
|
let text_style = self.element.metadata().style.text_style();
|
||||||
if let Some(text_style) = text_style {
|
if let Some(text_style) = text_style {
|
||||||
let mut current_text_style = cx.text_style();
|
let mut current_text_style = cx.text_style();
|
||||||
text_style.apply(&mut current_text_style);
|
text_style.apply(&mut current_text_style);
|
||||||
@ -516,7 +512,7 @@ impl<V: 'static> AnyElement<V> {
|
|||||||
from_element: element_layout.as_mut(),
|
from_element: element_layout.as_mut(),
|
||||||
};
|
};
|
||||||
|
|
||||||
for event_handler in self.element.handlers_mut().iter().cloned() {
|
for event_handler in self.element.metadata().handlers.iter().cloned() {
|
||||||
let EngineLayout { order, bounds } = layout.from_engine;
|
let EngineLayout { order, bounds } = layout.from_engine;
|
||||||
|
|
||||||
let view_id = cx.view_id();
|
let view_id = cx.view_id();
|
||||||
@ -551,12 +547,8 @@ impl<V: 'static> AnyElement<V> {
|
|||||||
impl<V: 'static> Element<V> for AnyElement<V> {
|
impl<V: 'static> Element<V> for AnyElement<V> {
|
||||||
type Layout = ();
|
type Layout = ();
|
||||||
|
|
||||||
fn style_mut(&mut self) -> &mut ElementStyle {
|
fn metadata(&mut self) -> &mut ElementMetadata<V> {
|
||||||
self.element.style_mut()
|
self.element.metadata()
|
||||||
}
|
|
||||||
|
|
||||||
fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>> {
|
|
||||||
self.element.handlers_mut()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
use color::black;
|
use color::black;
|
||||||
use components::button;
|
use components::button;
|
||||||
|
use div::div;
|
||||||
use element::Element;
|
use element::Element;
|
||||||
use frame::frame;
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
geometry::{rect::RectF, vector::vec2f},
|
geometry::{rect::RectF, vector::vec2f},
|
||||||
platform::{MouseButton, WindowOptions},
|
platform::WindowOptions,
|
||||||
};
|
};
|
||||||
use log::LevelFilter;
|
use log::LevelFilter;
|
||||||
use simplelog::SimpleLogger;
|
use simplelog::SimpleLogger;
|
||||||
@ -16,8 +16,8 @@ use view::view;
|
|||||||
mod adapter;
|
mod adapter;
|
||||||
mod color;
|
mod color;
|
||||||
mod components;
|
mod components;
|
||||||
|
mod div;
|
||||||
mod element;
|
mod element;
|
||||||
mod frame;
|
|
||||||
mod paint_context;
|
mod paint_context;
|
||||||
mod style;
|
mod style;
|
||||||
mod text;
|
mod text;
|
||||||
@ -44,7 +44,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn playground<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
fn playground<V: 'static>(theme: &ThemeColors) -> impl Element<V> {
|
||||||
frame()
|
div()
|
||||||
.text_color(black())
|
.text_color(black())
|
||||||
.h_full()
|
.h_full()
|
||||||
.w_half()
|
.w_half()
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
use crate::color::Hsla;
|
use crate::color::Hsla;
|
||||||
use gpui::geometry::{DefinedLength, Edges, Length, Point, Size};
|
use gpui::geometry::{DefinedLength, Edges, Length, Point, Size};
|
||||||
|
use playground_macros::Overrides;
|
||||||
pub use taffy::style::{
|
pub use taffy::style::{
|
||||||
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,
|
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,
|
||||||
Overflow, Position,
|
Overflow, Position,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
pub trait Overrides {
|
||||||
|
type Base;
|
||||||
|
|
||||||
|
fn is_some(&self) -> bool;
|
||||||
|
fn apply(&self, base: &mut Self::Base);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Overrides)]
|
||||||
|
#[overrides_crate = "crate"]
|
||||||
pub struct ElementStyle {
|
pub struct ElementStyle {
|
||||||
/// What layout strategy should be used?
|
/// What layout strategy should be used?
|
||||||
pub display: Display,
|
pub display: Display,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::element::{Element, ElementMetadata, EventHandler, IntoElement};
|
use crate::element::{Element, ElementMetadata, IntoElement};
|
||||||
use gpui::{geometry::Size, text_layout::LineLayout, RenderContext};
|
use gpui::{geometry::Size, text_layout::LineLayout, RenderContext};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -22,8 +22,8 @@ pub struct Text<V> {
|
|||||||
impl<V: 'static> Element<V> for Text<V> {
|
impl<V: 'static> Element<V> for Text<V> {
|
||||||
type Layout = Arc<Mutex<Option<TextLayout>>>;
|
type Layout = Arc<Mutex<Option<TextLayout>>>;
|
||||||
|
|
||||||
fn style_mut(&mut self) -> &mut crate::style::ElementStyle {
|
fn metadata(&mut self) -> &mut crate::element::ElementMetadata<V> {
|
||||||
&mut self.metadata.style
|
&mut self.metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
@ -91,10 +91,6 @@ impl<V: 'static> Element<V> for Text<V> {
|
|||||||
);
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handlers_mut(&mut self) -> &mut Vec<EventHandler<V>> {
|
|
||||||
&mut self.metadata.handlers
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TextLayout {
|
pub struct TextLayout {
|
||||||
|
@ -79,12 +79,8 @@ pub fn derive_element(input: TokenStream) -> TokenStream {
|
|||||||
{
|
{
|
||||||
type Layout = #crate_name::element::AnyElement<V>;
|
type Layout = #crate_name::element::AnyElement<V>;
|
||||||
|
|
||||||
fn style_mut(&mut self) -> &mut #crate_name::style::ElementStyle {
|
fn metadata(&mut self) -> &mut #crate_name::element::ElementMetadata<V> {
|
||||||
&mut self.metadata.style
|
&mut self.metadata
|
||||||
}
|
|
||||||
|
|
||||||
fn handlers_mut(&mut self) -> &mut Vec<#crate_name::element::EventHandler<V>> {
|
|
||||||
&mut self.metadata.handlers
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(
|
fn layout(
|
||||||
|
119
crates/gpui/playground_macros/src/derive_overrides.rs
Normal file
119
crates/gpui/playground_macros/src/derive_overrides.rs
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
extern crate proc_macro;
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::{format_ident, quote};
|
||||||
|
use syn::{parse_macro_input, Data, DeriveInput, Fields, Lit, Meta};
|
||||||
|
|
||||||
|
/// When deriving Overrides on a struct Foo, builds a new struct FooOverrides
|
||||||
|
/// that implements the Overrides trait so it can be applied to Foo.
|
||||||
|
pub fn derive_overrides(input: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
|
let crate_name: String = input
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.find_map(|attr| {
|
||||||
|
if attr.path.is_ident("overrides_crate") {
|
||||||
|
match attr.parse_meta() {
|
||||||
|
Ok(Meta::NameValue(nv)) => {
|
||||||
|
if let Lit::Str(s) = nv.lit {
|
||||||
|
Some(s.value())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| String::from("playground"));
|
||||||
|
let crate_name = format_ident!("{}", crate_name);
|
||||||
|
|
||||||
|
let ident = input.ident;
|
||||||
|
let new_ident = syn::Ident::new(&format!("{}Overrides", ident), ident.span());
|
||||||
|
let data = match input.data {
|
||||||
|
Data::Struct(s) => s,
|
||||||
|
_ => panic!("Override can only be derived for structs"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let fields = match data.fields {
|
||||||
|
Fields::Named(fields) => fields.named,
|
||||||
|
_ => panic!("Override can only be derived for structs with named fields"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_fields = fields
|
||||||
|
.iter()
|
||||||
|
.map(|f| {
|
||||||
|
let name = &f.ident;
|
||||||
|
let ty = &f.ty;
|
||||||
|
|
||||||
|
if let syn::Type::Path(typepath) = ty {
|
||||||
|
if typepath.path.segments.last().unwrap().ident == "Option" {
|
||||||
|
return quote! { #name: #ty };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quote! { #name: Option<#ty> }
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let names = fields.iter().map(|f| &f.ident);
|
||||||
|
let is_some_implementation = names.clone().map(|name| {
|
||||||
|
quote! {
|
||||||
|
self.#name.is_some()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let apply_implementation = fields.iter().map(|f| {
|
||||||
|
let name = &f.ident;
|
||||||
|
let ty = &f.ty;
|
||||||
|
|
||||||
|
if let syn::Type::Path(typepath) = ty {
|
||||||
|
if typepath.path.segments.last().unwrap().ident == "Option" {
|
||||||
|
return quote! {
|
||||||
|
base.#name = self.#name.clone();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
if let Some(value) = &self.#name {
|
||||||
|
base.#name = value.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let default_implementation = names.map(|name| {
|
||||||
|
quote! {
|
||||||
|
#name: None,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let expanded = quote! {
|
||||||
|
pub struct #new_ident {
|
||||||
|
#(#new_fields,)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl #crate_name::style::Overrides for #new_ident {
|
||||||
|
type Base = #ident;
|
||||||
|
|
||||||
|
fn is_some(&self) -> bool {
|
||||||
|
#(#is_some_implementation)||*
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply(&self, base: &mut Self::Base) {
|
||||||
|
#(#apply_implementation)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for #new_ident {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
#(#default_implementation)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(expanded)
|
||||||
|
}
|
@ -2,6 +2,7 @@ use proc_macro::TokenStream;
|
|||||||
|
|
||||||
mod derive_element;
|
mod derive_element;
|
||||||
mod derive_into_element;
|
mod derive_into_element;
|
||||||
|
mod derive_overrides;
|
||||||
mod tailwind_lengths;
|
mod tailwind_lengths;
|
||||||
|
|
||||||
#[proc_macro_derive(Element, attributes(element_crate))]
|
#[proc_macro_derive(Element, attributes(element_crate))]
|
||||||
@ -14,6 +15,11 @@ pub fn derive_into_element(input: TokenStream) -> TokenStream {
|
|||||||
derive_into_element::derive_into_element(input)
|
derive_into_element::derive_into_element(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(Overrides, attributes(overrides_crate))]
|
||||||
|
pub fn derive_overrides(input: TokenStream) -> TokenStream {
|
||||||
|
derive_overrides::derive_overrides(input)
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn tailwind_lengths(attr: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn tailwind_lengths(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
tailwind_lengths::tailwind_lengths(attr, item)
|
tailwind_lengths::tailwind_lengths(attr, item)
|
||||||
|
Loading…
Reference in New Issue
Block a user