Commit 85a6d5a0 authored by Florian Blasius's avatar Florian Blasius 🤘

[refactoring] api shared properties

parent 5183fcb7
......@@ -37,7 +37,7 @@ impl Widget for MainView {
fn create() -> Self::Template {
let state = Rc::new(MainViewState::default());
let button_count_text = SharedProperty::new(Text::from("Button count: 0"));
let button_count_text = Property::new(Text::from("Button count: 0"));
Template::new()
.state(state.clone())
......@@ -109,7 +109,7 @@ impl Widget for MainView {
.child(create_header("Text", 2, 0))
.child(
TextBlock::create()
.shared_text(button_count_text.clone())
.shared_text(button_count_text.share())
.margin((0.0, 8.0, 0.0, 0.0))
.attach_property(GridColumn(2))
.attach_property(GridRow(1)),
......
......@@ -37,7 +37,7 @@ impl Widget for MainView {
fn create() -> Self::Template {
let state = Rc::new(MainViewState::default());
let button_count_text = SharedProperty::new(Text::from("Button count: 0"));
let button_count_text = Property::new(Text::from("Button count: 0"));
let grid = Grid::create();
......@@ -115,7 +115,7 @@ impl Widget for MainView {
.child(
TextBlock::create()
.selector(Selector::new().class("body"))
.shared_text(button_count_text.clone())
.shared_text(button_count_text.share())
.margin((0.0, 8.0, 0.0, 0.0))
.attach_property(GridColumn(2))
.attach_property(GridRow(1)),
......
......@@ -68,7 +68,7 @@ macro_rules! property {
($type:ident, $property:ident, $method:ident, $shared_method:ident) => {
use dces::prelude::{Entity, EntityComponentManager};
use crate::widget::{get_property, SharedProperty, Template};
use crate::widget::{get_property, Property, Template};
pub trait $property: Sized + From<Template> + Into<Template> {
/// Transforms the property into a template.
......@@ -82,7 +82,7 @@ macro_rules! property {
}
/// Inserts a shared property.
fn $shared_method(self, $method: SharedProperty) -> Self {
fn $shared_method(self, $method: Property) -> Self {
self.template(|template| template.shared_property($method.into()))
}
}
......@@ -94,3 +94,44 @@ macro_rules! property {
}
};
}
macro_rules! widget {
( $(#[$widget_doc:meta])* $widget:ident { $($(#[$prop_doc:meta])* $property:ident: $property_type:tt ),*} ) => {
$(#[$widget_doc])*
pub struct $widget {
$(
$property: $property_type,
)*
}
impl $widget {
/// Creates a new instance of the widget, with all its properties. Used to build the template of the widget.
pub fn create() -> Self {
$widget {
$(
$property: $property_type::default(),
)*
}
}
$(
$(#[$prop_doc])*
pub fn $property(mut self, $property: impl Into<$property_type>) -> Self {
self.$property = $property.into();
self
}
)*
/// Builds the template of the widget.
pub fn build(self) -> Template {
let mut template = self.template();
$(
template.insert_property(TypeId::of::<$property_type>(), self.$property.into());
)*
template
}
}
};
}
\ No newline at end of file
......@@ -2,7 +2,7 @@ use crate::{
event::ClickHandler,
properties::*,
styling::{colors, fonts},
widget::{Container, FontIconBlock, SharedProperty, Stack, Template, TextBlock, Widget},
widget::{Container, FontIconBlock, Property, Stack, Template, TextBlock, Widget},
};
/// The `Button` widget can be clicked by user. It's used to perform an action.
......@@ -20,27 +20,27 @@ impl Widget for Button {
fn create() -> Self::Template {
// text properties
let text = SharedProperty::new(Text::default());
let foreground = SharedProperty::new(Foreground::from(colors::LINK_WATER_COLOR));
let text = Property::new(Text::default());
let foreground = Property::new(Foreground::from(colors::LINK_WATER_COLOR));
let font =
SharedProperty::new(Font::from(fonts::font_into_box(fonts::ROBOTO_REGULAR_FONT)));
let font_size = SharedProperty::new(FontSize::from(fonts::FONT_SIZE_12));
Property::new(Font::from(fonts::font_into_box(fonts::ROBOTO_REGULAR_FONT)));
let font_size = Property::new(FontSize::from(fonts::FONT_SIZE_12));
// icon properties
let icon = SharedProperty::new(FontIcon::default());
let icon_brush = SharedProperty::new(IconBrush::from(colors::LINK_WATER_COLOR));
let icon_font = SharedProperty::new(IconFont::from(fonts::font_into_box(
let icon = Property::new(FontIcon::default());
let icon_brush = Property::new(IconBrush::from(colors::LINK_WATER_COLOR));
let icon_font = Property::new(IconFont::from(fonts::font_into_box(
fonts::MATERIAL_ICONS_REGULAR_FONT,
)));
let icon_size = SharedProperty::new(IconSize::from(fonts::ICON_FONT_SIZE_12));
let icon_size = Property::new(IconSize::from(fonts::ICON_FONT_SIZE_12));
// container properties
let background = SharedProperty::new(Background::from(colors::LYNCH_COLOR));
let border_radius = SharedProperty::new(BorderRadius::from(2.0));
let border_thickness = SharedProperty::new(BorderThickness::from(0.0));
let border_brush = SharedProperty::new(BorderBrush::from("transparent"));
let padding = SharedProperty::new(Padding::from((8.0, 0.0, 8.0, 0.0)));
let opacity = SharedProperty::new(Opacity::from(1.0));
let background = Property::new(Background::from(colors::LYNCH_COLOR));
let border_radius = Property::new(BorderRadius::from(2.0));
let border_thickness = Property::new(BorderThickness::from(0.0));
let border_brush = Property::new(BorderBrush::from("transparent"));
let padding = Property::new(Padding::from((8.0, 0.0, 8.0, 0.0)));
let opacity = Property::new(Opacity::from(1.0));
ButtonTemplate::new()
.height(32.0)
......@@ -58,24 +58,24 @@ impl Widget for Button {
.child(
FontIconBlock::create()
.margin((0.0, 0.0, 2.0, 0.0))
.shared_font_icon(icon.clone())
.shared_icon_brush(icon_brush.clone())
.shared_icon_size(icon_size.clone())
.shared_icon_font(icon_font.clone()),
.shared_font_icon(icon.share())
.shared_icon_brush(icon_brush.share())
.shared_icon_size(icon_size.share())
.shared_icon_font(icon_font.share()),
)
.child(
TextBlock::create()
.shared_foreground(foreground.clone())
.shared_text(text.clone())
.shared_font(font.clone())
.shared_font_size(font_size.clone()),
.shared_foreground(foreground.share())
.shared_text(text.share())
.shared_font(font.share())
.shared_font_size(font_size.share()),
),
)
.shared_padding(padding.clone())
.shared_background(background.clone())
.shared_border_radius(border_radius.clone())
.shared_border_thickness(border_thickness.clone())
.shared_border_brush(border_brush.clone()),
.shared_padding(padding.share())
.shared_background(background.share())
.shared_border_radius(border_radius.share())
.shared_border_thickness(border_thickness.share())
.shared_border_brush(border_brush.share()),
)
.shared_text(text)
.shared_font(font)
......
......@@ -5,7 +5,7 @@ use crate::{
TextProperty,
},
theme::Selector,
widget::{Container, FontIconBlock, SharedProperty, Stack, Template, TextBlock, Widget},
widget::{Container, FontIconBlock, Property, Stack, Template, TextBlock, Widget},
};
/// The `Checkbox` widget can be switch its selected state. It contains a selection box and a text.
///
......@@ -21,9 +21,9 @@ impl Widget for CheckBox {
type Template = CheckBoxTemplate;
fn create() -> Self::Template {
let text = SharedProperty::new(Text::default());
let icon = SharedProperty::new(FontIcon::from(material_font_icons::CHECK_FONT_ICON));
let selector = SharedProperty::new(Selector::from("checkbox"));
let text = Property::new(Text::default());
let icon = Property::new(FontIcon::from(material_font_icons::CHECK_FONT_ICON));
let selector = Property::new(Selector::from("checkbox"));
CheckBoxTemplate::new()
.height(24.0)
......@@ -35,21 +35,21 @@ impl Widget for CheckBox {
.child(
Container::create()
.size(24.0, 24.0)
.shared_selector(selector.clone())
.shared_selector(selector.share())
.child(
FontIconBlock::create()
.vertical_alignment("Center")
.horizontal_alignment("Center")
.shared_font_icon(icon.clone())
.shared_selector(selector.clone()),
.shared_font_icon(icon.share())
.shared_selector(selector.share()),
),
)
.child(
TextBlock::create()
.vertical_alignment("Center")
.margin((8.0, 0.0, 0.0, 0.0))
.shared_text(text.clone())
.shared_selector(selector.clone()),
.shared_text(text.share())
.shared_selector(selector.share()),
),
)
.shared_font_icon(icon)
......
......@@ -2,7 +2,7 @@ use crate::theme::Selector;
pub use self::context::Context;
pub use self::message::{MessageBox, StringMessage};
pub use self::property::{get_property, PropertyResult, SharedProperty};
pub use self::property::{get_property, PropertyResult, Property};
pub use self::state::State;
pub use self::template::{Template, TemplateBase};
pub use self::widget_container::WidgetContainer;
......
......@@ -8,26 +8,26 @@ use dces::prelude::{Component, ComponentBox, Entity, EntityComponentManager, Sha
use super::WidgetContainer;
/// The `PropertyResult` enum is used to create concrete shared properties for a widget on run time from `SharedProperty` struct.
/// The `PropertyResult` enum is used to create concrete shared properties for a widget on run time from `Property` struct.
pub enum PropertyResult {
Property(ComponentBox, Rc<Cell<Option<Entity>>>),
Source(SharedComponentBox),
PropertyNotFound,
}
/// The `SharedProperty` struct is used to define shared properties for widgets. A shared property could be shared between different widgets.
/// The `Property` struct is used to define shared properties for widgets. A shared property could be shared between different widgets.
/// All references of a shared property will always share the same value. Only the origin shared property contains the concert property, all
/// other cloned shared properties only references to the origin.
pub struct SharedProperty {
pub struct Property {
pub source_chain: Rc<RefCell<Vec<Rc<Cell<Option<Entity>>>>>>,
pub property: Option<ComponentBox>,
pub type_id: TypeId,
}
impl SharedProperty {
/// Creates an new `SharedProperty` for the given `property`.
impl Property {
/// Creates an new `Property` for the given `property`.
pub fn new<P: Component>(property: P) -> Self {
SharedProperty {
Property {
source_chain: Rc::new(RefCell::new(vec![Rc::new(Cell::new(None))])),
property: Some(ComponentBox::new::<P>(property)),
type_id: TypeId::of::<P>(),
......@@ -40,7 +40,7 @@ impl SharedProperty {
}
/// Returns the concert property if the shared property is origin. If the shared property contains a reference to its origin the method returns
/// a `SharedComponentBox`. If its not the origion and does not contain a reference to the origin `PropertyResult::PropertyNotFound` will be returned.
/// a `SharedComponentBox`. If its not the origin and does not contain a reference to the origin `PropertyResult::PropertyNotFound` will be returned.
pub fn build(self) -> PropertyResult {
if let Some(property) = self.property {
return PropertyResult::Property(property, self.source_chain.borrow()[0].clone());
......@@ -53,11 +53,10 @@ impl SharedProperty {
PropertyResult::PropertyNotFound
}
}
impl Clone for SharedProperty {
fn clone(&self) -> Self {
SharedProperty {
pub fn share(&self) -> Self {
Property {
source_chain: self.source_chain.clone(),
property: None,
type_id: self.type_id,
......
......@@ -11,7 +11,7 @@ use crate::{
structs::Point,
};
use super::{SharedProperty, State};
use super::{Property, State};
/// `Template` is used to define the inner structure of a widget.
///
......@@ -43,7 +43,7 @@ pub struct Template {
pub layout: Box<dyn Layout>,
pub constraint: Constraint,
pub properties: HashMap<TypeId, ComponentBox>,
pub shared_properties: HashMap<TypeId, SharedProperty>,
pub shared_properties: HashMap<TypeId, Property>,
pub debug_name: String,
}
......@@ -233,7 +233,7 @@ impl Template {
/// Used to register a shared property for the template. Only one shared property per type can be registered.
/// If a property of the same type exists, it will be replaced by the given shared property.
pub fn shared_property(mut self, property: SharedProperty) -> Self {
pub fn shared_property(mut self, property: Property) -> Self {
if self.properties.contains_key(&property.type_id) {
self.properties.remove(&property.type_id);
}
......@@ -268,7 +268,7 @@ impl Template {
self,
vertical_alignment: V,
) -> Self {
self.shared_property(SharedProperty::new(vertical_alignment.into()))
self.shared_property(Property::new(vertical_alignment.into()))
}
}
......@@ -370,7 +370,7 @@ pub trait TemplateBase: Sized + From<Template> + Into<Template> {
}
/// Attaches a shared property.
fn attach_shared_property(self, property: SharedProperty) -> Self {
fn attach_shared_property(self, property: Property) -> Self {
self.template(|template| template.shared_property(property))
}
}
......@@ -6,7 +6,7 @@ use crate::{
HorizontalAlignment, PaddingProperty, PressedProperty, Selected, SelectedProperty,
},
theme::Selector,
widget::{Container, Context, Grid, SharedProperty, State, Template, Widget},
widget::{Container, Context, Grid, Property, State, Template, Widget},
};
// State to handle the position of switch toggle.
......@@ -48,8 +48,8 @@ impl Widget for Switch {
type Template = SwitchTemplate;
fn create() -> Self::Template {
let selector = SharedProperty::new(Selector::from("switch"));
let selected = SharedProperty::new(Selected::from(false));
let selector = Property::new(Selector::from("switch"));
let selected = Property::new(Selected::from(false));
SwitchTemplate::new()
.width(56.0)
......@@ -59,14 +59,14 @@ impl Widget for Switch {
.child(
Container::create()
.padding(4.0)
.shared_selector(selector.clone())
.shared_selector(selector.share())
.child(
Grid::create().child(
Container::create()
.size(24.0, 24.0)
.vertical_alignment("Center")
.horizontal_alignment("Start")
.attach_shared_property(selected.clone())
.attach_shared_property(selected.share())
.selector(Selector::from("switchtoggle").id("SwitchSwitchToggle")),
),
),
......
......@@ -10,7 +10,7 @@ use crate::{
styling::{colors, fonts},
theme::Selector,
widget::{
Container, Context, Cursor, Grid, ScrollViewer, SharedProperty, State, Template,
Container, Context, Cursor, Grid, ScrollViewer, Property, State, Template,
WaterMarkTextBlock, Widget,
},
};
......@@ -186,28 +186,28 @@ impl Widget for TextBox {
fn create() -> Self::Template {
// text properties
let text = SharedProperty::new(Text::default());
let foreground = SharedProperty::new(Foreground::from(colors::LINK_WATER_COLOR));
let text = Property::new(Text::default());
let foreground = Property::new(Foreground::from(colors::LINK_WATER_COLOR));
let font =
SharedProperty::new(Font::from(fonts::font_into_box(fonts::ROBOTO_REGULAR_FONT)));
let font_size = SharedProperty::new(FontSize::from(fonts::FONT_SIZE_12));
Property::new(Font::from(fonts::font_into_box(fonts::ROBOTO_REGULAR_FONT)));
let font_size = Property::new(FontSize::from(fonts::FONT_SIZE_12));
let water_mark = SharedProperty::new(WaterMark::default());
let water_mark = Property::new(WaterMark::default());
let selector = Selector::from("textbox");
let selection = SharedProperty::new(TextSelection::default());
let offset = SharedProperty::new(Offset::default());
let focused = SharedProperty::new(Focused(false));
let padding = SharedProperty::new(Padding::from(4.0));
let selection = Property::new(TextSelection::default());
let offset = Property::new(Offset::default());
let focused = Property::new(Focused(false));
let padding = Property::new(Padding::from(4.0));
let state = Rc::new(TextBoxState::default());
let _click_state = state.clone();
// container properties
let background = SharedProperty::new(Background::from(colors::LYNCH_COLOR));
let border_radius = SharedProperty::new(BorderRadius::from(2.0));
let border_thickness = SharedProperty::new(BorderThickness::from(0.0));
let border_brush = SharedProperty::new(BorderBrush::from("transparent"));
let padding = SharedProperty::new(Padding::from((8.0, 0.0, 8.0, 0.0)));
let opacity = SharedProperty::new(Opacity::from(1.0));
let background = Property::new(Background::from(colors::LYNCH_COLOR));
let border_radius = Property::new(BorderRadius::from(2.0));
let border_thickness = Property::new(BorderThickness::from(0.0));
let border_brush = Property::new(BorderBrush::from("transparent"));
let padding = Property::new(Padding::from((8.0, 0.0, 8.0, 0.0)));
let opacity = Property::new(Opacity::from(1.0));
TextBoxTemplate::new()
.size(128.0, 32.0)
......@@ -222,15 +222,15 @@ impl Widget for TextBox {
.child(
WaterMarkTextBlock::create()
.vertical_alignment("Center")
.shared_foreground(foreground.clone())
.shared_text(text.clone())
.shared_font(font.clone())
.shared_font_size(font_size.clone())
.shared_water_mark(water_mark.clone())
.attach_shared_property(focused.clone())
.shared_foreground(foreground.share())
.shared_text(text.share())
.shared_font(font.share())
.shared_font_size(font_size.share())
.shared_water_mark(water_mark.share())
.attach_shared_property(focused.share())
.selector(selector.clone().id("TextBoxTextBlock")),
)
.shared_offset(offset.clone())
.shared_offset(offset.share())
.scroll_viewer_mode(ScrollViewerMode::new(
ScrollMode::None,
ScrollMode::None,
......@@ -241,12 +241,12 @@ impl Widget for TextBox {
Cursor::create()
.margin(0.0)
.horizontal_alignment("Start")
.shared_text(text.clone())
.shared_font(font.clone())
.shared_font_size(font_size.clone())
.shared_text_selection(selection.clone())
.shared_offset(offset.clone())
.shared_focused(focused.clone())
.shared_text(text.share())
.shared_font(font.share())
.shared_font_size(font_size.share())
.shared_text_selection(selection.share())
.shared_offset(offset.share())
.shared_focused(focused.share())
.selector(Selector::from("cursor").id("TextBoxCursor")),
)
// .event_handler(MouseEventHandler::default().on_mouse_down(Rc::new(
......@@ -257,12 +257,12 @@ impl Widget for TextBox {
// ))),
)
.attach_property(selector.clone())
.attach_shared_property(focused.clone())
.shared_padding(padding.clone())
.shared_background(background.clone())
.shared_border_radius(border_radius.clone())
.shared_border_thickness(border_thickness.clone())
.shared_border_brush(border_brush.clone())
.attach_shared_property(focused.share())
.shared_padding(padding.share())
.shared_background(background.share())
.shared_border_radius(border_radius.share())
.shared_border_thickness(border_thickness.share())
.shared_border_brush(border_brush.share())
)
.shared_text(text)
.shared_font(font)
......
......@@ -4,7 +4,7 @@ use crate::{
SelectedProperty, Text, TextProperty,
},
theme::Selector,
widget::{Container, FontIconBlock, SharedProperty, Stack, Template, TextBlock, Widget},
widget::{Container, FontIconBlock, Property, Stack, Template, TextBlock, Widget},
};
/// The `ToggleButton` widget can be clicked by user. It's used to perform an action.
......@@ -21,9 +21,9 @@ impl Widget for ToggleButton {
type Template = ToggleButtonTemplate;
fn create() -> Self::Template {
let text = SharedProperty::new(Text::default());
let icon = SharedProperty::new(FontIcon::default());
let selector = SharedProperty::new(Selector::from("togglebutton"));
let text = Property::new(Text::default());
let icon = Property::new(FontIcon::default());
let selector = Property::new(Selector::from("togglebutton"));
ToggleButtonTemplate::new()
.height(32.0)
......@@ -34,7 +34,7 @@ impl Widget for ToggleButton {
.child(
Container::create()
.padding((8.0, 0.0, 8.0, 0.0))
.shared_selector(selector.clone())
.shared_selector(selector.share())
.child(
Stack::create()
.orientation("Horizontal")
......@@ -43,13 +43,13 @@ impl Widget for ToggleButton {
.child(
FontIconBlock::create()
.margin((0.0, 0.0, 2.0, 0.0))
.shared_font_icon(icon.clone())
.shared_selector(selector.clone()),
.shared_font_icon(icon.share())
.shared_selector(selector.share()),
)
.child(
TextBlock::create()
.shared_text(text.clone())
.shared_selector(selector.clone()),
.shared_text(text.share())
.shared_selector(selector.share()),
),
),
)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment