Commit 7ad2ccb2 authored by Florian Blasius's avatar Florian Blasius 🤘

[focus time] new widget and property macro

parent 249f3cc8
......@@ -129,11 +129,15 @@ impl Widget for MainView {
fn main() {
let mut world = World::from_container(Tree::default());
let mut context = WipBuildContext::new(&mut world);
let _wip_button = WipButton::create(&mut context)
.background()
.value("green")
.foreground()
.value("blue");
let _wip_button = WipButton::create()
.background("green")
.foreground("blue")
.text("Click me")
.on_click(|_| {
println!("Clicked");
false
})
.build(&mut context);
let mut application = Application::default();
......
......@@ -4,7 +4,7 @@ use crate::{
event::{Event, EventBox, EventHandler},
properties::Bounds,
structs::{Point, Position, Size},
widget::WidgetContainer,
widget::{WidgetContainer, WipWidget},
};
pub fn check_mouse_condition(position: Point, widget: &WidgetContainer<'_>) -> bool {
......@@ -94,3 +94,12 @@ pub trait ClickHandler: Sized + From<Template> + Into<Template> {
})
}
}
pub trait WipClickHandler<'a>: Sized + WipWidget<'a> {
/// Inserts a handler.
fn on_click<H: Fn(Point) -> bool + 'static>(self, handler: H) -> Self {
self.insert_handler(ClickEventHandler {
handler: Rc::new(handler)
})
}
}
\ No newline at end of file
......@@ -66,55 +66,6 @@ macro_rules! widget {
)
}
// macro_rules! wip_property {
// ($property:ident, $value:ident) => {
// use std::rc::Rc;
// use std::cell::{ Cell, RefCell };
// // use dces::entity::Entity;
// use dces::prelude::ComponentBox;
// use crate::widget::{ WipProperty, WipPropertyBuilder };
// pub enum $property {
// Property($value),
// Builder{ value: Option<$value>, source_chain: Rc<RefCell<Vec<Rc<Cell<Option<Entity>>>>>> }
// }
// impl WipProperty for $property {
// type Value = $value;
// fn value(&self) -> Self::Value {
// match self {
// $property::Property(value) => return value.clone(),
// _ => return $value::default()
// }
// }
// fn set_value(&mut self, value: Self::Value) {
// *self = $property::Property(value);
// }
// }
// impl WipPropertyBuilder for $property {
// type Value = $value;
// fn build(self) -> (Option<ComponentBox>, Option<Rc<RefCell<Vec<Rc<Cell<Option<Entity>>>>>>>) {
// match self {
// $property::Builder { value, source_chain } => {
// if let Some(value) = value {
// return (Some(ComponentBox::new($property::Property(value))), Some(source_chain))
// } else {
// return (None, Some(source_chain));
// }
// },
// _ => (None, None)
// }
// }
// }
// };
// }
/// Used to define a property.
#[macro_export]
macro_rules! property {
......@@ -156,111 +107,127 @@ macro_rules! property {
};
}
macro_rules! wip_widget {
( $(#[$widget_doc:meta])* $widget:ident { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),*} ) => {
$(#[$widget_doc])*
pub struct $type {
template: Template
/// Used to define a property.
#[macro_export]
macro_rules! wip_property {
($property:ident($type:ty)) => {
#[derive(Default)]
pub struct $property(pub $type);
impl From<$property> for $type {
fn from(property: $property) -> $type {
property.0.into()
}
}
impl $type {
/// Creates a new widget.
pub fn new() -> Self {
$type {
template: Template::new()
}
}
impl From<$type> for $property {
fn from(value: $type) -> $property {
$property(value)
}
}
pub fn child(mut self, child: Template) -> Self {
self.template = template.child(child);
self
}
impl Into<PropertySource<$property>> for $type {
fn into(self) -> PropertySource<$property> {
PropertySource::Value($property::from(self))
}
}
$(
$(#[$prop_doc])*
pub fn $property(mut self, $property: impl Into<$Property>) -> Self {
self.template.property($property.into());
self
}
)*
impl Into<PropertySource<$property>> for Entity {
fn into(self) -> PropertySource<$property> {
PropertySource::Source(self)
}
}
};
}
/*
pub struct Button {
build_context: &mut BuildContext,
id: Entity,
}
pub struct BuildContext {
world: &mut World,
}
/// Used to define a widget, with properties and event handlers.
macro_rules! wip_widget {
( $(#[$widget_doc:meta])* $widget:ident $(: $( $handler:ident ),*)* { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),* } ) => {
use std::{ any::TypeId, rc::Rc, collections::HashMap};
impl BuildContext {
fn property() -> Entity,
...
}
use dces::prelude::{Component, ComponentBox, SharedComponentBox };
pub fn new(build_context: &mut BuildContext) -> Self {
let id = build_context.create_widget();
use crate::{event::EventHandler, widget::{PropertySource, WipWidget}};
Button {
build_context,
id,
$(#[$widget_doc])*
pub struct $widget {
attached_properties: HashMap<TypeId, ComponentBox>,
shared_attached_properties: HashMap<TypeId, SharedComponentBox>,
event_handlers: Vec<Rc<dyn EventHandler>>,
$(
$property: PropertySource<$property_type>,
)*
}
}
Button::create(build_context).background().value("green").foreground().value("blue").attach(GridColumn(0)).attach_source::<GridRow>::(self.id).build()
pub struct Property {
widget: Button,
}
impl Property<P: Component> {
pub fn value(self, value: impl Into<P>) -> Button {
self.widget
}
pub fn source(id: Entity) -> Button {
}
}
fn background(self) -> Property {
Property {
widget: self,
impl $widget {
/// Sets an attached property or shares it by the given id.
pub fn attach<P: Component>(mut self, property: impl Into<PropertySource<P>>) -> Self {
match property.into() {
PropertySource::Value(value) => {
self.attached_properties.insert(TypeId::of::<P>(), ComponentBox::new(value));
},
PropertySource::Source(source) => {
self.shared_attached_properties.insert(TypeId::of::<P>(), SharedComponentBox::new(TypeId::of::<P>(), source));
}
}
self
}
$(
$(#[$prop_doc])*
pub fn $property<P: Into<PropertySource<$property_type>>>(mut self, $property: P) -> Self {
self.$property = $property.into();
self
}
)*
}
}
fn attach<P: Component>(property: impl Into<C>) -> Self {
$(
$(
impl<'a> $handler<'a> for $widget {}
)*
)*
}
impl<'a> WipWidget<'a> for $widget {
fn create() -> Self {
$widget {
attached_properties: HashMap::new(),
shared_attached_properties: HashMap::new(),
event_handlers: vec![],
$(
$property: PropertySource::Value($property_type::default()),
)*
}
}
fn insert_handler(mut self, handler: impl Into<Rc<dyn EventHandler>>) -> Self {
self.event_handlers.push(handler.into());
self
}
fn build(self, context: &mut WipBuildContext<'a>) -> WipTemplate {
let entity = context.create_entity();
fn build(mut self) -> Template {
Template::new()
.child(Container::new(self.build_context).background().source(self.id))
}
*/
for (_, property) in self.attached_properties {
context.register_property_box(entity, property);
}
#[macro_export]
macro_rules! wip_property {
($property:ident($type:ty)) => {
pub struct $property(pub $type);
for (_, property) in self.shared_attached_properties {
context.register_property_shared_box(entity, property);
}
impl From<$property> for $type {
fn from(property: $property) -> $type {
property.0.into()
}
}
$(
match self.$property {
PropertySource::Value(value) => {
context.register_property(entity, value);
},
PropertySource::Source(source) => {
context.register_shared_property::<$property_type>(entity, source);
}
}
)*
impl From<$type> for $property {
fn from(value: $type) -> $property {
$property(value)
$widget::template(context.create_entity(), context)
}
}
}
};
}
\ No newline at end of file
use crate::structs::{Brush, Color};
use crate::{
widget::PropertySource,
structs::{Brush, Color},
};
/// Used to draw the background brush of a widget.
#[derive(Clone)]
......@@ -35,4 +38,18 @@ impl From<&str> for Background {
// fn into(background: Background) -> Property {
// Property::new(background)
// }
// }
\ No newline at end of file
// }
wip_property!(WipBackground(Brush));
impl From<&str> for WipBackground {
fn from(s: &str) -> WipBackground {
WipBackground(s.into())
}
}
impl Into<PropertySource<WipBackground>> for &str {
fn into(self) -> PropertySource<WipBackground> {
PropertySource::Value(WipBackground::from(self))
}
}
\ No newline at end of file
use crate::structs::{Brush, Color};
use crate::{
widget::PropertySource,
structs::{Brush, Color},
};
/// Used to draw the foreground brush of a widget.
#[derive(Clone)]
pub struct Foreground(pub Brush);
property!(
Foreground,
ForegroundProperty,
foreground,
foreground_prop
);
property!(Foreground, ForegroundProperty, foreground, foreground_prop);
impl From<Foreground> for Color {
fn from(b: Foreground) -> Color {
......@@ -28,3 +26,17 @@ impl From<&str> for Foreground {
Foreground(s.into())
}
}
wip_property!(WipForeground(Brush));
impl From<&str> for WipForeground {
fn from(s: &str) -> WipForeground {
WipForeground(s.into())
}
}
impl Into<PropertySource<WipForeground>> for &str {
fn into(self) -> PropertySource<WipForeground> {
PropertySource::Value(WipForeground::from(self))
}
}
......@@ -2,7 +2,7 @@
pub use self::font_icon::{FontIcon, FontIconProperty, PrimaryFontIcon, SecondaryFontIcon};
pub use self::image::*;
pub use self::text::{Text, TextProperty};
pub use self::text::*;
pub use self::text_selection::*;
pub use self::water_mark::*;
......
use crate::widget::PropertySource;
/// The `Text` struct represents a string used for text drawing.
#[derive(Default, Clone)]
pub struct Text(pub String);
......@@ -17,3 +19,17 @@ impl From<String> for Text {
}
// todo tests!!!
wip_property!(WipText(String));
impl From<&str> for WipText {
fn from(s: &str) -> WipText {
WipText(s.into())
}
}
impl Into<PropertySource<WipText>> for &str {
fn into(self) -> PropertySource<WipText> {
PropertySource::Value(WipText::from(self))
}
}
\ No newline at end of file
use dces::prelude::Entity;
use crate::{
event::ClickHandler,
event::{ClickHandler, WipClickHandler},
properties::*,
styling::{colors, fonts},
widget::{Container, FontIconBlock, Property, Stack, Template, TextBlock, Widget },
widget::{Container, FontIconBlock, Property, Stack, Template, TextBlock, Widget, WipTextBlock, WipContainer, WipTemplateBuilder, WipBuildContext, WipTemplate },
};
widget!(
......@@ -100,3 +102,30 @@ impl Widget for Button {
.padding_prop(opacity)
}
}
wip_widget!(
///This is a button
WipButton: WipClickHandler {
/// Sets the background
background: WipBackground,
/// Sets the foreground
foreground: WipForeground,
/// Sets the text
text: WipText
}
);
impl<'a> WipTemplateBuilder<'a> for WipButton {
fn template(id: Entity, context: &mut WipBuildContext<'a>) -> WipTemplate {
WipTemplate::new(id).child(
WipContainer::create().background(id).build(context).child(
WipTextBlock::create()
.foreground(id)
.text(id)
.build(context),
),
)
}
}
\ No newline at end of file
use dces::prelude::Entity;
use crate::{
layout::PaddingLayout,
properties::*,
render_object::RectangleRenderObject,
widget::{Template, Widget},
widget::{Template, Widget, WipTemplateBuilder, WipBuildContext, WipTemplate},
};
widget!(
......@@ -32,3 +34,15 @@ impl Widget for Container {
}
}
wip_widget!(///This is a container
WipContainer {
/// Sets the background
background: WipBackground
});
impl<'a> WipTemplateBuilder<'a> for WipContainer {
fn template(id: Entity, context: &mut WipBuildContext<'a>) -> WipTemplate {
WipTemplate::new(id)
}
}
use std::rc::Rc;
use dces::prelude::{World, Entity, Component, ComponentBox, SharedComponentBox};
use crate::application::Tree;
use crate::theme::Selector;
use crate::event::EventHandler;
pub use self::context::Context;
pub use self::message::{MessageBox, StringMessage};
pub use self::property::{get_property, PropertyResult, Property, WipProperty, WipPropertyBuilder};
pub use self::property::{get_property, PropertyResult, Property, WipProperty, WipPropertyBuilder, PropertySource};
pub use self::state::State;
pub use self::template::{Template, TemplateBase};
pub use self::widget_container::WidgetContainer;
......@@ -35,3 +44,79 @@ pub fn remove_selector_from_widget(pseudo_class: &str, widget: &mut WidgetContai
selector.set_dirty(true);
}
}
pub struct WipTemplate {
id: Entity,
children: Vec<WipTemplate>,
// todo parent type
}
impl WipTemplate {
pub fn new(id: Entity) -> Self {
WipTemplate {
id,
children: vec![],
}
}
pub fn child(mut self, template: WipTemplate) -> Self {
self.children.push(template);
self
}
}
/// The `TemplateBuilder` trait provides the method for the widget template creation.
pub trait WipTemplateBuilder<'a> {
/// Creates the template of the widget and returns it.
fn template(id: Entity, context: &mut WipBuildContext<'a>) -> WipTemplate;
}
/// The `Widget` trait is used to define a new widget.
pub trait WipWidget<'a>: Sized + WipTemplateBuilder<'a> {
/// Creates a new widget.
fn create() -> Self;
/// Builds the widget and returns the template of the widget.
fn build(self, context: &mut WipBuildContext<'a>) -> WipTemplate;
/// Inerts a new event handler.
fn insert_handler(mut self, handler: impl Into<Rc<dyn EventHandler>>) -> Self;
}
pub struct WipBuildContext<'a> {
world: &'a mut World<Tree>,
}
impl<'a> WipBuildContext<'a> {
pub fn new(world: &'a mut World<Tree>) -> Self {
WipBuildContext { world }
}
pub fn create_entity(&mut self) -> Entity {
self.world.create_entity().build()
}
pub fn register_property<P: Component>(&mut self, entity: Entity, property: P) {
self.world
.entity_component_manager()
.register_component(entity, property);
}
pub fn register_property_box(&mut self, entity: Entity, property: ComponentBox) {
self.world
.entity_component_manager()
.register_component_box(entity, property);
}
pub fn register_property_shared_box(&mut self, entity: Entity, property: SharedComponentBox) {
self.world
.entity_component_manager()
.register_shared_component_box(entity, property);
}
pub fn register_shared_property<P: Component>(&mut self, target: Entity, source: Entity) {
self.world
.entity_component_manager()
.register_shared_component::<P>(target, source);
}
}
\ No newline at end of file
......@@ -84,3 +84,8 @@ where
.map(|r| r.clone())
.unwrap_or_default()
}
pub enum PropertySource<P: Component> {
Source(Entity),
Value(P),
}
\ No newline at end of file
......@@ -34,199 +34,5 @@ mod text_box;
mod toggle_button;
mod water_mark_text_block;
use dces::prelude::*;
use crate::application::Tree;
pub struct WipBuildContext<'a> {
world: &'a mut World<Tree>,
}
impl<'a> WipBuildContext<'a> {
pub fn new(world: &'a mut World<Tree>) -> Self {
WipBuildContext {
world,
}
}
pub fn create_entity(&mut self) -> Entity {
self.world.create_entity().build()
}
pub fn register_property<P: Component>(&mut self, entity: Entity, property: P) {
self.world.entity_component_manager().register_component(entity, property);
}
pub fn register_shared_property<P:Component>(&mut self, target: Entity, source: Entity) {