diff --git a/kayak_core/src/children.rs b/kayak_core/src/children.rs new file mode 100644 index 0000000000000000000000000000000000000000..69941dc5a0d4243f90b0432eb4f3afbef589f08b --- /dev/null +++ b/kayak_core/src/children.rs @@ -0,0 +1,31 @@ +use std::fmt::{Debug, Formatter}; +use std::sync::Arc; +use crate::{Index, KayakContextRef}; + +type ChildrenBuilder = Arc<dyn Fn(Option<Index>, &mut KayakContextRef) + Send + Sync>; + +/// A container for a function that generates child widgets +#[derive(Clone)] +pub struct Children(ChildrenBuilder); + +impl Children { + pub fn new(builder: ChildrenBuilder) -> Self { + Self(builder) + } + pub fn build(&self, id: Option<Index>, context: &mut KayakContextRef) { + self.0(id, context); + } +} + +impl Debug for Children { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Children").finish() + } +} + +impl PartialEq for Children { + fn eq(&self, _: &Self) -> bool { + // Never prevent "==" for being true because of this struct + true + } +} \ No newline at end of file diff --git a/kayak_core/src/fragment.rs b/kayak_core/src/fragment.rs index 535d528a9ad1560cdae94ef4ce355916d0ddfcf6..939f18f40ca0bf115ea9a778f4759c2d05bba982 100644 --- a/kayak_core/src/fragment.rs +++ b/kayak_core/src/fragment.rs @@ -1,13 +1,9 @@ -use derivative::*; - use crate::{context_ref::KayakContextRef, styles::Style, Index, Widget, WidgetProps, Children, OnEvent}; -#[derive(Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(Default, Debug, PartialEq, Clone)] pub struct FragmentProps { pub styles: Option<Style>, - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: crate::Children, + pub children: Option<crate::Children>, } #[derive(Default, Debug, PartialEq, Clone)] @@ -17,7 +13,7 @@ pub struct Fragment { } impl WidgetProps for FragmentProps { - fn get_children(&self) -> Children { + fn get_children(&self) -> Option<Children> { self.children.clone() } @@ -64,7 +60,7 @@ impl Widget for Fragment { let parent_id = self.get_id(); if let Some(children) = self.props.children.take() { let mut context = KayakContextRef::new(&mut context.context, Some(parent_id)); - children(Some(parent_id), &mut context); + children.build(Some(parent_id), &mut context); } else { return; } diff --git a/kayak_core/src/lib.rs b/kayak_core/src/lib.rs index 94f06d1f3a065138669ce8504ad68228f0ce63dc..2db69fe19dff7e187ac813fecd4a80d67e25fa51 100644 --- a/kayak_core/src/lib.rs +++ b/kayak_core/src/lib.rs @@ -23,10 +23,13 @@ pub mod tree; mod vec; pub mod widget; pub mod widget_manager; +mod children; +mod on_event; use std::sync::{Arc, RwLock}; pub use binding::*; +pub use children::Children; pub use color::Color; pub use context::*; pub use context_ref::KayakContextRef; @@ -38,6 +41,7 @@ pub use generational_arena::{Arena, Index}; pub use input_event::*; pub use keyboard::{KeyboardEvent, KeyboardModifiers}; pub use keys::KeyCode; +pub use on_event::OnEvent; pub use resources::Resources; pub use tree::{Tree, WidgetTree}; pub use vec::{VecTracker, VecTrackerProps}; @@ -50,23 +54,6 @@ pub mod derivative { /// Type alias for dynamic widget objects. We use [BaseWidget] so that we can be object-safe type BoxedWidget = Box<dyn BaseWidget>; -pub type Children = Option<Arc<dyn Fn(Option<crate::Index>, &mut KayakContextRef) + Send + Sync>>; - -#[derive(Clone)] -pub struct OnEvent( - pub Arc< - RwLock<dyn FnMut(&mut crate::context::KayakContext, &mut Event) + Send + Sync + 'static>, - >, -); - -impl OnEvent { - pub fn new<F: FnMut(&mut crate::context::KayakContext, &mut Event) + Send + Sync + 'static>( - f: F, - ) -> OnEvent { - OnEvent(Arc::new(RwLock::new(f))) - } -} - #[derive(Clone)] pub struct Handler<T = ()>(pub Arc<RwLock<dyn FnMut(T) + Send + Sync + 'static>>); diff --git a/kayak_core/src/on_event.rs b/kayak_core/src/on_event.rs new file mode 100644 index 0000000000000000000000000000000000000000..c2fcb26d8ecab1ba5fc8cfaa6491050de5bd859a --- /dev/null +++ b/kayak_core/src/on_event.rs @@ -0,0 +1,49 @@ +use std::fmt::{Debug, Formatter}; +use std::sync::{Arc, RwLock}; +use crate::{Event, KayakContext}; + +/// A container for a function that handles events +#[derive(Clone)] +pub struct OnEvent( + Arc< + RwLock<dyn FnMut(&mut KayakContext, &mut Event) + Send + Sync + 'static>, + >, +); + +impl OnEvent { + /// Create a new event handler + /// + /// The handler should be a closure that takes the following arguments: + /// 1. The current context + /// 2. The event + pub fn new<F: FnMut(&mut KayakContext, &mut Event) + Send + Sync + 'static>( + f: F, + ) -> OnEvent { + OnEvent(Arc::new(RwLock::new(f))) + } + + /// Call the event handler + /// + /// Returns true if the handler was successfully invoked. + pub fn try_call(&self, context: &mut KayakContext, event: &mut Event) -> bool { + if let Ok(mut on_event) = self.0.write() { + on_event(context, event); + true + } else { + false + } + } +} + +impl Debug for OnEvent { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("OnEvent").finish() + } +} + +impl PartialEq for OnEvent { + fn eq(&self, _: &Self) -> bool { + // Never prevent "==" for being true because of this struct + true + } +} \ No newline at end of file diff --git a/kayak_core/src/vec.rs b/kayak_core/src/vec.rs index f2413470e6dc2ea19fefdbc4ae7daa8babad4804..b25d7e0dd266db2f0d7092f99d601339a61a1483 100644 --- a/kayak_core/src/vec.rs +++ b/kayak_core/src/vec.rs @@ -1,21 +1,14 @@ -use derivative::*; - use crate::{context_ref::KayakContextRef, styles::Style, Index, Widget, Children, OnEvent, WidgetProps}; -#[derive(Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(Default, Debug, PartialEq, Clone)] pub struct VecTrackerProps<T> { pub data: Vec<T>, - #[derivative(Default(value = "None"))] pub styles: Option<Style>, - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: crate::Children, - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub on_event: Option<crate::OnEvent>, + pub children: Option<Children>, + pub on_event: Option<OnEvent>, } -#[derive(Derivative)] -#[derivative(Debug, PartialEq, Clone, Default)] +#[derive(Debug, PartialEq, Clone, Default)] pub struct VecTracker<T> { pub id: Index, pub props: VecTrackerProps<T>, @@ -50,7 +43,7 @@ impl<T> WidgetProps for VecTrackerProps<T> where T: Widget, { - fn get_children(&self) -> Children { + fn get_children(&self) -> Option<Children> { self.children.clone() } diff --git a/kayak_core/src/widget.rs b/kayak_core/src/widget.rs index 7d6bcaeb1b96aacc5d040dc7280974963033a228..e4185955fdb6e6546f945199a751dfb0a16deaa8 100644 --- a/kayak_core/src/widget.rs +++ b/kayak_core/src/widget.rs @@ -60,16 +60,14 @@ pub trait Widget: std::fmt::Debug + Clone + Default + PartialEq + AsAny + Send + /// Send an event to this widget fn on_event(&mut self, context: &mut KayakContext, event: &mut Event) { if let Some(on_event) = self.get_props().get_on_event() { - if let Ok(mut on_event) = on_event.0.write() { - on_event(context, event); - } + on_event.try_call(context, event); } } } /// Trait for props passed to a widget pub trait WidgetProps: std::fmt::Debug + AsAny + Send + Sync { - fn get_children(&self) -> Children; + fn get_children(&self) -> Option<Children>; fn get_styles(&self) -> Option<Style>; fn get_on_event(&self) -> Option<OnEvent>; fn get_focusable(&self) -> Option<bool>; diff --git a/kayak_render_macros/src/children.rs b/kayak_render_macros/src/children.rs index baa33e1e06943d7eb1b79228e365d617c1c64c9f..5870e64b7380a80716b0cb3daa68062bb4e54c21 100644 --- a/kayak_render_macros/src/children.rs +++ b/kayak_render_macros/src/children.rs @@ -87,11 +87,11 @@ impl Children { ); quote! { - Some(std::sync::Arc::new(move |parent_id: Option<#kayak_core::Index>, context: &mut #kayak_core::KayakContextRef| { + Some(#kayak_core::Children::new(std::sync::Arc::new(move |parent_id: Option<#kayak_core::Index>, context: &mut #kayak_core::KayakContextRef| { #cloned_attrs #children_builder context.commit(); - })) + }))) } } }; @@ -149,10 +149,10 @@ impl Children { } quote! { - Some(std::sync::Arc::new(move |parent_id: Option<#kayak_core::Index>, context: &mut #kayak_core::KayakContextRef| { + Some(#kayak_core::Children::new(std::sync::Arc::new(move |parent_id: Option<#kayak_core::Index>, context: &mut #kayak_core::KayakContextRef| { #(#output)* context.commit(); - })) + }))) } } } diff --git a/kayak_render_macros/src/lib.rs b/kayak_render_macros/src/lib.rs index 761726db8113894a55636783f62a87841ba45998..120dc8689e677a4f767d2cca4767a257030984a5 100644 --- a/kayak_render_macros/src/lib.rs +++ b/kayak_render_macros/src/lib.rs @@ -75,7 +75,7 @@ pub fn widget(args: TokenStream, item: TokenStream) -> TokenStream { function_component::create_function_widget(f, widget_args) } -#[proc_macro_derive(WidgetProps, attributes(props, widget_props))] +#[proc_macro_derive(WidgetProps, attributes(prop_field))] #[proc_macro_error] pub fn derive_widget_props(item: TokenStream) -> TokenStream { impl_widget_props(item) diff --git a/kayak_render_macros/src/widget_props.rs b/kayak_render_macros/src/widget_props.rs index 46dbb2c13201f3cc455d51d54abeee6125985ff5..b223ef8a15bbdf5ee864c259172a2873acb635e8 100644 --- a/kayak_render_macros/src/widget_props.rs +++ b/kayak_render_macros/src/widget_props.rs @@ -1,41 +1,19 @@ use proc_macro::TokenStream; -use proc_macro2::Ident; +use proc_macro2::{Ident}; use proc_macro_error::{emit_error, emit_warning}; use quote::quote; -use syn::{Data, DeriveInput, Field, Meta, NestedMeta, parse_macro_input, spanned::Spanned}; +use syn::{AttributeArgs, Data, DeriveInput, Field, Fields, ItemStruct, Meta, NestedMeta, parse_macro_input, spanned::Spanned}; +use crate::attribute::Attribute; use crate::get_core_crate; -/// The ident for the props helper attribute (`#[props(Children)]`) -const PROPS_HELPER_1: &str = "props"; -/// An alternate for the props helper attribute in case more specificity is needed to -/// prevent conflicts with other crates (`#[widget_props(Children)]`) -const PROPS_HELPER_2: &str = "widget_props"; +/// The ident for the props helper attribute (`#[prop_field(Children)]`) +const PROPS_HELPER_IDENT: &str = "prop_field"; - -/// Usage: -/// ``` -/// #[props(Children)] -/// ``` const PROP_CHILDREN: &str = "Children"; - -/// Usage: -/// ``` -/// #[props(Styles)] -/// ``` const PROP_STYLE: &str = "Styles"; - -/// Usage: -/// ``` -/// #[props(OnEvent)] -/// ``` const PROP_ON_EVENT: &str = "OnEvent"; - -/// Usage: -/// ``` -/// #[props(Focusable)] -/// ``` const PROP_FOCUSABLE: &str = "Focusable"; #[derive(Default)] @@ -64,15 +42,15 @@ pub(crate) fn impl_widget_props(input: TokenStream) -> TokenStream { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); let output = quote! { impl #impl_generics #kayak_core::WidgetProps for #ident #ty_generics #where_clause { - fn get_children(&self) -> kayak_core::Children { + fn get_children(&self) -> Option<#kayak_core::Children> { #children_return } - fn get_styles(&self) -> Option<kayak_core::styles::Style> { + fn get_styles(&self) -> Option<#kayak_core::styles::Style> { #styles_return } - fn get_on_event(&self) -> Option<kayak_core::OnEvent> { + fn get_on_event(&self) -> Option<#kayak_core::OnEvent> { #on_event_return } @@ -126,7 +104,7 @@ fn process_field(field: Field, props: &mut PropsHelpers) { for attr in field.attrs { if let Ok(meta) = attr.parse_meta() { if let Meta::List(meta) = meta { - if !meta.path.is_ident(PROPS_HELPER_1) && !meta.path.is_ident(PROPS_HELPER_2) { + if !meta.path.is_ident(PROPS_HELPER_IDENT) { continue; } diff --git a/rfcs/widget-restructure-rfc-1.md b/rfcs/widget-restructure-rfc-1.md index f071c8c51276b4d49627bc2581f8943e1133dbf2..10efd913415aef9d8454a2b296204a5fc94e6098 100644 --- a/rfcs/widget-restructure-rfc-1.md +++ b/rfcs/widget-restructure-rfc-1.md @@ -142,10 +142,10 @@ One additional feature for `WidgetProps` this RFC would like to propose is the a The derive macro would have some associated macros, which will be used to mark certain fields for use in the implementation. These are: -* `#[props(OnEvent)]` - Used to mark a field as the `OnEvent` prop -* `#[props(Styles)]` - Used to mark a field as the `Styles` prop -* `#[props(Focusable)]` - Used to mark a field as the `Focusable` prop -* `#[props(Children)]` - Used to mark a field as the `Children` prop +* `#[prop_field(OnEvent)]` - Used to mark a field as the `OnEvent` prop +* `#[prop_field(Styles)]` - Used to mark a field as the `Styles` prop +* `#[prop_field(Focusable)]` - Used to mark a field as the `Focusable` prop +* `#[prop_field(Children)]` - Used to mark a field as the `Children` prop There may be more added to this list in the future, but for now this is the main assortment. @@ -158,11 +158,11 @@ Additionally, they should be allowed to be specified as `Optional`. ```rust #[derive(WidgetProps)] struct MyWidgetProps { - #[props(OnEvent)] + #[prop_field(OnEvent)] event_handler: OnEvent - #[props(Focusable)] + #[prop_field(Focusable)] focusable: Optional<bool>, - #[props(Children)] + #[prop_field(Children)] children: Children, // Defined without the marker attribute: styles: Styles, @@ -237,11 +237,11 @@ For now though we can create our props struct and derive `WidgetProps` as explai #[derive(Debug, WidgetProps)] struct MyButtonProps { // Kayak Props - #[props(OnEvent)] + #[prop_field(OnEvent)] event_handler: Option<OnEvent>, - #[props(Styles)] + #[prop_field(Styles)] styles: Option<Style>, - #[props(Focusable)] + #[prop_field(Focusable)] focusable: bool, // Widget Props diff --git a/src/widgets/app.rs b/src/widgets/app.rs index bfa99d9bf4adc3426a384b54070588273c0074db..03216d91029d0ae86aa0bd4c6566892c334495c8 100644 --- a/src/widgets/app.rs +++ b/src/widgets/app.rs @@ -8,19 +8,18 @@ use crate::core::{ use crate::widgets::Clip; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct AppProps { - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/background.rs b/src/widgets/background.rs index b43034e7ab51b493ed3a43b5ca8e84b8c71d0cb7..be08aac9322fc36f42f6d8775d04c7b53d6029ee 100644 --- a/src/widgets/background.rs +++ b/src/widgets/background.rs @@ -6,19 +6,18 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct BackgroundProps { - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/button.rs b/src/widgets/button.rs index 02f311bcbd63cec67b8b5e05855ca29378f7fe3d..7c790d2443e52530dacf1a719fbd3fbcb34f58dc 100644 --- a/src/widgets/button.rs +++ b/src/widgets/button.rs @@ -6,19 +6,18 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct ButtonProps { - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "Some(true)"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/clip.rs b/src/widgets/clip.rs index a064606dd92734683ed532a40af604b89f7b032a..d710339621aa260bd70b4ae1e517a48751ecdf57 100644 --- a/src/widgets/clip.rs +++ b/src/widgets/clip.rs @@ -6,16 +6,15 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct ClipProps { - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, } diff --git a/src/widgets/element.rs b/src/widgets/element.rs index 40ccd503f2d76d9e015fbaf5351e29b728e399ef..6d0a4cab2c36cbb00d980f47775cba68e806868d 100644 --- a/src/widgets/element.rs +++ b/src/widgets/element.rs @@ -6,19 +6,18 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct ElementProps { - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/fold.rs b/src/widgets/fold.rs index f4d99d51b55e8797f3dd10256dd403d6c4f5823c..c9a2b4010c5fe9ecc136dc1733e16b8fa67cd828 100644 --- a/src/widgets/fold.rs +++ b/src/widgets/fold.rs @@ -8,23 +8,22 @@ use crate::core::{ use crate::widgets::{Background, Clip, If, Text}; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct FoldProps { pub label: String, pub open: Option<bool>, pub on_change: Option<Handler<bool>>, pub default_open: bool, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "Some(true)"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/if_element.rs b/src/widgets/if_element.rs index 6997ef9f2812ec11be8ad598086462c10d17f333..3fdb090d4f3a9a2491527af70ded45a6a9728a46 100644 --- a/src/widgets/if_element.rs +++ b/src/widgets/if_element.rs @@ -6,20 +6,19 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct IfProps { pub condition: bool, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/image.rs b/src/widgets/image.rs index 854e10d143b6293fc9f94cea1f133c69b8420bc5..79d421c246c798b21cf2b637e04beb7e31489fd8 100644 --- a/src/widgets/image.rs +++ b/src/widgets/image.rs @@ -6,20 +6,19 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct ImageProps { pub handle: u16, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/inspector.rs b/src/widgets/inspector.rs index bee6cd1d43f436996571a714724b060f8c013c4f..2b5cb7f4cb4b2cad46c417296978d169a4b66af4 100644 --- a/src/widgets/inspector.rs +++ b/src/widgets/inspector.rs @@ -15,7 +15,7 @@ pub enum InspectData { #[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct InspectorProps { - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, } diff --git a/src/widgets/nine_patch.rs b/src/widgets/nine_patch.rs index 31a7c1c1f2319b74cd504fc8ba62ee0006764c9e..830c61eb1f97e588073fa47ce4cfc60ec7d41bce 100644 --- a/src/widgets/nine_patch.rs +++ b/src/widgets/nine_patch.rs @@ -7,21 +7,20 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct NinePatchProps { pub handle: u16, pub border: Space, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/text.rs b/src/widgets/text.rs index 1a18142ac2a3e790de7535d756e8a322a33766dc..b1845c581b4e4f30a81428bf97209582b846f64a 100644 --- a/src/widgets/text.rs +++ b/src/widgets/text.rs @@ -9,20 +9,19 @@ use crate::core::{ widget, Children, Fragment, }; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct TextProps { pub content: String, pub font: Option<String>, pub line_height: Option<f32>, pub size: f32, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/text_box.rs b/src/widgets/text_box.rs index a5a2d8da7a0376857cc94e9f7b70879b2a03c0d0..14aa3e36d706c34b485cbd473f913ca8e92deb75 100644 --- a/src/widgets/text_box.rs +++ b/src/widgets/text_box.rs @@ -9,22 +9,21 @@ use std::sync::{Arc, RwLock}; use crate::widgets::{Background, Clip, Text}; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct TextBoxProps { pub value: String, pub on_change: Option<OnChange>, pub placeholder: Option<String>, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "Some(true)"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, } diff --git a/src/widgets/tooltip.rs b/src/widgets/tooltip.rs index 0fea0ac7b9bb7c7b15e9db9b4aeeefe251a1ea1e..ccdff94419081a710dcc99f87b80b8a324fe2d1f 100644 --- a/src/widgets/tooltip.rs +++ b/src/widgets/tooltip.rs @@ -21,34 +21,32 @@ pub struct TooltipData { pub visible: bool, } -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct TooltipProviderProps { pub position: (f32, f32), pub size: (f32, f32), - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, } -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct TooltipConsumerProps { pub anchor: Option<(f32, f32)>, pub size: Option<(f32, f32)>, pub text: String, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, } diff --git a/src/widgets/window.rs b/src/widgets/window.rs index 84ca2625619f0f4a29656e5c60214cc615f4a6f8..c6366e894a4cf8b10b48965531237d292478743b 100644 --- a/src/widgets/window.rs +++ b/src/widgets/window.rs @@ -9,23 +9,22 @@ use crate::core::{ use crate::widgets::{Background, Clip, Element, Text}; -#[derive(WidgetProps, Derivative)] -#[derivative(Default, Debug, PartialEq, Clone)] +#[derive(WidgetProps, Default, Debug, PartialEq, Clone)] pub struct WindowProps { pub draggable: bool, pub position: (f32, f32), pub size: (f32, f32), pub title: String, - #[props(Styles)] + #[prop_field(Styles)] pub styles: Option<Style>, - #[props(Children)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] - pub children: Children, - #[props(OnEvent)] - #[derivative(Default(value = "None"), Debug = "ignore", PartialEq = "ignore")] + #[prop_field(Children)] + + pub children: Option<Children>, + #[prop_field(OnEvent)] + pub on_event: Option<OnEvent>, - #[props(Focusable)] - #[derivative(Default(value = "None"), PartialEq = "ignore")] + #[prop_field(Focusable)] + pub focusable: Option<bool>, }